当中间值从未具体类型化时,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
是默认列表中的第一个,这是有充分理由的。)