[Haskell-cafe] Newbie: State monad example questions
dokondr at gmail.com
Wed May 21 18:19:56 EDT 2008
-- Jules, Oliver, thanks! Things are getting clarified, I hope.
-- Let me summarize how I now understand getAny operation, please correct me
if I am wrong.
getAny :: (Random a) => State StdGen a
getAny = do g <- get
(x,g') <- return $ random g
getAny operation may be abbreviated as:
-- 1) x calculation, equivalent to (x,g2) = random g1
-- 2) return x ~> State $ \s -> (x,s) -- puts x into State container
Thus getAny returns a State instantiated with a function which is a
composition of several binds <<= from the above 'do' block and which
-- 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
y <- getAny
passes a first value from the tuple generated by getAny State function into
'y' and puts 'y' into a new State object.
After that 'runState' in makeRnd extracts from this new State a function
parametrized by 'y' value.
As a result we get curried 'makeRnd' which we can call with some generator
instance and get a random value.
On Wed, May 21, 2008 at 10:31 PM, Olivier Boudry <olivier.boudry at gmail.com>
> On Wed, May 21, 2008 at 11:10 AM, Dmitri O.Kondratiev <dokondr at gmail.com>
>> But how will 'g1' actually get delivered from 'makeRandomValueST g1' to
>> invocation of 'getAny' I don't yet understand!
> It may be easier to understand the state passing if you remove the do
> notation and replace get, put and return with their definition in the
> instance declarations (Monad and MonadState).
> getAny :: (Random a) => State StdGen a
> getAny = do g <- get
> (x,g') <- return $ random g
> put g'
> return x
> get = State $ \s -> (s, s) -- copy the state as a return value and pass
> put s = State $ \_ -> ((), s) -- return unit, ignore the passed state and
> replace it with the state given as parameter.
> return a = State $ \s -> (a, s) -- return given value and pass state.
> getAnyNoSugar :: (Random a) => State StdGen a
> getAnyNoSugar = (State $ \s -> (s, s)) >>= \g ->
> (State $ \s -> (random g, s)) >>= \(x,g') ->
> (State $ \_ -> ((), g')) >>
> (State $ \s -> (x, s))
> The function is still useable this way and the state transformations should
> be a bit more visible. The first element of the tuple is the value that will
> be used to call the next function (of type Monad m => a -> m b). The second
> element of the tuple is the state and the (>>=) operator will handle passing
> it between actions.
> Desugaring the (>>=) and (>>) operators would give you something like this
> (I replaced `s` with `y` in the `put` and `return` desugaring and simplified
> State $ \s = let
> (g, s') = (\y -> (y,y)) s
> ((x,g'), s'') = (\y -> (random g, y)) s'
> (_, s''') = (\_ -> ((), g')) s''
> in (x, s''')
> Which is explict state passing between function calls. Extract the State
> using `runState`, run it with an initial state and it should give you the
> expected result.
Dmitri O. Kondratiev
dokondr at gmail.com
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the Haskell-Cafe