我正在尝试理解Haskell中的并行性,我很好奇的是seq
/ rseq
和par
/ rpar
<之间的签名差异/ p>
seq :: a -> b -> b
par :: a -> b -> b
rseq :: a -> Eval a
rpar :: a -> Eval a
我了解rseq
和rpar
是monadic版本,所以它们带有Eval
部分。 但为什么seq
和par
都不是a -> a
?有点像严格的身份......应该存在“包含”的原因。
围绕seq
似乎也有很多谜团。一些消息来源称a
在评估b
时评估(对WHNF)。其他消息来源称a
在通话时评估。这真令人困惑!虽然可以通过实际测试来测试一些东西,但我担心我很容易误解结果。
答案 0 :(得分:3)
类型a -> a
的函数已经严格,即id
。
Haskell是非严格的,因此调用函数的唯一原因是当您需要函数的结果时,因此当调用id y
时,您需要该值。以类似的方式,当调用seq x y
时,因为您需要该值。
Haskell中未指定seq
的操作语义,这可能是您发现它神秘的原因。更容易理解的功能是pseq
。 pseq
函数计算其对WHNF的第一个参数,然后返回其第二个参数。
seq
函数可能与pseq
相同,但也可能不同。
它由其指称语义定义(Haskell报告中的6.2节):
seq ⊥ b = ⊥
seq a b = b, if a /= ⊥
由此可以得出结论,seq
在两个参数中都是严格的。对于严格的函数,调用者很可能会评估参数,因为这不会产生语义差异。因此,在调用seq
时,调用者可以按任何顺序评估任何参数组合。
答案 1 :(得分:0)
简而言之,seq
doen 不评估其论点,它只是在a
和b
之间引入了依赖关系:只要b
被评估为WHNF,a
也被评估。
par
以同样的方式执行此操作:每当评估b
a
时,可以并行评估。
这种语义是seq a a
因此seq a
无用的原因。此外,允许seq
直接评估a
会破坏纯度。