假设:
Prelude Control.Parallel.Strategies> :t parMap
parMap :: Strategy b -> (a -> b) -> [a] -> [b]
Prelude Control.Parallel.Strategies> :i Strategy
type Strategy a = a -> Eval a
-- Defined in `Control.Parallel.Strategies'
我的理解是parMap
可以展开,将b
替换为b -> Eval b
:
parMap :: (a -> b -> Eval b) -> (a -> b -> Eval b) -> [b -> Eval b]
这似乎比Parallel and Concurrent Haskell中的示例版本更复杂:
parMap :: (a -> b) -> [a] -> Eval [b]
parMap f [] = return []
parMap f (a:as) = do
b <- rpar (f a)
bs <- parMap f as
return (b:bs)
在parMap
的标准库实现中,Strategy b
的含义是什么,即a -> b -> Eval b
?
答案 0 :(得分:4)
您的解释存在错误,Strategy
不是类型类,而是类型别名。如果您检查parMap
的签名,则Strategy b
后跟->
而不是=>
,这意味着parMap
期望Strategy b
为第一个论点。 Strategy b
是b -> Eval b
的别名,这意味着parMap
的签名可以扩展为:
parMap :: (b -> Eval b) -> (a -> b) -> [a] -> [b]
书籍parMap
与上面的书不同,因为它的签名是
parMap :: (a -> b) -> [a] -> Eval [b]
主要区别在于第一个版本使用给定的Strategy b
从参数[b]
计算(a -> b) -> [a]
,而第二个版本不计算[b]
但是Eval [b]
。 Eval [b]
指定如何生成[b]
,您必须致电runEval
才能使用它。
第一个版本更容易在程序中使用,因为您不需要调用runEval
并且它也更好,因为评估列表中每个元素的策略未预定义,就像在战略是rpar
的书中一样,但这只是一个论点。这意味着第一个版本更通用。请查看basic strategies,以便更好地了解您可以传递给标准parMap
的内容。