当中间值从未具体输入时,Haskell编译器如何为`(==)(fromInteger 0)(fromInteger 0)`发出代码?

Wil*_*ley 3 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> :t (==) (fromInteger 0) (fromInteger 1)
(==) (fromInteger 0) (fromInteger 1) :: Bool
Prelude> (==) (fromInteger 0) (fromInteger 1)
False
Run Code Online (Sandbox Code Playgroud)

魔法!目前还不清楚是如何或是否a具体,但代码运行成功!

根据类型推断规则,a 上面表示的类型变量彼此成功统一,因为它们Num a在不同的术语中具有兼容的约束.但是,a永远不要绑定到具体类型.我的问题是,在运行时,该(==)函数使用哪个实例字典(或专业化,等等)?

这是Haskell依赖于简单的二进制memcmp样式比较的情况吗?或者它可能只是在其实例列表中选择第一个实例,Num因为理论上它应该无关紧要(只要该实例的代数属性正确实现...)

luq*_*qui 9

是的,它是通过违约而具体化的,这几乎是你的第二个理论.

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

(虽然选择哪个实例确实很重要.例如2^64 == 0,True如果Int选择了Falseif ,但是如果Integer被选中, Integer则在默认列表中首先是有充分理由的.)