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