5ed4ac316f492165b8993789408350ad3b5df691
[ghc-hetmet.git] / ghc / compiler / utils / Maybes.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
3 %
4 \section[Maybes]{The `Maybe' types and associated utility functions}
5
6 \begin{code}
7 #if defined(COMPILING_GHC)
8 #include "HsVersions.h"
9 #endif
10
11 module Maybes (
12 --      Maybe(..), -- no, it's in 1.3
13         MaybeErr(..),
14
15         allMaybes,
16         catMaybes,
17         firstJust,
18         expectJust,
19         maybeToBool,
20
21         assocMaybe,
22         mkLookupFun, mkLookupFunDef,
23
24         failMaB,
25         failMaybe,
26         seqMaybe,
27         returnMaB,
28         returnMaybe,
29         thenMaB
30
31 #if ! defined(COMPILING_GHC)
32         , findJust
33         , foldlMaybeErrs
34         , listMaybeErrs
35 #endif
36     ) where
37
38 #if defined(COMPILING_GHC)
39
40 CHK_Ubiq() -- debugging consistency check
41
42 import Unique (Unique) -- only for specialising
43
44 #endif
45 \end{code}
46
47
48 %************************************************************************
49 %*                                                                      *
50 \subsection[Maybe type]{The @Maybe@ type}
51 %*                                                                      *
52 %************************************************************************
53
54 \begin{code}
55 maybeToBool :: Maybe a -> Bool
56 maybeToBool Nothing  = False
57 maybeToBool (Just x) = True
58 \end{code}
59
60 @catMaybes@ takes a list of @Maybe@s and returns a list of
61 the contents of all the @Just@s in it.  @allMaybes@ collects
62 a list of @Justs@ into a single @Just@, returning @Nothing@ if there
63 are any @Nothings@.
64
65 \begin{code}
66 catMaybes :: [Maybe a] -> [a]
67 catMaybes []                = []
68 catMaybes (Nothing : xs)   = catMaybes xs
69 catMaybes (Just x : xs)    = (x : catMaybes xs)
70
71 allMaybes :: [Maybe a] -> Maybe [a]
72 allMaybes [] = Just []
73 allMaybes (Nothing : ms) = Nothing
74 allMaybes (Just x  : ms) = case (allMaybes ms) of
75                              Nothing -> Nothing
76                              Just xs -> Just (x:xs)
77 \end{code}
78
79 @firstJust@ takes a list of @Maybes@ and returns the
80 first @Just@ if there is one, or @Nothing@ otherwise.
81
82 \begin{code}
83 firstJust :: [Maybe a] -> Maybe a
84 firstJust [] = Nothing
85 firstJust (Just x  : ms) = Just x
86 firstJust (Nothing : ms) = firstJust ms
87 \end{code}
88
89 \begin{code}
90 findJust :: (a -> Maybe b) -> [a] -> Maybe b
91 findJust f []     = Nothing
92 findJust f (a:as) = case f a of
93                       Nothing -> findJust f as
94                       b  -> b
95 \end{code}
96
97 \begin{code}
98 expectJust :: String -> Maybe a -> a
99 {-# INLINE expectJust #-}
100 expectJust err (Just x) = x
101 expectJust err Nothing  = error ("expectJust " ++ err)
102 \end{code}
103
104 The Maybe monad
105 ~~~~~~~~~~~~~~~
106 \begin{code}
107 seqMaybe :: Maybe a -> Maybe a -> Maybe a
108 seqMaybe (Just x) _  = Just x
109 seqMaybe Nothing  my = my
110
111 returnMaybe :: a -> Maybe a
112 returnMaybe = Just
113
114 failMaybe :: Maybe a
115 failMaybe = Nothing
116 \end{code}
117
118 Lookup functions
119 ~~~~~~~~~~~~~~~~
120
121 @assocMaybe@ looks up in an assocation list, returning
122 @Nothing@ if it fails.
123
124 \begin{code}
125 assocMaybe :: (Eq a) => [(a,b)] -> a -> Maybe b
126
127 assocMaybe alist key
128   = lookup alist
129   where
130     lookup []             = Nothing
131     lookup ((tv,ty):rest) = if key == tv then Just ty else lookup rest
132
133 #if defined(COMPILING_GHC)
134 {-# SPECIALIZE assocMaybe
135         :: [(FAST_STRING,   b)] -> FAST_STRING -> Maybe b
136          , [(Int,           b)] -> Int         -> Maybe b
137          , [(Unique,        b)] -> Unique      -> Maybe b
138          , [(RdrName,       b)] -> RdrName     -> Maybe b
139   #-}
140 #endif
141 \end{code}
142
143 @mkLookupFun eq alist@ is a function which looks up
144 its argument in the association list @alist@, returning a Maybe type.
145 @mkLookupFunDef@ is similar except that it is given a value to return
146 on failure.
147
148 \begin{code}
149 mkLookupFun :: (key -> key -> Bool)     -- Equality predicate
150             -> [(key,val)]              -- The assoc list
151             -> key                      -- The key
152             -> Maybe val                -- The corresponding value
153
154 mkLookupFun eq alist s
155   = case [a | (s',a) <- alist, s' `eq` s] of
156       []    -> Nothing
157       (a:_) -> Just a
158
159 mkLookupFunDef :: (key -> key -> Bool)  -- Equality predicate
160                -> [(key,val)]           -- The assoc list
161                -> val                   -- Value to return on failure
162                -> key                   -- The key
163                -> val                   -- The corresponding value
164
165 mkLookupFunDef eq alist deflt s
166   = case [a | (s',a) <- alist, s' `eq` s] of
167       []    -> deflt
168       (a:_) -> a
169 \end{code}
170
171 %************************************************************************
172 %*                                                                      *
173 \subsection[MaybeErr type]{The @MaybeErr@ type}
174 %*                                                                      *
175 %************************************************************************
176
177 \begin{code}
178 data MaybeErr val err = Succeeded val | Failed err
179 \end{code}
180
181 \begin{code}
182 thenMaB :: MaybeErr val1 err -> (val1 -> MaybeErr val2 err) -> MaybeErr val2 err
183 thenMaB m k
184   = case m of
185       Succeeded v -> k v
186       Failed e    -> Failed e
187
188 returnMaB :: val -> MaybeErr val err
189 returnMaB v = Succeeded v
190
191 failMaB :: err -> MaybeErr val err
192 failMaB e = Failed e
193 \end{code}
194
195
196 @listMaybeErrs@ takes a list of @MaybeErrs@ and, if they all succeed, returns
197 a @Succeeded@ of a list of their values.  If any fail, it returns a
198 @Failed@ of the list of all the errors in the list.
199
200 \begin{code}
201 listMaybeErrs :: [MaybeErr val err] -> MaybeErr [val] [err]
202 listMaybeErrs
203   = foldr combine (Succeeded [])
204   where
205     combine (Succeeded v) (Succeeded vs) = Succeeded (v:vs)
206     combine (Failed err)  (Succeeded _)  = Failed [err]
207     combine (Succeeded v) (Failed errs)  = Failed errs
208     combine (Failed err)  (Failed errs)  = Failed (err:errs)
209 \end{code}
210
211 @foldlMaybeErrs@ works along a list, carrying an accumulator; it
212 applies the given function to the accumulator and the next list item,
213 accumulating any errors that occur.
214
215 \begin{code}
216 foldlMaybeErrs :: (acc -> input -> MaybeErr acc err)
217                -> acc
218                -> [input]
219                -> MaybeErr acc [err]
220
221 foldlMaybeErrs k accum ins = do_it [] accum ins
222   where
223     do_it []   acc []     = Succeeded acc
224     do_it errs acc []     = Failed errs
225     do_it errs acc (v:vs) = case (k acc v) of
226                               Succeeded acc' -> do_it errs       acc' vs
227                               Failed err     -> do_it (err:errs) acc  vs
228 \end{code}