问题标签 [weak-head-normal-form]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
haskell - 什么是弱头范式?
弱头范式(WHNF) 是什么意思?头范式 ( HNF) 和范式(NF) 是什么意思?
熟悉的
seq
函数将表达式计算为我们所说 的头部范式 (缩写为 HNF)。一旦到达最外层的构造函数(“头部”),它就会停止。这与 标准形式 (NF) 不同,在标准形式中,表达式被完全评估。您还会听到 Haskell 程序员提到 弱 头范式 (WHNF)。对于法线数据,弱头范式与头范式相同。区别只出现在功能上,而且太深奥了,我们在这里不关心。
我已经阅读了一些资源和定义(Haskell Wiki和Haskell Mail List和Free Dictionary),但我不明白。有人可以举个例子或提供一个外行定义吗?
我猜它会类似于:
WHNFseq
和($!)
HNF 有什么关系?
更新
我仍然很困惑。我知道一些答案说忽略 HNF。从阅读各种定义来看,WHNF 和 HNF 中的常规数据似乎没有区别。但是,在功能方面似乎确实存在差异。如果没有区别,为什么seq
需要foldl'
?
另一个混淆点来自 Haskell Wiki,它指出seq
简化为 WHNF,并且不会对以下示例执行任何操作。然后他们说他们必须使用seq
强制评估。这不是强迫它到HNF吗?
常见新手栈溢出代码:
了解 seq 和弱头范式 (whnf) 的人可以立即明白这里出了什么问题。
(acc+x, len+1)
已经在 whnf 中,因此seq
(在 的定义中foldl'
)将值减少为 whnf,对此没有任何作用。这段代码将像原始示例一样构建 thunkfoldl
,它们只是在一个元组中。解决方案只是强制元组的组件,例如
performance - Haskell foldl'(++)性能不佳
我有这个代码:
这些函数返回每个元素乘以 2 的列表:
在 ghci 中:
为什么newList_bad
函数的工作速度比 慢 200 倍newList_good
?我知道这不是该任务的好解决方案。但是为什么这个无辜的代码工作得这么慢呢?
这是什么“4767099960字节”?对于那个简单的操作,Haskell 使用了 4 GiB?
编译后:
haskell - 弱头范式和求值顺序
我已经阅读了很多关于弱头正常形式和序列的内容。但是我仍然无法想象 Haskell 评估顺序背后的逻辑
演示何时以及如何使用的常见示例,但我仍然不明白常见示例如何
可能导致堆栈溢出。而另一个折叠定义使用seq
不
从我读过的对 seq 的解释中,作者非常小心地阐明了以下内容:
- 的第一个参数
seq
不能保证在第二个参数之前被评估 - 的第一个参数
seq
只会被评估为弱头范式 - 的第一个参数的评估
seq
只会在第二个评估为 WHNF 时发生
那么,如果以上是正确的(是吗?)那么为什么不foldl'
溢出foldl
呢?
当我们减少一个步骤时,它不应该是这样的吧?
在上面,第二个参数seq
不在 WHNF 中,因为需要完成一个函数应用程序。seq
我们是否保证在到达第二个参数的 WHNF 之前评估这里的第一个参数?
haskell - 为什么将内置函数应用于被认为是弱头范式的太少参数?
Haskell定义说:
一个表达式是弱头范式(WHNF),如果它是:
- 一个构造函数(最终应用于参数),例如 True、Just (square 42) 或 (:) 1
- 一个内置函数应用于太少的参数(可能没有),如 (+) 2 或 sqrt。
- 或 lambda 抽象 \x -> 表达式。
为什么内置函数会受到特殊对待?根据 lambda 演算,部分应用函数与任何其他函数之间没有区别,因为最后我们只有一个参数函数。
haskell - 了解涉及 GHCi let 绑定时 thunk 的不同行为
我一直在玩 Simon Marlow 关于 Haskell 中并行和并发编程的书中的一些示例,并偶然发现了一个我不太了解的有趣行为。这真的是关于我试图了解 GHC 的一些内部工作原理。
假设我在 REPL 中执行以下操作:
好的,这几乎是我所期望的,只是 z 已经被评估为 WHNF。让我们编写一个类似的程序并将其放在一个文件中:
并在 GHCi 中摆弄它:
所以这有点不同:z
没有提前评估为 WHNF。我的问题是:
为什么z
在执行时会在 REPL 中评估为 WHNF,let z = (x,x)
但在从文件加载定义时不会。我怀疑它与模式绑定有关,但我不知道在哪里查找以进行澄清(也许我完全错了)。我本来希望它以某种方式表现得像文件中的示例。
任何指示或简要解释为什么会发生这种情况?
haskell - 为什么 Haskell 认为 lambda 抽象是弱头范式(WHNF)?
在 Haskell 中,lambdas 被认为是在 WHNF 中,而未应用的用户定义函数则不是。这种区别背后的动机是什么?
haskell - Test if a value has been evaluated to weak head normal form
In Haskell, is it possible to test if a value has been evaluated to weak head normal form? If a function already exists, I would expect it to have a signature like
There are a few places that similar functionality lives.
A previous answer introduced me to the :sprint
ghci command, which will print only the portion of a value that has already been forced to weak head normal form. :sprint
can observe whether or not a value has been evaluated:
It's possible in IO
to examine properties that would otherwise be off-limits. For example, it's possible to compare in IO
to see if two values came from the same declaration. This is provided by the StableName
s in System.Mem.StableName
and used famously to solve the observable sharing problem in data-reify. The related StablePtr
does not provide a mechanism to check if the referenced value is in weak head normal form.
haskell - Haskell 中的表达式求值:固定子表达式的类型会导致父表达式的求值程度不同
我无法解释以下行为:
现在,当我为 x 指定类型时:
为什么 x 类型的规范强制 y 为其弱头范式(WHNF)?
我在阅读Simon Marlow 的 Parallel and Concurrent Programming In Haskell时意外发现了这种行为。
haskell - 减少 WHNF 中的 lambda 表达式
我必须将以下 lambda 表达式简化为 WHNF,但我不太确定该怎么做:
那么,我该怎么做呢?按名称减少呼叫?
(λz x. (λx. x) z) x
WHNF 中有这个表达式(其他示例)吗?
haskell - 在 Haskell 中将 WHNF 转换为 NF 感到困惑
在一个简单的例子中,通过打印将 WHNF 转换为 NF 效果很好
但在某种情况下,类型未声明它不起作用。
您能否详细解释一下为什么转换在最后一种情况下不起作用?