[GHC] #10675: GHC does not check the functional dependency consistency condition correctly

GHC ghc-devs at haskell.org
Wed Apr 19 12:24:36 UTC 2017


#10675: GHC does not check the functional dependency consistency condition
correctly
-------------------------------------+-------------------------------------
        Reporter:  simonpj           |                Owner:  (none)
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  Compiler          |              Version:  7.10.1
      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:15 simonpj]:  On the broader issue of should those
 instances be accepted together

 > Let me note that the commit in comment:5 added this note
 > {{{
 > ... Currenty [checking] if the two types are *contradicatory*,
 >  using (isNothing . tcUnifyTys).  But all the papers say
 > we should check if the two types are *equal* thus ...
 > }}}

 Thank you. So that confirms my suspicion in comment:11, bullet 3.

 > {{{
 > For now I'm leaving the bogus form because that's the way it has
 > been for years.
 > }}}

 Yes I think that's wise, given how many fragile programs are out there
 using FunDeps and overlaps.

 > Would someone like to fix the bogus-ness as suggested, and check what,
 if anything, goes wrong.

 I'm keen to help, but lack the resources or expertise.

 > It'd be worth checking what Hackage libraries build before, but fail to
 build after.

 I would guess that any library using type-level programming switches on
 `UndecidableInstances` by default, whether or not it actually needs it.

  > (...  Maybe they SHOULD fail.)    This has been wrong for a long time.

 Given the howls every time GHC tries to apply the FunDep rules more
 strictly; and given how long a time it's been wrong; I wonder if there's a
 softly-softly strategy?

 * Move from module-wide `UndecidableInstances` to a per-instance {-#
 UNDECIDABLE #-} pragma. (Same idea as with {-# OVERLAP* #-}.)
 * The '''Coverage Condition''' is defined in terms of checks on each
 instance alone, so it's just more closely targetting the logic.
 * Being in the instance gives a more in-your-face signal that this
 instance is suspicious -- essentially the programmer is acknowledging GHC
 can't necessarily enforce the '''Consistency Condition'''.
 * And I suspect a large proportion of instances do obey the '''Coverage
 Conditions'''.

 Could we go further to a per-parameter-per-instance flag?
 * The idiom I see is there's a bare type var in the instance decl, for the
 target of the FunDep. It doesn't appear elsewhere in the head, so it's
 breaking the '''Coverage Condition'''. But there's an equality constraint
 on it, where the improved type __would__ meet the '''Coverge Condition'''.
 Like:
 {{{
 instance (b ~ False) => TTypeEq a a' b    -- breaks Coverage, compare:
 instance                TTypeEq a a' False  -- Coverage OK
 }}}

 * The reason for the bare type var is to ensure this instance is {-#
 OVERLAPPABLE #-}; and a more specific instance will override it.

 With `{-# LANGUAGE  IrrefutableInstanceParams #-}` (or some equally ugly
 name), you can go:
 {{{
 instance TTypeEq a a' ~False   -- tilde prefix ? maybe too subtle
 }}}
 This:
 1. Is syntactic sugar for the form with Equality constraint, for a fresh-
 generated type var.
 2. Means the compiler can validate the '''Coverage Condition''', so this
 doesn't need {-# UNDECIDABLE #-}
 3. Lets the dog see the rabbit: the compiler can check the '''Consistency
 Condition'''.

 [To bikeshed about syntax, it's pleasing `~` is already the prefix for
 irrefutable pattern matches, and the operator for type Equality
 constraints. It appearing within the instance head is currently illegal
 syntax; but I guess with a very badly formed head, it might be confused
 with a type operator(?)]

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


More information about the ghc-tickets mailing list