1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
%
% (c) The University of Glasgow 2006
% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
%
\begin{code}
{-# OPTIONS -fno-warn-tabs #-}
-- The above warning supression flag is a temporary kludge.
-- While working on this module you are encouraged to remove it and
-- detab the module (please do the detabbing in a separate patch). See
-- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#TabsvsSpaces
-- for details
module Maybes (
module Data.Maybe,
MaybeErr(..), -- Instance of Monad
failME, isSuccess,
fmapM_maybe,
orElse,
mapCatMaybes,
allMaybes,
firstJust, firstJusts,
expectJust,
maybeToBool,
MaybeT(..)
) where
import Data.Maybe
infixr 4 `orElse`
\end{code}
%************************************************************************
%* *
\subsection[Maybe type]{The @Maybe@ type}
%* *
%************************************************************************
\begin{code}
maybeToBool :: Maybe a -> Bool
maybeToBool Nothing = False
maybeToBool (Just _) = True
-- | Collects a list of @Justs@ into a single @Just@, returning @Nothing@ if
-- there are any @Nothings@.
allMaybes :: [Maybe a] -> Maybe [a]
allMaybes [] = Just []
allMaybes (Nothing : _) = Nothing
allMaybes (Just x : ms) = case allMaybes ms of
Nothing -> Nothing
Just xs -> Just (x:xs)
firstJust :: Maybe a -> Maybe a -> Maybe a
firstJust (Just a) _ = Just a
firstJust Nothing b = b
-- | Takes a list of @Maybes@ and returns the first @Just@ if there is one, or
-- @Nothing@ otherwise.
firstJusts :: [Maybe a] -> Maybe a
firstJusts = foldr firstJust Nothing
\end{code}
\begin{code}
expectJust :: String -> Maybe a -> a
{-# INLINE expectJust #-}
expectJust _ (Just x) = x
expectJust err Nothing = error ("expectJust " ++ err)
\end{code}
\begin{code}
mapCatMaybes :: (a -> Maybe b) -> [a] -> [b]
mapCatMaybes _ [] = []
mapCatMaybes f (x:xs) = case f x of
Just y -> y : mapCatMaybes f xs
Nothing -> mapCatMaybes f xs
\end{code}
\begin{code}
-- | flipped version of @fromMaybe@.
orElse :: Maybe a -> a -> a
(Just x) `orElse` _ = x
Nothing `orElse` y = y
\end{code}
\begin{code}
fmapM_maybe :: Monad m => (a -> m b) -> Maybe a -> m (Maybe b)
fmapM_maybe _ Nothing = return Nothing
fmapM_maybe f (Just x) = do
x' <- f x
return $ Just x'
\end{code}
%************************************************************************
%* *
\subsection[MaybeT type]{The @MaybeT@ monad transformer}
%* *
%************************************************************************
\begin{code}
newtype MaybeT m a = MaybeT {runMaybeT :: m (Maybe a)}
instance Functor m => Functor (MaybeT m) where
fmap f x = MaybeT $ fmap (fmap f) $ runMaybeT x
instance Monad m => Monad (MaybeT m) where
return = MaybeT . return . Just
x >>= f = MaybeT $ runMaybeT x >>= maybe (return Nothing) (runMaybeT . f)
fail _ = MaybeT $ return Nothing
\end{code}
%************************************************************************
%* *
\subsection[MaybeErr type]{The @MaybeErr@ type}
%* *
%************************************************************************
\begin{code}
data MaybeErr err val = Succeeded val | Failed err
instance Monad (MaybeErr err) where
return v = Succeeded v
Succeeded v >>= k = k v
Failed e >>= _ = Failed e
isSuccess :: MaybeErr err val -> Bool
isSuccess (Succeeded {}) = True
isSuccess (Failed {}) = False
failME :: err -> MaybeErr err val
failME e = Failed e
\end{code}
|