I’m using System.Random and the Random typeclass in my application to generate random numbers. However I’d like to generate a list of random Floats of arbitrary length with a function like randoms :: StdGen -> Int -> ([Float], StdGen)
Without the constraint of getting a new generator, I could easily write
randoms gen n = (take n $ randoms gen) :: [Float]
However this leaves me with the same random generator I started with, which means if I were to run this function twice in a row I’d get the same list unless I went and used the generator elsewhere to get a new one.
How can I generate an infinite (or arbitrary length) list of random values while also “refreshing” my random generator.
Well, let’s look at the function you do have:
We can wrap this in the
Statemonad to get a stateful computation:Now, we can generate a bunch of floats just using
replicateM:Finally, we unwrap the
Stateto get back the explicit generator passing:If you combine all of these into one function definition you get:
In other words, we can describe the process as:
randomin theStatemonadntimesThis is why monads are such an important concept. Things that can seem tricky at first tend to be simple computations when viewed through the lens of the monad interface.