-- 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@gmail.com> wrote:
On Wed, May 21, 2008 at 11:10 AM, Dmitri O.Kondratiev <dokondr@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@gmail.com
http://www.geocities.com/dkondr