[GHC] #9371: Overlapping type families, segafult

GHC ghc-devs at haskell.org
Mon Jul 28 11:59:24 UTC 2014


#9371: Overlapping type families, segafult
----------------------------------------+----------------------------------
              Reporter:  pingu          |            Owner:
                  Type:  bug            |           Status:  new
              Priority:  normal         |        Milestone:
             Component:  Compiler       |          Version:  7.8.3
            Resolution:                 |         Keywords:
      Operating System:  Linux          |     Architecture:  x86_64 (amd64)
       Type of failure:  Runtime crash  |       Difficulty:  Unknown
             Test Case:                 |       Blocked By:
              Blocking:                 |  Related Tickets:
Differential Revisions:                 |
----------------------------------------+----------------------------------

Comment (by goldfire):

 At first reading, it seemed that comment:3 did not relate to this ticket.
 But, looking closer, I see how. I'll explain for others' benefit:

 The line `data D x = D1 (Either x ())` becomes somewhat like the two
 declarations

 {{{
 data DFInst1 x = D1 (Either x ())
 type D x = DFInst1 x
 }}}

 We create a proper datatype `DFInst1` that has no eta-reduction or
 anything strange, really, other than the fact that the user can't ever
 write its name. Data families are internally interpreted somewhat like
 type families, and thus we create the connection between `D` and
 `DFInst1`. However, as Simon explains, the ''second'' of my definitions
 above is eta-reduced.

 When processing `data D (x, y) = D2 (x, y)`, the relevant type-ish
 instance is `D (x, y) = DFInst2 x y`, which can''not'' be eta-reduced.
 Then, when comparing the instances `D = DFInst1` and `D (x, y) = DFInst2 x
 y`, the conflict-checker says that the left-hand sides (`<empty>` and
 `(x,y)`, respectively) are quite surely apart, because they are of
 different lengths!

 There is a fix here that involves much less theory than Simon's approach:
 fix the conflict checker to take this into account. There should ''never''
 be different lengths involved here (absent the eta-reduction), so when
 there are, we could just note a conflict. Even simpler, we could notice
 somehow that a data family is involved and spit out a conflict right away,
 as two data family instances are ''never'' compatible.

 That said, Simon asks a worthwhile question: do we need eta-reduction
 given the new implementation of GND? I think "yes":

 {{{
 import Control.Monad.Trans.Identity

 newtype MyList a = MkList [a]
 class C m where
   x :: IdentityT m Int
 instance C [] where
   x = IdentityT [1,2,3]
 deriving instance C MyList
 }}}

 This (silly) example requires the eta-reduction to work, and I don't see a
 compelling reason to reduce expressivity here. Yes, it would simplify the
 code somewhat, but I still don't think it's worth it.

 In answer to Simon's "why not cast `Monad Parser` to `Monad IO`": a lack
 of higher-kinded roles was a big part of the discussion, but there was
 another: superclasses. It's possible that the GND'd class has superclasses
 and that the superclass instances for the original type and the newtype
 are different. If we casted the whole instance, we would get the
 superclass instances from the original type, which would be quite strange.
 Indeed, before making any change related to roles, the old GND code also
 did not cast instances, because of this superclass issue.

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


More information about the ghc-tickets mailing list