[project @ 1996-01-08 20:28:12 by partain]
[ghc-hetmet.git] / ghc / compiler / utils / Maybes.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
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(..), MaybeErr(..),
13
14         allMaybes,      -- GHCI only
15         assocMaybe,
16         catMaybes,
17         failMaB,
18         failMaybe,
19         firstJust,
20         mapMaybe,       -- GHCI only
21         maybeToBool,
22         mkLookupFun,
23         returnMaB,
24         returnMaybe,    -- GHCI only
25         thenMaB,
26         thenMaybe       -- GHCI only
27
28 #if ! defined(COMPILING_GHC)
29         , findJust
30         , foldlMaybeErrs
31         , listMaybeErrs
32 #endif
33     ) where
34
35 #if defined(COMPILING_GHC)
36 import AbsUniType
37 import Id
38 import IdInfo
39 import Name
40 import Outputable
41 #if USE_ATTACK_PRAGMAS
42 import Util
43 #endif
44 #endif
45 \end{code}
46
47
48 %************************************************************************
49 %*                                                                      *
50 \subsection[Maybe type]{The @Maybe@ type}
51 %*                                                                      *
52 %************************************************************************
53
54 \begin{code}
55 #if __HASKELL1__ < 3
56 data Maybe a
57   = Nothing
58   | Just a
59 #endif
60 \end{code}
61
62 \begin{code}
63 maybeToBool :: Maybe a -> Bool
64 maybeToBool Nothing  = False
65 maybeToBool (Just x) = True
66 \end{code}
67
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
71 are any @Nothings@.
72
73 \begin{code}
74 catMaybes :: [Maybe a] -> [a]
75 catMaybes []                = []
76 catMaybes (Nothing : xs)   = catMaybes xs
77 catMaybes (Just x : xs)    = (x : catMaybes xs)
78
79 allMaybes :: [Maybe a] -> Maybe [a]
80 allMaybes [] = Just []
81 allMaybes (Nothing : ms) = Nothing
82 allMaybes (Just x  : ms) = case (allMaybes ms) of
83                              Nothing -> Nothing
84                              Just xs -> Just (x:xs)
85 \end{code}
86
87 @firstJust@ takes a list of @Maybes@ and returns the
88 first @Just@ if there is one, or @Nothing@ otherwise.
89
90 \begin{code}
91 firstJust :: [Maybe a] -> Maybe a
92 firstJust [] = Nothing
93 firstJust (Just x  : ms) = Just x
94 firstJust (Nothing : ms) = firstJust ms
95 \end{code}
96
97 \begin{code}
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
102                       b  -> b
103 \end{code}
104
105 @assocMaybe@ looks up in an assocation list, returning
106 @Nothing@ if it fails.
107
108 \begin{code}
109 assocMaybe :: (Eq a) => [(a,b)] -> a -> Maybe b
110
111 assocMaybe alist key
112   = lookup alist
113   where
114     lookup []             = Nothing
115     lookup ((tv,ty):rest) = if key == tv then Just ty else lookup rest
116
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
126   #-}
127 #endif
128 \end{code}
129
130 @mkLookupFun alist s@ is a function which looks up
131 @s@ in the association list @alist@, returning a Maybe type.
132
133 \begin{code}
134 mkLookupFun :: (key -> key -> Bool)     -- Equality predicate
135             -> [(key,val)]              -- The assoc list
136             -> key                      -- The key
137             -> Maybe val                -- The corresponding value
138
139 mkLookupFun eq alist s
140   = case [a | (s',a) <- alist, s' `eq` s] of
141       []    -> Nothing
142       (a:_) -> Just a
143 \end{code}
144
145 \begin{code}
146 #if __HASKELL1__ < 3
147 thenMaybe :: Maybe a -> (a -> Maybe b) -> Maybe b
148 m `thenMaybe` k = case m of
149                   Nothing -> Nothing
150                   Just a  -> k a
151 #endif
152 returnMaybe :: a -> Maybe a
153 returnMaybe = Just 
154
155 failMaybe :: Maybe a
156 failMaybe = Nothing
157
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')                     ))
163 \end{code}
164
165 %************************************************************************
166 %*                                                                      *
167 \subsection[MaybeErr type]{The @MaybeErr@ type}
168 %*                                                                      *
169 %************************************************************************
170
171 \begin{code}
172 data MaybeErr val err = Succeeded val | Failed err
173 \end{code}
174
175 \begin{code}
176 thenMaB :: MaybeErr val1 err -> (val1 -> MaybeErr val2 err) -> MaybeErr val2 err
177 thenMaB m k
178   = case m of
179       Succeeded v -> k v
180       Failed e    -> Failed e
181
182 returnMaB :: val -> MaybeErr val err
183 returnMaB v = Succeeded v
184
185 failMaB :: err -> MaybeErr val err
186 failMaB e = Failed e
187 \end{code}
188
189
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.
193
194 \begin{code}
195 listMaybeErrs :: [MaybeErr val err] -> MaybeErr [val] [err]
196 listMaybeErrs
197   = foldr combine (Succeeded []) 
198   where
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)
203 \end{code}
204
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.
208
209 \begin{code}
210 foldlMaybeErrs :: (acc -> input -> MaybeErr acc err)
211                -> acc
212                -> [input]
213                -> MaybeErr acc [err]
214
215 foldlMaybeErrs k accum ins = do_it [] accum ins
216   where
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
222 \end{code}