Note [Simplifying the instance context]
Consider
data T a b = C1 (Foo a) (Bar b)
| C2 Int (T b a)
| C3 (T a a)
deriving (Eq)
We want to come up with an instance declaration of the form
instance (Ping a, Pong b, ...) => Eq (T a b) where
x == y = ...
It is pretty easy, albeit tedious, to fill in the code "...". The
trick is to figure out what the context for the instance decl is,
namely Ping, Pong and friends.
Let's call the context reqd for the T instance of class C at types
(a,b, ...) C (T a b). Thus:
Eq (T a b) = (Ping a, Pong b, ...)
Now we can get a (recursive) equation from the data decl. This part
is done by inferConstraintsStock.
Eq (T a b) = Eq (Foo a) u Eq (Bar b) -- From C1
u Eq (T b a) u Eq Int -- From C2
u Eq (T a a) -- From C3
Foo and Bar may have explicit instances for Eq, in which case we can
just substitute for them. Alternatively, either or both may have
their Eq instances given by deriving clauses, in which case they
form part of the system of equations.
Now all we need do is simplify and solve the equations, iterating to
find the least fixpoint. This is done by simplifyInstanceConstraints.
Notice that the order of the arguments can
switch around, as here in the recursive calls to T.
Let's suppose Eq (Foo a) = Eq a, and Eq (Bar b) = Ping b.
We start with:
Eq (T a b) = {} -- The empty set
Next iteration:
Eq (T a b) = Eq (Foo a) u Eq (Bar b) -- From C1
u Eq (T b a) u Eq Int -- From C2
u Eq (T a a) -- From C3
After simplification:
= Eq a u Ping b u {} u {} u {}
= Eq a u Ping b
Next iteration:
Eq (T a b) = Eq (Foo a) u Eq (Bar b) -- From C1
u Eq (T b a) u Eq Int -- From C2
u Eq (T a a) -- From C3
After simplification:
= Eq a u Ping b
u (Eq b u Ping a)
u (Eq a u Ping a)
= Eq a u Ping b u Eq b u Ping a
The next iteration gives the same result, so this is the fixpoint. We
need to make a canonical form of the RHS to ensure convergence. We do
this by simplifying the RHS to a form in which
- the classes constrain only tyvars
- the list is sorted by tyvar (major key) and then class (minor key)
- no duplicates, of course References 0
This Note does not link to any other.
Referenced by 3
- Inferring the instance context GHC.Tc.Deriv.Infer
- Inferred contexts from method constraints GHC.Tc.Deriv.Infer
- GHC.Tc.Deriv.Infer call site