7

在一个简单的例子中,通过打印将 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 = _

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

4

1 回答 1

10

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

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

由于x本质上是“按需生成的多个值”,因此这里没有单一的 WHNF 或 NF。

请注意,如果我们计算(x :: Int) + (x :: Int),则将x被重新计算两次:GHC 通常不会“缓存”类型Int为连续计算的 WHNF。这类似于f 3 + f 3,其中f 3未缓存(记忆)。

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

于 2018-11-28T10:34:33.347 回答