How I learned difference between getStdGen and newStdGen

I have been working on random values recently and learned an important difference between getStdGen and newStdGen.

One functionality I recently added to client was ability of administrators to view, edit and create new people. Handler that processes incoming request to create a new person is shown below:

-- | Create new person
postAdminApiAddPersonR :: Handler Value
postAdminApiAddPersonR = do
    _ <- apiRequireAdmin
    msg <- requireJsonBody
    date <- runDB $ starDate
    _ <- raiseIfFailure $ validateAddPerson msg
    g <- liftIO newStdGen
    let person = evalRand (generatePersonM date msg) g
    pId <- runDB $ insert person
    returnJson (Entity pId person)

Basically it authenticates and authorizes user, validates the input and then calls generatePersonM to generate a random character based on the user supplied parameters. However, the initial version was always creating identical clones, no matter how many times I tried calling it.

The problem was how I was handling random generator. Originally I had g <- liftIO getStdGen, instead of g <- liftIO newStdGen. Both will give you global random generator. The difference is that newStdGen will also update it to a new value.

In a short lived program, where getStdGen is called only one, the difference doesn’t matter. In long running program like this, where random generator is requested multiple times the difference is very noticeable. Every time I was calling getStdGen, I was given the exact same value. And when I was using that exact same value in a pure function, I was getting exact same result as before. All this is explained in the documentation. I just weren’t paying enough attention to the little details.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s