Note: this is the completed version of
lecture MtlExample.
MtlExample
This file demonstrates the use of the mtl library
using the interpreter example from the Transformers module.
> module MtlExample whereThe definitions of StateT, ExceptT and Identity come from separate modules
in the mtl library.
> import Data.Function ((&))
> import Control.Monad.Identity
> ( Identity(runIdentity) )
> import Control.Monad.State
> ( StateT(runStateT), MonadState(put, get) )
> import Control.Monad.Except
> ( ExceptT, MonadError(throwError), runExceptT )> data Expr
> = Val Int
> | Div Expr Expr
> deriving (Show)> -- | evaluates to 42
> ok :: Expr
> ok =
> (Val 1972 `Div` Val 2)
> `Div` Val 23> -- | divide by zero error
> err :: Expr
> err =
> Val 2
> `Div` ( Val 1
> `Div` (Val 2 `Div` Val 3)
> )> -- | nicely format the error
> errorS :: Show a => a -> a -> String
> errorS y m = "Error dividing " ++ show y ++ " by " ++ show m> -- | increment the
> tickStateInt :: MonadState Int m => m ()
> tickStateInt = do
> (x :: Int) <- get
> put (x + 1)> eval :: (MonadError String m, MonadState Int m) => Expr -> m Int
> eval (Val n) = return n
> eval (Div x y) = do
> n <- eval x
> m <- eval y
> if m == 0
> then throwError $ errorS n m
> else do
> tickStateInt
> return (n `div` m)> -- | Show the result of runStateT, parameterized by a function
> -- to show the value
> showSt :: (a -> String) -> (a, Int) -> String
> showSt f (v, cnt) = f v ++ ", count: " ++ show cnt> -- | Show the result of runExceptT, parameterized by a function
> -- to show the value
> showEx :: (a -> String) -> Either String a -> String
> showEx _ (Left m) = "Raise: " ++ m
> showEx f (Right v) = "Result: " ++ f v> goExSt :: Expr -> String
> goExSt e = eval e -- :: StateT Int (ExceptT String Identity) Int
> & flip runStateT 0
> & runExceptT
> & runIdentity
> & showEx (showSt show) > goStEx :: Expr -> String
> goStEx e = eval e -- :: ExceptT String (StateT Int Identity) Int
> & runExceptT
> & flip runStateT 0
> & runIdentity
> & showSt (showEx show)> -- >>> goExSt ok
> -- "Result: 42, count: 2"> -- >>> goExSt err
> -- "Raise: Error dividing 1 by 0"> -- >>> goStEx ok
> -- "Result: 42, count: 2"> -- >>> goStEx err
> -- "Raise: Error dividing 1 by 0, count: 1"
CIS 5520: Advanced Programming