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
type family a /~ b where /~ a = 'False a /~ _ = 'True _
You can use it like this:
foo :: (Integral i, i /~ Word8 ~ 'True) => i -> () = undefinedfoo
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.