[Haskell-cafe] Newbie: State monad example questions
olivier.boudry at gmail.com
Thu May 22 09:49:54 EDT 2008
On Wed, May 21, 2008 at 6:19 PM, Dmitri O.Kondratiev <dokondr at gmail.com>
> -- Then we can use this State object (returned by getAny) in a function
> generating random values such as:
> makeRnd :: StdGen -> (Int, StdGen)
> makeRnd = runState (do
> y <- getAny
> return y)
You can simplify this:
do y <- m
is equivalent to
According to Monad Laws.
So you could write the same code as:
makeRnd = runState getAny
In that case, the use of the State Monad is not really interesting as you
just replaced a call to `random g` with a call to `runState getAny g`. The
State Monad is interesting if you have more than one action in the first
argument of the `runState` function because the state passing will only work
in a single `State s a`.
Thomas Hartman asked for use cases so I will describe programs I used the
State Monad for:
1) You can find a portion of the code here: http://hpaste.org/7809
The purpose of this program was extracting address parts (PO box, street,
city, country, postal code, ...) from addresses which are composed of a
name, 3 free text lines and a zip code. The state is a list of AddressPart
elements. If you look at the extractAddress function, it contains many other
function running in the State Monad. Each function can get and put the
state. The state will contain both unparsed and already parsed AddressPart
The big benefit I got from using the State Monad was that I was able to
reorder the functions by just copy/pasting the function name from one place
Each of the `State Address ()` function will get the state, try to find an
address part in the unparsed AddressPart elements and put a new State with
the recognized AddressPartS if any.
I think parsing is a common use case for the State Monad where you want to
store the unparsed data along with the parse result and don't want to care
about passing those elements from one function to another.
2) I also recently used the State Monad Transformer to build a single
Data.Map from a set of different files. The State is the Data.Map and the
action in the runStateT is a mapM_ over a list of file names.
processFile :: String -> StateT (PartsMap B.ByteString) IO ()
-- get the Map
-- add the file info
-- put the Map
runStateT (mapM_ processFile fileNames) M.Empty
-- each processFile call will get access to the result of the previous call
and put the updated Map.
I don't know if it's a common use case for the State Monad, but I found it
useful. I could probably have used foldM to achieve the same goal and don't
worry about using the State Monad.
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the Haskell-Cafe