Alternative instance for Compose

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

Alternative instance for Compose

Asad Saeeduddin

Hello folks,

base 4.14 has the following instance for `Compose f g`:

instance (Alternative f, Applicative g) => Alternative (Compose f g) where
    empty = Compose empty
    (<|>) = coerce ((<|>) :: f (g a) -> f (g a) -> f (g a))
      :: forall a . Compose f g a -> Compose f g a -> Compose f g a

This instance doesn't really do anything with the `Applicative g` constraint it is demanding. It's also kind of unclear what utility it delivers, given that the resulting Alternative instance is indistinguishable from the outer functor's Alternative instance. In other words: `getCompose $ Compose x <|> Compose y == x <|> y`.

It seems to me a more useful instance would be:

instance (Applicative f, Alternative g) => Alternative (Compose f g) where
    empty = Compose $ pure empty
    (<|>) = _ $ liftA2 (<|>)

This is also nicer in a mathematical sense: `Applicative` functors correspond to lax monoidal functors from `Hask, (- , -), ()` to `Hask, (-, -), ()`. We can interpret `Alternative`s as lax monoidal functors from `Hask, Either - -, Void` to `Hask, (-, -), ()`. Compatible lax monoidal functors compose, but if you think about the relevant "types" of the functors a bit, you'll realize that while we can compose an `Applicative` after an `Alternative` to get another `Alternative`, the reverse does not work. Hence the instance we have today, which has no choice but to just ignore the `Applicative` constraint it is demanding.

Does it make sense to replace the instance we have today with the `pure empty`, `liftA2 (<|>)` one?

Thanks,
Asad

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

Re: Alternative instance for Compose

Keith
With [], Maybe, and some other Alternative Functors, we have the nice property that empty <*> x = empty. (Think near-semiring.)

But with your lifted version, empty <*> Compose empty = Compose empty. The authentically empty 'empty' is still the true zero element.

-Keith

Sent from my phone with K-9 Mail.

On July 16, 2020 2:00:22 AM UTC, Asad Saeeduddin <[hidden email]> wrote:

Hello folks,

base 4.14 has the following instance for `Compose f g`:

instance (Alternative f, Applicative g) => Alternative (Compose f g) where
    empty = Compose empty
    (<|>) = coerce ((<|>) :: f (g a) -> f (g a) -> f (g a))
      :: forall a . Compose f g a -> Compose f g a -> Compose f g a

This instance doesn't really do anything with the `Applicative g` constraint it is demanding. It's also kind of unclear what utility it delivers, given that the resulting Alternative instance is indistinguishable from the outer functor's Alternative instance. In other words: `getCompose $ Compose x <|> Compose y == x <|> y`.

It seems to me a more useful instance would be:

instance (Applicative f, Alternative g) => Alternative (Compose f g) where
    empty = Compose $ pure empty
    (<|>) = _ $ liftA2 (<|>)

This is also nicer in a mathematical sense: `Applicative` functors correspond to lax monoidal functors from `Hask, (- , -), ()` to `Hask, (-, -), ()`. We can interpret `Alternative`s as lax monoidal functors from `Hask, Either - -, Void` to `Hask, (-, -), ()`. Compatible lax monoidal functors compose, but if you think about the relevant "types" of the functors a bit, you'll realize that while we can compose an `Applicative` after an `Alternative` to get another `Alternative`, the reverse does not work. Hence the instance we have today, which has no choice but to just ignore the `Applicative` constraint it is demanding.

Does it make sense to replace the instance we have today with the `pure empty`, `liftA2 (<|>)` one?

Thanks,
Asad

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