<div dir="ltr">Thanks for the clarification. I'd encourage you to start a separate discussion for coming up with a design for something better. Lets leave this thread for the smaller technical issue of merging an already well-liked extension (which I think is the best we can do in current Haskell) back into its main package.</div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Oct 16, 2014 at 5:03 PM, David Feuer <span dir="ltr"><<a href="mailto:david.feuer@gmail.com" target="_blank">david.feuer@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div><div><div><div><div><div>The important problem, as Edward Kmett would put it, is that Haskell is not good at dealing with lots of abstractions. In particular, making the typeclass hierarchy too fine-grained makes it painful to work with, because programmers have to satisfy the tower of superclass constraints in order to write an instance for a class. DefaultSignatures addresses this in a very limited way: If<br><br></div>A a => B a => C a => D a<br><br></div>then I may be able to give A, B, and C methods defaults with signatures so that I can declare an instance of D without needing to declare all the superclass instances. Unfortunately, this breaks down as soon as things branch:<br><br></div>A a => B a => C a => D a<br><br>||<br></div>V<br><br></div>E a => F a => G a<br><br></div>Both E and B may offer perfectly reasonable default definitions of a method in A, but I can only choose *one* of them. It also fails when class A is in someone else's module, and I'm doing a ton of work with subclasses of B and would like very much to add a default definition of a method in A, but simply can't. The current common use of DefaultSignatures is to use it *only* to provide defaults for Generic instances. While this single use-case works reasonably well, it effectively privileges Generic over everything else and leaves the general problem unsolved.<br><br></div><div>The sort of general solution I'd hope for would probably look something vaguely like this, but I imagine the type gurus might see problems:<br><br></div><div>Allow a *subclass* of a class to define (and override) default methods for the superclass. There is, of course, an immediate challenge: a single type could be a member of two subclasses, each of which defines a default for the same superclass method. The best solution I can think of to this is to require that such incoherent defaults be resolved manually by giving an explicit superclass instance declaration; ideally, that declaration would be able to access and choose from one of the available defaults, but that might be more trouble than it's worth.<br></div></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Oct 16, 2014 at 10:39 AM, José Pedro Magalhães <span dir="ltr"><<a href="mailto:dreixel@gmail.com" target="_blank">dreixel@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">I'd like to know exactly what is the important problem, and how DefaultSignatures are insufficiently general. Perhaps we can improve them, or come up with something better!</div><div class="gmail_extra"><br><div class="gmail_quote"><span>On Thu, Oct 16, 2014 at 2:36 PM, David Feuer <span dir="ltr"><<a href="mailto:david.feuer@gmail.com" target="_blank">david.feuer@gmail.com</a>></span> wrote:<br></span><div><div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><p dir="ltr">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.</p><div><div>
<div class="gmail_quote">On Oct 16, 2014 6:40 AM, "Herbert Valerio Riedel" <<a href="mailto:hvr@gnu.org" target="_blank">hvr@gnu.org</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
The Proposal<br>
============<br>
<br>
I hereby propose to merge `deepseq-generics`[2] into `deepseq`[1] in<br>
order to add Generics support to the `NFData` class based on the<br>
`-XDeriveGenerics` and `-XDefaultSignature` language extensions.<br>
<br>
A concrete patch is available for bike-review at [3]<br>
<br>
<br>
Prior Proposal & What's changed<br>
===============================<br>
<br>
About 2 years ago, I already proposed something similar[4].  Back then<br>
the major concern was avoiding a conditionally exported API as using the<br>
(back then) rather young `Generics` extension would leave the Haskell98<br>
domain.<br>
<br>
This lead to me release Generics support as a companion package[2] which<br>
turns out to have become a rather popular package (judging from the<br>
Hackage download-count stats).<br>
<br>
I only realized after the discussion was effectively finished, that<br>
having a separate `deepseq-generics` actually does have an IMO<br>
non-neglectable downside:<br>
<br>
  You can't support a `DefaultSignature`-based default implementation,<br>
as those need to be backed into the `NFData` class.<br>
<br>
Missing out on `DefaultSignature` would be a shame IMO, because<br>
<br>
 * There's a chance that starting with GHC 7.10 `deriving` may work for<br>
   arbitrary classes[5], putting `NFData` on equal footing as built-in<br>
   classes such as `Eq` or `Show`. Specifically, you would be able to<br>
   write<br>
<br>
      data Foo = Foo [Int] String (Bool,Char) | Bar (Maybe Char)<br>
                 deriving (Show, Generic, NFData)<br>
<br>
   instead of having to manually write the following boilerplate<br>
<br>
      instance NFData Foo where<br>
         rnf (Foo x y z) = rnf x `seq` rnf y `seq` rnf z<br>
         rnf (Bar x)     = rnf x<br>
<br>
   which gets tedious rather soon if you have many (and more complex)<br>
   types and tend to refactor regularly (with a risk of failing to adapt<br>
   your manual instances if you change the strictness of fields)<br>
<br>
<br>
 * The current default `rnf` implementation, i.e.<br>
<br>
     rnf a = a `seq` ()<br>
<br>
   is rather error-prone, as it's *very* easy to end up with an<br>
   incorrect instance. Especially after refactoring a type for which the<br>
   NF=WHNF assumption was broken after refactoring by adding new fields,<br>
   or changing the strictness of existing fields.<br>
<br>
   The Generics-derived `rnf` implementation does not have such a<br>
   problem.<br>
<br>
<br>
Moreover, popular packages are starting adopt (and even recommend) the<br>
use of Generics in combination with `DefaultSignature` to provide<br>
automatically derived default instances, most notably `hashable`[6],<br>
`binary`[7], or `aeson`[8] just to name a few. In addition to providing<br>
a precedence for the use of Generics, I consider those packages evidence<br>
for Generics to have proven itself to the point of replacing<br>
TemplateHaskell in these use-cases.<br>
<br>
<br>
Compatibility & Breakage Considerations<br>
=======================================<br>
<br>
 * This change requires a major version bump to deepseq-1.4.0<br>
<br>
 * `deepseq` needs to drop GHC 7.0.* support as GHC 7.2 is the first<br>
   version to support Generics & `DefaultSignature`.<br>
<br>
 * Code relying on the current `rnf` default-implementation will most<br>
   likely break (unless a `Generics` instance happens to be in-place)<br>
<br>
   However, it's easy to provide forward/backward-compatibility w/o any<br>
   CPP, by simply explicitly defining<br>
<br>
     instance NFData XYZ where rnf = seq x ()<br>
<br>
<br>
<br>
Discussion Period: 2 weeks<br>
<br>
<br>
<br>
 [1]: <a href="http://hackage.haskell.org/package/deepseq" target="_blank">http://hackage.haskell.org/package/deepseq</a><br>
 [2]: <a href="http://hackage.haskell.org/package/deepseq-generics" target="_blank">http://hackage.haskell.org/package/deepseq-generics</a><br>
 [3]: <a href="https://github.com/haskell/deepseq/pull/1" target="_blank">https://github.com/haskell/deepseq/pull/1</a><br>
 [4]: <a href="http://thread.gmane.org/gmane.comp.lang.haskell.libraries/17940" target="_blank">http://thread.gmane.org/gmane.comp.lang.haskell.libraries/17940</a><br>
 [5]: <a href="https://ghc.haskell.org/trac/ghc/ticket/5462" target="_blank">https://ghc.haskell.org/trac/ghc/ticket/5462</a><br>
 [6]: <a href="http://hackage.haskell.org/package/hashable" target="_blank">http://hackage.haskell.org/package/hashable</a><br>
 [7]: <a href="http://hackage.haskell.org/package/binary" target="_blank">http://hackage.haskell.org/package/binary</a><br>
 [8]: <a href="http://hackage.haskell.org/package/aeson" target="_blank">http://hackage.haskell.org/package/aeson</a><br>
_______________________________________________<br>
Libraries mailing list<br>
<a href="mailto:Libraries@haskell.org" target="_blank">Libraries@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/libraries" target="_blank">http://www.haskell.org/mailman/listinfo/libraries</a><br>
</blockquote></div>
</div></div><br>_______________________________________________<br>
Libraries mailing list<br>
<a href="mailto:Libraries@haskell.org" target="_blank">Libraries@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/libraries" target="_blank">http://www.haskell.org/mailman/listinfo/libraries</a><br>
<br></blockquote></div></div></div><br></div>
</blockquote></div><br></div>
</div></div><br>_______________________________________________<br>
Libraries mailing list<br>
<a href="mailto:Libraries@haskell.org">Libraries@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/libraries" target="_blank">http://www.haskell.org/mailman/listinfo/libraries</a><br>
<br></blockquote></div><br></div>