b29dd9c56454180f445f305127474df36e0c90c2
[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 #include "HsVersions.h"
8
9 module Maybes (
10 --      Maybe(..), -- no, it's in 1.3
11         MaybeErr(..),
12
13         mapMaybe,
14         allMaybes,
15         firstJust,
16         expectJust,
17         maybeToBool,
18
19         assocMaybe,
20         mkLookupFun, mkLookupFunDef,
21
22         failMaB,
23         failMaybe,
24         seqMaybe,
25         returnMaB,
26         returnMaybe,
27         thenMaB,
28         catMaybes
29     ) where
30
31 CHK_Ubiq()              -- debugging consistency check
32 import Unique  (Unique) -- only for specialising
33
34 #if __GLASGOW_HASKELL__ >= 204
35 import Maybe( catMaybes, mapMaybe )
36 #endif
37
38 \end{code}
39
40
41 %************************************************************************
42 %*                                                                      *
43 \subsection[Maybe type]{The @Maybe@ type}
44 %*                                                                      *
45 %************************************************************************
46
47 \begin{code}
48 maybeToBool :: Maybe a -> Bool
49 maybeToBool Nothing  = False
50 maybeToBool (Just x) = True
51 \end{code}
52
53 @catMaybes@ takes a list of @Maybe@s and returns a list of
54 the contents of all the @Just@s in it.  @allMaybes@ collects
55 a list of @Justs@ into a single @Just@, returning @Nothing@ if there
56 are any @Nothings@.
57
58 \begin{code}
59 allMaybes :: [Maybe a] -> Maybe [a]
60 allMaybes [] = Just []
61 allMaybes (Nothing : ms) = Nothing
62 allMaybes (Just x  : ms) = case (allMaybes ms) of
63                              Nothing -> Nothing
64                              Just xs -> Just (x:xs)
65
66 #if __GLASGOW_HASKELL__ < 204
67         -- After 2.04 we get these from the library Maybe
68 catMaybes :: [Maybe a] -> [a]
69 catMaybes []                = []
70 catMaybes (Nothing : xs)   = catMaybes xs
71 catMaybes (Just x : xs)    = (x : catMaybes xs)
72
73 mapMaybe :: (a -> Maybe b) -> [a] -> [b]
74 mapMaybe f [] = []
75 mapMaybe f (x:xs) = case f x of
76                         Just y  -> y : mapMaybe f xs
77                         Nothing -> mapMaybe f xs
78 #endif
79 \end{code}
80
81 @firstJust@ takes a list of @Maybes@ and returns the
82 first @Just@ if there is one, or @Nothing@ otherwise.
83
84 \begin{code}
85 firstJust :: [Maybe a] -> Maybe a
86 firstJust [] = Nothing
87 firstJust (Just x  : ms) = Just x
88 firstJust (Nothing : ms) = firstJust ms
89 \end{code}
90
91 \begin{code}
92 findJust :: (a -> Maybe b) -> [a] -> Maybe b
93 findJust f []     = Nothing
94 findJust f (a:as) = case f a of
95                       Nothing -> findJust f as
96                       b  -> b
97 \end{code}
98
99 \begin{code}
100 expectJust :: String -> Maybe a -> a
101 {-# INLINE expectJust #-}
102 expectJust err (Just x) = x
103 expectJust err Nothing  = error ("expectJust " ++ err)
104 \end{code}
105
106 The Maybe monad
107 ~~~~~~~~~~~~~~~
108 \begin{code}
109 seqMaybe :: Maybe a -> Maybe a -> Maybe a
110 seqMaybe (Just x) _  = Just x
111 seqMaybe Nothing  my = my
112
113 returnMaybe :: a -> Maybe a
114 returnMaybe = Just
115
116 failMaybe :: Maybe a
117 failMaybe = Nothing
118 \end{code}
119
120 Lookup functions
121 ~~~~~~~~~~~~~~~~
122
123 @assocMaybe@ looks up in an assocation list, returning
124 @Nothing@ if it fails.
125
126 \begin{code}
127 assocMaybe :: (Eq a) => [(a,b)] -> a -> Maybe b
128
129 assocMaybe alist key
130   = lookup alist
131   where
132     lookup []             = Nothing
133     lookup ((tv,ty):rest) = if key == tv then Just ty else lookup rest
134
135 {-# SPECIALIZE assocMaybe
136         :: [(FAST_STRING,   b)] -> FAST_STRING -> Maybe b
137          , [(Int,           b)] -> Int         -> Maybe b
138          , [(Unique,        b)] -> Unique      -> Maybe b
139   #-}
140 \end{code}
141
142 @mkLookupFun eq alist@ is a function which looks up
143 its argument in the association list @alist@, returning a Maybe type.
144 @mkLookupFunDef@ is similar except that it is given a value to return
145 on failure.
146
147 \begin{code}
148 mkLookupFun :: (key -> key -> Bool)     -- Equality predicate
149             -> [(key,val)]              -- The assoc list
150             -> key                      -- The key
151             -> Maybe val                -- The corresponding value
152
153 mkLookupFun eq alist s
154   = case [a | (s',a) <- alist, s' `eq` s] of
155       []    -> Nothing
156       (a:_) -> Just a
157
158 mkLookupFunDef :: (key -> key -> Bool)  -- Equality predicate
159                -> [(key,val)]           -- The assoc list
160                -> val                   -- Value to return on failure
161                -> key                   -- The key
162                -> val                   -- The corresponding value
163
164 mkLookupFunDef eq alist deflt s
165   = case [a | (s',a) <- alist, s' `eq` s] of
166       []    -> deflt
167       (a:_) -> a
168 \end{code}
169
170 %************************************************************************
171 %*                                                                      *
172 \subsection[MaybeErr type]{The @MaybeErr@ type}
173 %*                                                                      *
174 %************************************************************************
175
176 \begin{code}
177 data MaybeErr val err = Succeeded val | Failed err
178 \end{code}
179
180 \begin{code}
181 thenMaB :: MaybeErr val1 err -> (val1 -> MaybeErr val2 err) -> MaybeErr val2 err
182 thenMaB m k
183   = case m of
184       Succeeded v -> k v
185       Failed e    -> Failed e
186
187 returnMaB :: val -> MaybeErr val err
188 returnMaB v = Succeeded v
189
190 failMaB :: err -> MaybeErr val err
191 failMaB e = Failed e
192 \end{code}