[project @ 1999-05-18 15:03:54 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 --      Maybe(..), -- no, it's in 1.3
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[Maybe type]{The @Maybe@ type}
42 %*                                                                      *
43 %************************************************************************
44
45 \begin{code}
46 maybeToBool :: Maybe a -> Bool
47 maybeToBool Nothing  = False
48 maybeToBool (Just x) = True
49 \end{code}
50
51 @catMaybes@ takes a list of @Maybe@s and returns a list of
52 the contents of all the @Just@s in it.  @allMaybes@ collects
53 a list of @Justs@ into a single @Just@, returning @Nothing@ if there
54 are any @Nothings@.
55
56 \begin{code}
57 allMaybes :: [Maybe a] -> Maybe [a]
58 allMaybes [] = Just []
59 allMaybes (Nothing : ms) = Nothing
60 allMaybes (Just x  : ms) = case (allMaybes ms) of
61                              Nothing -> Nothing
62                              Just xs -> Just (x:xs)
63
64 \end{code}
65
66 @firstJust@ takes a list of @Maybes@ and returns the
67 first @Just@ if there is one, or @Nothing@ otherwise.
68
69 \begin{code}
70 firstJust :: [Maybe a] -> Maybe a
71 firstJust [] = Nothing
72 firstJust (Just x  : ms) = Just x
73 firstJust (Nothing : ms) = firstJust ms
74 \end{code}
75
76 \begin{code}
77 findJust :: (a -> Maybe b) -> [a] -> Maybe b
78 findJust f []     = Nothing
79 findJust f (a:as) = case f a of
80                       Nothing -> findJust f as
81                       b  -> b
82 \end{code}
83
84 \begin{code}
85 expectJust :: String -> Maybe a -> a
86 {-# INLINE expectJust #-}
87 expectJust err (Just x) = x
88 expectJust err Nothing  = error ("expectJust " ++ err)
89 \end{code}
90
91 The Maybe monad
92 ~~~~~~~~~~~~~~~
93 \begin{code}
94 seqMaybe :: Maybe a -> Maybe a -> Maybe a
95 seqMaybe (Just x) _  = Just x
96 seqMaybe Nothing  my = my
97
98 returnMaybe :: a -> Maybe a
99 returnMaybe = Just
100
101 failMaybe :: Maybe a
102 failMaybe = Nothing
103
104 orElse :: Maybe a -> a -> a
105 (Just x) `orElse` y = x
106 Nothing  `orElse` y = y
107 \end{code}
108
109 Lookup functions
110 ~~~~~~~~~~~~~~~~
111
112 @assocMaybe@ looks up in an assocation list, returning
113 @Nothing@ if it fails.
114
115 \begin{code}
116 assocMaybe :: (Eq a) => [(a,b)] -> a -> Maybe b
117
118 assocMaybe alist key
119   = lookup alist
120   where
121     lookup []             = Nothing
122     lookup ((tv,ty):rest) = if key == tv then Just ty else lookup rest
123 \end{code}
124
125 @mkLookupFun eq alist@ is a function which looks up
126 its argument in the association list @alist@, returning a Maybe type.
127 @mkLookupFunDef@ is similar except that it is given a value to return
128 on failure.
129
130 \begin{code}
131 mkLookupFun :: (key -> key -> Bool)     -- Equality predicate
132             -> [(key,val)]              -- The assoc list
133             -> key                      -- The key
134             -> Maybe val                -- The corresponding value
135
136 mkLookupFun eq alist s
137   = case [a | (s',a) <- alist, s' `eq` s] of
138       []    -> Nothing
139       (a:_) -> Just a
140
141 mkLookupFunDef :: (key -> key -> Bool)  -- Equality predicate
142                -> [(key,val)]           -- The assoc list
143                -> val                   -- Value to return on failure
144                -> key                   -- The key
145                -> val                   -- The corresponding value
146
147 mkLookupFunDef eq alist deflt s
148   = case [a | (s',a) <- alist, s' `eq` s] of
149       []    -> deflt
150       (a:_) -> a
151 \end{code}
152
153 %************************************************************************
154 %*                                                                      *
155 \subsection[MaybeErr type]{The @MaybeErr@ type}
156 %*                                                                      *
157 %************************************************************************
158
159 \begin{code}
160 data MaybeErr val err = Succeeded val | Failed err
161 \end{code}
162
163 \begin{code}
164 thenMaB :: MaybeErr val1 err -> (val1 -> MaybeErr val2 err) -> MaybeErr val2 err
165 thenMaB m k
166   = case m of
167       Succeeded v -> k v
168       Failed e    -> Failed e
169
170 returnMaB :: val -> MaybeErr val err
171 returnMaB v = Succeeded v
172
173 failMaB :: err -> MaybeErr val err
174 failMaB e = Failed e
175 \end{code}