27 |
27 |
, Result
|
28 |
28 |
, ResultT(..)
|
29 |
29 |
, resultT
|
30 |
|
, FromString(..)
|
|
30 |
, Error(..) -- re-export from Control.Monad.Error
|
31 |
31 |
, isOk
|
32 |
32 |
, isBad
|
33 |
33 |
, justOk
|
... | ... | |
74 |
74 |
-- | Type alias for a string Result.
|
75 |
75 |
type Result = GenericResult String
|
76 |
76 |
|
77 |
|
-- | Type class for things that can be built from strings.
|
78 |
|
class FromString a where
|
79 |
|
mkFromString :: String -> a
|
80 |
|
|
81 |
|
-- | Trivial 'String' instance; requires FlexibleInstances extension
|
82 |
|
-- though.
|
83 |
|
instance FromString [Char] where
|
84 |
|
mkFromString = id
|
85 |
|
|
86 |
77 |
-- | 'Monad' instance for 'GenericResult'.
|
87 |
|
instance (FromString a) => Monad (GenericResult a) where
|
|
78 |
instance (Error a) => Monad (GenericResult a) where
|
88 |
79 |
(>>=) (Bad x) _ = Bad x
|
89 |
80 |
(>>=) (Ok x) fn = fn x
|
90 |
81 |
return = Ok
|
91 |
|
fail = Bad . mkFromString
|
|
82 |
fail = Bad . strMsg
|
92 |
83 |
|
93 |
84 |
instance Functor (GenericResult a) where
|
94 |
85 |
fmap _ (Bad msg) = Bad msg
|
95 |
86 |
fmap fn (Ok val) = Ok (fn val)
|
96 |
87 |
|
97 |
|
instance (FromString a, Monoid a) => MonadPlus (GenericResult a) where
|
98 |
|
mzero = Bad $ mkFromString "zero Result when used as MonadPlus"
|
|
88 |
instance (Error a, Monoid a) => MonadPlus (GenericResult a) where
|
|
89 |
mzero = Bad $ strMsg "zero Result when used as MonadPlus"
|
99 |
90 |
-- for mplus, when we 'add' two Bad values, we concatenate their
|
100 |
91 |
-- error descriptions
|
101 |
|
(Bad x) `mplus` (Bad y) = Bad (x `mappend` mkFromString "; " `mappend` y)
|
|
92 |
(Bad x) `mplus` (Bad y) = Bad (x `mappend` strMsg "; " `mappend` y)
|
102 |
93 |
(Bad _) `mplus` x = x
|
103 |
94 |
x@(Ok _) `mplus` _ = x
|
104 |
95 |
|
105 |
|
instance (FromString a) => MonadError a (GenericResult a) where
|
|
96 |
instance (Error a) => MonadError a (GenericResult a) where
|
106 |
97 |
throwError = Bad
|
107 |
98 |
catchError x h = genericResult h (const x) x
|
108 |
99 |
|
... | ... | |
112 |
103 |
_ <*> (Bad x) = Bad x
|
113 |
104 |
(Ok f) <*> (Ok x) = Ok $ f x
|
114 |
105 |
|
115 |
|
instance (FromString a, Monoid a) => Alternative (GenericResult a) where
|
|
106 |
instance (Error a, Monoid a) => Alternative (GenericResult a) where
|
116 |
107 |
empty = mzero
|
117 |
108 |
(<|>) = mplus
|
118 |
109 |
|
... | ... | |
135 |
126 |
instance (Monad f) => Functor (ResultT a f) where
|
136 |
127 |
fmap f = ResultT . liftM (fmap f) . runResultT
|
137 |
128 |
|
138 |
|
instance (Monad m, FromString a) => Applicative (ResultT a m) where
|
|
129 |
instance (Monad m, Error a) => Applicative (ResultT a m) where
|
139 |
130 |
pure = return
|
140 |
131 |
(<*>) = ap
|
141 |
132 |
|
142 |
|
instance (Monad m, FromString a) => Monad (ResultT a m) where
|
143 |
|
fail err = ResultT (return . Bad $ mkFromString err)
|
|
133 |
instance (Monad m, Error a) => Monad (ResultT a m) where
|
|
134 |
fail err = ResultT (return . Bad $ strMsg err)
|
144 |
135 |
return = lift . return
|
145 |
136 |
(>>=) = flip (elimResultT throwError)
|
146 |
137 |
|
147 |
|
instance (Monad m, FromString a) => MonadError a (ResultT a m) where
|
|
138 |
instance (Monad m, Error a) => MonadError a (ResultT a m) where
|
148 |
139 |
throwError = resultT . Bad
|
149 |
140 |
catchError x h = elimResultT h return x
|
150 |
141 |
|
151 |
142 |
instance MonadTrans (ResultT a) where
|
152 |
143 |
lift = ResultT . liftM Ok
|
153 |
144 |
|
154 |
|
instance (MonadIO m, FromString a) => MonadIO (ResultT a m) where
|
|
145 |
instance (MonadIO m, Error a) => MonadIO (ResultT a m) where
|
155 |
146 |
liftIO = lift . liftIO
|
156 |
147 |
|
157 |
|
instance (Monad m, FromString a, Monoid a) => MonadPlus (ResultT a m) where
|
|
148 |
instance (Monad m, Error a, Monoid a) => MonadPlus (ResultT a m) where
|
158 |
149 |
mzero = ResultT $ return mzero
|
159 |
150 |
-- Ensure that 'y' isn't run if 'x' contains a value. This makes it a bit
|
160 |
151 |
-- more complicated than 'mplus' of 'GenericResult'.
|
161 |
152 |
mplus x y = elimResultT combine return x
|
162 |
153 |
where combine x' = ResultT $ liftM (mplus (Bad x')) (runResultT y)
|
163 |
154 |
|
164 |
|
instance (Monad m, FromString a, Monoid a) => Alternative (ResultT a m) where
|
|
155 |
instance (Monad m, Error a, Monoid a) => Alternative (ResultT a m) where
|
165 |
156 |
empty = mzero
|
166 |
157 |
(<|>) = mplus
|
167 |
158 |
|