
* Might it be simpler to treat the bespoke -> newtype optimization as a
#10598: DeriveAnyClass and GND don't work well together -------------------------------------+------------------------------------- Reporter: osa1 | Owner: RyanGlScott Type: bug | Status: patch Priority: normal | Milestone: 8.2.1 Component: Compiler | Version: 7.11 Resolution: | Keywords: Generics Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D2280 Wiki Page: | -------------------------------------+------------------------------------- Comment (by RyanGlScott): oerjan, hopefully this answers all of your questions: Replying to [comment:42 oerjan]: post-step, independent of the rest? Or is it ever important ''not'' to apply it? Even for step 1. Yes, there are cases where you don't want to replace the `bespoke` strategy with the `newtype` one. Consider the following example: {{{#!hs newtype Foo a = Foo (Maybe a) }}} What would happen if you tried implementing a `Traversable` instance for `Foo`? As it turns out, trying to define `traverse = coerce` is impossible at the moment: {{{ • Couldn't match representation of type ‘f (Maybe b)’ with that of ‘f (Foo b)’ arising from the coercion of the method ‘traverse’ from type ‘forall (f :: * -> *) a b. Applicative f => (a -> f b) -> Maybe a -> f (Maybe b)’ to type ‘forall (f :: * -> *) a b. Applicative f => (a -> f b) -> Foo a -> f (Foo b)’ NB: We cannot know what roles the parameters to ‘f’ have; we must assume that the role is nominal • When deriving the instance for (Traversable Foo) }}} This is because the type signature of `traverse` leads to an ill-roled coercion (see [https://ghc.haskell.org/trac/ghc/wiki/Roles#RolesandTraversable here] for the full story). Until #9123 is fixed, GHC will refuse to apply the `newtype` strategy to derived `Traversable` instances (unless you explicitly ask for it). BTW, the full list of classes that GHC avoids using the `newtype` strategy for can be found [http://git.haskell.org/ghc.git/blob/8ecac2512aed557b4f59fd697eabd3ef9ddfd6e9... here].
* Is 2(a) missing `Enum`?
No. The full list of "standard" classes for which `newtype` kicks in by default (without the presence of `-XGeneralizedNewtypeDeriving`) can be found [http://git.haskell.org/ghc.git/blob/8ecac2512aed557b4f59fd697eabd3ef9ddfd6e9... here]. As the comments there indicate, `Enum` isn't in that list because by default, deriving `Enum` for a newtype would fail since it checks for a datatype with all nullary constructors. Therefore, you have to enable `-XGeneralizedNewtypeDeriving` (or use the `newtype` keyword) to derive `Enum` for a newtype.
* Why is `Traversable` in 2(b)? I would have thought that the bespoke -> newtype optimization would apply to it. I guess there's some technical difference.
* All the examples in 2(c) are listed in a or b, leaving the strange impression that it can never be triggered. Although I assume `Functor` and `Foldable` belong there. (Which also tells me the last paragraph in my
* The phrase "can be successfully used with GeneralizedNewtypeDeriving" is needed in 2(c) as well. Should 2(d) apply or not if that check falls? If it does then sometimes standard classes ''could'' get anyclassed. If it does ''not'', then should the classes fall back to bespoke, at least if
* It seems that `Functor` and `Foldable` never get newtype derived if
See my answer above. previous comment has been taken care of). Sorry, I should have explicitly enumerated the remaining classes not listed in 2(a) or 2(b). They are `Functor`, `Foldable`, and `Enum`. their extensions are enabled? Yes, I should use that phrase, thank you for noticing that omission. I certainly don't want standard classes to be derived with the `anyclass` strategy. that extension is not enabled, even when it would be safe to do so. You have to explicitly enable `-XGeneralizedNewtypeDeriving` to derive `Functor` or `Foldable` that way because, by default, deriving them is guarded behind `-XDeriveFunctor` and `-XDeriveFoldable`. You can't just say `newtype Foo a = Foo (Maybe a) deriving Functor` and expect it to work without extensions, unlike `Eq`, `Ord`, `Ix`, and `Bounded`.
I think the algorithm can be simplified a bit: remove point 2(c) entirely, and say explicitly in point 2(d) that it ''doesn't'' apply to standard derivable classes.
I disagree. 2(a), (b), and (c) are all special cases for standard derivable classes, each with enough nuances that trying to cram one of them into 2(d) would make it even more confusing (than it already is).
Lastly, while thinking about this, I made a table of the (currently four-way) classification of the "standard/bespoke" classes:
Thank you, this is fantastic! I've updated the wiki page with the corrections above and incorporating your table (with some slight corrections). -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10598#comment:43 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler