I'm incompetently trying to play with the new closed type family feature of GHC 7.8 and I would like to find a nice way to branch on type level constructs.
I have something like
data (:::) :: Symbol -> * -> * where
data Result = Pre | Post | Match
type family Cmp a b :: Result where
Cmp (s ::: t) (s ::: t) = Match
Cmp (s1 ::: t1) (s2 ::: t2) = ???
where I would like to return different types depending on the result of
CmpSymbol
in GHC.TypeLits. It feels like something like
Cmp (s1 ::: t1) (s2 ::: t2) = (CmpSymbol s1 s2 ~ LT) => Pre
Cmp (s1 ::: t1) (s2 ::: t2) = (CmpSymbol s1 s2 ~ GT) => Post
should work, but it does not. Interestingly it's not a syntax error but instead a complaint that it is ill kinded.
I can somehow get it to work by using undecidable instances and a helper function:
type family Cmp a b :: Result where
Cmp (s ::: t) (s ::: t) = Match
Cmp (s1 ::: t1) (s2 ::: t2) = Fun (CmpSymbol s1 s2)
type family Fun r :: Result where
Fun LT = Pre
Fun GT = Post
But this feels rather clunky, surely there is a nicer way? Also ghci says
something like :kind! Cmp ("a" ::: Int) ("a" ::: String)
has type Fun 'EQ
even though Fun
is closed. Why is that? I also can't see an easy way to
work with ordinary classes here? What if the definition of Fun
was something
like
class Fun2 o r
instance Fun2 LT Pre
instance Fun2 GT Post
Is there any way to talk to type classes in a nice way or am I restricted to just
using other type families like Fun
?
That really is the only way, although I like to define some reusable type functions (==
and If
), in your case it would become If (CmpSymbol s1 s2 == LT) Pre Post
.
Unfortunately, there is no way to get a type function of kind LT -> Pre
from a class like Fun2.
Your example has kind Fun EQ
because CmpSymbol "a" "a"
is EQ
and you pass this to Fun
. The reason it doesn't just give an error is type families are evaluated as late as possible - here you don't ask for the "value" of Fun EQ
so it isn't necessary to evaluate it yet.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With