{-# LANGUAGE GADTs #-} module ExprGADT where -- | Statically typed arithmetic and logic expressions. data Expr a where -- literals Lit :: a -> Expr a -- integers Neg :: Expr Int -> Expr Int Add :: Expr Int -> Expr Int -> Expr Int Mul :: Expr Int -> Expr Int -> Expr Int -- booleans Not :: Expr Bool -> Expr Bool Or :: Expr Bool -> Expr Bool -> Expr Bool And :: Expr Bool -> Expr Bool -> Expr Bool -- mixed Equ :: Eq a => Expr a -> Expr a -> Expr Bool If :: Expr Bool -> Expr a -> Expr a -> Expr a -- With a plain data type, we would need a semantic domain like: -- Maybe (Either Bool Int) -- | Evaluate an expression to a value of the statically determined type. eval :: Expr a -> a eval (Lit a) = a eval (Neg e) = negate (eval e) eval (Add l r) = eval l + eval r eval (Mul l r) = eval l * eval r eval (Not e) = not (eval e) eval (Or l r) = eval l || eval r eval (And l r) = eval l && eval r eval (Equ l r) = eval l == eval r eval (If c t e) = if eval c then eval t else eval e