【问题标题】:Overlapping instances for between Double and Integral typesDouble 和 Integral 类型之间的重叠实例
【发布时间】:2014-05-16 19:07:59
【问题描述】:

我有以下类型类和实例:

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

为什么这些重叠?

谢谢!

【问题讨论】:

    标签: haskell typeclass


    【解决方案1】:

    很简单,这就是 GHC works

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

    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 现在没有实例,但有人可能会导入您的库并声明一个,此时即使检查了上下文,实例也会重叠。更糟糕的是,没有明智的方法来选择其中之一。

    【讨论】:

    • OverlappingInstances 允许这样做,选择最具体的实例。这有时很有用,但如果您还定义了instance Rational a => StatType a,它会立即再次中断。
    • 很少有使用 OverlappingInstances 的好案例,这不是其中之一。
    • 这完全有道理。谢谢。
    • 当然,我参加聚会有点晚了,但是@user2407038 - 你能详细说明一下吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-03
    • 1970-01-01
    相关资源
    最近更新 更多