I've been working through some Haskell Tutorials introducing GADTs using the typesafe evaluator examples. A lot of the evaluators operate on both Boolean and Int type. So the GADT type for an evaluator which has the functions (Constant Integer, Constant Boolean, Add, Multiply, and Check Equality) has the form:
data Expr a where
I :: Int -> Expr Int
B :: Bool -> Expr Bool
Add :: Expr Int -> Expr Int -> Expr Int
Mul :: Expr Int -> Expr Int -> Expr Int
Eq :: Expr Int -> Expr Int -> Expr Bool
I'm mostly fine with this example, but I would like to be able to define general constant types to be either Int or Bool types, rather than having separate entries for Int and Bool. Is this possible.
This seems to work if I just use a Type variable instead of Int or Bool in my GADT.
This makes the above example:
data Expr a where
Con :: t -> Expr t
Add :: Expr Int -> Expr Int -> Expr Int
Mul :: Expr Int -> Expr Int -> Expr Int
Eq :: Expr Int -> Expr Int -> Expr Bool
By then the Constant type is not restricted enough as I can then have a Constant List input, or a constant String/Float, where I ONLY want Constants to be Int or Bool.
I've thought about using TypeClasses (I think) to solve this as this seems to be able to limit the "domain" of the type variable such as using the "Ord" Class would limit the possible types that the typevariable t could take in the line
Con :: Ord t => t -> Term t
Unfortunately I'm not sure how to write my own class to do this to restrict the type variable to be just Boolean or Integer. Is this even the right track?
Thanks.