我的问题与存在不确定类型的中间值的类型类实例推导有关
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
实例列表中选择第一个实例,因为从理论上讲,这无关紧要(只要该实例的代数属性正确实现...)
答案 0 :(得分:9)
是的,defaulting将其具体化了,这几乎是您的第二个理论。
表达式[..]不明确,因为文字4是Haskell中的Num a =>类型。 4可以是Int,Float或作为Num实例的任何其他类型,因此出于上述相同原因,编译器无法选择任何特定类型。但是Haskell委员会认为这是太多限制。经过大量辩论,他们妥协并添加了一个临时规则来选择特定的默认类型。
(尽管选择哪个实例并不重要。例如,如果选择2^64 == 0
,True
为Int
,但是如果选择False
,则Integer
。 Integer
在默认列表中排在第一位,这是有充分理由的。)