Proposal: Add Applicative (and Monoid) instances in GHC.Generics

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

Proposal: Add Applicative (and Monoid) instances in GHC.Generics

Li-yao Xia-2
I propose to implement Applicative (and Monoid) instances in
GHC.Generics, where possible.

Note that we already have Applicative instances for most of those types,
with the notable exceptions of sums (:+:) (for good reason), and K1
(which is basically Const).

This would make it possible to easily derive Applicative and Monoid for
generic product types. That can be useful to merge large configuration
records, for example.

For that purpose, the missing Applicative instance for K1 is the actual
limiting factor, as it is sufficient in order to derive the product
Monoid and Applicative via Generic and Generic1, respectively. The
Monoid instances for the GHC.Generics constructors might just be fluff
on top of this.

Current alternatives include: roll your own, semigroups [1], or some
generic programming library (e.g., one-liner). This proposal offers a
more lightweight solution.

To summarize, and to organize bikeshedding, I would split this proposal
in three parts, in order of perceived usefulness:

1. Add an instance (Monoid c => Applicative (K1 i c))

2. Add helpers

         gmempty :: (Generic a, Applicative (Rep a)) => a
         gmempty = to (pure ())

         gmappend :: (Generic a, Applicative (Rep a)) => a -> a -> a
         gmappend a b = to (from a <*> from b)

         -- also gpure, gap for generic Applicative

3. Add Monoid instances

Regards,
Li-yao


[1]
https://hackage.haskell.org/package/semigroups-0.18.4/docs/Data-Semigroup-Generic.html

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

Re: Proposal: Add Applicative (and Monoid) instances in GHC.Generics

Ryan Scott
In response to each of your proposals:

> 1. Add an instance (Monoid c => Applicative (K1 i c))

This seems like a no-brainer to me. +1

> 2. Add helpers
>
>          gmempty :: (Generic a, Applicative (Rep a)) => a
>          gmempty = to (pure ())
>
>          gmappend :: (Generic a, Applicative (Rep a)) => a -> a -> a
>          gmappend a b = to (from a <*> from b)
>
>          -- also gpure, gap for generic Applicative

I'm weakly -1 on this. I don't think GHC.Generics should be a place
where we collect combinators for generically implementing various type
class methods. I'd prefer that these be left to downstream libraries,
especially since they're usually extremely straightforward to
implement and wouldn't cross the Fairbairn threshold for me.

> 3. Add Monoid instances

I think I support this idea. But just to be sure we're on the same
page: can you say which instances in particular you're adding, and how
you'd implement them?

Ryan S.
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add Applicative (and Monoid) instances in GHC.Generics

Oleg Grenrus
For helpers see `semigroups` package, Data.Semigroup.Generic module [1]

I indeed don't see strong argument for moving them into `base`, only if
we want to provide default `Generic` implementations for `Semigroup` &
`Monoid`. I'm not sure we do?

Oleg

[1]
http://hackage.haskell.org/package/semigroups-0.18.4/docs/Data-Semigroup-Generic.html

On 21.02.2018 20:16, Ryan Scott wrote:

> In response to each of your proposals:
>
>> 1. Add an instance (Monoid c => Applicative (K1 i c))
> This seems like a no-brainer to me. +1
>
>> 2. Add helpers
>>
>>          gmempty :: (Generic a, Applicative (Rep a)) => a
>>          gmempty = to (pure ())
>>
>>          gmappend :: (Generic a, Applicative (Rep a)) => a -> a -> a
>>          gmappend a b = to (from a <*> from b)
>>
>>          -- also gpure, gap for generic Applicative
> I'm weakly -1 on this. I don't think GHC.Generics should be a place
> where we collect combinators for generically implementing various type
> class methods. I'd prefer that these be left to downstream libraries,
> especially since they're usually extremely straightforward to
> implement and wouldn't cross the Fairbairn threshold for me.
>
>> 3. Add Monoid instances
> I think I support this idea. But just to be sure we're on the same
> page: can you say which instances in particular you're adding, and how
> you'd implement them?
>
> Ryan S.
> _______________________________________________
> Libraries mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries


_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

signature.asc (836 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add Applicative (and Monoid) instances in GHC.Generics

Edward Kmett-2
In reply to this post by Ryan Scott
+1 for adding the instances.

I'm fairly neutral on the helpers.

-Edward

On Wed, Feb 21, 2018 at 1:16 PM, Ryan Scott <[hidden email]> wrote:
In response to each of your proposals:

> 1. Add an instance (Monoid c => Applicative (K1 i c))

This seems like a no-brainer to me. +1

> 2. Add helpers
>
>          gmempty :: (Generic a, Applicative (Rep a)) => a
>          gmempty = to (pure ())
>
>          gmappend :: (Generic a, Applicative (Rep a)) => a -> a -> a
>          gmappend a b = to (from a <*> from b)
>
>          -- also gpure, gap for generic Applicative

I'm weakly -1 on this. I don't think GHC.Generics should be a place
where we collect combinators for generically implementing various type
class methods. I'd prefer that these be left to downstream libraries,
especially since they're usually extremely straightforward to
implement and wouldn't cross the Fairbairn threshold for me.

> 3. Add Monoid instances

I think I support this idea. But just to be sure we're on the same
page: can you say which instances in particular you're adding, and how
you'd implement them?

Ryan S.
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries


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

Re: Proposal: Add Applicative (and Monoid) instances in GHC.Generics (Libraries Digest, Vol 174, Issue 27)

Li-yao Xia-2
In reply to this post by Ryan Scott
Thanks everyone. So there is agreement on having Applicative and Monoid
instances, and on not having additional helpers for generic deriving.
That's fine to me.

Replying to Ryan:

>> 3. Add Monoid instances
>
> I think I support this idea. But just to be sure we're on the same
> page: can you say which instances in particular you're adding, and how
> you'd implement them?

The main Monoid instances would be:

Monoid (f p) => Monoid (M1 i c f p)  -- newtype-derived
Monoid a => Monoid (K1 i a p)  -- newtype-derived
(Monoid (f p), Monoid (g p)) => Monoid ((f :*: g) p)  -- product monoid
Monoid (U1 p)  -- unit-like

No instance for (:+:).

Now that you mention it, I'm not sure about adding Monoid instances for
the type constructors involved in Generic1, they would be (all
newtype-derived):

Monoid p => Monoid (Par1 p)
Monoid (f p) => Monoid (Rec1 f p)
Monoid (f (g p)) => Monoid ((f :.: g) p)

Is ther an opinion against that?

I forgot to mention Semigroup instances. They would follow the same
structure, and for completeness we can also have

Semigroup (V1 p)

This enables a more general "generic semigroup" than via Applicative.

Li-yao
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add Applicative (and Monoid) instances in GHC.Generics (Libraries Digest, Vol 174, Issue 27)

Ryan Scott
Those Monoid instances (and Semigroup instance for V1) you propose
sound reasonable.

I'd also be fine with adding Monoid instances for Par1, Rec1, and
(:.:), since we already define other instances like Eq, Ord, Read, and
Show for them. Besides, if we don't add them this time around, someone
else will just ask for them later :)

Ryan S.
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries