Haskell logo CIS 5520: Advanced Programming

Fall 2023

  • Home
  • Schedule
  • Homework
  • Resources
  • Software
  • Style guide
Note: this is the stubbed version of module MtlExample. Try to figure out how to fill in all parts of this file marked undefined. CIS 5520 students should be able to access this code through github. Eventually, the completed version will be available.

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