-
Notifications
You must be signed in to change notification settings - Fork 16
Description
Currently the Alternative
instance for Compose f g
is:
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
The some
and many
methods thus get their default definitions. If f
has an explicit definition for some
or many
in Alternative f
, then this gets ignored. If they are more efficient than the defaults, then this efficiency is discarded in Alternative (Compose f g)
.
In some cases, the resulting some
and many
in Alternative (Compose f g)
are completely broken. This occured to me with
(Monoid ann) => Alternative (Compose (Prod r e t) ((,) ann))
where Prod r e t
is from Earley. In the case of Earley, some
and many
have special case definitions, and using the default definitions instead results in infinite loops.
I propose the following definitions for some
and many
:
some :: (Alternative f, Applicative g) => Compose f g a -> Compose f g [a]
some (Compose v) = Compose (sequenceA <$> some v)
many :: (Alternative f, Applicative g) => Compose f g a -> Compose f g [a]
many (Compose v) = Compose (sequenceA <$> many v)
These definitions make sure to use the implementations of some
and many
from Alternative f
.
A related (accepted) proposal adds explicit definitions to Foldable (Compose f g)
: #57