在一个简单的示例中,通过打印将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 = _
您能否详细解释一下为什么在最后一种情况下无法进行转换?
答案 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
未被缓存(存储)。
这种重复计算正是单态限制试图避免的。