State Monad - using the updated state in an adhoc manner

Hi, 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: Get_a_random_number < 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 ) where 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, Phil.

On 2009 Jan 7, at 20:58, Phil wrote:
-- 124353542542 is just an arbitrary seed main :: IO() main = do let x = evalState getRanq1 (ranq1Init 124353542542) print (x)
You're throwing away the state you want to keep by using evalState there. But you're also missing the point of using State; done right the evalState *is* what you want. What you want to do is run all of your operations within State, exiting it only when you're done:
main = do print (evalState doRanqs (ranq1init 124353542542))
doRanqs = do r <- getRanq1 -- do something involving it another <- getRanq1 -- do more stuff
Alternately you may use a tail recursive function or a fold, etc., depending on what exactly you're trying to accomplish. You do *not* want to execState or runState every individual time you want a random number; if you do that you'll have to carry the random state around yourself (in effect you'd be rewriting the State monad by hand, poorly). Stay in State and let it do the carrying for you. -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH
participants (2)
-
Brandon S. Allbery KF8NH
-
Phil