Skip to content

Commit 8340a89

Browse files
committed
Merge pull request #41 from hdgarrood/exceptt
ExceptT
2 parents bbef860 + ad39b0a commit 8340a89

File tree

7 files changed

+307
-1
lines changed

7 files changed

+307
-1
lines changed

Gruntfile.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ module.exports = function(grunt) {
2626
src: ["src/Control/Monad/Error/*.purs", "src/Control/Monad/Error.purs"],
2727
dest: "docs/Monad/Error.md"
2828
},
29+
except: {
30+
src: ["src/Control/Monad/Except/*.purs", "src/Control/Monad/Except.purs"],
31+
dest: "docs/Monad/Except.md"
32+
},
2933
maybe: {
3034
src: "src/Control/Monad/Maybe/*.purs",
3135
dest: "docs/Monad/Maybe.md"

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Monad and comonad transformers based on [mtl](http://hackage.haskell.org/package
1313

1414
- [MonadTrans](docs/Monad/Trans.md)
1515
- [Errors](docs/Monad/Error.md)
16+
- [Exceptions](docs/Monad/Except.md)
1617
- [Maybe](docs/Monad/Maybe.md)
1718
- [State](docs/Monad/State.md)
1819
- [Writer](docs/Monad/Writer.md)
@@ -25,4 +26,4 @@ Monad and comonad transformers based on [mtl](http://hackage.haskell.org/package
2526
- [ComonadTrans](docs/Comonad/Trans.md)
2627
- [Environment](docs/Comonad/Env.md)
2728
- [Store](docs/Comonad/Store.md)
28-
- [Cowriter](docs/Comonad/Traced.md)
29+
- [Cowriter](docs/Comonad/Traced.md)

docs/Monad/Error.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,13 @@ instance monadErrorErrorT :: (Monad m) => MonadError e (ErrorT e m)
6262
```
6363

6464

65+
#### `monadErrorExceptT`
66+
67+
``` purescript
68+
instance monadErrorExceptT :: (Monad m) => MonadError e (ExceptT e m)
69+
```
70+
71+
6572
#### `monadErrorMaybeT`
6673

6774
``` purescript

docs/Monad/Except.md

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
# Module Documentation
2+
3+
## Module Control.Monad.Except.Trans
4+
5+
#### `ExceptT`
6+
7+
``` purescript
8+
newtype ExceptT e m a
9+
= ExceptT (m (Either e a))
10+
```
11+
12+
A monad transformer which adds exceptions to other monads, in the same way
13+
as `Except`. As before, `e` is the type of exceptions, and `a` is the type
14+
of successful results. The new type parameter `m` is the inner monad that
15+
computations run in.
16+
17+
#### `runExceptT`
18+
19+
``` purescript
20+
runExceptT :: forall e m a. ExceptT e m a -> m (Either e a)
21+
```
22+
23+
The inverse of `ExceptT`. Run a computation in the `ExceptT` monad.
24+
25+
#### `withExceptT`
26+
27+
``` purescript
28+
withExceptT :: forall e e' m a. (Functor m) => (e -> e') -> ExceptT e m a -> ExceptT e' m a
29+
```
30+
31+
Transform any exceptions thrown by an `ExceptT` computation using the given function.
32+
33+
#### `mapExceptT`
34+
35+
``` purescript
36+
mapExceptT :: forall e e' m n a b. (m (Either e a) -> n (Either e' b)) -> ExceptT e m a -> ExceptT e' n b
37+
```
38+
39+
Transform the unwrapped computation using the given function.
40+
41+
#### `functorExceptT`
42+
43+
``` purescript
44+
instance functorExceptT :: (Functor f) => Functor (ExceptT e f)
45+
```
46+
47+
48+
#### `applyExceptT`
49+
50+
``` purescript
51+
instance applyExceptT :: (Apply f) => Apply (ExceptT e f)
52+
```
53+
54+
55+
#### `applicativeExceptT`
56+
57+
``` purescript
58+
instance applicativeExceptT :: (Monad m) => Applicative (ExceptT e m)
59+
```
60+
61+
62+
#### `bindExceptT`
63+
64+
``` purescript
65+
instance bindExceptT :: (Monad m) => Bind (ExceptT e m)
66+
```
67+
68+
69+
#### `monadExceptT`
70+
71+
``` purescript
72+
instance monadExceptT :: (Monad m) => Monad (ExceptT e m)
73+
```
74+
75+
76+
#### `altExceptT`
77+
78+
``` purescript
79+
instance altExceptT :: (Semigroup e, Monad m) => Alt (ExceptT e m)
80+
```
81+
82+
83+
#### `plusExceptT`
84+
85+
``` purescript
86+
instance plusExceptT :: (Monoid e, Monad m) => Plus (ExceptT e m)
87+
```
88+
89+
90+
#### `alternativeExceptT`
91+
92+
``` purescript
93+
instance alternativeExceptT :: (Monoid e, Monad m) => Alternative (ExceptT e m)
94+
```
95+
96+
97+
#### `monadPlusExceptT`
98+
99+
``` purescript
100+
instance monadPlusExceptT :: (Monoid e, Monad m) => MonadPlus (ExceptT e m)
101+
```
102+
103+
104+
#### `throwE`
105+
106+
``` purescript
107+
throwE :: forall e m a. (Applicative m) => e -> ExceptT e m a
108+
```
109+
110+
Throw an exception in an `ExceptT` computation.
111+
112+
#### `catchE`
113+
114+
``` purescript
115+
catchE :: forall e e' m a. (Monad m) => ExceptT e m a -> (e -> ExceptT e' m a) -> ExceptT e' m a
116+
```
117+
118+
Catch an exception in an `ExceptT` computation.
119+
120+
121+
## Module Control.Monad.Except
122+
123+
#### `Except`
124+
125+
``` purescript
126+
type Except e a = ExceptT e Identity a
127+
```
128+
129+
A parametrizable exception monad; computations are either exceptions or
130+
pure values. If an exception is thrown (see `throwE`), the computation
131+
terminates with that value. Exceptions may also be caught with `catchE`,
132+
allowing the computation to resume and exit successfully.
133+
134+
The type parameter `e` is the type of exceptions, and `a` is the type
135+
of successful results.
136+
137+
A mechanism for trying many different computations until one succeeds is
138+
provided via the `Alt` instance, specifically the `(<|>)` function.
139+
The first computation to succeed is returned; if all fail, the exceptions
140+
are combined using their `Semigroup` instance. The `Plus` instance goes
141+
further and adds the possibility of a computation failing with an 'empty'
142+
exception; naturally, this requires the stronger constraint of a `Monoid`
143+
instance for the exception type.
144+
145+
#### `except`
146+
147+
``` purescript
148+
except :: forall e a. Either e a -> Except e a
149+
```
150+
151+
Construct a computation in the `Except` monad from an `Either` value.
152+
153+
#### `runExcept`
154+
155+
``` purescript
156+
runExcept :: forall e a. Except e a -> Either e a
157+
```
158+
159+
Run a computation in the `Except` monad. The inverse of `except`.
160+
161+
#### `mapExcept`
162+
163+
``` purescript
164+
mapExcept :: forall e e' a b. (Either e a -> Either e' b) -> Except e a -> Except e' b
165+
```
166+
167+
Transform the unwrapped computation using the given function.
168+
169+
#### `withExcept`
170+
171+
``` purescript
172+
withExcept :: forall e e' a. (e -> e') -> Except e a -> Except e' a
173+
```
174+
175+
Transform any exceptions thrown by an `Except` computation using the given function.

src/Control/Monad/Error/Class.purs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ module Control.Monad.Error.Class where
55
import Control.Monad.Trans
66
import Control.Monad.Error
77
import Control.Monad.Error.Trans
8+
import Control.Monad.Except.Trans
89
import Control.Monad.Maybe.Trans
910
import Control.Monad.Reader.Trans
1011
import Control.Monad.Writer.Trans
@@ -67,6 +68,10 @@ instance monadErrorErrorT :: (Monad m) => MonadError e (ErrorT e m) where
6768
Left e -> runErrorT (h e)
6869
Right x -> return (Right x)
6970

71+
instance monadErrorExceptT :: (Monad m) => MonadError e (ExceptT e m) where
72+
throwError = throwE
73+
catchError = catchE
74+
7075
instance monadErrorMaybeT :: (Monad m, MonadError e m) => MonadError e (MaybeT m) where
7176
throwError e = lift (throwError e)
7277
catchError = liftCatchMaybe catchError

src/Control/Monad/Except.purs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
2+
module Control.Monad.Except where
3+
4+
import Data.Either
5+
import Data.Identity
6+
import Control.Monad.Except.Trans
7+
8+
-- | A parametrizable exception monad; computations are either exceptions or
9+
-- | pure values. If an exception is thrown (see `throwE`), the computation
10+
-- | terminates with that value. Exceptions may also be caught with `catchE`,
11+
-- | allowing the computation to resume and exit successfully.
12+
-- |
13+
-- | The type parameter `e` is the type of exceptions, and `a` is the type
14+
-- | of successful results.
15+
-- |
16+
-- | A mechanism for trying many different computations until one succeeds is
17+
-- | provided via the `Alt` instance, specifically the `(<|>)` function.
18+
-- | The first computation to succeed is returned; if all fail, the exceptions
19+
-- | are combined using their `Semigroup` instance. The `Plus` instance goes
20+
-- | further and adds the possibility of a computation failing with an 'empty'
21+
-- | exception; naturally, this requires the stronger constraint of a `Monoid`
22+
-- | instance for the exception type.
23+
type Except e a = ExceptT e Identity a
24+
25+
-- | Construct a computation in the `Except` monad from an `Either` value.
26+
except :: forall e a. Either e a -> Except e a
27+
except = ExceptT <<< Identity
28+
29+
-- | Run a computation in the `Except` monad. The inverse of `except`.
30+
runExcept :: forall e a. Except e a -> Either e a
31+
runExcept = runIdentity <<< runExceptT
32+
33+
-- | Transform the unwrapped computation using the given function.
34+
mapExcept :: forall e e' a b. (Either e a -> Either e' b) -> Except e a -> Except e' b
35+
mapExcept f = mapExceptT (Identity <<< f <<< runIdentity)
36+
37+
-- | Transform any exceptions thrown by an `Except` computation using the given function.
38+
withExcept :: forall e e' a. (e -> e') -> Except e a -> Except e' a
39+
withExcept = withExceptT
40+

src/Control/Monad/Except/Trans.purs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
2+
module Control.Monad.Except.Trans where
3+
4+
import Control.Alt
5+
import Control.Plus
6+
import Control.Alternative
7+
import Control.MonadPlus
8+
import Data.Either
9+
import Data.Monoid
10+
11+
-- | A monad transformer which adds exceptions to other monads, in the same way
12+
-- | as `Except`. As before, `e` is the type of exceptions, and `a` is the type
13+
-- | of successful results. The new type parameter `m` is the inner monad that
14+
-- | computations run in.
15+
newtype ExceptT e m a = ExceptT (m (Either e a))
16+
17+
-- | The inverse of `ExceptT`. Run a computation in the `ExceptT` monad.
18+
runExceptT :: forall e m a. ExceptT e m a -> m (Either e a)
19+
runExceptT (ExceptT x) = x
20+
21+
-- | Transform any exceptions thrown by an `ExceptT` computation using the given function.
22+
withExceptT :: forall e e' m a. (Functor m) => (e -> e') -> ExceptT e m a -> ExceptT e' m a
23+
withExceptT f = ExceptT <<< (<$>) (mapLeft f) <<< runExceptT
24+
where
25+
mapLeft _ (Right x) = Right x
26+
mapLeft f (Left x) = Left (f x)
27+
28+
-- | Transform the unwrapped computation using the given function.
29+
mapExceptT :: forall e e' m n a b. (m (Either e a) -> n (Either e' b)) -> ExceptT e m a -> ExceptT e' n b
30+
mapExceptT f m = ExceptT (f (runExceptT m))
31+
32+
instance functorExceptT :: (Functor m) => Functor (ExceptT e m) where
33+
(<$>) f = mapExceptT ((<$>) ((<$>) f))
34+
35+
instance applyExceptT :: (Apply m) => Apply (ExceptT e m) where
36+
(<*>) (ExceptT f) (ExceptT x) =
37+
let f' = (<*>) <$> f
38+
x' = f' <*> x
39+
in ExceptT x'
40+
41+
instance applicativeExceptT :: (Applicative m) => Applicative (ExceptT e m) where
42+
pure = ExceptT <<< pure <<< Right
43+
44+
instance bindExceptT :: (Monad m) => Bind (ExceptT e m) where
45+
(>>=) m k = ExceptT (runExceptT m >>=
46+
either (return <<< Left) (runExceptT <<< k))
47+
48+
instance monadExceptT :: (Monad m) => Monad (ExceptT e m)
49+
50+
instance altExceptT :: (Semigroup e, Monad m) => Alt (ExceptT e m) where
51+
(<|>) m n = ExceptT $ do
52+
rm <- runExceptT m
53+
case rm of
54+
Right x -> pure (Right x)
55+
Left err -> do
56+
rn <- runExceptT n
57+
case rn of
58+
Right x -> pure (Right x)
59+
Left err' -> pure (Left (err <> err'))
60+
61+
instance plusExceptT :: (Monoid e, Monad m) => Plus (ExceptT e m) where
62+
empty = throwE mempty
63+
64+
instance alternativeExceptT :: (Monoid e, Monad m) => Alternative (ExceptT e m)
65+
66+
instance monadPlusExceptT :: (Monoid e, Monad m) => MonadPlus (ExceptT e m)
67+
68+
-- | Throw an exception in an `ExceptT` computation.
69+
throwE :: forall e m a. (Applicative m) => e -> ExceptT e m a
70+
throwE = ExceptT <<< pure <<< Left
71+
72+
-- | Catch an exception in an `ExceptT` computation.
73+
catchE :: forall e e' m a. (Monad m) => ExceptT e m a -> (e -> ExceptT e' m a) -> ExceptT e' m a
74+
catchE m handler = ExceptT (runExceptT m >>= either (runExceptT <<< handler) (pure <<< Right))

0 commit comments

Comments
 (0)