
On Wed, May 21, 2008 at 6:19 PM, Dmitri O.Kondratiev
-- 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 return y is equivalent to `do m` or `m` 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 elements. 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 to another. 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. Best regards, Olivier.