[project @ 2000-03-23 17:45:17 by simonpj]
[ghc-hetmet.git] / ghc / compiler / utils / Maybes.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
3 %
4 \section[Maybes]{The `Maybe' types and associated utility functions}
5
6 \begin{code}
7 module Maybes (
8         Maybe2(..), Maybe3(..),
9         MaybeErr(..),
10
11         orElse, 
12         mapMaybe,
13         allMaybes,
14         firstJust,
15         expectJust,
16         maybeToBool,
17
18         assocMaybe,
19         mkLookupFun, mkLookupFunDef,
20
21         failMaB,
22         failMaybe,
23         seqMaybe,
24         returnMaB,
25         returnMaybe,
26         thenMaB,
27         catMaybes
28     ) where
29
30 #include "HsVersions.h"
31
32 import Maybe( catMaybes, mapMaybe )
33
34
35 infixr 4 `orElse`
36 \end{code}
37
38
39 %************************************************************************
40 %*                                                                      *
41 \subsection[Maybe2,3 types]{The @Maybe2@ and @Maybe3@ types}
42 %*                                                                      *
43 %************************************************************************
44
45 \begin{code}
46 data Maybe2 a b   = Just2 a b   | Nothing2  deriving (Eq,Show)
47 data Maybe3 a b c = Just3 a b c | Nothing3  deriving (Eq,Show)
48 \end{code}
49
50
51 %************************************************************************
52 %*                                                                      *
53 \subsection[Maybe type]{The @Maybe@ type}
54 %*                                                                      *
55 %************************************************************************
56
57 \begin{code}
58 maybeToBool :: Maybe a -> Bool
59 maybeToBool Nothing  = False
60 maybeToBool (Just x) = True
61 \end{code}
62
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
66 are any @Nothings@.
67
68 \begin{code}
69 allMaybes :: [Maybe a] -> Maybe [a]
70 allMaybes [] = Just []
71 allMaybes (Nothing : ms) = Nothing
72 allMaybes (Just x  : ms) = case (allMaybes ms) of
73                              Nothing -> Nothing
74                              Just xs -> Just (x:xs)
75
76 \end{code}
77
78 @firstJust@ takes a list of @Maybes@ and returns the
79 first @Just@ if there is one, or @Nothing@ otherwise.
80
81 \begin{code}
82 firstJust :: [Maybe a] -> Maybe a
83 firstJust [] = Nothing
84 firstJust (Just x  : ms) = Just x
85 firstJust (Nothing : ms) = firstJust ms
86 \end{code}
87
88 \begin{code}
89 findJust :: (a -> Maybe b) -> [a] -> Maybe b
90 findJust f []     = Nothing
91 findJust f (a:as) = case f a of
92                       Nothing -> findJust f as
93                       b  -> b
94 \end{code}
95
96 \begin{code}
97 expectJust :: String -> Maybe a -> a
98 {-# INLINE expectJust #-}
99 expectJust err (Just x) = x
100 expectJust err Nothing  = error ("expectJust " ++ err)
101 \end{code}
102
103 The Maybe monad
104 ~~~~~~~~~~~~~~~
105 \begin{code}
106 seqMaybe :: Maybe a -> Maybe a -> Maybe a
107 seqMaybe (Just x) _  = Just x
108 seqMaybe Nothing  my = my
109
110 returnMaybe :: a -> Maybe a
111 returnMaybe = Just
112
113 failMaybe :: Maybe a
114 failMaybe = Nothing
115
116 orElse :: Maybe a -> a -> a
117 (Just x) `orElse` y = x
118 Nothing  `orElse` y = y
119 \end{code}
120
121 Lookup functions
122 ~~~~~~~~~~~~~~~~
123
124 @assocMaybe@ looks up in an assocation list, returning
125 @Nothing@ if it fails.
126
127 \begin{code}
128 assocMaybe :: (Eq a) => [(a,b)] -> a -> Maybe b
129
130 assocMaybe alist key
131   = lookup alist
132   where
133     lookup []             = Nothing
134     lookup ((tv,ty):rest) = if key == tv then Just ty else lookup rest
135 \end{code}
136
137 @mkLookupFun eq alist@ is a function which looks up
138 its argument in the association list @alist@, returning a Maybe type.
139 @mkLookupFunDef@ is similar except that it is given a value to return
140 on failure.
141
142 \begin{code}
143 mkLookupFun :: (key -> key -> Bool)     -- Equality predicate
144             -> [(key,val)]              -- The assoc list
145             -> key                      -- The key
146             -> Maybe val                -- The corresponding value
147
148 mkLookupFun eq alist s
149   = case [a | (s',a) <- alist, s' `eq` s] of
150       []    -> Nothing
151       (a:_) -> Just a
152
153 mkLookupFunDef :: (key -> key -> Bool)  -- Equality predicate
154                -> [(key,val)]           -- The assoc list
155                -> val                   -- Value to return on failure
156                -> key                   -- The key
157                -> val                   -- The corresponding value
158
159 mkLookupFunDef eq alist deflt s
160   = case [a | (s',a) <- alist, s' `eq` s] of
161       []    -> deflt
162       (a:_) -> a
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