Here’s a fun trick. If you want to define a function that accepts
everything but one type, you can make a type family like this. If the
two types unify, we produce the type 'False
of kind
Bool
.
type family a /~ b where
/~ a = 'False
a /~ _ = 'True _
You can use it like this:
foo :: (Integral i, i /~ Word8 ~ 'True) => i -> ()
= undefined foo
The argument can be any type i
that doesn’t unify with
Word8
. So this type-checks:
= foo (undefined :: Int) bar
But this doesn’t:
= foo (undefined :: Word8) bad
Couldn't match type ‘'False’ with ‘'True’.
Not that I have a use for this. It was just discussed at work.