A Quick Lap with the State Monad
16 Mar 2014Introduction
The State monad gives functionality of both the Reader monad and Writer monad in one. When using the State monad you’re able to read the state at any time and then set it back again, providing read/write access.
Key Points
- The function
get
is used to read the current state - The function
put
is used to set the state runState
is used to manage execution of functions that run in the State monad- Operations in the State monad can use
>>=
to be chained together - Functions in the State monad are decorated with
State s v
. Wheres
is the type of the state andv
is the return type from the function<
An Example
import Control.Monad.State
-- | Starts a value off.
-- This function doesn't perform any calculation at all, it just prepares an
-- initial value to start in the calculation pipeline
--
start :: Int -> State [String] Int
start x = do
put ["Starting with " ++ show x]
return x
-- | Halve a value
-- Any value passed into this function gets halved
--
half :: Int -> State [String] Int
half x = do
s <- get
let ns = s ++ ["Halving " ++ show x]
put ns
return (x `div` 2)
-- | Squares a value
-- Any value passed into this function gets squared
--
sqr :: Int -> State [String] Int
sqr x = do
s <- get
let ns = s ++ ["Squaring " ++ show x]
put ns
return (x * x)
main :: IO ()
main = do
let c = runState $ start 10 >>= half >>= sqr >>= half
let work = c [""]
let ans = fst $ work
let log = snd $ work
putStrLn $ "Answer: " ++ show ans
putStrLn ""
putStrLn " ==== Log ==== "
mapM_ putStrLn log