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