I have GADT like this one:
data TType a where
TInt :: TType Int
TBool :: TType Bool
I want to have a function like this one:
genTType :: Gen (TType a)
Which can generate random constructor of TType type. I can do this simply by creating existentially qualified data type like
data AnyType = forall a . MkAnyType (TType a)
then generate random number from 0 to 1 (including) and create AnyType depending on the integer value. Like this:
intToAnyType :: Int -> AnyType
intToAnyType 0 = MkAnyType TInt
intToAnyType 1 = MkAnyType TBool
intToAnyType _ = error "Impossible happened"
But this approach has couple drawbacks to me:
- No external type safety. If I add another constructor to
TTypedata type I can forgot to fix tests and compiler won't warn me about this. - Compiler can't stop me from writing
intToAnyType 1 = MkAnyType TInt. - I don't like this
error.Inttype is too broad to me. It would be nice to make this pattern-matching exhaustive.
What can I do in Haskell to eliminate as much as possible drawbacks here? Preferably using generators from this module: