Monad: State
This summary follows the minimum useable principle.
Readings
- learn you a haskell: for a few monads and more
Hackage Control.Monad.Trans.State.Lazy
newtype StateT s m a = StateT { runStateT :: s -> m (a,s) }
Simple definition from learn you a haskell
newtype State s a = State { runState :: s -> (a,s) }

Complete definition from Control.Monad.Trans
newtype StateT s m a = StateT { runStateT :: s -> m (a,s) }
instance (Monad m) => Monad (StateT s m) where
return a = StateT $ \ s -> return (a, s)
m >>= k = StateT $ \ s -> do
~(a, s') <- runStateT m s
runStateT (k a) s'
fail str = StateT $ \ _ -> fail str
Self recap

Monadic Semantics
- Target type :
a - Context type :
State sorStateT s m- Explicitly : transformation among
target types. - Implicitly : Each computation produce new state information of type
sand pass to the following computation in the target types transformation.
- Explicitly : transformation among
- A function from
stoa. >s -> a- Sometimes, the value of
swill be updated and could affect following computation, so the new value need to be preserved. >s -> (a,s)- Now we have a new type
newtype State s a = State {runState ::s -> (a,s)}.- Two or more computations of type
a -> State s bcould be composed by>>=or>=>means each computation use the informationspassed by previous one. (There could be other compositions that use state of other computation in different ways.) >f >>= g :: s0 -> (a,s1) -> ( a -> s1 -> (b,s2)) -> (s0 -> (b,s2)
>s0, s1, s2are values of the types.
> Clearly,>>=and>=>chained these computations and hide the intermediate states1, produce a function betweens0ands2.- auxiliary functions
get,put,return- each produce a State monad in different purposes
- these special purpose State monads are composed by
>>=and>>operator.- They collectively work as a single State Monad for certain function.
get
getthe current value of the state from previous State computation.get :: (Monad m) => StateT s m s get = state $ \ s -> (s, s)
put
putupdates the value ofs.put :: (Monad m) => s -> StateT s m () put s = state $ \ _ -> ((), s)
return / pure
combine the computation result
atogether with whateversis.instance (Monad m) => Monad (StateT s m) where return a = StateT $ \ s -> return (a, s)>>=m >>= k = StateT $ \ s -> do ~(a, s') <- runStateT m s runStateT (k a) s'summary
Use
getto receivesfrom previous State computation, useputto update the value ofsif necessary, and combine computation resultawiths.
state
turn a simple state style computation into State Monad
state :: (Monad m) => (s -> (a, s)) -- ^pure state transformer -> StateT s m a -- ^equivalent state-passing computation state f = StateT (return . f) -- this return is pair with m above.
runState
Unwrap a state monad computation as a function.( The inverse of ‘state’.)
newtype StateT s m a = StateT { runStateT :: s -> m (a,s) } runState :: State s a -- ^state-passing computation to execute -> s -- ^initial state -> (a, s) -- ^return value and final state runState m = runIdentity . runStateT m
evalStateT
- When we do not need the information in
sanymore. Use
evalStateTorevalStateto get function of types -> m aors -> aevalStateT evalStateT :: (Monad m) => StateT s m a -> s -> m a evalStateT m s = do ~(a, _) <- runStateT m s return aevalState :: State s a -- ^state-passing computation to execute -> s -- ^initial value -> a -- ^return value of the state computation evalState m s = fst (runState m s) {-# INLINE evalState #-}
Common usage
- use
getto introduce the state. (compulsory) - some pure function ::
s -> atransformstoa. (optional) returnwrapainto State Monad. (compulsory)putupdates the state. (optional, must followed by areturn)evaState/evalStateT
or
runState/runStateT
get the function of type:: s -> (a,s)wrapped inside. They each works slight differently. (compulsory)
5.1 runState / runStateT retrive functions-> (a,s)ors -> m (a,s)
5.2 evalState / evalStateT retrive functions -> aors -> m a- feed to initial state
s0into the functions -> (a,s)and get the final resultaand final states.
Intuition:
- State Monad wrap a function from type
sto an core outputaand new value of types. get,put,returneach represent Reader Monad of different specific purpose.- Usually, they composed (>>=) (>>) together to form a functional State Monad.
necessary import
-- | Imports before Example One
import Control.Monad.Trans.State
import Control.Monad -- for operator >=>
Example one
- In general . State Monad is a function, the output include an extra part of information that is of the same type of the input.
- The input of
>=> or >>=operation will always be the first one the Initial state will also be the first one as well .
s1 :: Int -> State String Float s1 i = do s <- get let is = show i ++ "_"++ s r = fromIntegral i / (fromIntegral . length) is put is return rs2 :: Float -> State String String s2 f = do s <- get let sf = show f ++ "_"++ s put sf return sfs3 :: String -> State String Int s3 str = do s <- get let ns = str ++ "_" ++ s put ns return $ length nssChainOne :: Int -> State String Int sChainOne = s1 >=> s2 >=> s3> :info sChainOne sChainOne :: Int -> State String Int > let sFunc = runState $ sChainOne 20 sFunc :: String -> (Int, String) > let r = sFunc "emmettng" > r (43,"1.8181819_20_emmettng_1.8181819_20_emmettng")
Intuition:
State String Int
- Explicitly Int : Target Operations include:
- s1 :: Int -> Float , s2 :: Float -> String, s3 :: String -> Int
- These transformation composed together as Int -> Int
- Implicitly State String: Context Semantics:
- There is an extra piece of information of type String involved in these transformations. SO, s1 :: Int -> String -> Float.
- Furthermore, the value of String might be updated and pass to the following function: s1 :: Int -> String (Float,String), so the same as s2 and s3.
return/pureis always about bring value oftarget typeinto thisComputation Context.