[Haskell-cafe] Newbie: State monad example questions

David Menendez dave at zednenem.com
Thu May 22 18:03:16 EDT 2008


2008/5/22 Olivier Boudry <olivier.boudry at gmail.com>:
> On Wed, May 21, 2008 at 6:19 PM, Dmitri O.Kondratiev <dokondr at gmail.com>
> wrote:
>
>>
>> -- 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`.

Incidentally, since random has type (Random a, RandomGen g) => g ->
(a,g), getAny could have been defined simply as

    getAny = State random

It may be helpful to prove that this definition is equivalent to the
one given in the original post.

Oh, and here's a super-simple example using the state monad:

    randR :: (Random a) => (a,a) -> State StdGen a
    randR range = State (randomR range)

    twoDice :: State StdGen Int
    twoDice = do
        d1 <- randR (1,6)
        d2 <- randR (1,6)
        return (d1 + d2)

    nDice :: Int -> State StdGen Int
    nDice n | n < 1 = return 0
    nDice n = do
        x <- randR (1,6)
        y <- rollN (n - 1)
        return (x + y)

Because State StdGen is a monad, you can rewrite nDice without
explicit recursion using foldM:

    nDice n = foldM (\sum m -> liftM (sum+) m) 0 $ take n $ repeat (randR (1,6))

-- 
Dave Menendez <dave at zednenem.com>
<http://www.eyrie.org/~zednenem/>


More information about the Haskell-Cafe mailing list