A complication.
Consider the following snippet:
class D u a where printD :: u -> a -> String
instance D a a where printD _ _ = "Same type instance."
instance {-# overlapping #-} D u (f x) where printD _ _ = "Instance with a type constructor."
And this is how it works:
λ printD 1 'a'
...
...No instance for (D Integer Char)...
...
λ printD 1 1
"Same type instance."
λ printD [1] [1]
...
...Overlapping instances for D [Integer] [Integer]
...
λ printD [1] ['a']
"Instance with a type constructor."
Note that the overlapping instances are not resolved, despite the pragma being supplied to this end.
A solution.
It took some guesswork to arrive at the following adjusted definition:
class D' u a where printD' :: u -> a -> String
instance (u ~ a) => D' u a where printD' _ _ = "Same type instance."
instance {-# overlapping #-} D' u (f x) where printD' _ _ = "Instance with a type constructor."
It works as I expected the previous to:
λ printD' 1 'a'
...
...No instance for (Num Char)...
...
λ printD' 1 1
"Same type instance."
λ printD' [1] [1]
"Instance with a type constructor."
λ printD' [1] ['a']
"Instance with a type constructor."
My questions.
I am having a hard time understanding what is happening here. Is there an explanation?
Particularly, I can put forward two separate questions:
- Why is the overlap not resolved in the first snippet?
- Why is the overlap resolved in the second snippet?
But, if the issues are connected, perhaps a single, unified theory would serve explaining this case better.
P.S. concerning a close / duplicate vote I am aware that ~
signifies type equality, and I am consciously using it to obtain the behaviour I need (particularly, printD' 1 'a'
not matching). It hardly explains anything concerning specifically the case I presented, where the two ways of stating type equality (the ~
and the instance D a a
) lead to two subtly distinct behaviours.
note I tested the snippets above with ghc
8.4.3
and 8.6.0.20180810