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

GHC ghc-devs at haskell.org
Wed Jun 3 03:03:09 UTC 2015


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

Comment (by goldfire):

 Replying to [comment:62 rwbarton]:
 > * Is there a wiki page or similar describing the meaning of functional
 dependencies under `DysfunctionalDependencies`? I think I understand the
 meaning in the case of `class C a b | a -> b`: I think the condition is
 that for any type `a0`, there is at most one ''instance declaration''
 `instance C a[vs] b[vs]` for which `a[vs]` unifies with `a0`, but this
 unification may not fully determine `b[vs]`. But I don't know what it
 means to write a dysfunctional dependency like `class C a b c | a -> b`.
 How does that differ from the dependency `a c -> b`?

 My understanding of `DysfunctionalDependencies` is much, much simpler:
 just omit the check that takes place at instance declarations. For
 example, the following would be accepted:

 {{{
 class Terrible a b | a -> b
 instance Terrible Int Bool
 instance Terrible Int Char
 }}}

 Now, suppose we have

 {{{
 foo :: Terrible a b => a -> b
 foo = undefined
 }}}

 and we call `show (foo (5 :: Int))`. GHC has to figure out what type the
 argument to `show` has so it can supply the right `Show` instance. In this
 case, the type inferred for `foo (5 :: Int)` will either be `Bool` or
 `Char`, depending on the whims of GHC at the moment. They're called
 dysfunctional for a reason!

 Nevertheless, they can be useful if the user is careful to construct a set
 of instances that isn't terrible, but still doesn't meet the liberal
 coverage condition. Much like with `IncoherentInstances`, it's up to the
 user not to shoot themselves in the foot.

 >
 > * Would adding `DysfunctionalDependencies` get in the way of some day
 desugaring functional dependencies into type families, and removing the
 fundep solver code? (Is this likely to ever happen anyways?)

 This is a good point. The only reason I'm not against
 `DysfunctionalDependencies` is that I know functional dependencies don't
 make it into Core, and so you can't use this feature to write
 `unsafeCoerce`. But if we did desugar functional dependencies into
 something that does exist in Core, `DysfunctionalDependencies` would be in
 deep water. Is this a reason to avoid writing the feature? Perhaps. It
 certainly gives me pause when thinking about it.

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


More information about the ghc-tickets mailing list