我有以下类型类和实例:
class StatType a where
toDouble :: a -> Double
instance StatType Double where
toDouble = id
instance Integral a => StatType a where
toDouble = fromIntegral
avg :: StatType a => [a] -> Double
avg = undefined
然后是表达式
*Example> avg ([1,2,3,4] :: [Double])
报告有关重叠实例的类型错误
Overlapping instances for StatType Double
arising from a use of `avg'
Matching instances:
instance StatType Double -- Defined at Example.hs:61:10
instance Integral a => StatType a -- Defined at Example.hs:63:10
类型系统无法在这两个实例之间进行选择。但是,Double
不是Integral
类型。
*Example> :i Double
data Double = GHC.Types.D# GHC.Prim.Double#
-- Defined in `GHC.Types'
instance StatType Double -- Defined at Example.hs:
instance Enum Double -- Defined in `GHC.Float'
instance Eq Double -- Defined in `GHC.Classes'
instance Floating Double -- Defined in `GHC.Float'
instance Fractional Double -- Defined in `GHC.Float'
instance Num Double -- Defined in `GHC.Float'
instance Ord Double -- Defined in `GHC.Classes'
instance Read Double -- Defined in `GHC.Read'
instance Real Double -- Defined in `GHC.Float'
instance RealFloat Double -- Defined in `GHC.Float'
instance RealFrac Double -- Defined in `GHC.Float'
instance Show Double -- Defined in `GHC.Float'
我不认为Integral
暗示其中一个或其他什么?
fromIntegral (3 :: Double)
引发了类型错误,因为Double
不是Integral
个实例。
为什么这些重叠?
谢谢!
答案 0 :(得分:7)
很简单,这就是GHC works
的方式当GHC试图解决约束C Int Bool时,它会尝试 匹配约束的每个实例声明,by 实例化实例声明的头部。考虑这些 声明:
instance context1 => C Int a where ... -- (A) instance context2 => C a Bool where ... -- (B)
GHC的默认行为是,一个实例必须匹配 它试图解决的约束。例如,约束C Int Bool匹配实例(A)和(B),因此将被拒绝;而 C Int Char仅匹配(A),因此选择(A)。
请注意
- 匹配时,GHC不会考虑实例声明的上下文(context1等)。
所以ghc看不到
instance StatType Double
instance Integral a => StatType a
它看到了
instance StatType Double
instance StatType a
显然重叠。
它的工作原理是类型类是开放的。现在没有Integral Double
的实例,但有人可能会导入您的库并声明一个,此时即使检查了上下文,实例也会重叠。更糟糕的是,没有明智的方式来偏爱另一个。