Proposal: Add Semigroup/Monoid instance to Data.Functor.Compose

David Feuer david.feuer at gmail.com
Fri Nov 30 22:49:59 UTC 2018


The FlexibleContexts one is as general as possible. The
QuantifiedConstraints one is simultaneously less general and harder to
understand. I see no possible advantage.

On Fri, Nov 30, 2018, 5:25 PM Daniel Cartwright <chessai1996 at gmail.com
wrote:

> Ah, yeah, I see that now, in the "natural" comment. In that case I'm not
> sure if I prefer the version with FlexibleContexts or QuantifiedConstraints.
>
> On Fri, Nov 30, 2018, 5:18 PM David Feuer <david.feuer at gmail.com wrote:
>
>> I'm suggesting that the lifting instance is the *wrong one*. Lifting is
>> Ap's job. Compose is just for composing things.
>>
>> On Fri, Nov 30, 2018, 5:14 PM Daniel Cartwright <chessai1996 at gmail.com
>> wrote:
>>
>>> Yeah, the instance being defined with Ap is certainly a good way to go.
>>> We can use DerivingVia and Data.Monoid.Ap.
>>>
>>>
>>> On Fri, Nov 30, 2018, 4:55 PM David Feuer <david.feuer at gmail.com wrote:
>>>
>>>> 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 <
>>>> chessai1996 at gmail.com> wrote:
>>>> >
>>>> > 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 at haskell.org
>>>> > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>>>>
>>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/libraries/attachments/20181130/d4314049/attachment.html>


More information about the Libraries mailing list