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



尊敬的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)。是因为在"解析"函数调用时没有使用上下文吗?如果是,为什么?

提前感谢!

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

首先,从文档来看:

匹配时,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)

这样就不会有重叠,因为元组不是列表。

相关内容

  • 没有找到相关文章

最新更新