7

因此,Haskellseq函数强制评估它的第一个参数并返回第二个参数。因此它是一个中缀运算符。如果你想强制评估一个表达式,直觉上这样的特性将是一个一元运算符。所以,而不是

seq :: a -> b -> b

这将是

seq :: a -> a

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

4

1 回答 1

18

思考的方式a `seq` b不是它“评估”,而是它在anda之间创建依赖关系,因此当您进行评估时,您也会进行评估。abba

这意味着,例如,这a `seq` a完全是多余的:你告诉 Haskell 在评估a时进行评估a。按照同样的逻辑,seq a只有一个论据与简单地自己编写没有什么不同a

只是seq a以某种方式评估a是行不通的。问题是它seq a本身就是一个可能不会被计算的表达式——例如,它可能在一些嵌套的 thunk 内部。因此,只有当您开始评估整个表达式时,它才会变得相关seq a——此时您a无论如何都会自己评估。

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

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

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

于 2016-09-22T17:23:58.930 回答