Haskell 理解';sprint&x27;在计算多态性表达式之后
鉴于: 我运行Haskell 理解';sprint&x27;在计算多态性表达式之后,haskell,polymorphism,ghci,thunk,Haskell,Polymorphism,Ghci,Thunk,鉴于: 我运行sprint打印其值: λ: let x = 1 + 2 正如所料,这是未评估的 但是,在评估x之后: λ: :sprint x x = _ sprint仍然输出。,即未评估: λ: x 3 为什么会这样?这是因为x是多态的 与之相比: λ: :sprint x x = _ 当x为多态性时,GHCI无法用特定值替换thunk,因为您以后可能会将其作为不同的类型进行评估。这是因为x为多态性 与之相比: λ: :sprint x x = _ 当x是多态性时,GHCI不能用特定
sprint
打印其值:
λ: let x = 1 + 2
正如所料,这是未评估的
但是,在评估x
之后:
λ: :sprint x
x = _
sprint
仍然输出。
,即未评估:
λ: x
3
为什么会这样?这是因为
x
是多态的
与之相比:
λ: :sprint x
x = _
当
x
为多态性时,GHCI无法用特定值替换thunk,因为您以后可能会将其作为不同的类型进行评估。这是因为x
为多态性
与之相比:
λ: :sprint x
x = _
当
x
是多态性时,GHCI不能用特定的值替换thunk,因为您以后可能会将其作为不同的类型进行计算。为什么多态性会影响其表达式值?我认为这里的关键是,带有typeclass约束的“值”,例如Num a=>a
,实际上不是普通值。相反,它实际上是一个从类型类字典到值的函数。@KevinMeredith在不知道它是哪个函数的情况下运行+
函数是不可能的。例如,一个复数将有两个字段,这两个字段都需要添加;该版本的+
的编译代码完全不同。当您评估x
(通过在提示下键入x
)时,GHCi必须选择一个具体类型(通过默认设置;如果默认规则不适用,则会引发错误)并调用该类型的+
版本。但是x
本身就是所有(Num)类型;它总是一个未计算的thunk,因为您总是可以创建新的Num实例,然后使用x
作为这些类型。@KevinMeredith Alexis Kind是100%正确的。在Haskell编译期间,类型类被删除。这是通过引入显式的“dictionary参数”来实现的,这些参数带来了关于应该使用哪个实例的信息。因此,x
成为类型为NumDict a->a
的函数,其中类型NumDict a
包含类型a
的Num
操作的实现。当你尝试计算x
时,它的类型被默认为Integer
,因此你实际上在做x NumDictInteger
,其中NumDictInteger
是由Integer
的实例声明定义的。多态性为什么会影响它的表达式值?我认为这里的关键是带有typeclass约束的“值”,例如Num a=>a
,实际上不是普通值。相反,它实际上是一个从类型类字典到值的函数。@KevinMeredith在不知道它是哪个函数的情况下运行+
函数是不可能的。例如,一个复数将有两个字段,这两个字段都需要添加;该版本的+
的编译代码完全不同。当您评估x
(通过在提示下键入x
)时,GHCi必须选择一个具体类型(通过默认设置;如果默认规则不适用,则会引发错误)并调用该类型的+
版本。但是x
本身就是所有(Num)类型;它总是一个未计算的thunk,因为您总是可以创建新的Num实例,然后使用x
作为这些类型。@KevinMeredith Alexis Kind是100%正确的。在Haskell编译期间,类型类被删除。这是通过引入显式的“dictionary参数”来实现的,这些参数带来了关于应该使用哪个实例的信息。因此,x
成为类型为NumDict a->a
的函数,其中类型NumDict a
包含类型a
的Num
操作的实现。当您尝试计算x
时,它的类型默认为Integer
,因此您实际上是在执行x NumDictInteger
,其中NumDictInteger
由Integer
的实例声明定义。