[Advice] Documenting the "refined by" relation for concepts
Dear all, When documenting a concept in a generic library, it is common to include what this concept is a "refinement of", i.e. which other concept(s) it specializes. For example, see the ForwardContainer concept from the SGI STL [1], which is a refinement of the Container concept. I find documenting this relation very useful. However, I have never seen the reverse relation of being "refined by" documented. It has been suggested to me [2] that Hana should document this "refined by" relation. Having never seen it done before, I'd like to know what the seasoned generic library writers think about it. The possibilities I personally see are 1. It's just not useful, and that's why it's not done 2. It's actually harmful, because you can't predict who is going to refine a concept 3. There's no "logical" reason behind this, it just happened to work that way in the SGI STL and everybody else followed that lead. Any input is appreciated. Regards, Louis [1]: https://www.sgi.com/tech/stl/ForwardContainer.html [2]: https://github.com/ldionne/hana/issues/104
On 6/13/15 1:12 PM, Louis Dionne wrote:
Dear all,
When documenting a concept in a generic library, it is common to include what this concept is a "refinement of", i.e. which other concept(s) it specializes. For example, see the ForwardContainer concept from the SGI STL [1], which is a refinement of the Container concept.
I find documenting this relation very useful. However, I have never seen the reverse relation of being "refined by" documented. It has been suggested to me [2] that Hana should document this "refined by" relation. Having never seen it done before, I'd like to know what the seasoned generic library writers think about it. The possibilities I personally see are
1. It's just not useful, and that's why it's not done True - the dependency relation is that the "derived concept" depends upon the "base concept" but not the other way around. It's exactly analogous to a class hierarchy. In fact, if you use Boost Concept Checking library (as you should be) You'll find that a "refinement of" concept is defined as a C++ base type and a "refined by" concept is defined as a C++ derived class. Just as a base class cannot specify anything about anything derived from it - a "refinement of" concept can't say anything about the "refined by" concepts other than that which is already described by the "base" concept. This is touched upon in my "Advice - Type Requirements" in the boost library incubator.
2. It's actually harmful, because you can't predict who is going to refine a concept
Also true - It could never be accurate. However, it's common for documentation of at concept to contain a section named "Models" which are basically classes which follow (model) the concept. I'm sympathetic to the question though. The original inventors of the terms "concept" , "model" chose nomenclature which has confused the issue for two generations of programmers. It doesn't help things any either when otherwise well respected authors define concepts like "Sortable" which confusing things even more. Robert Ramey
Robert Ramey
[...]
2. It's actually harmful, because you can't predict who is going to refine a concept
Also true - It could never be accurate.
However, it's common for documentation of at concept to contain a section named "Models" which are basically classes which follow (model) the concept.
Providing a list of the models of a concept is a good idea and it is pretty common for generic libraries too. Hana follows that. Thanks for your input, Louis
2015-06-13 17:12 GMT-03:00 Louis Dionne
Having never seen it done before, I'd like to know what the seasoned generic library writers think about it.
In Boost.Http (not part of Boost yet), I've put the "refined by" members within the "see also" section: https://boostgsoc14.github.io/boost.http/reference/socket_concept.html#refer... 2. It's actually harmful, because you can't predict who is going to
refine a concept
I think this is the most important concern from what you've mentioned. -- Vinícius dos Santos Oliveira https://about.me/vinipsmaker
Vinícius dos Santos Oliveira
2015-06-13 17:12 GMT-03:00 Louis Dionne
: Having never seen it done before, I'd like to know what the seasoned generic library writers think about it.
In Boost.Http (not part of Boost yet), I've put the "refined by" members within the "see also" section:
I think that's an interesting idea, really. This way, you don't pretend offering an exhaustive list of refined-by concepts, but you still give some help to the user who's looking for them. I might do just that. Thanks for your input, Louis
Le 13/06/15 22:12, Louis Dionne a écrit :
Dear all,
When documenting a concept in a generic library, it is common to include what this concept is a "refinement of", i.e. which other concept(s) it specializes. For example, see the ForwardContainer concept from the SGI STL [1], which is a refinement of the Container concept.
I find documenting this relation very useful. However, I have never seen the reverse relation of being "refined by" documented. It has been suggested to me [2] that Hana should document this "refined by" relation. Having never seen it done before, I'd like to know what the seasoned generic library writers think about it. The possibilities I personally see are
1. It's just not useful, and that's why it's not done 2. It's actually harmful, because you can't predict who is going to refine a concept 3. There's no "logical" reason behind this, it just happened to work that way in the SGI STL and everybody else followed that lead.
Any input is appreciated.
Let me put the context. Hana Concepts as Haskell type classes list the type that an instance/model of the type class/concept. E.g. in The Applicative Concept we see " Concrete models Either, Lazy, Optional, Tuple " The refined by is no more than another case, that is not concrete but generic. Let me put the context. Hana Concepts as Haskell type classes list the type that an instance/model of the type class/concept. E.g. in The Applicative Concept we see Concrete models Either, Lazy, Optional, Tuple The refined by is no more than another case, that is not concrete but generic. E.g. as we have Applicative(T) => Monad(T) .... Wouldn't be useful to add on the Applicative documentation that any concret model of Monad is a concrete model of Applicative. My concern was about documenting these more generic cases as Hana has made the decision to document the models of relationship. Both will are subject to the same problems, this information can not be complete, but it can be for the types and concepts in Hana. Another example that is not missing as Hana don't see Optional as a Monoid. Imagine that it was the case, and Hana contained a such a mapping. I would find normal to find this in the Optional documentation on the section Modeled concepts Monoid(T) => Monoid(Optional(T)) The question is if this should also appear as well a on the Monoid one. Best, Vicente P.S. All this is no more than a cross reference between the Concepts and the models. P.S.S. I recognize that maintaining this information manually is subject to errors, but I know that we are talking with experts that know how to generate these kind of cross reference information automatically ;-)
Vicente J. Botet Escriba
[...]
My concern was about documenting these more generic cases as Hana has made the decision to document the models of relationship. Both will are subject to the same problems, this information can not be complete, but it can be for the types and concepts in Hana.
That is correct; we could at least provide an exhaustive list of sub-concepts provided by Hana. It is also true that the "concrete models" are subject to the same problem, since models can be added without Hana's knowledge. That went under my radar when I gave the (2) argument, since Hana provides a (non-exhaustive) list of the concrete models.
Another example that is not missing as Hana don't see Optional as a Monoid. Imagine that it was the case, and Hana contained a such a mapping.
I would find normal to find this in the Optional documentation on the section Modeled concepts
Monoid(T) => Monoid(Optional(T))
The question is if this should also appear as well a on the Monoid one.
That is a bit different because Optional is a data type and Monoid is a concept. Instead, if that was something like Monoid(T), SomeConcept(F) => Monoid(F(T)) I think I would just expect to see this on the Monoid's documentation, not on SomeConcept's. This is how Haskell's documentation works, anyway.
P.S. All this is no more than a cross reference between the Concepts and the models.
I thought it was cross-referencing between the super- and sub- concepts? Cross-referencing between concepts and models is already done: - Concepts have a list of their models - Data types have a list of the concepts they are a model of
P.S.S. I recognize that maintaining this information manually is subject to errors, but I know that we are talking with experts that know how to generate these kind of cross reference information automatically
Lol. I think it's time for me to move away from Doxygen. I literally have __no clue__ how to do this with Doxygen, or if it's even possible. Regards, Louis
On 14/06/2015 08:12, Louis Dionne wrote:
When documenting a concept in a generic library, it is common to include what this concept is a "refinement of", i.e. which other concept(s) it specializes. For example, see the ForwardContainer concept from the SGI STL [1], which is a refinement of the Container concept.
I find documenting this relation very useful. However, I have never seen the reverse relation of being "refined by" documented. It has been suggested to me [2] that Hana should document this "refined by" relation. Having never seen it done before, I'd like to know what the seasoned generic library writers think about it.
Well, I'm not a seasoned generic library writer, but in my view as a user of such libraries it is always very useful to be able to navigate from a base class/interface to its derived classes in the documentation, and the same would apply to concepts. (Not just derived/refined concepts, but also if there are classes provided in the library that actually implement these concepts.) One of the reasons that this is sometimes left out of documentation is that it's usually an open relationship and thus can never be complete -- other libraries or the user's own code could (and often does) add additional types that "should" have been listed, though of course they can't be. However I don't think that's a good reason to not document this relation for the types that are actually provided by the library, though. (The other reason that it's often left out is that many libraries only define purely-open concepts with no internal implementations and no refinements, so there's no relations *to* document.) That's my $0.10, anyway. (Due to exchange rates and not having any smaller coins any more.)
On 6/14/15 8:31 PM, Gavin Lambert wrote:
Well, I'm not a seasoned generic library writer, but in my view as a user of such libraries it is always very useful to be able to navigate from a base class/interface to its derived classes in the documentation, and the same would apply to concepts. (Not just derived/refined concepts, but also if there are classes provided in the library that actually implement these concepts.)
Any derived concepts that the library includes will have their own pages which will refer to the base concept so it's not like anything will be lost but not including a pointer from the base to the derived. In fact, this might well be confusing as it might obscure the essential dependency relationship. This is especially true as the library undergoes maintenance. I would recommend doing it the standard way as illustrated by the SGI documentation. And most library actually only have a few new concepts anyway. I haven't seen any other than STL which define more than a small # of concepts (5?). Robert Ramey
On 15/06/2015 17:05, Robert Ramey wrote:
On 6/14/15 8:31 PM, Gavin Lambert wrote:
Well, I'm not a seasoned generic library writer, but in my view as a user of such libraries it is always very useful to be able to navigate from a base class/interface to its derived classes in the documentation, and the same would apply to concepts. (Not just derived/refined concepts, but also if there are classes provided in the library that actually implement these concepts.)
Any derived concepts that the library includes will have their own pages which will refer to the base concept so it's not like anything will be lost but not including a pointer from the base to the derived.
Yes, something is lost: if you are looking at the documentation for the base type/concept, you have no way to find any derived type/concepts without trawling the entire documentation and hoping that they have sufficiently similar names to be recognisable. (Which is usually the case, but not always.)
In fact, this might well be confusing as it might obscure the essential dependency relationship.
I don't see how -- you can clearly indicate the difference between base and derived by putting them in different sections or with appropriate headings. Possibly this particular style is only suited to a "large" library, but the .NET Framework documentation has a good example of a minimalist style that still conveys the necessary information: an "Inheritance Hierarchy" section that shows a tree with base types above and derived types below the current type. Libraries with only a small tree of types/concepts may be better served with a more verbose style though, for improved clarity.
This is especially true as the library undergoes maintenance.
Ideally the tools should keep the docs up to date automatically (at least the reference section).
I would recommend doing it the standard way as illustrated by the SGI documentation.
The SGI docs sometimes list the derived types/concepts in the base doc's "See Also" section, which is good. It would be better if it were called out more explicitly, though, as otherwise they're mixed in with other types that have a lesser relationship; and it would be better still if it were more consistent about listing them at all.
And most library actually only have a few new concepts anyway. I haven't seen any other than STL which define more than a small # of concepts (5?).
I did make that point. (Boost.Asio has quite a few, incidentally.)
Gavin Lambert
[...]
Well, I'm not a seasoned generic library writer, but in my view as a user of such libraries it is always very useful to be able to navigate from a base class/interface to its derived classes in the documentation, and the same would apply to concepts. (Not just derived/refined concepts, but also if there are classes provided in the library that actually implement these concepts.)
One of the reasons that this is sometimes left out of documentation is that it's usually an open relationship and thus can never be complete -- other libraries or the user's own code could (and often does) add additional types that "should" have been listed, though of course they can't be. However I don't think that's a good reason to not document this relation for the types that are actually provided by the library, though.
I agree that providing a list of the sub-concepts defined by the library is useful to the user. I think I'll do that in one way or the other, perhaps like Vinicius suggested (in a "See also" section) or by providing a "Non-exhaustive list of sub-concepts" thing. In all cases, I must find a way to handle this automatically, or I'll regret this really fast. Regards, Louis
participants (5)
-
Gavin Lambert
-
Louis Dionne
-
Robert Ramey
-
Vicente J. Botet Escriba
-
Vinícius dos Santos Oliveira