{-# LANGUAGE GADTs #-}
data Expression a where
Number :: Int -> Expression Int
Boolean :: Bool -> Expression Bool
Not :: Expression Bool -> Expression Bool
Even :: Expression Int -> Expression Bool
Add :: Enum a => Expression a -> Expression a -> Expression Int
Max :: Ord a => Expression a -> Expression a -> Expression a
evaluate :: Expression a -> a
evaluate (Number n) = n
evaluate (Boolean p) = p
evaluate (Add n m) = fromEnum (evaluate n) + fromEnum (evaluate m)
evaluate (Even n) = even $ evaluate n
evaluate (Not p) = not $ evaluate p
evaluate (Max x y) = max (evaluate x) (evaluate y)