import Control.Monad.Except import Control.Monad.State data Exp = Plus Exp Exp | Minus Exp Exp | Times Exp Exp | Div Exp Exp | Const Int deriving Show answer = (Div (Div (Const 1972) (Const 2)) (Const 23)) err = (Div (Const 1) (Const 0)) -- variants of eval using standard mtl library monads -- MONAD LIBRARY VAR 1: Error Handling type MLE = Either String evalMLE :: Exp -> MLE Int evalMLE (Div e1 e2) = do a <- evalMLE e1; b <- evalMLE e2; if b == 0 then (throwError "division by 0") else return (a `div` b) evalMLE (Const i) = return i -- MONAD LIBRARY VAR 2: State type MLS = State Int tick :: (Num s, MonadState s m) => m () tick = do st <- get; put (st+1) evalMLS :: Exp -> MLS Int evalMLS (Div e1 e2) = do a <- evalMLS e1; b <- evalMLS e2; tick; return (a `div` b) evalMLS (Const i) = return i runMLS s exp = runState (evalMLS exp) s