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

时间:2018-11-28 10:24:07

标签: haskell weak-head-normal-form

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

您能否详细解释一下为什么在最后一种情况下无法进行转换?

1 个答案:

答案 0 :(得分:10)

由于在GHCi中禁用了单棱镜限制,因此最后一个x是类型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未被缓存(存储)。

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