[Haskell-cafe] Newbie: State monad example questions
Dmitri O.Kondratiev
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
put g'
return x
{--
getAny operation may be abbreviated as:
do {
-- 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
calculates 'x'
--}
-- 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)
{--
where:
y <- getAny
return y
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>
wrote:
> On Wed, May 21, 2008 at 11:10 AM, Dmitri O.Kondratiev <dokondr at gmail.com>
> wrote:
>
>> 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
> state
> 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
> it):
>
> 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.
>
> Regards,
>
> Olivier.
>
--
Dmitri O. Kondratiev
dokondr at gmail.com
http://www.geocities.com/dkondr
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20080522/a7eb43b7/attachment.htm
More information about the Haskell-Cafe
mailing list