{-# LANGUAGE GADTs #-} data Expr a where I :: Int -> Expr Int Plus :: Expr Int -> Expr Int -> Expr Int Pair :: Expr a -> Expr b -> Expr (a, b) Fst :: Expr (a, b) -> Expr a Snd :: Expr (a, b) -> Expr b deriving instance Show (Expr a) data Value a where VI :: Int -> Value Int VPair :: Value a -> Value b -> Value (a, b) deriving instance Show (Value a) interpret :: Expr a -> Value a interpret (I i) = VI i interpret (Plus e1 e2) = case (interpret e1, interpret e2) of (VI a, VI b) -> VI (a + b) interpret (Pair e1 e2) = VPair (interpret e1) (interpret e2) interpret (Fst e) = case interpret e of VPair a _ -> a interpret (Snd e) = case interpret e of VPair _ b -> b main :: IO () main = print $ interpret $ Plus (Fst (Pair (I 2) (I 3))) (I 4)