Haskell的seq是如何使用的?

时间:2016-09-22 17:19:52

标签: haskell strictness

因此,Haskell seq函数强制评估它的第一个参数并返回第三个参数。因此它是一个中缀运算符。如果要强制评估表达式,直观地说这样的特征将是一元运算符。所以,而不是

seq :: a -> b -> b

它将是

seq :: a -> a

因此,如果您想要的值为a,为什么要返回b,以及如何构建b的返回值。显然,我不是在考虑Haskell。 :)

1 个答案:

答案 0 :(得分:16)

考虑a `seq` b的方式不是它“评估a”,而是它在ab之间创建了一个依赖关系,所以当你去评估b您评估a

这意味着,例如,a `seq` a完全是多余的:您在评估a时告诉Haskell评估a。按照同样的逻辑,只有一个参数的seq a与简单地单独编写a没有任何不同。

seq a以某种方式评估a是行不通的。问题是seq a本身就是一个可能未被评估的表达式 - 例如,它可能深入到某些嵌套的thunk中。因此,当您评估整个seq a表达式时,它才会变得相关 - 无论如何,您将一直在评估a

@ Rhymoid在严格折叠(foldl')中如何使用它的例子很好。我们的目标是编写一个折叠,以便在我们评估最终结果时,在每个步骤完全评估其中间累积值(acc)。这是通过在累计值和递归调用之间添加seq来完成的:

foldl' f z (x:xs) = 
  let z' = f z x in z' `seq` foldl' f z' xs

您可以在折叠中seq的每个应用之间将其显示为f的长链,将所有这些应用连接到最终结果。这样,当您评估最终表达式(即通过对列表求和得到的数字)时,它会严格评估中间值(即在列表中折叠时的部分总和)。