[GHC] #8634: Relax functional dependency coherence check ("liberal coverage condition")

GHC ghc-devs at haskell.org
Mon Jul 21 15:17:19 UTC 2014


#8634: Relax functional dependency coherence check ("liberal coverage condition")
-------------------------------------+-------------------------------------
              Reporter:  danilo2     |             Owner:
                  Type:  feature     |            Status:  new
  request                            |         Milestone:  7.10.1
              Priority:  high        |           Version:  7.7
             Component:  Compiler    |          Keywords:
            Resolution:              |  Operating System:  Unknown/Multiple
Differential Revisions:  Phab:D69    |   Type of failure:  None/Unknown
          Architecture:              |         Test Case:
  Unknown/Multiple                   |          Blocking:
            Difficulty:  Unknown     |
            Blocked By:              |
       Related Tickets:  #1241,      |
  #2247, #8356, #9103, #9227         |
-------------------------------------+-------------------------------------

Comment (by simonpj):

 OK, Martin, that's a good example (in comment:26).  Let's see a bit more
 detail.
 We start with
 {{{
   F [a] [b], F [a] c
 }}}
 Now there are two sorts of "improvement" rules which might fire:
   A. '''Between two constraints'''.  Since we have `F [a] [b]` and `F [a]
 c`, we may derive `[b] ~ c`.  After all the class fundep for `F` claims
 that `a -> b`.

   B. '''Between a constraint and an instance declaration'''.  Here we have
      * `instance forall p q.  F q p => F [p] [q]`  (I have alpha-renamed.)
      * `F [a] c`
   Since the `[a]` matches the `[p]` we may conclude that `c ~ [q']`, where
 `q'` is a fresh unification variable, reflecting the fact that the
 instance declaration says the second parameter must be a list but doesn't
 tell you what the element type is.

 So Martin's point is that there are two possible solution paths:
 {{{
   F [a] [b], F [a] c
 ===> Use (A) to combine the two
   F [a] [b], F [a] c, c ~ [b]
 ===> Use the instance declaration to simplify
   F b a, c ~ [b]
 }}}
 Here is the other path:
 {{{
   F [a] [b], F [a] c
 ===> use the instance declaration
   F b a, F [a] c
 ===> use (B) to combine the second constraint with the instance
   F b a, F [a] c, c ~ [q']
 ===> use the instance declaration again
   F b a, F q' a, c ~ [q']
 (stuck)
 }}}
 This is helpful: it's a concrete example that demonstrates how minor
 variations in the way the inference engine works may lead to unpredictable
 failures in type inference.

 One possible reaction is that if you are going to lift the Coverage
 Condition, then (A) yields too many equalities, and you shouldn't use it.
 But (B) is still useful, and is actually what is wanted here.  So maybe we
 want
 {{{
 class C a b | a ~> b
 }}}
 notice `a ~> b` rather than `a -> b`, meaning "`a` specifies the ''shape''
 of `b`", which would make use improvement rule (B) but not (A) for this
 fundep.

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/8634#comment:30>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list