如何使用randomRIO生成无限的随机数列表?

时间:2015-07-10 13:26:47

标签: haskell

我正在尝试使用randomRIO生成无限的随机数列表。

import System.Random

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

它会编译但在运行时会挂起。

3 个答案:

答案 0 :(得分:5)

您的代码存在的问题是它永远不会发生故障。每当您执行g时,它最初会计算第一个随机数并将其存储在n中。然后它再次递归地回调相同的函数g,这个函数一直在继续。要获得无限列表,您可以使用randomRs函数:

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

然后您可以使用它生成任意数量的随机数:

λ> g2 >>= \x -> return $ take 5 $ x
[5,4,6,5,6]

答案 1 :(得分:4)

嗯,你不能,大致相同的reason why you can't lazily mapM over State(然后使用结果状态)。 randomRIO生成一个值,并且只有在生成此值后才能使用monadic程序流。

产生无限随机值流的方法当然是randomRs。您可以轻松地将其与getStdRandom结合使用,以便在IO

中生成此类流
import Control.Arrow

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

有了这个,

g :: IO [Integer]
g = randomRsIO (1,6)

答案 2 :(得分:0)

你想要一个使用randomRIO的答案。我知道问题被问到已经很久了。

这是使用liftM,您可以在其中生成范围低l到高h的随机数,并保持附加列表数次。所以我们有一个长度为num的随机数列表。

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))