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
21 mkLookupFun, mkLookupFunDef,
30 #if defined(COMPILING_GHC)
39 #if defined(COMPILING_GHC)
41 CHK_Ubiq() -- debugging consistency check
43 import Unique (Unique) -- only for specialising
46 import Maybe -- renamer will tell us if there are any conflicts
51 %************************************************************************
53 \subsection[Maybe type]{The @Maybe@ type}
55 %************************************************************************
58 maybeToBool :: Maybe a -> Bool
59 maybeToBool Nothing = False
60 maybeToBool (Just x) = True
63 @catMaybes@ takes a list of @Maybe@s and returns a list of
64 the contents of all the @Just@s in it. @allMaybes@ collects
65 a list of @Justs@ into a single @Just@, returning @Nothing@ if there
70 catMaybes :: [Maybe a] -> [a]
72 catMaybes (Nothing : xs) = catMaybes xs
73 catMaybes (Just x : xs) = (x : catMaybes xs)
76 allMaybes :: [Maybe a] -> Maybe [a]
77 allMaybes [] = Just []
78 allMaybes (Nothing : ms) = Nothing
79 allMaybes (Just x : ms) = case (allMaybes ms) of
81 Just xs -> Just (x:xs)
84 @firstJust@ takes a list of @Maybes@ and returns the
85 first @Just@ if there is one, or @Nothing@ otherwise.
88 firstJust :: [Maybe a] -> Maybe a
89 firstJust [] = Nothing
90 firstJust (Just x : ms) = Just x
91 firstJust (Nothing : ms) = firstJust ms
95 findJust :: (a -> Maybe b) -> [a] -> Maybe b
96 findJust f [] = Nothing
97 findJust f (a:as) = case f a of
98 Nothing -> findJust f as
103 expectJust :: String -> Maybe a -> a
104 {-# INLINE expectJust #-}
105 expectJust err (Just x) = x
106 expectJust err Nothing = error ("expectJust " ++ err)
112 seqMaybe :: Maybe a -> Maybe a -> Maybe a
113 seqMaybe (Just x) _ = Just x
114 seqMaybe Nothing my = my
116 returnMaybe :: a -> Maybe a
126 @assocMaybe@ looks up in an assocation list, returning
127 @Nothing@ if it fails.
130 assocMaybe :: (Eq a) => [(a,b)] -> a -> Maybe b
136 lookup ((tv,ty):rest) = if key == tv then Just ty else lookup rest
138 #if defined(COMPILING_GHC)
139 {-# SPECIALIZE assocMaybe
140 :: [(FAST_STRING, b)] -> FAST_STRING -> Maybe b
141 , [(Int, b)] -> Int -> Maybe b
142 , [(Unique, b)] -> Unique -> Maybe b
143 , [(RdrName, b)] -> RdrName -> Maybe b
148 @mkLookupFun eq alist@ is a function which looks up
149 its argument in the association list @alist@, returning a Maybe type.
150 @mkLookupFunDef@ is similar except that it is given a value to return
154 mkLookupFun :: (key -> key -> Bool) -- Equality predicate
155 -> [(key,val)] -- The assoc list
157 -> Maybe val -- The corresponding value
159 mkLookupFun eq alist s
160 = case [a | (s',a) <- alist, s' `eq` s] of
164 mkLookupFunDef :: (key -> key -> Bool) -- Equality predicate
165 -> [(key,val)] -- The assoc list
166 -> val -- Value to return on failure
168 -> val -- The corresponding value
170 mkLookupFunDef eq alist deflt s
171 = case [a | (s',a) <- alist, s' `eq` s] of
176 %************************************************************************
178 \subsection[MaybeErr type]{The @MaybeErr@ type}
180 %************************************************************************
183 data MaybeErr val err = Succeeded val | Failed err
187 thenMaB :: MaybeErr val1 err -> (val1 -> MaybeErr val2 err) -> MaybeErr val2 err
193 returnMaB :: val -> MaybeErr val err
194 returnMaB v = Succeeded v
196 failMaB :: err -> MaybeErr val err
201 @listMaybeErrs@ takes a list of @MaybeErrs@ and, if they all succeed, returns
202 a @Succeeded@ of a list of their values. If any fail, it returns a
203 @Failed@ of the list of all the errors in the list.
206 listMaybeErrs :: [MaybeErr val err] -> MaybeErr [val] [err]
208 = foldr combine (Succeeded [])
210 combine (Succeeded v) (Succeeded vs) = Succeeded (v:vs)
211 combine (Failed err) (Succeeded _) = Failed [err]
212 combine (Succeeded v) (Failed errs) = Failed errs
213 combine (Failed err) (Failed errs) = Failed (err:errs)
216 @foldlMaybeErrs@ works along a list, carrying an accumulator; it
217 applies the given function to the accumulator and the next list item,
218 accumulating any errors that occur.
221 foldlMaybeErrs :: (acc -> input -> MaybeErr acc err)
224 -> MaybeErr acc [err]
226 foldlMaybeErrs k accum ins = do_it [] accum ins
228 do_it [] acc [] = Succeeded acc
229 do_it errs acc [] = Failed errs
230 do_it errs acc (v:vs) = case (k acc v) of
231 Succeeded acc' -> do_it errs acc' vs
232 Failed err -> do_it (err:errs) acc vs