These are chat archives for boostorg/hana

3rd
May 2015
Manu Sánchez
@Manu343726
May 03 2015 08:45
People discussing about bii here! This is the last thing I expected ;)
Hans Meyer
@HaMster21
May 03 2015 08:48
Seems to be the perfect place to make an upcoming library for boost available to everyone ^^
Manu Sánchez
@Manu343726
May 03 2015 08:49
I'm still trying to get a Haskell type system for metaprogramming, and today I relalized that Concepts Lite is the right way to go. So I was going to start writting concepts for my library but then stoped: What if you can use exactly the same concepts for both the metaprogramming type system and the C++ type system? That's why I'm here.
Louis Dionne
@ldionne
May 03 2015 11:12
Actually, I want to talk about this with Eric. I think we can make his range library work on heterogeneous sequences by doing subtle modifications to the concepts.
So yeah, your idea isn’t crazy at all Manu.
Manu Sánchez
@Manu343726
May 03 2015 11:28
First of all I will try to get a Concepts Lite compiler working (I'm trying to build gcc-clite on windows/cygwin, completely unsuccessful. Seems impossible to me being able to play battlefield while doing meta stuff...). Later wrap your existing concepts as constexpr boolean predicates as their implementation expects (What about a clitebranch?). Then I could continue haskellizing both TMP and C++ with Hana as the starting point.
Louis Dionne
@ldionne
May 03 2015 11:41
That sounds like a great idea, seriously.
One challenge though is that C++ is a strict language. So you can’t have exactly the same concepts as in Haskell. For example, you can’t right fold infinite lists in C++.
This message was deleted
Manu Sánchez
@Manu343726
May 03 2015 12:28
Of course one of the first things we should do here is to identify what parts of Haskell (Concepts/Typeclasses, prelude, etc) that are directly "mappable" to C++.
Louis Dionne
@ldionne
May 03 2015 12:28
Functor
Applicative if you let go of automatic currying
Monad just the same
Manu Sánchez
@Manu343726
May 03 2015 12:30
Do you have a curry adaptor in Hana?
Louis Dionne
@ldionne
May 03 2015 12:32
For Foldable, you have to consider strict folds only, which means that you can’t implement any, elem and find as lazy right folds. This is why Hana has the Searchable concept, which basically encapsulates Foldables that might be infinite.
Yes, Hana has the curry adaptor.
Regarding Applicative, by the way, Hana uses the curry adaptor to emulate automatic currying. This makes things like f <transform> x <ap> y <ap> z equivalent to curry(f) <transform> x <ap> y <ap> z, where <...> is just infix application of .
Manu Sánchez
@Manu343726
May 03 2015 12:36
I have been wondering about a lazy adaptor for a long time for exactly this reason. But this "hey do you have an adaptor for X?" is starting to look as reinventing the whole language. I have no problem with that.
Louis Dionne
@ldionne
May 03 2015 12:37
This exact process happens here. Given f a function inside an Applicative and n arguments inside the same Applicative, I simply fmap curry f, which gives me an Applicative of curried functions.
I’m not sure how a lazy adaptor would help.
To implement lazy folds, I mean.
One problem is that Haskell does deep laziness, in the sense that every subexpressions of every expression is lazy. With a lazy adaptor, we can only get superficial laziness at one level.
Manu Sánchez
@Manu343726
May 03 2015 12:40
Exactly. That's what I mean by reinventing the language. To make this really work in the most Haskell-like way, users should rely in the features provided here only.
Louis Dionne
@ldionne
May 03 2015 12:42
I think one thing to reconsider is the value of laziness in a strict language like C++. It is obviously useful in some contexts, but it might not be worth the immense pain that you’re up to if you try to have deep laziness.
Conceptually, having deep laziness in C++ means to do the “evaluation” of lazy thunks manually, whereas it is done automatically in Haskell. Also, you won’t be memoizing the results of computations, which makes a lot of brilliant lazy patterns completely worthless.
My impression is that evaluating lazy thunks manually will be very painful from a programmer’s perspective.
Anyway, that’s the current state of my understanding of things. This is why Hana does not try to go lazy except in some simple cases (e.g. for conditional statements), and this is also why the usual Haskell concepts are broken up into more parts (Iterable, Foldable and Searchable instead of just Foldable in Haskell).
Louis Dionne
@ldionne
May 03 2015 12:48
But I agree that laziness would be something nice to have. Also, I’d like to point out that this issue is really not limited to metaprogramming or implementing Haskell in C++. Indeed, the range-v3 people are bumping against similar issues, see ericniebler/range-v3#142.
Manu Sánchez
@Manu343726
May 03 2015 13:10

Being frankly the only use case that comes to my mind for laziness (From the C++ point of view) are infinite ranges and related. In depth laziness and non-strict functions are cool, but their advantages may not worth the effort. Let's forget lazy for now (right fold included).

I'm gonna try to focus on translating the existing concepts to CL for now.

What I don't know is what to do with Turbo xD. I have a lot of plans for it, but it's a looooooooooong roadmap. But I will keep with it as an ideas "incubator". Algebraic datatypes as nested structs starts to look great, at least for me. But there's a lot of work to do first. Like Manu343726/Turbo#8
Louis Dionne
@ldionne
May 03 2015 13:26
I think anything that tries to see how things would look with concepts is a good thing, since concepts are the future for C++. In the long term, I think even metaprogramming libraries will have to use Concepts (for the better). I’d be interested to watch your progress on this topic; please consider making your work in that direction publicly available on GitHub.
Also, if you keep on pushing in the direction of pure type-level metaprogramming (with Turbo), I’d suggest that you carefully take into account the possible compile-time penalty for recursively evaluating expressions through eval. I’m not sure whether your eval evaluates recursively, but it could be costly if it does. I don’t know for sure, but just be careful.
Nicola Bonelli
@awgn
May 03 2015 14:00
Hi there!
Manu Sánchez
@Manu343726
May 03 2015 14:03
So asking for feedback on twitter works after all :)
Nicola Bonelli
@awgn
May 03 2015 14:06
Ahah well, after all the topic is pretty hot right now. Onestly I was interested in trying this chat 😅
Manu Sánchez
@Manu343726
May 03 2015 14:09

:point_up: May 3 2015 6:26 AM

eval did full recursive evaluation at the beginning, but as Turbo evolved recursive evaluation has lost importance in favor of thinking of eval as a way to evaluate all kind of expressions. Should I evaluate any template parameters prior to evaluate the template itself? I'm not that sure these days. Not for non-function templates. Also those should be evaluated lazily, not just evaluate the whole parameter list prior to function evaluation as I currently do. That's one of the reasons I'm focusing the effort on having comfortable curryable metafunctions.

Louis Dionne
@ldionne
May 03 2015 14:18
@awgn Hi!
@Manu343726 I don’t know if that might be of interest to you, but MPL11 has a curry metafunction here.
Manu Sánchez
@Manu343726
May 03 2015 14:24
@ldionne what does ::type mean? If curry is evaluated without arguments returns curry itself, else the next one (via apply)?
Nicola Bonelli
@awgn
May 03 2015 14:26
Manu, being lazy in your template mtp library means not accessing to ::type right?
Louis Dionne
@ldionne
May 03 2015 14:27
MPL11 is lazy from the ground up (you can actually right fold infinite lists with it). It only manipulates what we call “boxed” values, i.e. values with a nested ::type. This is what curry<…>::type is; it just evaluates the curry<…> value itself. It does not perform any kind of computation.
I think I’m not being clear enough. 1 sec.
Manu Sánchez
@Manu343726
May 03 2015 14:28
@ldionne that makes sense. I understood that pretty well from your readme, don't worry. So type there is to behave like a boxed entity.
Louis Dionne
@ldionne
May 03 2015 14:28
Yeah, exactly.
In the same vein, you can see in the curry<1, f> specialization that I evaluate the metafunction class with f::type::template apply<x>. The f::type part means: “unbox the metafunction f”, and then call this with x.
Manu Sánchez
@Manu343726
May 03 2015 14:30
@awgn for metafunctions, yes. If you write everything via metafunctions it behaves eager like Eric's Meta. But Turbo also supports metafunctions classes.
Nicola Bonelli
@awgn
May 03 2015 14:33
I need to give a look at your libs guys, otherwise I risk to reinvent the wheel :-)
Manu Sánchez
@Manu343726
May 03 2015 14:34

@ldionne got it thanks!

What I'm doing is to return a closure until the metafunctions accepts the arguments. That is, the metafunction is curryed until you enter all the arguments needed:

template<template<typename...> class Function>
struct curry
{
    template<typename... Args>
    struct apply
    {
        using f = just_t<Function, Args...>;

        template<typename F, bool is_function = has_type<F>::value>
        struct call
        {
            using type = typename F::type;
        };

        template<typename F>
        struct call<F, false>
        {
            struct type
            {
                template<typename... Tail>
                struct apply
                {
                    using type = eval_mc<curry, Args..., Tail...>;
                };
            };
        };

        using type = typename call<f>::type;
    };
};
just_t tries to instance a template with the given arguments, else returns Nothing. Of course Nothing is not a metafunction nor has a ::type member.
Louis Dionne
@ldionne
May 03 2015 14:37
@awgn I looked at your Cat library, and it is not reinventing Hana in the following sense: Cat manipulates sequences whose length is known at runtime, whereas Hana manipulates sequences whose length is known at compile-time. This distinction makes a huge difference because it allows Hana sequences to hold objects with different types, but then you also lose a lot of properties like being able to append a runtime-known number of elements to a Hana sequence.
Manu Sánchez
@Manu343726
May 03 2015 14:38
And to index those sequences at runtime :(
Louis Dionne
@ldionne
May 03 2015 14:39
Yeah, but it only makes sense when you think about it; the type of the returned value would have to depend on a runtime integer, which is impossible. You need to use a dependently-typed language for that (Agda, Coq & al, I'm not too knowledgeable there).
@Manu343726 , How does your curry utility handles variadic metafunctions?
When does it stop evaluating? IIUC, it will stop at the first argument. For example, how would you curry the following:
template <typename ...T>
struct pack_size {
    using type = std::integral_constant<std::size_t, sizeof...(T)>;    
};
Nicola Bonelli
@awgn
May 03 2015 14:42
Sorry guys my GF is reclaiming me... Talk later 😒
Manu Sánchez
@Manu343726
May 03 2015 14:43
@ldionne good catch ;) It doesn't, since a variadic template is always instantiable regardless of the arguments. What I have is a Continue tag. $(f, a, b, c, Continue), where fis a variadic metafunction.
Louis Dionne
@ldionne
May 03 2015 14:43
@Manu343726 From my current understanding, it is impossible to automatically curry variadic metafunctions (or functions for that matter). The user has to say "consider this function as a __n -ary function for currying".
How does the continue trick work?
Manu Sánchez
@Manu343726
May 03 2015 14:46
Checking the back argument prior to evaluation. I have played with a Curry tag that comes at the beginning too, just to make the thing O(1).
Louis Dionne
@ldionne
May 03 2015 14:48
Ok, so before you evaluate the thing, you check whether it's got a Continue tag at the end, and if so, you just return the expression as-is instead of fetching the nested ::type?
Manu Sánchez
@Manu343726
May 03 2015 14:49
Exactly, I return a closure (The type struct in the false specialization of call above.
eval_mc means "evaluate metafunction class" just typename F::template apply<Args...>::type less ugly
Louis Dionne
@ldionne
May 03 2015 15:01
Oh, ok I get it.