我是哈斯凯尔的新手,我现在已经试图解决这个问题了一段时间。我想使用randomRIO生成一个随机大小的列表,并使用randomIO使用随机数填充该列表。我试图通过创建一个从randomRIO随机生成的函数来解决这个问题:
x <- randomRIO(1,5)
let y = randList x []
函数本身就是这样的:
randList :: Int -> IO [Int] -> IO [Int]
randList 0 xs = return [xs]
randList g xs = do
t <- randomIO
let a = t:randList (g-1) xs
return [a]
我不确定如何在递归函数中处理monad IO,但这就是我对它的看法。感谢任何帮助!
答案 0 :(得分:4)
您可以使用replicateM
重复执行randomIO
,每次都会生成一个新号码。您可以预先致电randomRIO
以确定列表的长度:
import Control.Monad (replicateM)
import System.Random (randomIO, randomRIO)
randList :: IO [Int]
randList = do
len <- randomRIO (1,5)
replicateM len randomIO
现在,你的定义实际上并不遥远。但有几点:
鉴于您希望能够调用randList x []
,randList
的第二个参数显然是一个简单的列表。不是某种IO动作。所以你的类型应该是
randList :: Int -> [Int] -> IO [Int]
在您的第一次模式匹配中
randList 0 xs = return [xs]
请记住,xs
已经是一个列表。因此,当您执行return [xs]
时,您将获得一个IO [[Int]]
列表。你想要的是一个简单的return xs
。
在您的第二个定义中
randList g xs = do
t <- randomIO
let a = t:randList (g-1) xs
return [a]
表达式t:randList ...
毫无意义。 :
的右侧必须是列表。 randList
不会产生列表,但会产生IO操作。你真正想要做的是将randList
(列表)的第二个参数视为&#34;累加器&#34;,它逐渐建立起来。所以你想要生成一个数字,将它添加到累加器,然后递归g
减一:
randList g xs = do
t <- randomIO
randList (g-1) (t:xs)