Make Applicative a superclass of Monad
[ghc.git] / compiler / utils / Maybes.lhs
1 %
2 % (c) The University of Glasgow 2006
3 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
4 %
5
6 \begin{code}
7 {-# LANGUAGE CPP #-}
8 module Maybes (
9         module Data.Maybe,
10
11         MaybeErr(..), -- Instance of Monad
12         failME, isSuccess,
13
14         orElse,
15         firstJust, firstJusts,
16         whenIsJust,
17         expectJust,
18
19         MaybeT(..)
20     ) where
21 #if __GLASGOW_HASKELL__ < 709
22 import Control.Applicative
23 #endif
24 import Control.Monad
25 import Data.Maybe
26
27 infixr 4 `orElse`
28 \end{code}
29
30 %************************************************************************
31 %*                                                                      *
32 \subsection[Maybe type]{The @Maybe@ type}
33 %*                                                                      *
34 %************************************************************************
35
36 \begin{code}
37 firstJust :: Maybe a -> Maybe a -> Maybe a
38 firstJust a b = firstJusts [a, b]
39
40 -- | Takes a list of @Maybes@ and returns the first @Just@ if there is one, or
41 -- @Nothing@ otherwise.
42 firstJusts :: [Maybe a] -> Maybe a
43 firstJusts = msum
44
45 expectJust :: String -> Maybe a -> a
46 {-# INLINE expectJust #-}
47 expectJust _   (Just x) = x
48 expectJust err Nothing  = error ("expectJust " ++ err)
49
50 whenIsJust :: Monad m => Maybe a -> (a -> m ()) -> m ()
51 whenIsJust (Just x) f = f x
52 whenIsJust Nothing  _ = return ()
53
54 -- | Flipped version of @fromMaybe@, useful for chaining.
55 orElse :: Maybe a -> a -> a
56 orElse = flip fromMaybe
57 \end{code}
58
59 %************************************************************************
60 %*                                                                      *
61 \subsection[MaybeT type]{The @MaybeT@ monad transformer}
62 %*                                                                      *
63 %************************************************************************
64
65 \begin{code}
66
67 newtype MaybeT m a = MaybeT {runMaybeT :: m (Maybe a)}
68
69 instance Functor m => Functor (MaybeT m) where
70   fmap f x = MaybeT $ fmap (fmap f) $ runMaybeT x
71
72 instance (Monad m, Functor m) => Applicative (MaybeT m) where
73   pure  = return
74   (<*>) = ap
75
76 instance Monad m => Monad (MaybeT m) where
77   return = MaybeT . return . Just
78   x >>= f = MaybeT $ runMaybeT x >>= maybe (return Nothing) (runMaybeT . f)
79   fail _ = MaybeT $ return Nothing
80
81 \end{code}
82
83
84 %************************************************************************
85 %*                                                                      *
86 \subsection[MaybeErr type]{The @MaybeErr@ type}
87 %*                                                                      *
88 %************************************************************************
89
90 \begin{code}
91 data MaybeErr err val = Succeeded val | Failed err
92
93 instance Functor (MaybeErr err) where
94   fmap = liftM
95
96 instance Applicative (MaybeErr err) where
97   pure  = return
98   (<*>) = ap
99
100 instance Monad (MaybeErr err) where
101   return v = Succeeded v
102   Succeeded v >>= k = k v
103   Failed e    >>= _ = Failed e
104
105 isSuccess :: MaybeErr err val -> Bool
106 isSuccess (Succeeded {}) = True
107 isSuccess (Failed {})    = False
108
109 failME :: err -> MaybeErr err val
110 failME e = Failed e
111 \end{code}