% % (c) The University of Glasgow 2006 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 % \begin{code}
module Maybes (
module Data.Maybe,

failME, isSuccess,

orElse,
mapCatMaybes,
allMaybes,
firstJust, firstJusts,
whenIsJust,
expectJust,
maybeToBool,

MaybeT(..)
) where
import Control.Applicative
import Data.Maybe

infixr 4 orElse

\end{code} %************************************************************************ %* * \subsection[Maybe type]{The @Maybe@ type} %* * %************************************************************************ \begin{code}
maybeToBool :: Maybe a -> Bool
maybeToBool Nothing  = False
maybeToBool (Just _) = True

-- | Collects a list of @Justs@ into a single @Just@, returning @Nothing@ if
-- there are any @Nothings@.
allMaybes :: [Maybe a] -> Maybe [a]
allMaybes [] = Just []
allMaybes (Nothing : _)  = Nothing
allMaybes (Just x  : ms) = case allMaybes ms of
Nothing -> Nothing
Just xs -> Just (x:xs)

firstJust :: Maybe a -> Maybe a -> Maybe a
firstJust (Just a) _ = Just a
firstJust Nothing  b = b

-- | Takes a list of @Maybes@ and returns the first @Just@ if there is one, or
-- @Nothing@ otherwise.
firstJusts :: [Maybe a] -> Maybe a
firstJusts = foldr firstJust Nothing

\end{code} \begin{code}
expectJust :: String -> Maybe a -> a
{-# INLINE expectJust #-}
expectJust _   (Just x) = x
expectJust err Nothing  = error ("expectJust " ++ err)

\end{code} \begin{code}
mapCatMaybes :: (a -> Maybe b) -> [a] -> [b]
mapCatMaybes _ [] = []
mapCatMaybes f (x:xs) = case f x of
Just y  -> y : mapCatMaybes f xs
Nothing -> mapCatMaybes f xs

whenIsJust :: Monad m => Maybe a -> (a -> m ()) -> m ()
whenIsJust (Just x) f = f x
whenIsJust Nothing  _ = return ()

\end{code} \begin{code}
-- | flipped version of @fromMaybe@.
orElse :: Maybe a -> a -> a
(Just x) orElse _ = x
Nothing  orElse y = y

\end{code} %************************************************************************ %* * \subsection[MaybeT type]{The @MaybeT@ monad transformer} %* * %************************************************************************ \begin{code}

newtype MaybeT m a = MaybeT {runMaybeT :: m (Maybe a)}

instance Functor m => Functor (MaybeT m) where
fmap f x = MaybeT $fmap (fmap f)$ runMaybeT x

instance (Monad m, Functor m) => Applicative (MaybeT m) where
pure  = return
(<*>) = ap

return = MaybeT . return . Just
x >>= f = MaybeT $runMaybeT x >>= maybe (return Nothing) (runMaybeT . f) fail _ = MaybeT$ return Nothing


\end{code} %************************************************************************ %* * \subsection[MaybeErr type]{The @MaybeErr@ type} %* * %************************************************************************ \begin{code}
data MaybeErr err val = Succeeded val | Failed err

instance Functor (MaybeErr err) where
fmap = liftM

instance Applicative (MaybeErr err) where
pure  = return
(<*>) = ap