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

Bog*_*kiy 7 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
Run Code Online (Sandbox Code Playgroud)

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

Prelude> let x = 1 + 2
Prelude> :sprint x
x = _
Prelude> x
3
Prelude> :sprint x
x = _
Run Code Online (Sandbox Code Playgroud)

你能解释为什么转换在最后一种情况下不起作用吗?

chi*_*chi 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通常不会"缓存"类型的WHNF以Int进行连续计算.这类似于f 3 + f 3,其中f 3没有缓存(memoized).

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