Double和Integral类型之间的重叠实例

时间:2014-05-16 19:08:00

标签: haskell typeclass

我有以下类型类和实例:

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个实例。

为什么这些重叠?

谢谢!

1 个答案:

答案 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 的实例,但有人可能会导入您的库并声明一个,此时即使检查了上下文,实例也会重叠。更糟糕的是,没有明智的方式来偏爱另一个。