Dear Haskell/GHC experts,
I don't really understand why GHC reports overlapping instances while only one is actually valid according the provided contexts. For instance, let's consider the following piece of code:
{-# 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)]
Compiling it gives:
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)]
The point is that ('a', True)
has type (Char, Bool)
which is not an instance of C
. Therefore, instance C a => C [a]
is not applicable to the value [('a', True)]
.
Therefore, why does GHC consider it?
The question is really about understanding the behaviour of GHC, not about how to avoid the issue (e.g. using OverlappingInstances
). Is it because contexts are not used when "resolving" a function call? And if so, why?
Thanks in advance!
My understanding (could be very wrong):
First, from the documentation:
In your case, the type passed to
foo
is[(Char,Bool)]
. This satisfies the generic[a]
and the more specialised[(Char,a)]
. In the absence ofOverlappingInstances
flag, the most specific match scenario does not apply, and an error is reported.Now if you were to tweak your code slightly like so:
Then there would be no overlap, because a tuple is not a list.