4

I'm trying to generate an infinite list of random numbers using randomRIO.

import System.Random

g :: IO [Integer]
g = do
  n <- randomRIO (1,6) :: IO Integer
  f <- g
  return (n : f)

It compiles but hangs when run.

3 Answers3

6

The problem with your code is that it never teminates. Whenever you execute g, it initially calcuates the first random number and stores it in n. Then it again recursively calls back to the same function g which goes on and on. To get an infinite list you can use the randomRs function:

g2 :: IO [Integer]
g2 = do
  g <- newStdGen
  return $ randomRs (1,6) g

And then you can produce any number of random numbers using it:

λ> g2 >>= \x -> return $ take 5 $ x
[5,4,6,5,6]
Sibi
  • 47,472
  • 16
  • 95
  • 163
  • This won't work correctly: `getStdGen` does not update the global RNG state, like `randomRIO` does. You need `getStdRandom` to achieve this effect. – leftaroundabout Jul 10 '15 at 13:58
5

Well, you can't, for much the same reason why you can't lazily mapM over State (and then use the result state afterwards). randomRIO produces a single value and only hands on the monadic program flow after this value has been produced.

The way to produce infinite streams of random values is of course randomRs. You can easily couple it with getStdRandom to produce such streams right in IO:

import Control.Arrow

randomRsIO :: Random a => (a,a) -> IO [a]
randomRsIO range = getStdRandom $ split >>> first (randomRs range)

With that,

g :: IO [Integer]
g = randomRsIO (1,6)
Community
  • 1
  • 1
leftaroundabout
  • 117,950
  • 5
  • 174
  • 319
0

You wanted an answer using randomRIO. I know its been a long time since the question was asked.

This is using liftM where you can generate a random number in range low l to high h and keep appending to a list num times. So we have a list of length num of random numbers.

import Control.Monad
import System.Random
gx :: Int -> Int -> Int -> IO [Int]
gx l h num = do
        x <- randomRIO(l,h)
        if num <=1 then return [x] else liftM (x:) (gx l h (num-1))
Akshay Hazari
  • 3,186
  • 4
  • 48
  • 84