Haskell / GHC:报告重叠实例,而上下文仅允许单个实例

时间:2017-01-06 09:52:39

标签: haskell ghc overlapping-instances

亲爱的Haskell / GHC专家,

我真的不明白为什么GHC报告重叠实例,而根据提供的上下文只有一个实际上有效。例如,让我们考虑以下代码:

{-# LANGUAGE FlexibleInstances #-}

class C a where
    foo :: a -> String
    foo x = "OK"

instance C Bool
instance (C a) => C [a]
instance (C a) => C [(Char, a)]

main = print $ foo [('a', True)]

编译它给出:

Test.hs:13:16: error:
    * Overlapping instances for C [(Char, Bool)]
        arising from a use of `foo'
      Matching instances:
        instance C a => C [a] -- Defined at Test.hs:9:10
        instance C a => C [(Char, a)] -- Defined at Test.hs:11:10
    * In the second argument of `($)', namely `foo [('a', True)]'
      In the expression: print $ foo [('a', True)]
      In an equation for `main': main = print $ foo [('a', True)]

重点是('a', True)的类型(Char, Bool)不是C的实例。因此,instance C a => C [a]不适用于值[('a', True)]

因此,为什么GHC会考虑它?

问题实际上是关于理解GHC的行为,而不是如何避免这个问题(例如使用OverlappingInstances)。是因为当"解决"时不使用上下文一个函数调用?如果是这样,为什么?

提前致谢!

1 个答案:

答案 0 :(得分:2)

我的理解(可能是非常错误的):

首先,来自documentation

  

匹配时,GHC不考虑实例的上下文   声明(context1等)。 GHC的默认行为正是如此   一个实例必须与它试图解决的约束相匹配。可能存在重叠的可能性(通过包括声明(A)和(B),比如说);仅当特定约束匹配多个时才会报告错误。

     

-XOverlappingInstances标志指示GHC允许多个   要匹配的实例,只要有最具体的实例。

在您的情况下,传递给foo的类型为[(Char,Bool)]。这满足通用[a]和更专业的[(Char,a)]。如果没有OverlappingInstances标志,则最具体的匹配方案不适用,并报告错误。

现在,如果您稍微调整代码:

instance C Bool
instance (C a) => C [a]
instance (C a) => C (Char, a)

然后就没有重叠了,因为元组不是列表。