data Exp = Plus Exp Exp | Minus Exp Exp | Times Exp Exp | Div Exp Exp | Const Int deriving Show eval :: Exp -> Int eval (Plus e1 e2) = (eval e1) + (eval e2) eval (Minus e1 e2) = (eval e1) - (eval e2) eval (Times e1 e2) = (eval e1) * (eval e2) eval (Div e1 e2) = (eval e1) `div` (eval e2) eval (Const i) = i answer = (Div (Div (Const 1972) (Const 2)) (Const 23)) err = (Div (Const 1) (Const 0)) -- VAR 1: Error handling data M1 a = Raise Exception | Return a deriving Show type Exception = String evalE :: Exp -> M1 Int -- Plus, Minus, Times cases omitted. evalE (Div e1 e2) = case evalE e1 of Return a -> case evalE e2 of Return b -> if b == 0 then Raise "division by 0" else Return (a `div` b) Raise s -> Raise s Raise s -> Raise s evalE (Const i) = Return i -- VAR 2: State type M2 a = State -> (a, State) type State = Int evalS :: Exp -> M2 Int -- Plus, Minus, Times cases omitted. evalS (Div e1 e2) x = let (a, y) = evalS e1 x in let (b, z) = evalS e2 y in (a `div` b, z+1) evalS (Const i) x = (i, x) -- VAR 3: Output type M3 a = (a, Output) type Output = String evalO :: Exp -> M3 Int -- Plus, Minus, Times cases omitted. evalO (Div e1 e2) = let (a, x) = evalO e1 in let (b, y) = evalO e2 in (a `div` b, x ++ y ++ line (Div e1 e2) (a `div` b)) evalO (Const i) = (i, line (Const i) i) line :: Exp -> Int -> Output line e a = show e ++ "=" ++ show a ++ "\n"