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