[project @ 1996-06-05 06:44:31 by partain]
[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 #endif
43 \end{code}
44
45
46 %************************************************************************
47 %*                                                                      *
48 \subsection[Maybe type]{The @Maybe@ type}
49 %*                                                                      *
50 %************************************************************************
51
52 \begin{code}
53 maybeToBool :: Maybe a -> Bool
54 maybeToBool Nothing  = False
55 maybeToBool (Just x) = True
56 \end{code}
57
58 @catMaybes@ takes a list of @Maybe@s and returns a list of
59 the contents of all the @Just@s in it.  @allMaybes@ collects
60 a list of @Justs@ into a single @Just@, returning @Nothing@ if there
61 are any @Nothings@.
62
63 \begin{code}
64 catMaybes :: [Maybe a] -> [a]
65 catMaybes []                = []
66 catMaybes (Nothing : xs)   = catMaybes xs
67 catMaybes (Just x : xs)    = (x : catMaybes xs)
68
69 allMaybes :: [Maybe a] -> Maybe [a]
70 allMaybes [] = Just []
71 allMaybes (Nothing : ms) = Nothing
72 allMaybes (Just x  : ms) = case (allMaybes ms) of
73                              Nothing -> Nothing
74                              Just xs -> Just (x:xs)
75 \end{code}
76
77 @firstJust@ takes a list of @Maybes@ and returns the
78 first @Just@ if there is one, or @Nothing@ otherwise.
79
80 \begin{code}
81 firstJust :: [Maybe a] -> Maybe a
82 firstJust [] = Nothing
83 firstJust (Just x  : ms) = Just x
84 firstJust (Nothing : ms) = firstJust ms
85 \end{code}
86
87 \begin{code}
88 findJust :: (a -> Maybe b) -> [a] -> Maybe b
89 findJust f []     = Nothing
90 findJust f (a:as) = case f a of
91                       Nothing -> findJust f as
92                       b  -> b
93 \end{code}
94
95 \begin{code}
96 expectJust :: String -> Maybe a -> a
97 {-# INLINE expectJust #-}
98 expectJust err (Just x) = x
99 expectJust err Nothing  = error ("expectJust " ++ err)
100 \end{code}
101
102 The Maybe monad
103 ~~~~~~~~~~~~~~~
104 \begin{code}
105 seqMaybe :: Maybe a -> Maybe a -> Maybe a
106 seqMaybe (Just x) _  = Just x
107 seqMaybe Nothing  my = my
108
109 returnMaybe :: a -> Maybe a
110 returnMaybe = Just
111
112 failMaybe :: Maybe a
113 failMaybe = Nothing
114 \end{code}
115
116 Lookup functions
117 ~~~~~~~~~~~~~~~~
118
119 @assocMaybe@ looks up in an assocation list, returning
120 @Nothing@ if it fails.
121
122 \begin{code}
123 assocMaybe :: (Eq a) => [(a,b)] -> a -> Maybe b
124
125 assocMaybe alist key
126   = lookup alist
127   where
128     lookup []             = Nothing
129     lookup ((tv,ty):rest) = if key == tv then Just ty else lookup rest
130
131 #if defined(COMPILING_GHC)
132 {-? SPECIALIZE assocMaybe
133         :: [(String,        b)] -> String        -> Maybe b,
134            [(Id,            b)] -> Id            -> Maybe b,
135            [(Class,         b)] -> Class         -> Maybe b,
136            [(Int,           b)] -> Int           -> Maybe b,
137            [(Name,          b)] -> Name          -> Maybe b,
138            [(TyVar,         b)] -> TyVar         -> Maybe b,
139            [(TyVarTemplate, b)] -> TyVarTemplate -> Maybe b
140   #-}
141 #endif
142 \end{code}
143
144 @mkLookupFun eq alist@ is a function which looks up
145 its argument in the association list @alist@, returning a Maybe type.
146 @mkLookupFunDef@ is similar except that it is given a value to return
147 on failure.
148
149 \begin{code}
150 mkLookupFun :: (key -> key -> Bool)     -- Equality predicate
151             -> [(key,val)]              -- The assoc list
152             -> key                      -- The key
153             -> Maybe val                -- The corresponding value
154
155 mkLookupFun eq alist s
156   = case [a | (s',a) <- alist, s' `eq` s] of
157       []    -> Nothing
158       (a:_) -> Just a
159
160 mkLookupFunDef :: (key -> key -> Bool)  -- Equality predicate
161                -> [(key,val)]           -- The assoc list
162                -> val                   -- Value to return on failure
163                -> key                   -- The key
164                -> val                   -- The corresponding value
165
166 mkLookupFunDef eq alist deflt s
167   = case [a | (s',a) <- alist, s' `eq` s] of
168       []    -> deflt
169       (a:_) -> a
170 \end{code}
171
172 %************************************************************************
173 %*                                                                      *
174 \subsection[MaybeErr type]{The @MaybeErr@ type}
175 %*                                                                      *
176 %************************************************************************
177
178 \begin{code}
179 data MaybeErr val err = Succeeded val | Failed err
180 \end{code}
181
182 \begin{code}
183 thenMaB :: MaybeErr val1 err -> (val1 -> MaybeErr val2 err) -> MaybeErr val2 err
184 thenMaB m k
185   = case m of
186       Succeeded v -> k v
187       Failed e    -> Failed e
188
189 returnMaB :: val -> MaybeErr val err
190 returnMaB v = Succeeded v
191
192 failMaB :: err -> MaybeErr val err
193 failMaB e = Failed e
194 \end{code}
195
196
197 @listMaybeErrs@ takes a list of @MaybeErrs@ and, if they all succeed, returns
198 a @Succeeded@ of a list of their values.  If any fail, it returns a
199 @Failed@ of the list of all the errors in the list.
200
201 \begin{code}
202 listMaybeErrs :: [MaybeErr val err] -> MaybeErr [val] [err]
203 listMaybeErrs
204   = foldr combine (Succeeded [])
205   where
206     combine (Succeeded v) (Succeeded vs) = Succeeded (v:vs)
207     combine (Failed err)  (Succeeded _)  = Failed [err]
208     combine (Succeeded v) (Failed errs)  = Failed errs
209     combine (Failed err)  (Failed errs)  = Failed (err:errs)
210 \end{code}
211
212 @foldlMaybeErrs@ works along a list, carrying an accumulator; it
213 applies the given function to the accumulator and the next list item,
214 accumulating any errors that occur.
215
216 \begin{code}
217 foldlMaybeErrs :: (acc -> input -> MaybeErr acc err)
218                -> acc
219                -> [input]
220                -> MaybeErr acc [err]
221
222 foldlMaybeErrs k accum ins = do_it [] accum ins
223   where
224     do_it []   acc []     = Succeeded acc
225     do_it errs acc []     = Failed errs
226     do_it errs acc (v:vs) = case (k acc v) of
227                               Succeeded acc' -> do_it errs       acc' vs
228                               Failed err     -> do_it (err:errs) acc  vs
229 \end{code}