Re: [GHC] #14070: Allow ‘unsafe’ deriving strategy, deriving code with ‘unsafeCoerce’

GHC ghc-devs at haskell.org
Sat Aug 26 16:37:04 UTC 2017


#14070: Allow ‘unsafe’ deriving strategy, deriving code with ‘unsafeCoerce’
-------------------------------------+-------------------------------------
        Reporter:  Iceland_jack      |                Owner:  (none)
            Type:  feature request   |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  Compiler          |              Version:  8.0.1
      Resolution:                    |             Keywords:
                                     |  QuantifiedContexts, deriving
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):

 Quantified contexts wouldn't make that example work. There's a bigger
 problem with that example in that there's no way for GHC to reason about
 how it should be derived. To pick a slightly simpler example:

 {{{
 λ> newtype Foo a = Foo (forall xx. Show a => IO xx) deriving newtype
 Functor

 <interactive>:7:67: error:
     • Can't make a derived instance of
         ‘Functor Foo’ with the newtype strategy:
         cannot eta-reduce the representation type enough
     • In the newtype declaration for ‘Foo’
 }}}

 This error message hints at the fundamental limitation here that
 `GeneralizedNewtypeDeriving` faces. Let's describe algorithmically what
 GND is doing on a simple example:

 {{{#!hs
 class C (a :: * -> *)

 newtype N a = N (UnderlyingType a) deriving newtype C
 }}}

 First, in order for this to work about, one must be able to drop a type
 variable from `N`, since the last parameter to `C` is of kind `* -> *`. We
 //can// do this, so everything is good so far. But there's another issue:
 GHC wants to emit an instance like this:

 {{{#!hs
 instance <context> => C N
 }}}

 What should `<context>` be? To determine this, GHC must be able to take
 `UnderlyingType a`, eta reduce one type variable from it, attach `C` in
 front, and simplify. For instance, if `UnderlyingType a` is `Identity a`,
 then GHC would first emit:

 {{{#!hs
 instance C Identity => C N
 }}}

 And then simplify `C Identity` as much as possible. (For instance, if
 there is a `C Identity` instance in scope, the derived instance would
 simplify down to just `instance C N`.)

 But if `UnderlyingType a = forall xx. Show a => IO xx`, this won't work
 out, since `a` can't be eta reduced! (The ability to eta reduce a type is
 really a property that only certain types exhibit, such as data type
 constructors.) Not even an `unsafe newtype` strategy would help you here,
 since the issue doesn't concern typechecking code, but rather coming up
 with the code that needs to be typechecked in the first place.

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


More information about the ghc-tickets mailing list