如何在Haskell

时间:2016-02-18 07:14:13

标签: haskell

我是哈斯凯尔的新手,我现在已经试图解决这个问题了一段时间。我想使用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,但这就是我对它的看法。感谢任何帮助!

1 个答案:

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