在 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
未缓存(记忆)。
这种重复计算正是单态限制试图避免的。
在一个简单的例子中,通过打印将 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
未缓存(记忆)。
这种重复计算正是单态限制试图避免的。