[Haskell-beginners] Creating lists of random numbers
Daniel Fischer
daniel.is.fischer at web.de
Thu Oct 21 09:21:14 EDT 2010
On Thursday 21 October 2010 14:58:45, Tom Hobbs wrote:
> Hi all,
>
> I'm trying to create a list of random integers (either 0s or 1s).
> I've got one way to work, but I'm trying to use replicate to replace
> this implementation but it's not going well. Can anyone help, please?
>
> Here's the version I want to replace;
>
> ugly :: Int -> [Int]
> ugly 0 = []
> ugly s = ugly (s-1) ++ [ran]
> where
> ran = unsafePerformIO (randomRIO (0,1)) :: Int
>
> This one works as expected.
>
> Here's the broken version;
>
> broken :: Int -> [Int]
> broken s = replicate s ran
> where
> ran = unsafePerformIO (randomRIO (0,1)) :: Int
>
> The problem with broken is that "ran" seems to be evaluated once and
> then replicated, so my list contains the same random number s times.
Right, ran is just a plain Int, it doesn't need to be evaluated more than
once.
You could try
stillUgly :: Int -> [Int]
stillUgly n = replicate n (f ())
where
{-# NOINLINE f #-}
f () = unsafePerformIO (randomRIO (0,1))
but you shouldn't.
> I'd like it to be re-evaluated with each replication.
>
> Also, I've heard of the dangers of using unsafePerformIO. Can anyone
> suggest a different way to generate random numbers?
A) pass the generator explicitly
ranList :: StdGen -> Int -> [Int]
ranList sg n = take n $ randomRs (0,1) sg
and then, if you must,
B)
bearable :: Int -> [Int]
bearable n = unsafePerformIO $ do
sg <- getStdGen
return $ ranList sg n
but really, pass the generator. If that's too inconvenient, use MonadRandom
(I've forgotten the name of the package, search hackage).
>
> (Finally, a question that doesn't involve serialisation!)
>
> Cheers,
>
> Tom
More information about the Beginners
mailing list