mercredi 12 juin 2019

Create random numbers in a repeatable way and hiding generator threading (Using Haskell Monad)

I need to create random data in Haskell. I want my code to be: a) repeatable b) the threading of generators to be implicit

I understand Monads generally and the way that Random Generators work. My approach is to thread the generator through the code so I can repeat the random numbers but want to hide the threading of the generators in a Monad. I'm thinking that the State Monad is a good approach.

Here's some simple code: type Gen a = State StdGen a

roll :: Gen Int
roll = state $ randomR (1, 6)

roll2 :: Gen Int
roll2 = (+) <$> roll <*> roll

test :: Int -> IO ()
test seed = do
  let gen = mkStdGen seed
  print (evalState roll gen)
  print (evalState roll gen)
  print (evalState roll2 gen)
  print (evalState roll2 gen)

I'm trying to use State so that I can push the threading of the generator into the State Monad but the results of roll are the same and results of roll2 are the same. I can see that this is because I'm passing gen into the functions multiple times so of course it would produce the same output. So that makes me think I need to get a new generator from each function. But then I'm back to having to thread the generator through the code which is what I'm trying to avoid by using State. I feel like I'm missing a trick!

I explored MonadRandom too and that did push the threading away from my code but I couldn't see how to make that approach be repeatable.

I've hunted a lot and tried many things but seem to always either be able to hide the generators OR make the code repeatable but not both.

I'm keen to use a Monad more specific than IO.

I'm also going to build a series of more complex functions which will generate random lists of numbers so I need to have a simple way to make these random functions rely on each other. I managed that with MonadRandom but again I couldn't see how that could be repeatable.

Any help appreciated.




Aucun commentaire:

Enregistrer un commentaire