[GHC] #16194: deriving, wrong code: newtype T cat a = MkT ((forall xx. cat xx xx) -> a) deriving stock Functor

GHC ghc-devs at haskell.org
Wed Jan 16 16:39:37 UTC 2019


#16194: deriving, wrong code: newtype T cat a = MkT ((forall xx. cat xx xx) -> a)
deriving stock Functor
-------------------------------------+-------------------------------------
        Reporter:  Iceland_jack      |                Owner:  (none)
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  Compiler          |              Version:  8.7
      Resolution:                    |             Keywords:  DeriveFunctor
                                     |  deriving RankNTypes
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 RyanGlScott):

 This is rather delicate. Here is the instance you likely have in your
 head:

 {{{#!hs
 instance Functor (T cat) where
   fmap f (MkT g) = MkT (\x -> f (g x))
 }}}

 As `-ddump-deriv` reveals, this isn't quite the code that GHC is
 producing. It's actually producing this:

 {{{#!hs
 instance Functor (T cat) where
   fmap f (MkT g) = MkT ((\g' x -> f (g' x)) g)
 }}}

 Normally, these two implementations would be equivalent. However, because
 `g` has a higher-rank type `forall xx. cat xx xx`, applying `(\g' x -> f
 (g' x))` to `g` causes its type to be instantiated with a skolem `xx0`.
 This is why you get this error message:

 {{{
 Couldn't match type ‘forall xx. cat xx xx’ with ‘cat xx0 xx0’
 }}}

 There are advantages to generating code similar to the second instance. In
 more complicated examples (e.g., `newtype T a = MkT (Int -> Int -> a)`),
 using the unapplied form allows for a more compositional code-generation
 strategy that doesn't have to reason about substituting in arguments.

 In short, could this be fixed? Theoretically speaking, yes, but it would
 require a lot of work for not much gain. Personally, I'm inclined to just
 require users to write out this particular instance by hand.

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


More information about the ghc-tickets mailing list