data Term = Con Int | Div Term Term deriving (Show); type M a = (Output, a); type Output = String; answer, err :: Term; answer = (Div (Div (Con 1972) (Con 2)) (Con 23)); err = (Div (Con 1)(Con 0)); unit :: a -> M a; unit a = ("", a); (★) :: M a -> (a -> M b) -> M b; m★k = let (x, a) = m in let (y, b) = k a in (x ++ y, b); out :: Output -> M (); out x = (x, ()); eval :: Term -> M Int; eval (Con a) = out(line (Con a) a) ★ \_ -> unit a; eval (Div t u) = eval t ★ \a -> eval u ★ \b -> out (line (Div t u) (quot a b)) ★ \_ -> unit (quot a b); line :: Term -> Int -> Output; line t a = "eval (" ++ show t ++ ") <= " ++ show a ++ "\n"; main = let (a, b) = eval answer in do putStrLn(a); print(b) -- > eval (Con 1972) <= 1972 -- > eval (Con 2) <= 2 -- > eval (Div (Con 1972) (Con 2)) <= 986 -- > eval (Con 23) <= 23 -- > eval (Div (Div (Con 1972) (Con 2)) (Con 23)) <= 42 -- > 42