
The alternate one can be written much more simply with
FlexibleContexts instead of QuantifiedConstraints:
instance Semigroup (f (g a)) => Semigroup (Compose f g a) where
Compose x <> Compose y = Compose (x <> y)
instance Monoid (f (g a)) => Monoid (Compose f g a) where
mempty = Compose mempty
That strikes me as the most natural way to do it. The lifting
instances are more naturally done using this oft-proposed type:
newtype Ap f a = Ap (f a)
instance (Applicative f, Semigroup a) => Semigroup (Ap f a) where
Ap x <> Ap y = Ap (liftA2 (<>) x y)
instance (Applicative f, Monoid a) => Monoid (Ap f a) where
mempty = pure mempty
Now Ap (Compose f g) a will do the lifting you want.
On Fri, Nov 30, 2018 at 4:13 PM Daniel Cartwright
Data.Functor.Compose:
newtype Compose f g a = Compose { getCompose :: f (g a) }
there's clear-cut, more traditional instances if `f` and `g` are Applicative:
instance (Applicative f, Applicative g, Semigroup a) => Semigroup (Compose f g a) where (<>) = liftA2 (<>)
instance (Applicative f, Applicative g, Monoid a) => Monoid (Compose f g a) where mempty = pure mempty
There's an alternative with `QuantifiedConstraints`, but it's arguable that this is desirable:
instance (forall x. Semigroup x => Semigroup (f x), forall x. Semigroup x => Semigroup (g x), Semigroup a) => Semigroup (Compose f g a) where Compose x <> Compose y = Compose (x <> y)
Both to seem to fit the commonplace spirit of lifting monoids up through applicative contexts. _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries