Abel Sinkovics
[...]
It would be useful to add a step-by-step guide to the documentation for extending the library with custom algebraic data-types - for example a "how to build your own Optional/Either/etc" (Note: I was reading Optional's implementation as an example to build my own data types).
Once I learned how to build my own data-types, I could easily create the ones I needed and they worked intuitively (to me). So it seems to be well supported and should be better documented.
This should be part of the (still incomplete) section of the tutorial on "Extending the library". I guess using a concrete example like Optional is a good idea. Thanks for the heads up.
It is great that the library makes it possible to have static if_ and switch_ in the body of a function. I think a few things should be pointed out about them (probably in the documentation):
- when entering a branch of an if_ (or switch_) you are calling a different function which is not (always) the same as having a block inside your function body. You might (and are very likely to) be affected by how you pass arguments to this function (capture in the lambda, pass by value, pass by rvalue reference, etc). This is something to be aware of when using these constructs.
Definitely. I will add this to the documentation.
- if you use these structures (especially if you have 2 or 3 nested layers of them in the same function), the same variable might have different names on each level (eg. to make sure that a branch of the if_ gets instantiated only when it is needed and safe to do so). This can be confusing.
There's actually a different way to do it, but it is not documented in the tutorial. It is documented in the reference of `eval_if` [1]. I will try to add it to the tutorial.
[...]
Even though I haven't tried it, but based on the documentation the Lazy type seems to be an interesting way to approach lazy evaluation for metaprograms. The idea of the lazy monad seems very interesting. One thing I'd fix in Lazy's documentation: eval_if is mentioned in Lazy's doc, however there is no link to it and it was not trivial to find eval_if's doc. I'd make the places mentioning eval_if links to its description.
Taking a note to add links to eval_if. More generally, this should always be handled properly but the documentation tool, but this does not happen with Doxygen :-(.
Why is string not a model of the Constant concept? I tend to think of strings as values and since they contain characters only, they should be representable at runtime. (the question is probably how they should be represented).
String used to be a model of Constant. The problem is that the `value`
function, which extracts the value from the Constant, should preserve the
semantics of the original Constant. However, since String's value was
(formerly) a `char const*`, that structure was not preserved. For example,
it would be true that
"abcd"_s < "abcde"_s
while
value_of("abcd"_s) < value_of("abcde"_s)
would not necessarily hold, because it would compare two `char const*`.
The proper workaround would be to have a compile-time string class, and
the `value()` of a Hana String should be a constexpr object of that type.
However, if you need a `char const*` from a Hana String, you can use
`to
What is the reason behind using tag dispatching in Hana? More specifically, why is tag dispatching used instead of for example enable_if? For example:
template
>> auto head(T t); template
>> auto head(T t); ...
It is not clear to me why tag dispatching is preferred over this (or a similar) approach. (eg. does tag dispatching perform better?) It might be explained in the documentation.
I wanted a two-layer dispatching system because the first layer (the
functions you call) are actually function objects, which allows using them
in higher-order algorithms. They can also do some compile-time sanity checks,
which improves error messages.
Now, we could just as well write:
template
[...]
Multiple types are models of the Monad concept, however, the documentation does not explain how the monadic operations are implemented for the different types (eg. what chain is doing for lists, etc). I believe it is not (always) trivial and should be explained in the documentation (I had simliar things in Metamonad and decided to add it to the documentation).
Technically, the implementation of `flatten` for Sequences is documented in the Sequence concept. From there, you could derive the implementation of `chain` and all the other functions from Monad. Of course, doing so is not easy and I will add this to the documentation.
I really like it that for some elements (eg. Functor's transform operation) the documentation contains benchmarks.
In the future, I plan to provide benchmarks for almost every algorithm. That used to be the case, but I changed the benchmarking system and didn't have the time to rewrite them all.
[...]
Thanks a lot for your review, Abel! Regards, Louis [1]: http://goo.gl/c0qgsb