From ghc/libraries/base/GHC/Base.hs
there is this recursive declaration:
... :: f a -> f [a]
...
many_v = some_v <|> pure []
some_v = liftA2 (:) v many_v -- (:) <$> v <*> many_v
The argument v
must be a value of a type that is instance of
Alternative
(and Applicative
and Functor
).
v
is lifted already and just needs to be applied (<*>
).
The application results in a lifted list.
some
and many
make recursive applications of the constructor of v
,
and put the constructed values into a list.
some
stops application, when the first empty
is constructed
many
continues application beyond that
[]
is instance of Alternative
:
instance Alternative [] where
empty = []
(<|>) = (++)
some
tries with list:
av = [[2], [2,3], [], [2,3,5]]
some av -- no error, but never stops
do {v <- some av; return v;} -- no error, but never stops
Comparing to letter
in
What are Alternative's "some" and "many" useful for?:
import Control.Monad(Functor(..))
import Control.Applicative
import Data.Char
newtype P a = P { runP :: String -> [(a,String)] }
instance Functor P where
fmap f (P q) = P (\s -> [ (f y,ys) | (y,ys) <- q s])
instance Applicative P where
pure x = P (\s -> [(x,s)])
P p <*> P q = P (\s -> [(x y, ys) | (x,xs) <- p s, (y,ys) <- q xs])
letter = P p where
p (x:xs) | isAlpha x = [(x,xs)]
p _ = []
instance Alternative P where
P p <|> P q = P (\s-> p s ++ q s)
empty = P (\s-> [])
with usage:
runP (many letter) "ab123"
letter
is a smart constructor, that
constructs a value of P
with field runP
using local variable p
.
(The result of the accessor) runP
is a function.
P
is a type implementing Alternative
as well as a constructor.
P
stands for parser.
fmap
is not used in some
and many
.
<*>
leads to an application of the function runP
,
whose argument is not yet here.
Basically some
and many
construct a program that will eat from its argument.
The argument must be a list.
Due to laziness the recursion stops at the first constructor.
p = some letter -- constructs a program accessed via @runP@
runP p "a1" -- [("a","1")]
q = some [2] -- basically also a program
q -- never stops
Recursive application is not empty
([]
for list),
because there is no source of criteria to stop, i.e. no input.
These stop:
some [] -- []
many [] -- [[]]
some Nothing -- Nothing
many Nothing -- Just []
There are more requirements on the argument of some
and many
(v
).
v
is value of a type that is instance of Alternative
.
- The recursive application of the constructor of the
v
type must stop with empty
.
v
must contain a function applied during construction with <*>
to have stop criteria.
Conclusion:
some
and many
cannot be applied to list values,
even though list implements Alternative
.
Why does list implement Alternative
?
I think, it is to add the Monoid
interface <|>
and empty
on top of Applicative
,
not because of some
and many
.
foldr (<|>) [] [[2],[],[3,4]] -- [2,3,4]
some
and many
seem to be just for parser construction
or more generally construction of a program consuming input
and producing more outputs, of which some can be empty
.
That is quite general already.
But the place in Alternative
is only justified,
if most of Alternative
instances have a sensible usage for it.
That is not the case.