弱头正常型 (WHNF)是什么意思?正常形式 (HNF)和标准形式 (NF)是什么意思?
真实世界Haskell状态:
我们熟悉的seq
函数将表达式求值为
调用头部标准型(缩写为HNF)。它一旦到达就会停止
最外层的构造函数(“头”)。这不同于正常
. form (NF),其中表达式被完全求值
你还会听到Haskell程序员引用弱 head normal
表单(WHNF)。对于正规数据,弱头正规形式与
头部正常形式。这种差异只出现在函数中,也是如此
. .
我读了一些资源和定义(Haskell维基和Haskell邮件列表和免费字典),但我不明白。谁能举个例子或者给出一个外行的定义?
我猜它会类似于:
WHNF = thunk : thunk
HNF = 0 : thunk
NF = 0 : 1 : 2 : 3 : []
seq
和($!)
如何与WHNF和HNF相关?
我还是很困惑。我知道有些答案说忽略HNF。从各种定义来看,WHNF和HNF中的常规数据似乎没有区别。然而,当涉及到函数时,似乎确实有区别。如果没有区别,为什么seq
对于foldl'
是必要的?
另一个混淆点来自Haskell Wiki,它声明seq
简化为WHNF,并且不会对下面的例子做任何事情。然后他们说他们必须使用seq
来强制求值。这不是强迫它去HNF吗?
常见的新手堆栈溢出代码:
理解seq和弱头标准形式(whnf)的人可以立即理解这里出了什么问题。myAverage = uncurry (/) . foldl' (\(acc, len) x -> (acc+x, len+1)) (0,0)
(acc+x, len+1)
已经在whnf中,所以seq
(在foldl'
的定义中)将一个值简化为whnf,对此不做任何操作。这段代码将像最初的foldl
示例一样构建坦克,它们只是在元组中。解决办法就是强迫 元组的组成部分,例如myAverage = uncurry (/) . foldl' (\(acc, len) x -> acc `seq` len `seq` (acc+x, len+1)) (0,0)