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

Tim*_*Tim 4 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
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实例.

为什么这些重叠?

谢谢!

use*_*038 7

很简单,这就是GHC的工作原理

当GHC试图解决约束C Int Bool时,它会尝试通过实例化实例声明的头部来匹配约束的每个实例声明.考虑这些声明:

instance context1 => C Int a     where ...  -- (A)
instance context2 => C a   Bool  where ...  -- (B)
Run Code Online (Sandbox Code Playgroud)

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 现在,但是有人可能会导入您的图书馆,并宣布一个,此时即使上下文被检查的情况下,将重叠.更糟糕的是,没有明智的方式来偏爱另一个.

  • 使用OverlappingInstances的情况很少,这不是其中之一. (2认同)