Paul
Paul

Reputation: 21985

Initial state of state monad and how it first gets passed along

I was reading about the State monad and after writing the code below I cannot understand how the initial state (mkStdGen 42) is passed into the rollDice function?

How can get work on that initial value?

I understand how the rollDice function works, but I cannot imagine how the initial state is lifted into the monad.

import Control.Monad.Trans.State
import System.Random

rollDice :: State StdGen Int
rollDice = do
    generator <- get
    let (x, s) = randomR (1,6) generator
    put s
    return x

main :: IO ()
main = putStrLn . show $ evalState rollDice (mkStdGen 42)

Upvotes: 1

Views: 214

Answers (1)

Zeta
Zeta

Reputation: 105925

To keep things simple, think about a State s a as a function, which takes an initial state s and returns a value and a new state (a , s), just as in the wikibook:

newtype State s a = S { runState :: s -> (s , a) }

Now lets use rollDicePure = runState rollDice. What's rollDicePure type? Given that runState only removes the State newtype, it should be

rollDicePure :: StdGen -> (Int, StdGen)

So runState (or evalState/execState) simply turn a stateful computation into a simple function, whose argument is the initial state.

If you wonder how get then gets this state, think of it as

getPure :: s -> (s, s)
getPure st = (st, st)

The actual definitions are a little bit more complicated than that, but the semantics hold.

Upvotes: 4

Related Questions