如何在Haskell中生成随机整数?

时间:2018-06-25 12:20:42

标签: haskell random io int

我正在尝试使用以下代码生成随机索引(Int):randomRIO (0, 2 :: Int)。但是它会生成IO整数,因此我无法执行以下操作:[1,2,3] !! randomIndex。将IO Int转换为Int必须做什么?谢谢。

2 个答案:

答案 0 :(得分:6)

  

...此代码:randomRIO (0, 2 :: Int)。但是它会生成IO Int ...

否,它一个IO Int值。这样的值类似于过程语言中的“功能” int f()。如果是Python,那么您也不能只写

Python 3.5.2 (default, Nov 23 2017, 16:37:01) 
Type 'copyright', 'credits' or 'license' for more information
IPython 6.1.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import random

In [2]: def f():
   ...:     return random.randint(0,2)
   ...: 

In [3]: [1,2,3][f]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-3-74d3c2a164a4> in <module>()
----> 1 [1,2,3][f]

TypeError: list indices must be integers or slices, not function

相反,您需要调用操作。实际上,只有这样才能产生一个Int数字。在大多数语言中,只需提供参数即可完成此操作,在这种情况下,只需提供空元组()

In [4]: [1,2,3][f()]
Out[4]: 2

但是,这混入了两个不同的概念,即提供论据和产生副作用。 (在这种情况下,副作用是对内置随机生成器状态的修改,因此您不会每次都得到相同的数字。)

Haskell做得更好,它有专门的运算符来整理副作用的顺序。正如Daniel Wagner所说,它们分别是fmap>>=。但是,如果这些infix-operator和高阶类型签名对您来说似乎很神秘,您还可以使用Haskell的do表示法,实际上这只是同一件事的语法糖:

main :: IO ()
main = do
   randomIndex <- randomRIO (0,2)
   print $ [1,2,3] !! randomIndex

或者在ghci提示符下(实际上是一个大的IO-do块)

GHCi, version 8.2.1: http://www.haskell.org/ghc/  :? for help
Loaded GHCi configuration from /home/sagemuej/.ghci
Loaded GHCi configuration from /home/sagemuej/.ghc/ghci.conf
Prelude> :m +System.Random
Prelude System.Random> randomIndex <- randomRIO (0,2 :: Int)
Prelude System.Random> [1,2,3] !! randomIndex
1

foo <- actionlet foo = action之间的区别类似于Python中foo = action()foo = action之间的区别。

答案 1 :(得分:2)

您不能将IO a转换为a;但是您可以将使用a的函数转换为使用IO a的函数。以下是两个最重要的转换:

(<$>) :: (a ->    b) -> (IO a -> IO b)
(=<<) :: (a -> IO b) -> (IO a -> IO b)

由于您要使用的函数\index -> [1,2,3] !! index没有返回类型IO,因此(<$>)对您来说更合适。所以:

System.Random> (\index -> [1,2,3] !! index) <$> randomRIO (0, 2)
1