【发布时间】:2016-06-22 03:27:52
【问题描述】:
给定:
λ: let x = 1 + 2
我运行sprint 来打印它的值:
λ: :sprint x
x = _
正如预期的那样,它没有被评估。
但是,在评估x之后:
λ: x
3
sprint 仍然输出_,即未评估:
λ: :sprint x
x = _
为什么会这样?
【问题讨论】:
标签: haskell polymorphism ghci thunk
给定:
λ: let x = 1 + 2
我运行sprint 来打印它的值:
λ: :sprint x
x = _
正如预期的那样,它没有被评估。
但是,在评估x之后:
λ: x
3
sprint 仍然输出_,即未评估:
λ: :sprint x
x = _
为什么会这样?
【问题讨论】:
标签: haskell polymorphism ghci thunk
这是因为x 是多态的。
比较:
Prelude> let x = 1 + 2 :: Int
Prelude> :sprint x
x = _
Prelude> x
3
Prelude> :sprint x
x = 3
Prelude>
当x 是多态时,GHCI 不能用特定值替换 thunk,因为您以后可能会将其评估为不同的类型。
【讨论】:
Num a => a,并不是真正的普通值。相反,它实际上是一个从类型类字典到值的函数。
+ 函数是不可能的。例如,一个复数会有两个字段,这两个字段都需要相加;该版本+ 的编译代码完全不同。当您评估x(通过在提示符处输入x)时,GHCi 必须选择一个具体类型(默认情况下;如果默认规则不适用,它将引发错误)并调用该类型的+ 版本。但是x本身就是all(Num)类型;它始终是未经评估的重击,因为您始终可以创建新的 Num 实例,然后使用 x 作为这些类型。
x 变成了一个NumDict a -> a 类型的函数,其中NumDict a 类型包含a 类型的Num 操作的实现。当您尝试评估x 时,它的类型默认为Integer,因此您实际上正在执行x NumDictInteger,其中NumDictInteger 由Integer 的实例声明为Num 定义。