Proposal: Add a Semigroup-equivalent superclass of Alternative
Mario Blažević
blamario at ciktel.net
Sun Apr 5 15:05:20 UTC 2015
On 03/29/2015 08:20 AM, Jeremy wrote:
> The proposal to make Semigroup a superclass of Monoid was discussed a while
> ago [1], and the conclusion was to "put this off until the dust has settled
> from the AMP and FT changes".
It has occurred to me that the Alternative class, which is pretty
much a constructor version of Monoid, would benefit from the same
treatment. The greatest difficulty seems to be in finding the name for
the Semigroup-equivalent superclass of Alternative. For lack of
imagination,I'll just call it Semigroup1:
class Applicative f => Semigroup1 f where
(<|>) :: f a -> f a -> f a
some :: f a -> f [a]
many :: f a -> f [a]
class Semigroup1 f => Alternative f where
empty :: f a
The rationale for this change:
1. All the theoretical arguments for introducing Semigroup carry over
with no change.
2. There are existing data types that could be made instances of
Semigroup1, and not of Alternative. I have not performed any
comprehensive survey, but QuickCheck's Gen type can provide one example:
instance Semigroup1 Gen where
f <|> g = oneof [f, g]
3. Most interesting instances of Alternative are various parser types. A
parser type that doesn't define empty is a parser that cannot fail by
construction. That makes intuitive sense. I can imagine some benefits
from a set of parser combinators that generated two types, only one of
which could fail. Fill in the blanks:
instance Semigroup1 IrrefutableParser
instance Alternative Parser
token :: a -> Parser a
optional :: Parser a -> IrrefutableParser (Maybe a)
many0 :: Parser a -> IrrefutableParser [a]
There are, of course, two important differences between the Monoid
and Alternative situation. First, the Semigroup class already exists, if
not in base. That only means the proposal outlined above requires more
critique and bikeshedding.
The other difference is that the Semigroup operator (<>) is
different from the Monoid operator mappend. This is mostly an
unfortunate backward compatibility issue, but it does have a benefit of
allowing the two classes to exist independently for a while before they
are brought together. If we really, *really* desire the same doubtful
benefit for Alternative, we can use a new operator name for the
Semigroup1 class (I refuse to provide one in this proposal) and then
eventually stipulate (<|>) = i-refuse-to-provide-one-in-this-proposal.
My preference, if available, would be to just move the <|> operator
into the superclass in 7.12. It's such a perfect operator name. Without
a new GHC extension, however, this would mean that every existing
instance of Alternative would be broken in 7.12. Furthermore, there
would be no way to write an Alternative instance valid in both 7.10 and
7.12 without CPP directives. The only saving grace here is that the
Alternative instances are relatively few, and it may just be possible to
coordinate all the changes.
So, here's a question to all authors of parser libraries and
everybody else that has defined Alternative instances: would you be able
and willing to add CPP directives to your code for this purpose?
For everybody else: this is a proposal, so vote on it.
More information about the Libraries
mailing list