<div dir="auto"><div>Yeah, the instance being defined with Ap is certainly a good way to go. We can use DerivingVia and Data.Monoid.Ap.</div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote" dir="auto"><div dir="ltr">On Fri, Nov 30, 2018, 4:55 PM David Feuer <<a href="mailto:david.feuer@gmail.com">david.feuer@gmail.com</a> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">The alternate one can be written much more simply with<br>
FlexibleContexts instead of QuantifiedConstraints:<br>
<br>
instance Semigroup (f (g a)) => Semigroup (Compose f g a) where<br>
  Compose x <> Compose y = Compose (x <> y)<br>
instance Monoid (f (g a)) => Monoid (Compose f g a) where<br>
  mempty = Compose mempty<br>
<br>
That strikes me as the most natural way to do it. The lifting<br>
instances are more naturally done using this oft-proposed type:<br>
<br>
newtype Ap f a = Ap (f a)<br>
instance (Applicative f, Semigroup a) => Semigroup (Ap f a) where<br>
  Ap x <> Ap y = Ap (liftA2 (<>) x y)<br>
instance (Applicative f, Monoid a) => Monoid (Ap f a) where<br>
  mempty = pure mempty<br>
<br>
Now Ap (Compose f g) a will do the lifting you want.<br>
<br>
On Fri, Nov 30, 2018 at 4:13 PM Daniel Cartwright <<a href="mailto:chessai1996@gmail.com" target="_blank" rel="noreferrer">chessai1996@gmail.com</a>> wrote:<br>
><br>
> Data.Functor.Compose:<br>
><br>
> newtype Compose f g a = Compose { getCompose :: f (g a) }<br>
><br>
> there's clear-cut, more traditional instances if `f` and `g` are Applicative:<br>
><br>
> instance (Applicative f, Applicative g, Semigroup a) => Semigroup (Compose f g a) where<br>
>   (<>) = liftA2 (<>)<br>
><br>
> instance (Applicative f, Applicative g, Monoid a) => Monoid (Compose f g a) where<br>
>   mempty = pure mempty<br>
><br>
> There's an alternative with `QuantifiedConstraints`, but it's arguable that this is desirable:<br>
><br>
> instance (forall x. Semigroup x => Semigroup (f x), forall x. Semigroup x => Semigroup (g x), Semigroup a) => Semigroup (Compose f g a) where<br>
>   Compose x <> Compose y = Compose (x <> y)<br>
><br>
> Both to seem to fit the commonplace spirit of lifting monoids up through applicative contexts.<br>
> _______________________________________________<br>
> Libraries mailing list<br>
> <a href="mailto:Libraries@haskell.org" target="_blank" rel="noreferrer">Libraries@haskell.org</a><br>
> <a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries" rel="noreferrer noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries</a><br>
</blockquote></div></div></div>