[Haskell-cafe] Newbie: State monad example questions

Luke Palmer lrpalmer at gmail.com
Mon May 19 19:27:14 EDT 2008


Hi Dmitri.  I'm just going to ramble on about what I know and how I
think of things, and maybe you'll pick something up :-)

On 5/19/08, Dmitri O.Kondratiev <dokondr at gmail.com> wrote:
> getAny :: (Random a) => State StdGen a
> getAny = do g      <- get
>             (x,g') <- return $ random g
>             put g'
>             return x
>
> Questions:
> return (random g) = State (\s -> ((a,g), s))
>
> Is  it correct?

Yes, where a is a random value and g is a new generator.

> 2) What x and g' will match to in:
>        do ...
>     (x,g') <- return $ random g
>
> which, as I understand equals to:
>        do ...
>     (x,g') <- State (\s -> ((a,g), s))
>
> What x and g' will match to in the last expression?

Well, I also suggest working through the desugared version of >>= as
the other poster suggested:

    State (\s -> ((a,g), s)) >>= (\(x,g') -> ...)

The question is, what values do x and g' have in '...'.  Expand out
the definition and see.  State is kind of complicated, but you will
get an answer.

But I can provide some intuition aside from the formality.

    x <- action

"Does" the action and names the return value "x".  Your action is
"return $ random g", namely it's an action that doesn't have any
effects and just returns a value.  So:

   (x,g') <- return $ random g

Is equivalent to:

   let (x,g') = random g

Nothing particular to State is happening here.

> 3) In general, in do expression (pseudo):
>     do { x <- State (\s -> (a, s)); ...}
>
> What x will refer to? Will x stand for a whole lambda function: \s -> (a, s)
> ?

Here x will be equal to a, and the implicit state will be unchanged
after the binding.

> 4) How 'g <- get' works in this function (getAny) ?

The representation of a state action is "State f", where f takes the
current state as an argument and returns the result of the computation
along with the new state.  "get" is defined as:

   get = State $ \s -> (s,s)

So its function takes a state, and returns the current state as the
return value as well as the next state; that is to say, it does not
update the state and it also returns it.  So:

    x <- get
    ...

Gives the name "x" to the implicit state at the time "get" was called.

> 5) Why we need 'put g'?

Otherwise this function would not modify the implicit state, and you'd
always get the same random number back when you called it.

Something to keep in mind:  If you have an "action :: m a" for some
monad m, then in:

    x <- action

x will name a value of type Foo.

Luke


More information about the Haskell-Cafe mailing list