我有以下类型类和实例:
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
Run Code Online (Sandbox Code Playgroud)
但接下来的表达
*Example> avg ([1,2,3,4] :: [Double])
Run Code Online (Sandbox Code Playgroud)
报告有关重叠实例的类型错误
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
Run Code Online (Sandbox Code Playgroud)
类型系统无法在这两个实例之间进行选择.但是,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'
Run Code Online (Sandbox Code Playgroud)
我不认为Integral这些或其中任何一个暗示?
fromIntegral (3 :: Double)引发类型错误,因为Double它不是Integral实例.
为什么这些重叠?
谢谢!
很简单,这就是GHC的工作原理
当GHC试图解决约束C Int Bool时,它会尝试通过实例化实例声明的头部来匹配约束的每个实例声明.考虑这些声明:
Run Code Online (Sandbox Code Playgroud)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
Run Code Online (Sandbox Code Playgroud)
它看到了
instance StatType Double
instance StatType a
Run Code Online (Sandbox Code Playgroud)
这显然是重叠的.
它的工作原理是类型类是开放的.没有任何背景的Integral Double 现在,但是有人可能会导入您的图书馆,并宣布一个,此时即使上下文被检查的情况下,将重叠.更糟糕的是,没有明智的方式来偏爱另一个.