Alternative
With Alternative, we get some useful combinators from the base libraries for free:
code:manysome.hs
many, some :: Alternative f => f a -> f a (many means “zero or more occurences”, the *-operator,
some means “one or more occurences”.)
Furthermore, we get
code:optional.hs
optional :: Alternative f => f a -> f (Maybe a)
for optional values.
code:phone.hs
phone :: Person -> Maybe Phone phone p = case personHomePhone p of
Just x -> Just x
Nothing -> personWorkPhone p
-- Can be rewritten into
phone :: Person -> Maybe Phone
phone p = personHomePhone p <|> personWorkPhone p
code:maybe.hs
instance Alternative Maybe where empty :: Maybe a
empty = Nothing
(<|>) :: Maybe a -> Maybe a -> Maybe a Just a <|> _ = Just a
Nothing <|> b = b
code:list.hs
instance Alternative [] where empty :: a empty = []
(<|>) :: a -> a -> a (<|>) = (++) guard in Control.Applicative works as filter
code:guard.hs
guard :: Alternative f => Bool -> f ()
guard False = empty
guard True = pure()
code:example.hs
myFilter :: (a -> Bool) -> a -> a myFilter p xs = do
x <- xs
guard (p x)
return x
MonadPlus
code:monadplus.hs
class (Alternative m, Monad m) => MonadPlus m where
mzero :: m a
mplus :: m a -> m a -> m a
Alternative is to Applicative as MonadPlus is to Monad
Often we have
code:monadplus.hs
mzero = empty
mplus = (<|>)
Maybe and Lists are instances of MonadPlus, too.
The Functor and Applicative instances immediately give us other useful combinators:
code:something.hs
(<$) :: a -> Parser b -> Parser a
(<*) :: Parser a -> Parser b -> Parser a
(*>) :: Parser a -> Parser b -> Parser b
These are useful when we don’t care about some of the intermediate results:
code:example.hs
char :: Char -> Parser ()
char c = () <$ satisfy (== c)