RE:: Can a TC plugin create new skolem vars when simplifying Givens?

Nick writes
Here's a small indicative example. In the "simplify Givens" step, the plugin receives
[G] (p `Union` Singleton A) ~ (q `Union` Singleton B)
and I would ideally simplify that to
[G] p ~ (x `Union` Singleton B)
[G] q ~ (x `Union` Singleton A)
If we think of Union as a type-level function (which it is?), then the step you outline above is similar to what happens during “flattening” of the Givens. We get this:
[G] fsk1 ~ p `Union` Singleton B (CFunEqCan)
[G] fsk2 ~ q `Union` Singleton A (CFunEqCan)
[G] fsk1 ~ fsk2 (CTyEqCan)
* The newly generated skolems are called “flatten-skolems” or fsks for short.
* The new skolems are kept in the `inert_fsks` field of the `InertSet`.
* A new one is created by `TcSMonad.newFlattenSkolem`
* All fsks are eliminated by TsSMonad.unflattenGivens
Returning to your point, you are exploiting a property of sets that allows you to say that if
p U X = q U Y
Then suppose r = p • q
then p = r U Y, q = r U X
And now we can eliminate all uses of p, q in favour of r. But if you do this in a type system, we have a problem: where is ‘r’ bound? E.g. if you have
f :: forall p q. (p `Union` A) ~ (q `Union` B) => blah
Then p, q are bound by the forall, but r is not. To put it another way, what well-typed Core program would you like to generate?
You could do this:
[G] fsk1 ~ p `Union` Singleton B (CFunEqCan)
[G] fsk2 ~ q `Union` Singleton A (CFunEqCan)
[G] fsk3 ~ p `Intersect` q (CFunEqCan)
[G] fsk4 ~ fsk3 `Union` Singleton B (CFunEqCan)
[G] fsk5 ~ fsk3 `Union` Singleton A (CFunEqCan)
[G] fsk1 ~ fsk2 (CTyEqCan)
[G] p ~ fks4 (CTyEqCan)
[G] q ~ fsk5 (CTyEqCan)
The ‘r’ is just fsk3. It’ll be eliminated by unflattenGivens, so there is no problem with scoping.
I have no idea whether that’ll help you prove the things you want to prove!
Simon
From: ghc-devs
participants (1)
-
Simon Peyton Jones