2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
4 \section[Maybes]{The `Maybe' types and associated utility functions}
7 #if defined(COMPILING_GHC)
8 #include "HsVersions.h"
12 Maybe(..), MaybeErr(..),
14 allMaybes, -- GHCI only
20 mapMaybe, -- GHCI only
24 returnMaybe, -- GHCI only
26 thenMaybe -- GHCI only
28 #if ! defined(COMPILING_GHC)
35 #if defined(COMPILING_GHC)
41 #if USE_ATTACK_PRAGMAS
48 %************************************************************************
50 \subsection[Maybe type]{The @Maybe@ type}
52 %************************************************************************
63 maybeToBool :: Maybe a -> Bool
64 maybeToBool Nothing = False
65 maybeToBool (Just x) = True
68 @catMaybes@ takes a list of @Maybe@s and returns a list of
69 the contents of all the @Just@s in it. @allMaybes@ collects
70 a list of @Justs@ into a single @Just@, returning @Nothing@ if there
74 catMaybes :: [Maybe a] -> [a]
76 catMaybes (Nothing : xs) = catMaybes xs
77 catMaybes (Just x : xs) = (x : catMaybes xs)
79 allMaybes :: [Maybe a] -> Maybe [a]
80 allMaybes [] = Just []
81 allMaybes (Nothing : ms) = Nothing
82 allMaybes (Just x : ms) = case (allMaybes ms) of
84 Just xs -> Just (x:xs)
87 @firstJust@ takes a list of @Maybes@ and returns the
88 first @Just@ if there is one, or @Nothing@ otherwise.
91 firstJust :: [Maybe a] -> Maybe a
92 firstJust [] = Nothing
93 firstJust (Just x : ms) = Just x
94 firstJust (Nothing : ms) = firstJust ms
98 findJust :: (a -> Maybe b) -> [a] -> Maybe b
99 findJust f [] = Nothing
100 findJust f (a:as) = case f a of
101 Nothing -> findJust f as
105 @assocMaybe@ looks up in an assocation list, returning
106 @Nothing@ if it fails.
109 assocMaybe :: (Eq a) => [(a,b)] -> a -> Maybe b
115 lookup ((tv,ty):rest) = if key == tv then Just ty else lookup rest
117 #if defined(COMPILING_GHC)
118 {-# SPECIALIZE assocMaybe
119 :: [(String, b)] -> String -> Maybe b,
120 [(Id, b)] -> Id -> Maybe b,
121 [(Class, b)] -> Class -> Maybe b,
122 [(Int, b)] -> Int -> Maybe b,
123 [(Name, b)] -> Name -> Maybe b,
124 [(TyVar, b)] -> TyVar -> Maybe b,
125 [(TyVarTemplate, b)] -> TyVarTemplate -> Maybe b
130 @mkLookupFun alist s@ is a function which looks up
131 @s@ in the association list @alist@, returning a Maybe type.
134 mkLookupFun :: (key -> key -> Bool) -- Equality predicate
135 -> [(key,val)] -- The assoc list
137 -> Maybe val -- The corresponding value
139 mkLookupFun eq alist s
140 = case [a | (s',a) <- alist, s' `eq` s] of
147 thenMaybe :: Maybe a -> (a -> Maybe b) -> Maybe b
148 m `thenMaybe` k = case m of
152 returnMaybe :: a -> Maybe a
158 mapMaybe :: (a -> Maybe b) -> [a] -> Maybe [b]
159 mapMaybe f [] = returnMaybe []
160 mapMaybe f (x:xs) = f x `thenMaybe` (\ x' ->
161 mapMaybe f xs `thenMaybe` (\ xs' ->
162 returnMaybe (x':xs') ))
165 %************************************************************************
167 \subsection[MaybeErr type]{The @MaybeErr@ type}
169 %************************************************************************
172 data MaybeErr val err = Succeeded val | Failed err
176 thenMaB :: MaybeErr val1 err -> (val1 -> MaybeErr val2 err) -> MaybeErr val2 err
182 returnMaB :: val -> MaybeErr val err
183 returnMaB v = Succeeded v
185 failMaB :: err -> MaybeErr val err
190 @listMaybeErrs@ takes a list of @MaybeErrs@ and, if they all succeed, returns
191 a @Succeeded@ of a list of their values. If any fail, it returns a
192 @Failed@ of the list of all the errors in the list.
195 listMaybeErrs :: [MaybeErr val err] -> MaybeErr [val] [err]
197 = foldr combine (Succeeded [])
199 combine (Succeeded v) (Succeeded vs) = Succeeded (v:vs)
200 combine (Failed err) (Succeeded _) = Failed [err]
201 combine (Succeeded v) (Failed errs) = Failed errs
202 combine (Failed err) (Failed errs) = Failed (err:errs)
205 @foldlMaybeErrs@ works along a list, carrying an accumulator; it
206 applies the given function to the accumulator and the next list item,
207 accumulating any errors that occur.
210 foldlMaybeErrs :: (acc -> input -> MaybeErr acc err)
213 -> MaybeErr acc [err]
215 foldlMaybeErrs k accum ins = do_it [] accum ins
217 do_it [] acc [] = Succeeded acc
218 do_it errs acc [] = Failed errs
219 do_it errs acc (v:vs) = case (k acc v) of
220 Succeeded acc' -> do_it errs acc' vs
221 Failed err -> do_it (err:errs) acc vs