%**<title>The Haskell 98 Library Report: Monad Utilities</title>
%**~header
\section{Monad Utilities}
\label{Monad}

\outline{
\inputHS{lib-hdrs/Monad}
}

The @Monad@ library defines the @MonadPlus@ class, and 
provides some useful operations on monads.

\subsection{Naming conventions}

The functions in this library use the following naming conventions:
\begin{itemize}
\item
A postfix ``@M@'' always stands for a function in the Kleisli category:
@m@ is added to function results (modulo currying) and nowhere else.
So, for example,
\bprog
@
  filter  ::            (a ->   Bool) -> [a] ->   [a]
  filterM :: Monad m => (a -> m Bool) -> [a] -> m [a]
@
\eprog

\item A postfix ``@_@'' changes the result type from @(m a)@ to @(m ())@.
Thus (in the @Prelude@):
\bprog
@
sequence  :: Monad m => [m a] -> m [a] 
sequence_ :: Monad m => [m a] -> m () 
@
\eprog

\item A prefix ``@m@'' generalises an existing function to a monadic form.
Thus, for example:
\bprog
@
  sum  :: Num a       => [a]   -> a
  msum :: MonadPlus m => [m a] -> m a
@
\eprog
\end{itemize}

\subsection{Class @MonadPlus@}

The @MonadPlus@ class is defined as follows:
\bprog
@
class  Monad m => MonadPlus m  where
    mzero  :: m a
    mplus  :: m a -> m a -> m a
@
\eprog
The class methods @mzero@ and @mplus@ are the zero and plus
of the monad.

Lists and the @Maybe@ type are instances of @MonadPlus@, thus:
\bprog
@
instance  MonadPlus Maybe  where
    mzero                 = Nothing
    Nothing `mplus` ys    = ys
    xs      `mplus` ys    = xs

instance  MonadPlus []  where
    mzero = []
    mplus = (++)
@
\eprog


\subsection{Functions}

The @join@ function is the conventional monad join operator.  It is
used to remove one level of monadic structure, projecting its bound
argument into the outer level.

% There is no convincing small-scale example for mapAndUnzipM
The @mapAndUnzipM@ function maps its first argument over a list,
returning the result as a pair of lists.  This function is mainly used
with complicated data structures or a state-transforming monad.

The @zipWithM@ function generalises @zipWith@ to arbitrary monads.
For instance the following function displays a file, prefixing
each line with its line number,
\par
{\small
\bprog
@
listFile :: String -> IO ()
listFile nm =
  do cts <- readFile nm
     zipWithM_ (\i line -> do putStr (show i); putStr ": "; putStrLn line)
               [1..]
               (lines cts)
@
\eprog
}
The @foldM@ function is analogous to @foldl@, except that its result
is encapsulated in a monad.  Note that @foldM@ works from
left-to-right over the list arguments.  This could be an issue where
@(>>)@ and the ``folded function'' are not commutative. 
\bprog
@
    foldM f a1 [x1, x2, ..., xm ]
==  
    do
      a2 <- f a1 x1
      a3 <- f a2 x2
      ...
      f am xm
@
\eprog
If right-to-left
evaluation is required, the input list should be reversed.

% Omitted for now.  These functions are very useful in parsing libraries
% - but in a slightly modified form:
% o It is conventional to return the _longest_ parse first - not 
%   shortest first.
% o The function is too strict - you can't get any part of the result
%   until the entire parse completes.  The fix is to use the function
%   force when defining zeroOrMore.
%   
%     force :: Parser a -> Parser a
%     force (P m) = P (\i -> let x = p i in
%                            (fst (head x), snd (head x)) : tail x)
%
%   but how are we to generalise this to an arbitrary monad?
%
% The @zeroOrMore@ function performs an action repeatedly - returning
% the list of all results obtained.  The @oneOrMore@ function is similar
% but the action must succeed at least once.  That is,
% \bprog
% <at>
% zeroOrMore m = zero ++ 
% 		 [ [a0]       | a0 <- m ] ++
% 		 [ [a0,a1]    | a0 <- m, a1 <- m ] ++
% 		 [ [a0,a1,a2] | a0 <- m, a1 <- m, a2 <- m ] ++
% 		 ...
% 
% oneOrMore m  = [ [a0]       | a0 <- m ] ++
% 		 [ [a0,a1]    | a0 <- m, a1 <- m ] ++
% 		 [ [a0,a1,a2] | a0 <- m, a1 <- m, a2 <- m ] ++
% 		 ...
% <at>
% \eprog

The @when@ and @unless@ functions provide conditional execution of
monadic expressions.  For example,
\bprog
@
when debug (putStr "Debugging\n")
@
\eprog
will output the string @"Debugging\n"@ if the Boolean value @debug@ is
@True@, and otherwise do nothing.

The monadic lifting operators promote a function to a monad.  The
function arguments are scanned left to right.  For example,
\bprog
@
liftM2 (+) [0,1] [0,2] = [0,2,1,3]
liftM2 (+) (Just 1) Nothing = Nothing
@
\eprog

In many situations, the @liftM@ operations can be replaced by uses
of @ap@, which promotes function application.
\bprog
@
return f `ap` x1 `ap` ... `ap` xn
@
\eprog
is equivalent to
\bprog
@
liftMn f x1 x2 ... xn
@
\eprog
\clearpage
\subsection{Library {\tt Monad}}
\inputHS{lib-code/Monad}

%**~footer

