Aws*_*tic 0 benchmarking haskell list haskell-criterion io-monad
我是Haskell的新手,并且在整个IO事情上遇到了麻烦.
我试图找出遍历haskell列表所需的时间.我想生成一个随机数列表并将其作为参数传递给函数,以便我可以打印列表的每个元素.我正在使用CRITERION包作为基准.这是代码:
{-# LANGUAGE OverloadedStrings #-}
import System.Random
import Control.Exception
import Criterion.Main
printElements [] = return ()
printElements (x:xs) = do print(x)
printElements xs
randomList 0 = return []
randomList n = do
x <- randomRIO (1,100)
xs <- randomList (n-1)
return (x:xs)
main = defaultMain [
bgroup "printElements" [ bench "[1,2,3]" $ whnf printElements (randomList 10)
, bench "[4,5,6]" $ whnf printElements [4,5,6,4,2,5]
, bench "[7,8,9]" $ whnf printElements [7,8,9,2,3,4]
, bench "[10,11,12]" $ whnf printElements [10,11, 12,4,5]
]
]
Run Code Online (Sandbox Code Playgroud)
运行代码时出错:
listtraversal.hs:18:67:
Couldn't match expected type ‘[a0]’ with actual type ‘IO [t0]’
In the second argument of ‘whnf’, namely ‘(randomList 10)’
In the second argument of ‘($)’, namely
‘whnf printElements (randomList 10)’
Run Code Online (Sandbox Code Playgroud)
简而言之,您需要将函数绑定到IO
值,而不是尝试将其应用于值中包含的IO
值.
-- instead of whnf printElements (randomList 10)
randomList 10 >>= whnf printElements
Run Code Online (Sandbox Code Playgroud)
randomList
不返回值列表; 它返回一个IO
动作,当执行时,它可以生成一个值列表.忽略实现引起的各种约束,类型是
randomList :: (...) => t1 -> IO [t] -- not t1 -> [t]
Run Code Online (Sandbox Code Playgroud)
因此,您无法直接使用IO
操作可以生成的值列表; 您需要使用monad实例将值绑定到适当的函数.whnf printElements
就是这样一个功能; 它需要一个列表并返回一个IO
动作.
whnf printElements :: Show a => [a] -> IO ()
Run Code Online (Sandbox Code Playgroud)
我们不是将列表拉出并传递给它whnf printElements
,而是使用"将"函数"推送" 到一个IO
值中>>=
.该运营商的类型,专门为IO
monad,是
(>>=) :: IO a -> (a -> IO b) -> IO b
Run Code Online (Sandbox Code Playgroud)
在这种情况下,第一个IO a
值是IO [t]
返回的值randomList
.whnf printElements
是a -> IO b
我们绑定的功能.结果是一个新IO
值,它取第一个IO
值,拉出包装值,应用给定函数,并返回结果.
换句话说,IO
monad本身负责将结果randomList
与你的函数分开并将其应用于它,而不是你明确地去做.
(你可能已经注意到我已经说过>>=
将一个值绑定到一个函数,反之亦然.或许更准确地说它将>>=
它们绑定在一起就成了一个IO
动作.)