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 /~ a = 'False
_ /~ _ = 'TrueYou can use it like this:
foo :: (Integral i, i /~ Word8 ~ 'True) => i -> ()
foo = undefinedThe argument can be any type i that doesn’t unify with
Word8. So this type-checks:
bar = foo (undefined :: Int)But this doesn’t:
bad = foo (undefined :: Word8)Couldn't match type ‘'False’ with ‘'True’.Not that I have a use for this. It was just discussed at work.