问题标签 [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.

0 投票
9 回答
36084 浏览

haskell - 什么是弱头范式?

弱头范式(WHNF) 是什么意思?范式 ( HNF) 和范式(NF) 是什么意思?

真实世界的 Haskell状态:

熟悉的 seq 函数将表达式计算为我们所说 的头部范式 (缩写为 HNF)。一旦到达最外层的构造函数(“头部”),它就会停止。这与 标准形式 (NF) 不同,在标准形式中,表达式被完全评估。

您还会听到 Haskell 程序员提到  头范式 (WHNF)。对于法线数据,弱头范式与头范式相同。区别只出现在功能上,而且太深奥了,我们在这里不关心。

我已经阅读了一些资源和定义(Haskell WikiHaskell Mail ListFree Dictionary),但我不明白。有人可以举个例子或提供一个外行定义吗?

我猜它会类似于:

WHNFseq($!)HNF 有什么关系?

更新

我仍然很困惑。我知道一些答案说忽略 HNF。从阅读各种定义来看,WHNF 和 HNF 中的常规数据似乎没有区别。但是,在功能方面似乎确实存在差异。如果没有区别,为什么seq需要foldl'

另一个混淆点来自 Haskell Wiki,它指出seq简化为 WHNF,并且不会对以下示例执行任何操作。然后他们说他们必须使用seq强制评估。这不是强迫它到HNF吗?

常见新手栈溢出代码:

了解 seq 和弱头范式 (whnf) 的人可以立即明白这里出了什么问题。 (acc+x, len+1) 已经在 whnf 中,因此 seq (在 的定义中 foldl')将值减少为 whnf,对此没有任何作用。这段代码将像原始示例一样构建 thunk  foldl ,它们只是在一个元组中。解决方案只是强制元组的组件,例如

- Stackoverflow 上的 Haskell Wiki

0 投票
3 回答
1197 浏览

performance - Haskell foldl'(++)性能不佳

我有这个代码:

这些函数返回每个元素乘以 2 的列表:

在 ghci 中:

为什么newList_bad函数的工作速度比 慢 200 倍newList_good?我知道这不是该任务的好解决方案。但是为什么这个无辜的代码工作得这么慢呢?

这是什么“4767099960字节”?对于那个简单的操作,Haskell 使用了 4 GiB?

编译后:

0 投票
1 回答
201 浏览

haskell - 弱头范式和求值顺序

我已经阅读了很多关于弱头正常形式和序列的内容。但是我仍然无法想象 Haskell 评估顺序背后的逻辑

演示何时以及如何使用的常见示例,但我仍然不明白常见示例如何

可能导致堆栈溢出。而另一个折叠定义使用seq

从我读过的对 seq 的解释中,作者非常小心地阐明了以下内容:

  • 的第一个参数seq不能保证在第二个参数之前被评估
  • 的第一个参数seq只会被评估为弱头范式
  • 的第一个参数的评估seq只会在第二个评估为 WHNF 时发生

那么,如果以上是正确的(是吗?)那么为什么不foldl'溢出foldl呢?

当我们减少一个步骤时,它不应该是这样的吧?

在上面,第二个参数seq不在 WHNF 中,因为需要完成一个函数应用程序。seq我们是否保证在到达第二个参数的 WHNF 之前评估这里的第一个参数?

0 投票
2 回答
1130 浏览

haskell - 为什么将内置函数应用于被认为是弱头范式的太少参数?

Haskell定义说:

一个表达式是弱头范式(WHNF),如果它是:

  • 一个构造函数(最终应用于参数),例如 True、Just (square 42) 或 (:) 1
  • 一个内置函数应用于太少的参数(可能没有),如 (+) 2 或 sqrt。
  • 或 lambda 抽象 \x -> 表达式。

为什么内置函数会受到特殊对待?根据 lambda 演算,部分应用函数与任何其他函数之间没有区别,因为最后我们只有一个参数函数。

0 投票
1 回答
522 浏览

haskell - 了解涉及 GHCi let 绑定时 thunk 的不同行为

我一直在玩 Simon Marlow 关于 Haskell 中并行和并发编程的书中的一些示例,并偶然发现了一个我不太了解的有趣行为。这真的是关于我试图了解 GHC 的一些内部工作原理。

假设我在 REPL 中执行以下操作:

好的,这几乎是我所期望的,只是 z 已经被评估为 WHNF。让我们编写一个类似的程序并将其放在一个文件中:

并在 GHCi 中摆弄它:

所以这有点不同:z没有提前评估为 WHNF。我的问题是:

为什么z在执行时会在 REPL 中评估为 WHNF,let z = (x,x)但在从文件加载定义时不会。我怀疑它与模式绑定有关,但我不知道在哪里查找以进行澄清(也许我完全错了)。我本来希望它以某种方式表现得像文件中的示例。

任何指示或简要解释为什么会发生这种情况?

0 投票
1 回答
309 浏览

haskell - 为什么 Haskell 认为 lambda 抽象是弱头范式(WHNF)?

在 Haskell 中,lambdas 被认为是在 WHNF 中,而未应用的用户定义函数则不是。这种区别背后的动机是什么?

0 投票
4 回答
1277 浏览

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 StableNames 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.

0 投票
1 回答
132 浏览

haskell - Haskell 中的表达式求值:固定子表达式的类型会导致父表达式的求值程度不同

我无法解释以下行为:

现在,当我为 x 指定类型时:

为什么 x 类型的规范强制 y 为其弱头范式(WHNF)

我在阅读Simon Marlow 的 Parallel and Concurrent Programming In Haskell时意外发现了这种行为。

0 投票
1 回答
680 浏览

haskell - 减少 WHNF 中的 lambda 表达式

我必须将以下 lambda 表达式简化为 WHNF,但我不太确定该怎么做:

那么,我该怎么做呢?按名称减少呼叫?

(λz x. (λx. x) z) xWHNF 中有这个表达式(其他示例)吗?

0 投票
1 回答
112 浏览

haskell - 在 Haskell 中将 WHNF 转换为 NF 感到困惑

在一个简单的例子中,通过打印将 WHNF 转换为 NF 效果很好

但在某种情况下,类型未声明它不起作用。

您能否详细解释一下为什么转换在最后一种情况下不起作用?