[PROPOSAL] Adding Generics-based DefaultSignature to `deepseq` package

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
13 messages Options
Reply | Threaded
Open this post in threaded view
|

[PROPOSAL] Adding Generics-based DefaultSignature to `deepseq` package

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
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: [PROPOSAL] Adding Generics-based DefaultSignature to `deepseq` package

José Pedro Magalhães-3


On Thu, Oct 16, 2014 at 11:39 AM, Herbert Valerio Riedel <[hidden email]> wrote:

 * 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`.

A very high chance, I hope! :-)

I'm all in favour of this proposal.


Cheers,
Pedro



_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: [PROPOSAL] Adding Generics-based DefaultSignature to `deepseq` package

Bardur Arantsson-2
In reply to this post by Herbert Valerio Riedel
On 2014-10-16 12:39, Herbert Valerio Riedel wrote:

>
> 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]
>

+1


_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: [PROPOSAL] Adding Generics-based DefaultSignature to `deepseq` package

David Feuer
In reply to this post by Herbert Valerio Riedel

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" <[hidden email]> wrote:

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
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: [PROPOSAL] Adding Generics-based DefaultSignature to `deepseq` package

Johan Tibell-2
Could you elaborate on this? What other existing options are better?

On Thu, Oct 16, 2014 at 3:36 PM, David Feuer <[hidden email]> wrote:

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" <[hidden email]> wrote:

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
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries



_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: [PROPOSAL] Adding Generics-based DefaultSignature to `deepseq` package

David Feuer

I don't know that any existing options *are* better.

On Oct 16, 2014 9:52 AM, "Johan Tibell" <[hidden email]> wrote:
Could you elaborate on this? What other existing options are better?

On Thu, Oct 16, 2014 at 3:36 PM, David Feuer <[hidden email]> wrote:

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" <[hidden email]> wrote:

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
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries



_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: [PROPOSAL] Adding Generics-based DefaultSignature to `deepseq` package

José Pedro Magalhães-3
In reply to this post by David Feuer
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!

On Thu, Oct 16, 2014 at 2:36 PM, David Feuer <[hidden email]> wrote:

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" <[hidden email]> wrote:

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
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries



_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: [PROPOSAL] Adding Generics-based DefaultSignature to `deepseq` package

David Feuer
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

A a => B a => C a => D a

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:

A a => B a => C a => D a

||
V

E a => F a => G a

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.

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:

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.

On Thu, Oct 16, 2014 at 10:39 AM, José Pedro Magalhães <[hidden email]> wrote:
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!

On Thu, Oct 16, 2014 at 2:36 PM, David Feuer <[hidden email]> wrote:

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" <[hidden email]> wrote:

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
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries




_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: [PROPOSAL] Adding Generics-based DefaultSignature to `deepseq` package

Johan Tibell-2
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.

On Thu, Oct 16, 2014 at 5:03 PM, David Feuer <[hidden email]> wrote:
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

A a => B a => C a => D a

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:

A a => B a => C a => D a

||
V

E a => F a => G a

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.

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:

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.

On Thu, Oct 16, 2014 at 10:39 AM, José Pedro Magalhães <[hidden email]> wrote:
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!

On Thu, Oct 16, 2014 at 2:36 PM, David Feuer <[hidden email]> wrote:

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" <[hidden email]> wrote:

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
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries




_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries



_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: [PROPOSAL] Adding Generics-based DefaultSignature to `deepseq` package

Erik Hesselink
In reply to this post by David Feuer
This reminds me of the default superclass instances proposals that
people are working on. I found three different ones on the GHC trac
[1,2,3].

Erik

[1] https://ghc.haskell.org/trac/ghc/wiki/DefaultSuperclassInstances
[2] https://ghc.haskell.org/trac/ghc/wiki/IntrinsicSuperclasses
[3] https://ghc.haskell.org/trac/ghc/wiki/InstanceTemplates


On Thu, Oct 16, 2014 at 5:03 PM, David Feuer <[hidden email]> wrote:

> 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
>
> A a => B a => C a => D a
>
> 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:
>
> A a => B a => C a => D a
>
> ||
> V
>
> E a => F a => G a
>
> 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.
>
> 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:
>
> 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.
>
> On Thu, Oct 16, 2014 at 10:39 AM, José Pedro Magalhães <[hidden email]>
> wrote:
>>
>> 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!
>>
>> On Thu, Oct 16, 2014 at 2:36 PM, David Feuer <[hidden email]>
>> wrote:
>>>
>>> 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" <[hidden email]> wrote:
>>>>
>>>>
>>>> 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
>>>> [hidden email]
>>>> http://www.haskell.org/mailman/listinfo/libraries
>>>
>>>
>>> _______________________________________________
>>> Libraries mailing list
>>> [hidden email]
>>> http://www.haskell.org/mailman/listinfo/libraries
>>>
>>
>
>
> _______________________________________________
> Libraries mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/libraries
>
_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: [PROPOSAL] Adding Generics-based DefaultSignature to `deepseq` package

Andres Löh-3
In reply to this post by 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]

+1

Cheers,
  Andres
_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: [PROPOSAL] Adding Generics-based DefaultSignature to `deepseq` package

Edward Kmett-2
On one hand, the change is a path to a better deepseq that is more correct.

On the other hand 

1.) It does change the semantics of existing code. 

2.) It does cause existing code that works to break if they don't supply a Generic instance or a manual default.

Admittedly: 

#1 happens by making it more strict, which is what we want in the case of NFData, for once.
#2 is something that is easily rectified and makes the resulting code more robust/useful anyways. Folks who don't want to lean on generics have the option to just write the rnf x = seq x () default, so nobody is being forced to lean on the extension.

I'm somewhat on the fence about this, because I don't like silent semantics changes, but as it is only happening by making things more strict in the one place in the language where that is the very point, you can consider me weakly +1.

-Edward


On Thu, Oct 16, 2014 at 1:09 PM, Andres Löh <[hidden email]> wrote:
> 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]

+1

Cheers,
  Andres
_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries


_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: [PROPOSAL] Adding Generics-based DefaultSignature to `deepseq` package

Andreas Abel
I am +1 on this change.  I was naively under the wrong impression that a
simple

   instance NFData Bla

is enough already with the current package.  I would be nice if it
worked, and the proposal seems to achieve this (at least if one derives
Generic).

--Andreas

On 16.10.2014 21:41, Edward Kmett wrote:

> On one hand, the change is a path to a better deepseq that is more correct.
>
> On the other hand
>
> 1.) It does change the semantics of existing code.
>
> 2.) It does cause existing code that works to break if they don't supply
> a Generic instance or a manual default.
>
> Admittedly:
>
> #1 happens by making it more strict, which is what we want in the case
> of NFData, for once.
> #2 is something that is easily rectified and makes the resulting code
> more robust/useful anyways. Folks who don't want to lean on generics
> have the option to just write the rnf x = seq x ()default, so nobody is
> being forced to lean on the extension.
>
> I'm somewhat on the fence about this, because I don't like silent
> semantics changes, but as it is only happening by making things more
> strict /in the one place in the language/ where that is the very point,
> you can consider me weakly +1.
>
> -Edward
>
>
> On Thu, Oct 16, 2014 at 1:09 PM, Andres Löh <[hidden email]
> <mailto:[hidden email]>> wrote:
>
>     > 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]
>
>     +1
>
>     Cheers,
>        Andres
>     _______________________________________________
>     Libraries mailing list
>     [hidden email] <mailto:[hidden email]>
>     http://www.haskell.org/mailman/listinfo/libraries
>
>
>
>
> _______________________________________________
> Libraries mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/libraries
>


--
Andreas Abel  <><      Du bist der geliebte Mensch.

Department of Computer Science and Engineering
Chalmers and Gothenburg University, Sweden

[hidden email]
http://www2.tcs.ifi.lmu.de/~abel/
_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries