1

亲爱的 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]不适用于 value [('a', True)]

所以,GHC为什么会考虑呢?

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

提前致谢!

4

1 回答 1

2

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

首先,从文档中:

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

-XOverlappingInstances 标志指示 GHC 允许匹配多个实例,前提是存在最具体的实例。

在您的情况下,传递给的类型foo[(Char,Bool)]. 这满足通用[a]和更专业的[(Char,a)]。在没有OverlappingInstancesflag的情况下,最具体的比赛场景不适用,报错。

现在,如果您要像这样稍微调整代码:

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

那么就不会有重叠,因为元组不是列表。

于 2017-01-06T10:36:10.717 回答