
#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