Grégoire Locqueville | Easy Type-Level Flags In Haskell

9 Likes

I think your last eval :: Expr unsafeFlag -> Maybe Double definition is missing a TFlag unsafeFlag constraint (since it calls whenFlag :: TFlag a => ...).

1 Like

Indeed, thanks for notifying me, I just corrected it :slight_smile:

1 Like

Great article! The last eval function that returns Maybe Double should have liftA2 (+) (eval x) (eval y), no?

1 Like

You’re right! Corrected :slight_smile:

1 Like

Why is TFlag needed as a class?

This HKD: best or worst thing ever? - #7 by rhendric extends on the use of Void/() for cardinality

1 Like

I should have guessed that people had thought of this before me x) (to be honest, I did, I just didn’t realize that kind of thing was a common pattern).

Regarding the type class, that’s the solution I came up with to write functions such as the post’s eval, that is, functions that consume types with a generic type flag. There may be another way, I’m which case I’m happy to hear about it :slight_smile:

Reminds me of Trees That Grow: trees that grow guidance · Wiki · Glasgow Haskell Compiler / GHC · GitLab

But your blog post provides a good intuition and introduction to the idea!

3 Likes

Yes people have mentioned it elsewhere too, but I didn’t get the chance to get into it yet! Might do a nice follow-up post maybe? Anyway thanks for the link, all I found was the paper, having stuff written out more in a programming oriented style as well should help :slight_smile:

In the definition of data Expr unsafeFlag it seems as though you’re missing the unsafeFlag in each of the Expr parameters of Div. Or am I mistaken and you are referring to the first data Expr at the top of the post?

1 Like

You’re not mistaken, it’s astonishing how many oversights one can pack in such a small post. I’ll update it when I get the chance, thanks for the heads up.

I believe that if you make the field that can contain Void strict, you don’t have to include a case for it when you know that it’s Void.

You can also do something similar to what you have here with a GADT, but your implementation doesn’t need GADTs which is nice.

2 Likes
eval (Div w x y) = whenFlag w $
  if eval y == Just 0.0
    then Nothing
    else (/) <$> eval x <*> eval y

whenFlag returns an f (), eval returns a Maybe Double. It’s why I don’t understand TFlag, as that is your only use of it. Also, another definition of TFlag is this. class TFlag a where getRefl :: a -> Refl a (). See Leibniz equality in Haskell, part 1 - Ryan Scott.

Wait you’re totally right, my code still doesn’t compile, and this time the issue is pretty fundamental… I’m very embarrassed to have published such a flawed blog post. It is salvageable, though, I’ll update it ASAP. Thanks for pointing out the issue.

1 Like