class Expr e where intVal :: Int -> e Int boolVal :: Bool -> e Bool add :: e Int -> e Int -> e Int isZero :: e Int -> e Bool if' :: e Bool -> e t -> e t -> e t newtype Eval a = Eval {runEval :: a} instance Expr Eval where intVal x = Eval x boolVal x = Eval x add x y = Eval $ runEval x + runEval y isZero x = Eval $ runEval x == 0 if' x y z = if (runEval x) then y else z newtype Print a = Print {printExpr :: String} instance Expr Print where intVal x = Print $ show x boolVal x = Print $ show x add x y = Print $ printExpr x ++ "+" ++ printExpr y isZero x = Print $ "isZero(" ++ printExpr x ++ ")" if' x y z = Print $ "if (" ++ printExpr x ++ ") then (" ++ printExpr y ++ ") else (" ++ printExpr z ++ ")"