I just learned about random
function.
To my understanding, random
function takes a value of type which is an instance of RandomGen
and returns a random value whose value we can specify. On the other hand, mksdGen
takes an Int
and generates a random generator which random
function needs.
I was trying to generate random Bool
values. In order to do that, I made a function randomBool
.
randomBool :: Int -> Bool
randomBool = fst . random . mkStdGen
Then I found a lot more True
s than False
s with small numbers.
And I was curious about it and checked as following
> length $ takeWhile randomBool [1..]
53667
I think this means that for the first 53667 positive integers, random . mkStdGen
returns True
, which do not seem to be very random to me.
Is it very normal? Or am I doing something wrong that make True
happen more easily?
Informally, when you call mkStdGen
with seeds that are close together you will get two 'similar' generators. In your example you're actually creating new generators for each seed supplied, and since those seeds are 1, 2, 3, etc., they'll yield similar streams.
When you call random
with a generator, you actually get back a new generator in the second element of the pair:
Prelude System.Random> random (mkStdGen 100) :: (Bool, StdGen)
(True,4041414 40692)
So a good idea is to use this provided generator for your next call to random
. I.e.,
Prelude System.Random> let (i, gen0) = random (mkStdGen 100) :: (Bool, StdGen)
Prelude System.Random> let (j, gen1) = random gen0 :: (Bool, StdGen)
Prelude System.Random> let (k, gen2) = random gen1 :: (Bool, StdGen)
Prelude System.Random> (i, j, k)
(True, False, False)
So to make a bunch of random values, you want to pass the generator as state. You can set this up manually via a State
monad or something, or just use the randoms
function, which handles passing the generator state for you:
Prelude System.Random> take 10 $ randoms (mkStdGen 100) :: [Bool]
[True,False,False,False,False,True,True,False,False,True]
If you don't particularly care about being in IO
(it happens) you can use randomIO
:
Prelude System.Random> import Control.Monad
Prelude System.Random Control.Monad> replicateM 10 randomIO :: IO [Bool]
[True,True,False,True,True,False,False,False,True,True]
This section of LYAH might be a useful read.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With