dev*_*ium 2 random haskell functional-programming
假设我想在Haskell中生成一个随机数.为此,我会利用
randomRIO (0, 10)
Run Code Online (Sandbox Code Playgroud)
为我生成0到10之间的数字.它的类型是
randomRIO (0,10) :: (Random a, Num a) => IO a
Run Code Online (Sandbox Code Playgroud)
现在,假设我将其结果赋值给一个值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
Run Code Online (Sandbox Code Playgroud)
当尝试询问Ghci时,问题也会发生
[randomRIO (0, 10) | x <- [0..10]]
Run Code Online (Sandbox Code Playgroud)
错误信息有点神秘,如何在Haskell中使用随机数?
ham*_*mar 10
type的IO Integer
值不是整数.这是一个动作,当执行时,将返回一个整数.区别很重要.执行IO
操作的唯一方法是将它们连接起来main
,或者将它们键入GHCi.
这randomRIO (0, 10)
是一个动作,当执行时,在0
和之间返回一个随机数10
.请注意,这不是一个函数,因为函数必须始终在给定相同输入的情况下返回相同的结果,尽管我们有时将其称为不纯函数.
所以问题是,你如何采取一个返回整数的动作并使一个动作返回整数加2?简单,您可以使用fmap
组合动作和纯函数将其结果转换为新动作.
fmap (+2) $ randomRIO (0, 10)
Run Code Online (Sandbox Code Playgroud)
Control.Monad
包含许多有用的功能,用于从其他操作中构建新操作.对于您的第二个示例,我们可以使用replicateM
,它创建一个操作,在执行时,多次运行原始操作,将结果收集到列表中:
replicateM 10 $ randomRIO (0, 10)
Run Code Online (Sandbox Code Playgroud)
您还可以使用do
-notation 手动获取类似结果.
有关更多信息,您应该阅读monad,例如在Learn You a Haskell中.