Automatically deriving Generic for every algebraic data type
Andres Löh
andres.loeh at gmail.com
Thu Feb 4 14:27:16 UTC 2016
I agree with Ryan on this, i.e., a general automatic DeriveGeneric
would not be a good idea right now. Note also that it is already the
case that if you want to derive certain classes, you may have to
derive other classes as well, namely if superclasses are involved. So
you cannot say "deriving Ord", but rather have to say "deriving (Eq,
Ord)". In this sense, I don't think the situation with "Serialize" is
that much worse.
An AutoDeriveGeneric language extension that can be enabled for
particular modules might be a possible compromise I could live with.
I think it is worth thinking more generally about a replacement for
"deriving" that has the chance of making different approaches feel
more similar. I'm not overly happy with the current situation wrt
DeriveAnyClass and the way conflicts between built-in, newtype- and
anyclass-deriving are resolved.
Cheers,
Andres
On Thu, Feb 4, 2016 at 3:20 PM, Ryan Scott <ryan.gl.scott at gmail.com> wrote:
> I'm a pretty solid -1 on this idea.
>
> On a general level, I'm opposed to the idea of deriving typeclasses
> without the programmer opting in. Most typeclasses express operations
> that your datatype must support, and in the case of Generic(1), it
> mandates that users can convert between values of your datatype and an
> isomorphic representation type. As Oleg noted, this completely
> destroys encapsulation for datatypes whose constructors you don't want
> to export.
>
> Another issue is the nontrivial cost of automatic derivation.
> Typeclasses can be surprisingly expensive to derive. About a year ago,
> Reid Barton measured the amount of increase in code size that each
> derivable typeclass contributes [1], and Generic was far and away the
> most expensive one. There's also the issue that deriving Generic on
> large datatypes can drastically increase the amount of memory needed
> during compilation [2].
>
> Yet another problem is that deriving Generic1 simply doesn't work for
> every datatype. Not only does deriving Generic1 not work with
> sophisticated language features (e.g., -XExistentialQuantification
> [3]) by design, but there are still a number of outstanding bugs that
> prevent legitimate Generic1 from being deriving automatically. For
> example, the following datatype:
>
> newtype Compose (f :: k1 -> *) (g :: k2 -> k1) (a :: k2) = Compose (f (g a))
>
> chokes when attempting to derive Generic1 automatically [4]. You have
> to hack around this by using -XStandaloneDeriving with a
> programmer-specified instance context.
>
> One could imagine a compromise in which Generic(1) would not be
> derived for datatypes for which attempting to derive those classes
> yields an error. But I would argue that this is very undesirable,
> since programmers would just expect every datatype to work out of the
> box with Generic(1), only to find "Cannot find instance Generic1
> Compose"-like errors when they try using Generic1 operations on
> datatypes that trip the bug mentioned in [4].
>
> There are exceptions to the don't-derive-typeclasses-automatically
> rule, with Typeable being a notable example [5]. But deriving Typeable
> has the benefit that (1) it doesn't impose many requirements on your
> datatype (other than you can get a TypeRep for it), (2) it's cheap to
> derive (see the table in [1]), and (3) it works on literally every
> datatype.
>
> Ryan S.
> -----
> [1] https://ghc.haskell.org/trac/ghc/ticket/9557#comment:8
> [2] https://ghc.haskell.org/trac/ghc/ticket/5642
> [3] https://ghc.haskell.org/trac/ghc/ticket/10514
> [4] https://ghc.haskell.org/trac/ghc/ticket/10524#comment:16
> [5] https://ghc.haskell.org/trac/ghc/ticket/8950
> _______________________________________________
> ghc-devs mailing list
> ghc-devs at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
More information about the ghc-devs
mailing list