在Haskell中使用随机数显示整数运算时出现问题

时间:2011-08-12 18:41:21

标签: haskell random functional-programming

假设我想在Haskell中生成一个随机数。为此,我将使用

randomRIO (0, 10)

为我生成0到10之间的数字。它的类型是

randomRIO (0,10) :: (Random a, Num a) => IO a

现在,假设我将结果分配给值k。它的类型是IO Integer

尝试执行k + 2等通常的算术运算会在Ghci中产生以下结果:

<interactive>:1:3:
    No instance for (Num (IO Integer))
      arising from the literal `2'
    Possible fix: add an instance declaration for (Num (IO Integer))
    In the second argument of `(+)', namely `2'
    In the expression: k + 2
    In an equation for `it': it = k + 2

当尝试向Ghci询问

时,问题也会发生
[randomRIO (0, 10) | x <- [0..10]]

错误信息有点神秘,如何在Haskell中使用随机数?

3 个答案:

答案 0 :(得分:10)

类型IO Integer的值不是整数。这是一个动作,当执行时,将返回一个整数。区别很重要。执行IO操作的唯一方法是将它们连接到main,或者将它们键入GHCi。

因此randomRIO (0, 10)是一项操作,执行后会在010之间返回一个随机数。请注意,这是不是函数,因为函数必须始终在给定相同输入的情况下返回相同的结果,尽管我们有时将其称为不纯函数

所以问题是,你如何采取一个返回整数的动作并使一个动作返回整数加2?很简单,您可以使用fmap组合动作和纯函数,将其结果转换为新动作。

fmap (+2) $ randomRIO (0, 10)

Control.Monad包含许多用于从其他操作构建新操作的有用功能。对于您的第二个示例,我们可以使用replicateM,这会创建一个操作,在执行时,多次运行原始操作,将结果收集到列表中:

replicateM 10 $ randomRIO (0, 10)

您还可以使用do - 表示法手动获得类似的结果。

有关详细信息,请阅读monad,例如Learn You a Haskell

答案 1 :(得分:4)

最好通过Learn You a Haskell之类的资源来完成工作。一个非常相关的部分是here

答案 2 :(得分:3)

由于您提到了GHCi,请注意您还可以在提示中执行IO操作,并使用<-将操作中的值绑定到名称。

a <- randomRIO (0, 10)
a + 2

但是,我建议你阅读安东尼和哈马尔联系的教程。它将更详细地解释上述语法(以及操纵monadic值的其他方法)。