
Le 05/03/15 15:41, Louis Dionne a écrit :
Dear Boost,
As some may be aware of, I am currently working on a metaprogramming library called Hana, with the intention of proposing it for inclusion in Boost. The purpose of that library is to act as a toolbox for expressing computations on both types (like the MPL) and heterogeneous values (like Fusion). The library is built around C++14 idioms and implementation techniques to maximize expressiveness and performance. Hi and thanks in advance for your work. I am now requesting feedback from the community, with the intention of asking for a formal review in the next months. A similar review was asked for in last August. The library has undergone several modifications since then, both to address issues raised during the review and for general improvement. Here are some issues that were raised during the review and addressed:
- Usage of names and terms unknown to C++ programmers: Efforts were made to make this better, and several functions were renamed (`fmap` is now `transform`). When possible, the documentation also uses terms more familiar to C++ programmers, like concept instead of "type class". I'm not sure the use of the term "concept" instead of "type class" is appropriated (given that the C++ standard is defining concepts in a different way). Hana "type class" is based, as Concept C++0x, on signatures. An instance "type" of a "type class" needs a mapping of the signature. I can live with the term TypeClass. Nevertheless if you don't want to use it I will suggest you the terms "MappedConcept" or "SignaturedConcept" instead of "Concept".
- The order of the arguments to some algorithms was unfortunate for C++. It was consistent with Haskell, but it turned out to be cumbersome in C++. Just for curiosity, could you give some examples of these changes and why it was cumbersome? This is changed in most places.
- Inability to easily implement individual algorithms: This is fixed, and algorithms are now standalone structures using tag-dispatching, almost exactly as in Fusion. Just for curiosity, could you give some examples of these changes and why it was difficult before the changes?
- Lack of a good introductory tutorial: A lot of work has gone into improving both the tutorial and the reference documentation.
I appreciate what has been done already to improve the tutorial. Next follows some comments about the design. DataTypes and TypeClasses ---------------------- I appreciate what has been done already. I have some trouble with the "datatype" use. If I understand it correctly, the type you map to a "type class" is not the type itself but its datatype (which can be the same). In Haskell, type classes can be universally quantified or not. E.g. the "type class" Eq is not universally quantified class Eq a `(==) :: a -> a -> Bool (/=) :: a -> a -> Bool while the "type class" Functor it is universally quantified class Functor f where fmap :: (a -> b) -> f a -> f b That means that the instance mapping for Eq is from types (*) and the instance mapping for Functor is for type constructors having one parameter (* ->*). Let me show the instance mapping for Either in Haskell (Eq a, Eq b) => Eq (Either a b) Functor (Either a) Note the difference. In the first case the instance is Either a b. In the second it is Either a. I don't see this nuance in your library. The datatype of left<A>/right<B> is Either, and the instance of Comparable and Functor is always Either. BTW, I'm missing a type either<A,B> see below I'm wondering if the library shouldn't make this difference and make either<A,B> be an instance of Comparable and either<A,_> be an instance of Functor, where either<A,_> stands for the universal type constructor having a parameter. Compile-time error reporting -------------------- I would expect that the library provide some king of "TypeClass" check use (As Eric's Range library does with Concepts) so that the compile time errors are more explicit. Unnamed data types ----------------- I'm missing, between other, the concrete types _either<A,B> and _maybe<T>, as we have _pair<A,B>. How the user can declare a structure having data members with these data types? About a pure type meta programming sub-library Hana/Meta ---------------------------------------------------- While I agree that it is good to be able to define the algorithms only once for types and values, I find the syntax cumbersome when the user wants only to work at the meta-programming level. I wonder if the library shouldn't contain a sublibrary Hana/Meta that defines in a meta namespace all the algorithms/types that work directly on types and integral constants. Instead of defining a hana::tuple_t, I suggest to define it in meta::tuple that works only with types and a meta::transform that works only on types. This will allow to write ([1]) static_assert( meta::transform<meta:: tuple<int, char const, void>, std::add_pointer>{} == meta::tuple<int*, char const*, void*>{} , ""); instead of static_assert( hana::transform(hana::tuple_t<int, char const, void>, hana::metafunction<std::add_pointer>) == hana::tuple_t<int*, char const*, void*> , ""); The definition of meta::transform will just do the steps 2 and 3 of the process you describe: 1. Wrap the types with |type<...>| so they become values 2. Apply whatever type transformation |F| by using |metafunction<F>| 3. Unwrap the result with |decltype(...)::type| namespace meta { template <class Tuple, class F> using transform = |decltype(|hana::transform(Tuple{}, ||hana::metafunction<F>))::type } An additional advantage of having this Meta library is that it can be defined using just a C++11 compiler, as it is done in Eric's Meta library. Best, Vicente [1] the name could be also meta::list.