在 Haskell 中将随机生成的列表作为参数传递



我是Haskell的新手,对整个IO的事情确实有问题。

我试图找出在哈斯克尔中遍历列表需要多长时间。我想生成一个随机数列表并将其作为参数传递给函数,以便我可以打印列表的每个元素。我正在使用标准包作为基准测试。这是代码:

{-# 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]
]
]

运行代码时出错:

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)’

简而言之,您需要将函数绑定IO值,而不是尝试将其应用于包装在IO值中的值。

-- instead of whnf printElements (randomList 10)
randomList 10 >>= whnf printElements

randomList不返回值列表;它返回一个IO操作,该操作在执行时可以生成值列表。忽略实现引起的各种约束,类型为

randomList :: (...) => t1 -> IO [t]  -- not t1 -> [t]

因此,您不能直接使用IO操作可以生成的值列表;您需要使用 monad 实例将值绑定到适当的函数。whnf printElements就是这样一种功能;它接受一个列表并返回一个IO操作。

whnf printElements :: Show a => [a] -> IO ()

我们不是拉出列表并将其传递给whnf printElements,而是使用>>=将函数"推送">IO值中。该运算符的类型专门用于IOmonad,是

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

在这种情况下,第一个IO a值是randomList返回的IO [t]值。whnf printElements是我们绑定到的a -> IO b函数。 结果是一个新的IO值,该值采用第一个IO值,提取包装的值,应用给定的函数,并返回结果。

换句话说,IOmonad 本身负责将结果从randomList中拉开并应用你的函数,而不是你显式地这样做。


(你可能已经注意到,我说过>>=将值绑定到函数,反之亦然。也许更准确地说,>>=将它们绑定成一个单一的IO动作。

相关内容

  • 没有找到相关文章

最新更新