Haskell的seq是如何使用的?

Geo*_*rge 6 haskell strictness

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

seq :: a -> b -> b
Run Code Online (Sandbox Code Playgroud)

这将是

seq :: a -> a
Run Code Online (Sandbox Code Playgroud)

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

Tik*_*vis 16

思考的方式a `seq` b不在于它"评估a",但它创造之间的相关性ab,这样,当你去评估b你评估a为好.

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

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

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

foldl' f z (x:xs) = 
  let z' = f z x in z' `seq` foldl' f z' xs
Run Code Online (Sandbox Code Playgroud)

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

  • @George在其他语言中习惯使用的不适用于Haskell的特性之一是:函数应用程序显然没有"使用"应用程序中的所有参数.特别是,仅仅因为应用程序`foldl'fz'xs`具有`z'作为参数不一定*(即没有检查`foldl'的定义)意味着'z'被使用.这是你使用的关于'z'`的论点倒下的地方:`z'`是一个函数的参数,因此不一定使用. (7认同)
  • @George`folll(\ xy - > 1)undefined [2]`求值为1,而不是试图评估`undefined`.相比之下,使用'foldl'`错误,因为它确实评估它. (2认同)