因此,Haskell seq函数强制评估它的第一个参数并返回第三个参数。因此它是一个中缀运算符。如果要强制评估表达式,直观地说这样的特征将是一元运算符。所以,而不是
seq :: a -> b -> b
它将是
seq :: a -> a
因此,如果您想要的值为a
,为什么要返回b
,以及如何构建b
的返回值。显然,我不是在考虑Haskell。 :)
答案 0 :(得分:16)
考虑a `seq` b
的方式不是它“评估a
”,而是它在a
和b
之间创建了一个依赖关系,所以当你去评估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
的长链,将所有这些应用连接到最终结果。这样,当您评估最终表达式(即通过对列表求和得到的数字)时,它会严格评估中间值(即在列表中折叠时的部分总和)。