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

Confused by converting WHNF to NF in Haskell

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

Prelude> let x = 1 + 2 :: Int
Prelude> :sprint x
x = _
Prelude> x
3
Prelude> :sprint x
x = 3

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

Prelude> let x = 1 + 2
Prelude> :sprint x
x = _
Prelude> x
3
Prelude> :sprint x
x = _

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

由于在 GHCi 中禁用了单态限制,所以最后的 x 是类型 x :: Num a => a 的多态值。所以它不是一个简单的整数,而是一种函数 DictNum a -> a 可以创建任何数字类型的值。

确实,x :: Int, x :: Float, x :: Double 会 运行 并产生不同的值。这些值在数值上相同,但在计算上不同,因为它们是不同类型的表示。

因为 x 本质上是 "multiple values, generated on demand",所以这里没有单独的 WHNF 或 NF。

请注意,如果我们计算 (x :: Int) + (x :: Int),那么 x 将被重新计算 两次 :GHC 通常不会 "cache" WHNF输入 Int 进行连续计算。这类似于 f 3 + f 3,其中 f 3 未缓存(记忆)。

这种重复计算正是单态限制试图避免的。