type I a = a; data Term = Con Int | Div Term Term; answer, err :: Term; answer = (Div (Div (Con 1972) (Con 2)) (Con 23)); err = (Div (Con 1)(Con 0)); data M a = Raise Exception | Return a; type Exception = String; unit :: a -> M a; unit a = Return a; (★) :: M a -> (a -> M b) -> M b; m★k = case m of Raise e -> Raise e; Return a -> k a; raise :: Exception -> M a; raise e = Raise e; eval :: Term -> M Int; eval (Con a) = Return a; eval (Div t u) = eval t ★ \a -> eval u ★ \b -> if b == 0 then raise "divide by zero"; else unit (quot a b); sh :: M Int -> String; sh (Raise e) = e; sh (Return a) = show a; main = print ((sh (eval answer)) ++ "; " ++(sh (eval err))) -- > "42; divide by zero"