Skip to content

Instantly share code, notes, and snippets.

@xfire
Created July 13, 2011 16:02
Show Gist options
  • Save xfire/1080612 to your computer and use it in GitHub Desktop.
Save xfire/1080612 to your computer and use it in GitHub Desktop.
monad transformer stack example
import Control.Monad.Reader
import Control.Monad.State
import Control.Monad.Writer
-- our monad transformer stack
-- a reader with an prefix string for the log
-- a state with the current value as integer
-- a writer to log the work done
-- all in a IO monad
type Prefix = String
type Counter = Int
type Log = [String]
type MT = ReaderT Prefix (StateT Counter (WriterT Log IO))
-- get value from state
getS = lift $ get
-- modify state
modS f = lift $ modify f
-- write string to log
tellW s = lift $ lift $ tell [s]
-- count the number in the state down to 0 and
-- protocols every step in the writer. in doing
-- so, the prefix from the reader is prepended to
-- the logging string.
countDown :: MT ()
countDown = do n <- getS
modS (\x -> x - 1)
n' <- getS
prefix <- ask
let l = prefix ++ ": count from [" ++ show n ++ "] to: [" ++ show n' ++ "]"
tellW l
liftIO $ putStrLn l
if n' > 0
then countDown
else return ()
-- initialize our monad transformer stack with a prefix value and a value
-- from which we can count down and run a computation k inside this context.
runMT :: MT a -> Prefix -> Int -> IO (a, Counter, Log)
runMT k prefix start = do ((a, c), l) <- runWriterT (runStateT (runReaderT k prefix) start)
return (a, c, l)
main = do
putStrLn "start count down..."
(_, c, l) <- runMT countDown "countDown" 10
putStrLn "...count down finished"
putStrLn ""
putStr "the state value: "
putStrLn $ show c
putStrLn "the writer contains:"
mapM_ putStrLn l
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment