[GHC] #9210: "overlapping instances" through FunctionalDependencies
GHC
ghc-devs at haskell.org
Fri Apr 21 02:17:51 UTC 2017
#9210: "overlapping instances" through FunctionalDependencies
-------------------------------------+-------------------------------------
Reporter: rwbarton | Owner: (none)
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler (Type | Version: 7.8.2
checker) |
Resolution: | Keywords: FunDeps
Operating System: Unknown/Multiple | Architecture:
| Unknown/Multiple
Type of failure: None/Unknown | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s):
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by AntC):
Replying to [comment:11 diatchki]:
> The check for overlapping is done when GHC resolves instances. This is
unrelated to this example. You can easily modify it, so that there are no
overlapping instances:
>
> {{{
> class Foo tag a b c | a b -> c
>
> instance Foo Int (x, a) x ((), a)
> instance Foo Bool (x, a) a (x, ())
> }}}
No, that class decl is not allowed, according to the FDs-via-CHRs paper,
Section 6.2 on Non-full dependencies. (And this example is similar to
yours on #10675 -- which I think is also disallowed.) If the FD is non-
full, the class must have a super-class constraint to enforce the FD.
Otherwise we still get inconsistent behaviour, which is your complaint on
#10675.
.
>
> The check for the consistency of FDs ought to be done whenever instances
exist in the same scope, ...
You mean like dear old Hugs? Yes I miss it for that reason. But I think
you can still get inconsistent behaviour with overlapping instances, if
some instances are in scope in one module but different instances in scope
in a different module.
I think what it needs is to ban overlap altogether. (And that means for
non-full FDs, banning overlap of the params involved with that FD. We have
to be canny there: allow identical params, modulo alpha renaming.) Then we
just reject any instance that attempts to overlap. (Again Hugs in effect
did that with its check "Instance is inconsistent with FunDeps".)
But what we can do currently with overlapping instances is useful. We need
a more expressive way to say in the instance: yes I know this looks like
it overlaps, but actually I don't want it to; when the use site appears to
be ambiguous, always pick that instance. For example with instance guards:
{{{
class Foo a b c | a b -> c
instance Foo (x, a) x ((), a) | x /~ a
instance Foo (x, a) a (x, ())
}}}
The guard on that first instance says: `x` must not be unifiable with `a`,
so do not select this instance if unifiable. That's the same as Richard's
apartness check for Closed Type Families selecting equations. More
discussion here https://typesandkinds.wordpress.com/2013/04/29/coincident-
overlap-in-type-families/
.
>
> As far as I can tell, the new behavior in 8 is how GHC uses FDs to
perform improvements. Instead of just using one of the instances, it will
now try to improve with all of the instances. As a result, if there are
inconsistencies, it will try to improve in two different ways, and report
a delayed error.
"New"? You're describing the behaviour Simon raises in #10675, which was
at 7.10. And judging by "Examples in the testsuite that exploit this
loophole ", it's been around for some time. I agree with you that GHC
should not try to merge or mingle/mangle type improvements from different
instances. The behaviour in #10675 is just nuts. (But trying to cure it
might be worse than the disease. It does seem to be a swamp.)
.
>
> The underlying bug of failing to detect the inconsistency of the
instances is still present.
>
> The thing that we should be checking is:
> {{{
> forall x1 a2 x2 a2. ( (x1,a1) ~ (x2,a2), x1 ~ a2 ) => ( ((), a1) ~ (x2,
()) )
> }}}
Yes, which we can do with a superclass constraint, such as a type function
with equality constraint.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/9210#comment:12>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list