Alternative instance for Compose

Asad Saeeduddin masaeedu at gmail.com
Thu Jul 16 02:00:22 UTC 2020


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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/libraries/attachments/20200715/cce7d8ab/attachment.html>


More information about the Libraries mailing list