当中间值从未具体类型化时,Haskell编译器如何为`(==)(fromInteger 0)(fromInteger 0)`生成代码?

当中间值从未具体类型化时,Haskell编译器如何为`(==)(fromInteger 0)(fromInteger 0)`生成代码?,haskell,instance,Haskell,Instance,我的问题与类型不明的中间值存在时的类型类实例推断有关 Prelude> :t fromInteger 0 fromInteger 0 :: Num a => a Prelude> :t (==) (==) :: Eq a => a -> a -> Bool Prelude> :t (==) (fromInteger 0) (==) (fromInteger 0) :: (Eq a, Num a) => a -> Bool Prelude>

我的问题与类型不明的中间值存在时的类型类实例推断有关

Prelude> :t fromInteger 0
fromInteger 0 :: Num a => a
Prelude> :t (==)
(==) :: Eq a => a -> a -> Bool
Prelude> :t (==) (fromInteger 0)
(==) (fromInteger 0) :: (Eq a, Num a) => a -> Bool
Prelude> :t (==) (fromInteger 0) (fromInteger 1)
(==) (fromInteger 0) (fromInteger 1) :: Bool
Prelude> (==) (fromInteger 0) (fromInteger 1)
False
魔法!尚不清楚
a
是如何或是否具体化的,但代码运行成功

根据类型推断规则,上面用
a
表示的类型变量成功地相互统一,因为它们在不同的术语中具有兼容的
Num a
约束。但是,
a
从不绑定到具体类型。我的问题是,在运行时,
(==)
函数使用哪个实例字典(或专门化,无论什么)


在这种情况下,Haskell是否依赖于简单的二进制
memcmp
样式比较?或者它只是在
Num
实例列表中选择第一个实例,因为理论上它不重要(只要该实例的代数属性正确实现…)

是的,它是由具体化的,这几乎是你的第二个理论

表达式[…]不明确,因为文本4是Haskell中的Num a=>a类型。4可以是Int、Float或Num实例的任何其他类型,因此编译器不能出于上述相同的原因选择任何特定类型。但是哈斯克尔委员会认为这是太多的限制。经过多次辩论,他们妥协并添加了一个选择特定默认类型的特别规则

(虽然选择哪个实例并不重要。例如,如果选择了
Int
,则
2^64==0
True
,但如果选择了
Integer
,则
False
Integer
是默认列表中的第一个,这是有充分理由的。)