[Haskell-cafe] infinite list of random elements

Cale Gibbard cgibbard at gmail.com
Mon Jul 30 17:53:43 EDT 2007


On 30/07/07, Chad Scherrer <chad.scherrer at gmail.com> wrote:
> I'm trying to do something I thought would be pretty simple, but it's
> giving me trouble.
>
> Given a list, say [1,2,3], I'd like to be able to generate an infinite
> list of random elements from that list, in this case maybe
> [1,2,1,3,2,1,3,2,3,1,2,...]. I'm using IO for random purely due to
> laziness (my own, not Haskell's).
>
> I was thinking the best way to do this might be to first write this function:
>
> randomElts :: [a] -> [IO a]
> randomElts [] = []
> randomElts [x] = repeat (return x)
> randomElts xs = repeat r
>   where
>   bds = (1, length xs)
>   xArr = listArray bds xs
>   r = do
>     i <- randomRIO bds
>     return (xArr ! i)
>
> Then I should be able to do this in ghci:
>
> > sequence . take 5 $ randomElts [1,2,3]
> [*** Exception: stack overflow
>
> Any idea what's going on? I thought laziness (Haskell's, not my own)
> would save me on this one.

I don't get that result. However, you can't compute an infinite random
list in IO without using something like unsafeInterleaveIO. However,
you will probably be interested in randoms/randomRs, which take a
random generator, and give an infinite list of results.

Using that, we could write something like:

randomElts :: [a] -> IO [a]
randomElts [] = return []
randomElts xs = do g <- newStdGen
                   return (map (xArr !) (randomRs bds g))
 where bds = (1, length xs)
       xArr = listArray bds xs

which for a nonempty input list, gives an infinite list of
pseudorandom elements of that input list.

 - Cale


More information about the Haskell-Cafe mailing list