Haskell logo CIS 5520: Advanced Programming

Fall 2023

  • Home
  • Schedule
  • Homework
  • Resources
  • Software
  • Style guide
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 where

The 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"
Design adapted from Minimalistic Design | Powered by Pandoc and Hakyll