2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
4 \section[Maybes]{The `Maybe' types and associated utility functions}
7 #if defined(COMPILING_GHC)
8 #include "HsVersions.h"
12 -- Maybe(..), -- no, it's in 1.3
15 allMaybes, -- GHCI only
22 mkLookupFun, mkLookupFunDef,
27 mapMaybe, -- GHCI only
29 returnMaybe, -- GHCI only
31 thenMaybe -- GHCI only
33 #if ! defined(COMPILING_GHC)
40 #if defined(COMPILING_GHC)
42 CHK_Ubiq() -- debugging consistency check
44 #if USE_ATTACK_PRAGMAS
51 %************************************************************************
53 \subsection[Maybe type]{The @Maybe@ type}
55 %************************************************************************
66 maybeToBool :: Maybe a -> Bool
67 maybeToBool Nothing = False
68 maybeToBool (Just x) = True
71 @catMaybes@ takes a list of @Maybe@s and returns a list of
72 the contents of all the @Just@s in it. @allMaybes@ collects
73 a list of @Justs@ into a single @Just@, returning @Nothing@ if there
77 catMaybes :: [Maybe a] -> [a]
79 catMaybes (Nothing : xs) = catMaybes xs
80 catMaybes (Just x : xs) = (x : catMaybes xs)
82 allMaybes :: [Maybe a] -> Maybe [a]
83 allMaybes [] = Just []
84 allMaybes (Nothing : ms) = Nothing
85 allMaybes (Just x : ms) = case (allMaybes ms) of
87 Just xs -> Just (x:xs)
90 @firstJust@ takes a list of @Maybes@ and returns the
91 first @Just@ if there is one, or @Nothing@ otherwise.
94 firstJust :: [Maybe a] -> Maybe a
95 firstJust [] = Nothing
96 firstJust (Just x : ms) = Just x
97 firstJust (Nothing : ms) = firstJust ms
101 findJust :: (a -> Maybe b) -> [a] -> Maybe b
102 findJust f [] = Nothing
103 findJust f (a:as) = case f a of
104 Nothing -> findJust f as
109 expectJust :: String -> Maybe a -> a
110 {-# INLINE expectJust #-}
111 expectJust err (Just x) = x
112 expectJust err Nothing = error ("expectJust " ++ err)
119 thenMaybe :: Maybe a -> (a -> Maybe b) -> Maybe b
120 m `thenMaybe` k = case m of
125 seqMaybe :: Maybe a -> Maybe a -> Maybe a
126 seqMaybe (Just x) _ = Just x
127 seqMaybe Nothing my = my
129 returnMaybe :: a -> Maybe a
135 mapMaybe :: (a -> Maybe b) -> [a] -> Maybe [b]
136 mapMaybe f [] = returnMaybe []
137 mapMaybe f (x:xs) = f x `thenMaybe` \ x' ->
138 mapMaybe f xs `thenMaybe` \ xs' ->
145 @assocMaybe@ looks up in an assocation list, returning
146 @Nothing@ if it fails.
149 assocMaybe :: (Eq a) => [(a,b)] -> a -> Maybe b
155 lookup ((tv,ty):rest) = if key == tv then Just ty else lookup rest
157 #if defined(COMPILING_GHC)
158 {-? SPECIALIZE assocMaybe
159 :: [(String, b)] -> String -> Maybe b,
160 [(Id, b)] -> Id -> Maybe b,
161 [(Class, b)] -> Class -> Maybe b,
162 [(Int, b)] -> Int -> Maybe b,
163 [(Name, b)] -> Name -> Maybe b,
164 [(TyVar, b)] -> TyVar -> Maybe b,
165 [(TyVarTemplate, b)] -> TyVarTemplate -> Maybe b
170 @mkLookupFun eq alist@ is a function which looks up
171 its argument in the association list @alist@, returning a Maybe type.
172 @mkLookupFunDef@ is similar except that it is given a value to return
176 mkLookupFun :: (key -> key -> Bool) -- Equality predicate
177 -> [(key,val)] -- The assoc list
179 -> Maybe val -- The corresponding value
181 mkLookupFun eq alist s
182 = case [a | (s',a) <- alist, s' `eq` s] of
186 mkLookupFunDef :: (key -> key -> Bool) -- Equality predicate
187 -> [(key,val)] -- The assoc list
188 -> val -- Value to return on failure
190 -> val -- The corresponding value
192 mkLookupFunDef eq alist deflt s
193 = case [a | (s',a) <- alist, s' `eq` s] of
198 %************************************************************************
200 \subsection[MaybeErr type]{The @MaybeErr@ type}
202 %************************************************************************
205 data MaybeErr val err = Succeeded val | Failed err
209 thenMaB :: MaybeErr val1 err -> (val1 -> MaybeErr val2 err) -> MaybeErr val2 err
215 returnMaB :: val -> MaybeErr val err
216 returnMaB v = Succeeded v
218 failMaB :: err -> MaybeErr val err
223 @listMaybeErrs@ takes a list of @MaybeErrs@ and, if they all succeed, returns
224 a @Succeeded@ of a list of their values. If any fail, it returns a
225 @Failed@ of the list of all the errors in the list.
228 listMaybeErrs :: [MaybeErr val err] -> MaybeErr [val] [err]
230 = foldr combine (Succeeded [])
232 combine (Succeeded v) (Succeeded vs) = Succeeded (v:vs)
233 combine (Failed err) (Succeeded _) = Failed [err]
234 combine (Succeeded v) (Failed errs) = Failed errs
235 combine (Failed err) (Failed errs) = Failed (err:errs)
238 @foldlMaybeErrs@ works along a list, carrying an accumulator; it
239 applies the given function to the accumulator and the next list item,
240 accumulating any errors that occur.
243 foldlMaybeErrs :: (acc -> input -> MaybeErr acc err)
246 -> MaybeErr acc [err]
248 foldlMaybeErrs k accum ins = do_it [] accum ins
250 do_it [] acc [] = Succeeded acc
251 do_it errs acc [] = Failed errs
252 do_it errs acc (v:vs) = case (k acc v) of
253 Succeeded acc' -> do_it errs acc' vs
254 Failed err -> do_it (err:errs) acc vs