[Haskell-cafe] State Monad - using the updated state in an adhoc manner

Phil pbeadling at mail2web.com
Wed Jan 7 20:58:30 EST 2009


I¹m a newbie looking to get my head around using the State Monad for random
number generation.  I¹ve written non-monad code that achieves this no
problem.  When attempting to use the state monad I can get what I know to be
the correct initial value and state, but can¹t figure out for the life of me
how to then increment it without binding more calls there and then.  Doing
several contiguous calls is not what I want to do here ­ and the examples
I¹ve read all show this (using something like liftM2 (,) myRandom myRandom).
I want to be able to do:


< a whole load of other stuff >

Get the next number as defined by the updated state in the first call

<some more stuff>

Get another number, and so on.

I get the first number fine, but am lost at how to get the second, third,
forth etc without binding there and then.  I just want each number one at a
time where and when I want it, rather than saying give 1,2,10 or even Œn¹
numbers now.  I¹m sure it¹s blindly obvious!

Note: I¹m not using Haskell¹s built in Random functionality (nor is that an
option), I¹ll spare the details of the method I¹m using (NRC¹s ranq1) as I
know it works for the non-Monad case, and it¹s irrelevent to the question.
So the code is:

ranq1 :: Word64 -> ( Double, Word64 )
ranq1 state = ( output, newState )
    newState = ranq1Increment state
    output = convert_to_double newState

ranq1Init :: Word64 -> Word64
ranq1Init = convert_to_word64 . ranq1Increment . xor_v_init

-- I¹ll leave the detail of how ranq1Increment works out for brevity.  I
know this bit works fine.  Same goes for the init function it¹s just
providing an initial state.

-- The Monad State Attempt
getRanq1 :: State Word64 Double
getRanq1 = do
  state <- get
  let ( randDouble, newState ) = ranq1 state
  put newState
  return randDouble

_________ And then in my main _________

-- 124353542542 is just an arbitrary seed
main :: IO()
main = do
       let x = evalState getRanq1 (ranq1Init 124353542542)
       print (x)

As I said this works fine; x gives me the correct first value for this
sequence, but how do I then get the second and third without writing the
giveMeTenRandoms style function?  I guess what I want is a next() type
function, imperatively speaking.

Many thanks for any help,


-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20090108/d9572e4b/attachment-0001.htm

More information about the Haskell-Cafe mailing list