[GHC] #14331: Overzealous free-floating kind check causes deriving clause to be rejected

GHC ghc-devs at haskell.org
Wed Oct 18 08:36:30 UTC 2017


#14331: Overzealous free-floating kind check causes deriving clause to be rejected
-------------------------------------+-------------------------------------
        Reporter:  RyanGlScott       |                Owner:  (none)
            Type:  bug               |               Status:  merge
        Priority:  normal            |            Milestone:  8.2.2
       Component:  Compiler (Type    |              Version:  8.2.1
  checker)                           |
      Resolution:                    |             Keywords:  deriving
Operating System:  Unknown/Multiple  |         Architecture:
                                     |  Unknown/Multiple
 Type of failure:  GHC rejects       |            Test Case:
  valid program                      |  deriving/should_compile/T14331
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by simonpj):

 > the logic in comment:26 also means that `data Proxy a = P deriving
 Functor` should fail

 Not at all!  After elaborating the data type decl we have
 {{{
 data P {k} (a::k) = P deriving( Functor )
 }}}
 Now we create an instance declaration in which we are free to instantiate
 `k` (and indeed `a`) as much as we plase:
 {{{
 instance Functor (P (*->*)) where ...
 }}}
 The quantified variables of the data type decl can freely be instantiated
 in the (derived) instance.  We want the most general such instantiation so
 that the derived instance is applicable as much as poss; hence
 unification.

 I have belatedly realised that the real stumbling block here is when the
 same variable appears ''both'' in the data type decl ''and'' in the
 `deriving` clause.  For example here
 {{{
 -- C :: * -> * -> Constraint
 data D k (a::k) = ... deriving( forall x. C x )
 }}}
 is fine: we get an instance looking like
 {{{
 instance forall x (b::*).  (...) => C x (D * b) where ...
 }}}
 The `x` from the `deriving` is universally quantified in the instance; the
 `k` and `a` are instantiated to `*` and `b` respectively; then we quantify
 over `b`.

 But the nasty case is this:
 {{{
 data D k (a::k) = ... deriving( C2 k a )
 }}}
 The `k` and `a` belong both to the data decl (hence it's in the "freely
 instantiate" camp) but also belong somehow in the instance.  Can I freely
 instantiate the `k` in the instance?  And the `k`?  It'd be very odd if I
 got an instance like
 {{{
 instance ... => C2 * a (D * a) where ...
 }}}
 because the `deriving` part explicitly said `k` not `*`.

 This seems very hard to specify.  It's much easier to think of the data
 type decl and the instance entirely separately.

 Do we need the same variable to appear in both places?  That is, what if
 we said that the type variables from the data type don't scope over the
 'deriving' clause?  Then
 {{{
 data D k (a::k) = ... deriving( C2 k a )
 }}}
 would mean
 {{{
 data D k (a::k) = ... deriving( forall kk aa. C2 kk aa )
 }}}
 where I've alpha-renamed to make it clear.  What would go wrong if we did
 that?

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


More information about the ghc-tickets mailing list