
I'm generally opposed to DefaultSignatures as an upside-down,
insufficiently-general attempt to solve an important problem, and generally
think the less relies on them the better.
On Oct 16, 2014 6:40 AM, "Herbert Valerio Riedel"
The Proposal ============
I hereby propose to merge `deepseq-generics`[2] into `deepseq`[1] in order to add Generics support to the `NFData` class based on the `-XDeriveGenerics` and `-XDefaultSignature` language extensions.
A concrete patch is available for bike-review at [3]
Prior Proposal & What's changed ===============================
About 2 years ago, I already proposed something similar[4]. Back then the major concern was avoiding a conditionally exported API as using the (back then) rather young `Generics` extension would leave the Haskell98 domain.
This lead to me release Generics support as a companion package[2] which turns out to have become a rather popular package (judging from the Hackage download-count stats).
I only realized after the discussion was effectively finished, that having a separate `deepseq-generics` actually does have an IMO non-neglectable downside:
You can't support a `DefaultSignature`-based default implementation, as those need to be backed into the `NFData` class.
Missing out on `DefaultSignature` would be a shame IMO, because
* There's a chance that starting with GHC 7.10 `deriving` may work for arbitrary classes[5], putting `NFData` on equal footing as built-in classes such as `Eq` or `Show`. Specifically, you would be able to write
data Foo = Foo [Int] String (Bool,Char) | Bar (Maybe Char) deriving (Show, Generic, NFData)
instead of having to manually write the following boilerplate
instance NFData Foo where rnf (Foo x y z) = rnf x `seq` rnf y `seq` rnf z rnf (Bar x) = rnf x
which gets tedious rather soon if you have many (and more complex) types and tend to refactor regularly (with a risk of failing to adapt your manual instances if you change the strictness of fields)
* The current default `rnf` implementation, i.e.
rnf a = a `seq` ()
is rather error-prone, as it's *very* easy to end up with an incorrect instance. Especially after refactoring a type for which the NF=WHNF assumption was broken after refactoring by adding new fields, or changing the strictness of existing fields.
The Generics-derived `rnf` implementation does not have such a problem.
Moreover, popular packages are starting adopt (and even recommend) the use of Generics in combination with `DefaultSignature` to provide automatically derived default instances, most notably `hashable`[6], `binary`[7], or `aeson`[8] just to name a few. In addition to providing a precedence for the use of Generics, I consider those packages evidence for Generics to have proven itself to the point of replacing TemplateHaskell in these use-cases.
Compatibility & Breakage Considerations =======================================
* This change requires a major version bump to deepseq-1.4.0
* `deepseq` needs to drop GHC 7.0.* support as GHC 7.2 is the first version to support Generics & `DefaultSignature`.
* Code relying on the current `rnf` default-implementation will most likely break (unless a `Generics` instance happens to be in-place)
However, it's easy to provide forward/backward-compatibility w/o any CPP, by simply explicitly defining
instance NFData XYZ where rnf = seq x ()
Discussion Period: 2 weeks
[1]: http://hackage.haskell.org/package/deepseq [2]: http://hackage.haskell.org/package/deepseq-generics [3]: https://github.com/haskell/deepseq/pull/1 [4]: http://thread.gmane.org/gmane.comp.lang.haskell.libraries/17940 [5]: https://ghc.haskell.org/trac/ghc/ticket/5462 [6]: http://hackage.haskell.org/package/hashable [7]: http://hackage.haskell.org/package/binary [8]: http://hackage.haskell.org/package/aeson _______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries