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