pfultz2
[...]
But as user if I was defining my own `sum` function, how would I do it? I can't change the typeclass, since it is in another library. Is there a way for me as an user to optimize my sum function based on which MCD was implemented? And if so, couldn't the library do the same?
Well, if you define the `sum` function, that's because you are defining an instance of the corresponding type class (Foldable). Hence, you are already choosing the MCD: namespace boost { namespace hana { template <> struct Foldable::instance<YourDatatype> : Foldable::the_mcd_you_want { // minimal complete definition here template <typename Xs> static constexpr auto sum_impl(Xs xs) { // your custom sum implementation } }; }} // end namespace boost::hana Am I missing your point?
If you go look at the Foldable type class in Haskell, you'll see that there are a bunch of related functions provided with the type class, yet they are not included in it. My opinion is that they might just as well be included in the type class, as you could then redefine them for improved performance. I just searched online for a rationale or at least some insight about this decision, but I did not find anything.
I think the rational is similar to the rational for using non-member functions. One reason is consistency. People are going to add new algorithms, but they won't be added to the typeclass. Futhermore, if they want to allow overloading the algorithm for optimization, they will create new typeclasses. So now you have two different ways to accomplish the same thing.
The truth is that I think users should not feel the need to add methods to existing type classes. If a method can be implemented in a type class _and_ has a general utility, then it should be added to the type class for everyone to benefit. If, however, you need more "structure" than provided by existing type classes to do something, then you create a new type class which carries that additional "structure" and in which you can implement more operations. That's how I see it.
Another reason, is it will make the typeclass simpler and improve encapsulation. A typeclass is defined by the minimum necessary and not by another 50 algorithms.
I disagree. Type classes are _already_ defined by their minimal complete definition(s). While this is not the case in the current documentation, I'd like to actually document an equivalent implementation for each method using only methods in a minimal complete definition. That would make it more obvious that type classes are defined by their MCDs.
- It's important to note that the `decltype_` function will only work for constexpr-friendly types.
I don't get it? Can you please expand?
I should clarify that I'm referring to the use of `decltype_` within the context of constexpr. It will work outside of that. So, for example, if I were to static_assert that two types were the same, as a simple example:
template<class T> void foo(T x) { auto y = bar(); static_assert(decltype_(x) == decltype_(y), "Not matching types"); }
This won't work for if types are not a literal type nor have a constexpr constructed. This will fail even if `decltype_` was to take the expression by reference. Ultimately, I believe the language should be changed to allow for this.
It should work; Hana was designed exactly to deal with that. Here's what
happens (that's going to be in the tutorial also):
1. decltype_(x) == decltype_(y) returns a bool_<true or false>
2. bool_<b> has a constexpr conversion to bool defined as:
template <bool b>
struct bool_type {
constexpr operator bool() const { return b; }
};
Since the conversion is always constexpr, it's used in the `static_assert`
and it works. Now, it does not __actually__ works because of what I think
is a bug in Clang. For it to work, you have to define a dummy object like
that:
template