我正在尝试使用randomRIO生成无限的随机数列表。
import System.Random
g :: IO [Integer]
g = do
n <- randomRIO (1,6) :: IO Integer
f <- g
return (n : f)
它会编译但在运行时会挂起。
答案 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))