I made a simple code showing how much time a Random.bool appears to be True or False every milliseconds. The generator produced booleans with the current timestamp as seed.
I would expect the booleans will change almost each iterations but i get an unexpected big series of True or False.
What's happening so ?
Edit: I have better results with boolRandom (time*time).
Live preview on share-elm 0.15, with Random.int 0 1
Here in 0.16 with Random.bool :
import Signal
import Random
import Time exposing (Time)
import Graphics.Element exposing (Element, show, flow, down)
type alias Stat = {time: Time, true: Int, false: Int}
newStat: Stat
newStat = Stat 0 0 0
scene : Stat -> Element
scene stat =
flow down
[ "Time: "++(toString stat.time) |> show
, "True: "++(toString stat.true) |> show
, "False: "++(toString stat.false) |> show
]
boolRandom : Time -> Bool
boolRandom time =
Random.generate Random.bool (Random.initialSeed (round time)) |> fst
updateData : Time -> Stat -> Stat
updateData time stat =
if boolRandom time == True
then {stat | time = time , true = stat.true+1}
else {stat | time = time , false = stat.false+1}
updateEvery : Signal Stat
updateEvery =
Signal.foldp updateData newStat (Time.every Time.millisecond)
main = Signal.map scene updateEvery
Do not use the current time as a random seed, because of exactly the problem you are experiencing. You should call Random.initialSeed
exactly once in your program (that means one invocation, not in one function that's called N times). Whenever you generate a random number, it gives you a new seed, and you should keep the seed in the Stat
type instead of the time. Then:
updateData : Time -> Stat -> Stat
updateData time stat =
let (bool, seed) = Random.generate Random.bool stat.seed
in if bool
then {stat | seed = seed , true = stat.true+1}
else {stat | seed = seed , false = stat.false+1}
You can also delete boolRandom
- throwing away the new seed with fst
is bad!
So, how do you get a good random seed in the first place? The current time is actually a poor choice since it's not uniformly distributed. Instead, evaluate Math.floor(Math.random()*0xFFFFFFFF)
in your JS console of choice and paste in the result. To get a program that varies each run, pass the result of evaluating that expression in through port.