[GHC] #13368: Derive superclasses automatically if possible
GHC
ghc-devs at haskell.org
Fri Mar 3 14:24:04 UTC 2017
#13368: Derive superclasses automatically if possible
-------------------------------------+-------------------------------------
Reporter: Iceland_jack | Owner: (none)
Type: feature request | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 8.0.1
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
| Unknown/Multiple
Type of failure: None/Unknown | Test Case:
Blocked By: | Blocking:
Related Tickets: #10607 | Differential Rev(s):
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by RyanGlScott):
This proposal shares many similarities with the
[https://ghc.haskell.org/trac/ghc/wiki/IntrinsicSuperclasses
IntrinsicSuperclasses] and
[https://ghc.haskell.org/trac/ghc/wiki/InstanceTemplates
InstanceTemplates] proposals, so I'll link them here. However, this
proposal shares many of their downsides, which I'll briefly expound upon
here.
First, there's the technical challenges to this proposal. Not all
instances are made equal, and `deriving` exposes this in many ways. For
instance, suppose you tried this under your proposal:
{{{#!hs
class Traversable f => Witherable f where ...
newtype Wrapped f a = Wrap (f a)
deriving newtype Witherable
}}}
This would attempt the following:
* `deriving newtype instance Functor f => Functor (Wrapped f)`
* `deriving newtype instance Foldable f => Foldable (Wrapped f)`
* `deriving newtype instance Traversable f => Traversable (Wrapped f)`
* `deriving newtype instance Witherable f => Witherable (Wrapped f)`
But trying to derive `Traversable` that way will fail, as it is ill-roled!
See #13153. So not only would this throw an error, but it would throw an
error that talks about a completely different class than `Witherable`.
Mysterious.
What's more, there's quite a number of ambiguities you'd have to deal
with. For instance, what happens under your proposal in this scenario?
{{{#!hs
class Show a => MyShow a where ...
data Foo
deriving newtype MyShow
instance Show Foo
}}}
Since `Show` is a superclass of `MyShow`, you might expect the `deriving
newtype MyShow` clause to derive `instance Show Foo` as well. But there's
already an `instance Show Foo`! So we'd either have to error here, or come
up with a scheme for defaulting to existing instances when scenarios like
the above one crop up.
You might respond: "But that's easy! Just use the existing `Show Foo`
instance!" But it gets even hairier than that:
{{{#!hs
class Show a => MyShow1 a where ...
class Show a => MyShow2 a where ...
data Foo
deriving newtype MyShow1
deriving anyclass MyShow2
}}}
Now we must ask: which of the two deriving clauses will implicitly derive
`Show` behind the scenes? The choice matters, because a `newtype`-derived
`Show` instance will be completely different than an `anyclass`-derived
one! If the answer to this question is "use the first deriving clause",
then now the order in which you write `deriving` clauses matters, which is
a property that Haskell has never had up to this point.
Finally, there's one more objection I will make not on technical grounds,
but on aesthetic ones. This proposal would lose the property that all
instances are explicitly asked for by the user. I (personally) find the
idea of instances being snuck in behind the scenes quite shady and hard to
reason about, and in addition, we'd lose things like concrete source
locations for every instance, the ability to annotate all instances with
Haddocks, etc.
So my opinion in that it's a huge amount of complexity for very little
gain and many drawbacks. I like the idea of doing something like this in
Template Haskell, so I'm glad that someone is pursuing this in #10607.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13368#comment:1>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list