Li-yao Xia
2018-02-20 23:51:26 UTC
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
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