Skip to content

Explicitly define many and some in Alternative instance of Data.Functor.Compose #181

@jameshaydon

Description

@jameshaydon

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    approvedApproved by CLC votebase-4.20Implemented in base-4.20 (GHC 9.10)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions