Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate list of random values and also get a new generator

Tags:

random

haskell

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.

like image 216
Sam Stern Avatar asked Jan 07 '13 20:01

Sam Stern


People also ask

How do you generate random data from a list?

Using random. randrange() to select random value from a list. random. randrange() method is used to generate a random number in a given range, we can specify the range to be 0 to the length of the list, and get the index, and then the corresponding value.

How do I make a random generator in Python?

To generate random number in Python, randint() function is used. This function is defined in random module.


1 Answers

Well, let's look at the function you do have:

random :: StdGen -> (Float, StdGen)  -- From System.Random

We can wrap this in the State monad to get a stateful computation:

state :: (s -> (a, s)) -> State s a  -- From Control.Monad.Trans.State

random' :: State StdGen Float
random' = state random

Now, we can generate a bunch of floats just using replicateM:

replicateM :: (Monad m) => Int -> m a -> m [a]  -- From Control.Monad

randoms' :: Int -> State StdGen [Float]
randoms' n = replicateM n random'

Finally, we unwrap the State to get back the explicit generator passing:

randoms :: Int -> StdGen -> ([Float], StdGen)
randoms n = runState (randoms' n)

If you combine all of these into one function definition you get:

randoms :: Int -> StdGen -> ([Float], StdGen)
randoms n = runState (replicateM n (state random))

In other words, we can describe the process as:

  • wrap random in the State monad
  • replicate it n times
  • unwrap it

This 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.

like image 90
Gabriella Gonzalez Avatar answered Oct 21 '22 15:10

Gabriella Gonzalez