From the class's name and usage in parsers and with Maybe
I thought that it's behaviour would be to choose the first non-empty input from a <|> b <|> c
. So I expected that for input
[] <|> [1] <|> [2, 3]
it would return the first non-empty list, i.e.:
[1]
but it actually just concats the whole thing, producing:
[1,2,3]
So I am wondering what's the reasoning behind such an implementation? Is it actually correct?
P.S. Is there any standard function that does what I expected from Alternative
?
When implementing an
Alternative f
(orMonadPlus f
) instance, you have to select a monoid overf a
and implement it usingempty
and<|>
. For some structures, such as lists, there can be several possibilities. The most natural monoidal operation for lists is their concatenation (with[]
being the identity element). Taking the first non-empty element, as you suggest, is also a possibility, but not as natural for lists. Your operation almost ignores the structure (the length) of lists, it only checks if a list is empty or not. And it doesn't add anything new, because this kind of monoidal operation is already available asMaybe
's instance ofAlternative
, which is designed to represent (non)empty values.This is also reflected in the instance of
MonadPlus
of[]
. As described on HaskellWiki, there are two possible sets of laws for instances ofMonadPlus
:[]
Maybe
,IO
andSTM
.If we chose your implementation of
Alternative
andMonadPlus
, then we'd have only instances satisfying... + LeftCatch
, nothing satisfying LeftDistribution. And again,MonadPlus
of[]
wouldn't be very different fromMonadPlus
ofMaybe
. And we wouldn't have anything that would enable us to solve things like the send+more=money puzzle. So it's much more interesting to choose themplus
/<|>
of[]
to be concatenation.