Skip to content

Commit

Permalink
Merge pull request #41 from hdgarrood/exceptt
Browse files Browse the repository at this point in the history
ExceptT
  • Loading branch information
paf31 committed Apr 17, 2015
2 parents bbef860 + ad39b0a commit 8340a89
Show file tree
Hide file tree
Showing 7 changed files with 307 additions and 1 deletion.
4 changes: 4 additions & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ module.exports = function(grunt) {
src: ["src/Control/Monad/Error/*.purs", "src/Control/Monad/Error.purs"],
dest: "docs/Monad/Error.md"
},
except: {
src: ["src/Control/Monad/Except/*.purs", "src/Control/Monad/Except.purs"],
dest: "docs/Monad/Except.md"
},
maybe: {
src: "src/Control/Monad/Maybe/*.purs",
dest: "docs/Monad/Maybe.md"
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Monad and comonad transformers based on [mtl](http://hackage.haskell.org/package

- [MonadTrans](docs/Monad/Trans.md)
- [Errors](docs/Monad/Error.md)
- [Exceptions](docs/Monad/Except.md)
- [Maybe](docs/Monad/Maybe.md)
- [State](docs/Monad/State.md)
- [Writer](docs/Monad/Writer.md)
Expand All @@ -25,4 +26,4 @@ Monad and comonad transformers based on [mtl](http://hackage.haskell.org/package
- [ComonadTrans](docs/Comonad/Trans.md)
- [Environment](docs/Comonad/Env.md)
- [Store](docs/Comonad/Store.md)
- [Cowriter](docs/Comonad/Traced.md)
- [Cowriter](docs/Comonad/Traced.md)
7 changes: 7 additions & 0 deletions docs/Monad/Error.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@ instance monadErrorErrorT :: (Monad m) => MonadError e (ErrorT e m)
```


#### `monadErrorExceptT`

``` purescript
instance monadErrorExceptT :: (Monad m) => MonadError e (ExceptT e m)
```


#### `monadErrorMaybeT`

``` purescript
Expand Down
175 changes: 175 additions & 0 deletions docs/Monad/Except.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
# Module Documentation

## Module Control.Monad.Except.Trans

#### `ExceptT`

``` purescript
newtype ExceptT e m a
= ExceptT (m (Either e a))
```

A monad transformer which adds exceptions to other monads, in the same way
as `Except`. As before, `e` is the type of exceptions, and `a` is the type
of successful results. The new type parameter `m` is the inner monad that
computations run in.

#### `runExceptT`

``` purescript
runExceptT :: forall e m a. ExceptT e m a -> m (Either e a)
```

The inverse of `ExceptT`. Run a computation in the `ExceptT` monad.

#### `withExceptT`

``` purescript
withExceptT :: forall e e' m a. (Functor m) => (e -> e') -> ExceptT e m a -> ExceptT e' m a
```

Transform any exceptions thrown by an `ExceptT` computation using the given function.

#### `mapExceptT`

``` purescript
mapExceptT :: forall e e' m n a b. (m (Either e a) -> n (Either e' b)) -> ExceptT e m a -> ExceptT e' n b
```

Transform the unwrapped computation using the given function.

#### `functorExceptT`

``` purescript
instance functorExceptT :: (Functor f) => Functor (ExceptT e f)
```


#### `applyExceptT`

``` purescript
instance applyExceptT :: (Apply f) => Apply (ExceptT e f)
```


#### `applicativeExceptT`

``` purescript
instance applicativeExceptT :: (Monad m) => Applicative (ExceptT e m)
```


#### `bindExceptT`

``` purescript
instance bindExceptT :: (Monad m) => Bind (ExceptT e m)
```


#### `monadExceptT`

``` purescript
instance monadExceptT :: (Monad m) => Monad (ExceptT e m)
```


#### `altExceptT`

``` purescript
instance altExceptT :: (Semigroup e, Monad m) => Alt (ExceptT e m)
```


#### `plusExceptT`

``` purescript
instance plusExceptT :: (Monoid e, Monad m) => Plus (ExceptT e m)
```


#### `alternativeExceptT`

``` purescript
instance alternativeExceptT :: (Monoid e, Monad m) => Alternative (ExceptT e m)
```


#### `monadPlusExceptT`

``` purescript
instance monadPlusExceptT :: (Monoid e, Monad m) => MonadPlus (ExceptT e m)
```


#### `throwE`

``` purescript
throwE :: forall e m a. (Applicative m) => e -> ExceptT e m a
```

Throw an exception in an `ExceptT` computation.

#### `catchE`

``` purescript
catchE :: forall e e' m a. (Monad m) => ExceptT e m a -> (e -> ExceptT e' m a) -> ExceptT e' m a
```

Catch an exception in an `ExceptT` computation.


## Module Control.Monad.Except

#### `Except`

``` purescript
type Except e a = ExceptT e Identity a
```

A parametrizable exception monad; computations are either exceptions or
pure values. If an exception is thrown (see `throwE`), the computation
terminates with that value. Exceptions may also be caught with `catchE`,
allowing the computation to resume and exit successfully.

The type parameter `e` is the type of exceptions, and `a` is the type
of successful results.

A mechanism for trying many different computations until one succeeds is
provided via the `Alt` instance, specifically the `(<|>)` function.
The first computation to succeed is returned; if all fail, the exceptions
are combined using their `Semigroup` instance. The `Plus` instance goes
further and adds the possibility of a computation failing with an 'empty'
exception; naturally, this requires the stronger constraint of a `Monoid`
instance for the exception type.

#### `except`

``` purescript
except :: forall e a. Either e a -> Except e a
```

Construct a computation in the `Except` monad from an `Either` value.

#### `runExcept`

``` purescript
runExcept :: forall e a. Except e a -> Either e a
```

Run a computation in the `Except` monad. The inverse of `except`.

#### `mapExcept`

``` purescript
mapExcept :: forall e e' a b. (Either e a -> Either e' b) -> Except e a -> Except e' b
```

Transform the unwrapped computation using the given function.

#### `withExcept`

``` purescript
withExcept :: forall e e' a. (e -> e') -> Except e a -> Except e' a
```

Transform any exceptions thrown by an `Except` computation using the given function.
5 changes: 5 additions & 0 deletions src/Control/Monad/Error/Class.purs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module Control.Monad.Error.Class where
import Control.Monad.Trans
import Control.Monad.Error
import Control.Monad.Error.Trans
import Control.Monad.Except.Trans
import Control.Monad.Maybe.Trans
import Control.Monad.Reader.Trans
import Control.Monad.Writer.Trans
Expand Down Expand Up @@ -67,6 +68,10 @@ instance monadErrorErrorT :: (Monad m) => MonadError e (ErrorT e m) where
Left e -> runErrorT (h e)
Right x -> return (Right x)

instance monadErrorExceptT :: (Monad m) => MonadError e (ExceptT e m) where
throwError = throwE
catchError = catchE

instance monadErrorMaybeT :: (Monad m, MonadError e m) => MonadError e (MaybeT m) where
throwError e = lift (throwError e)
catchError = liftCatchMaybe catchError
Expand Down
40 changes: 40 additions & 0 deletions src/Control/Monad/Except.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@

module Control.Monad.Except where

import Data.Either
import Data.Identity
import Control.Monad.Except.Trans

-- | A parametrizable exception monad; computations are either exceptions or
-- | pure values. If an exception is thrown (see `throwE`), the computation
-- | terminates with that value. Exceptions may also be caught with `catchE`,
-- | allowing the computation to resume and exit successfully.
-- |
-- | The type parameter `e` is the type of exceptions, and `a` is the type
-- | of successful results.
-- |
-- | A mechanism for trying many different computations until one succeeds is
-- | provided via the `Alt` instance, specifically the `(<|>)` function.
-- | The first computation to succeed is returned; if all fail, the exceptions
-- | are combined using their `Semigroup` instance. The `Plus` instance goes
-- | further and adds the possibility of a computation failing with an 'empty'
-- | exception; naturally, this requires the stronger constraint of a `Monoid`
-- | instance for the exception type.
type Except e a = ExceptT e Identity a

-- | Construct a computation in the `Except` monad from an `Either` value.
except :: forall e a. Either e a -> Except e a
except = ExceptT <<< Identity

-- | Run a computation in the `Except` monad. The inverse of `except`.
runExcept :: forall e a. Except e a -> Either e a
runExcept = runIdentity <<< runExceptT

-- | Transform the unwrapped computation using the given function.
mapExcept :: forall e e' a b. (Either e a -> Either e' b) -> Except e a -> Except e' b
mapExcept f = mapExceptT (Identity <<< f <<< runIdentity)

-- | Transform any exceptions thrown by an `Except` computation using the given function.
withExcept :: forall e e' a. (e -> e') -> Except e a -> Except e' a
withExcept = withExceptT

74 changes: 74 additions & 0 deletions src/Control/Monad/Except/Trans.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@

module Control.Monad.Except.Trans where

import Control.Alt
import Control.Plus
import Control.Alternative
import Control.MonadPlus
import Data.Either
import Data.Monoid

-- | A monad transformer which adds exceptions to other monads, in the same way
-- | as `Except`. As before, `e` is the type of exceptions, and `a` is the type
-- | of successful results. The new type parameter `m` is the inner monad that
-- | computations run in.
newtype ExceptT e m a = ExceptT (m (Either e a))

-- | The inverse of `ExceptT`. Run a computation in the `ExceptT` monad.
runExceptT :: forall e m a. ExceptT e m a -> m (Either e a)
runExceptT (ExceptT x) = x

-- | Transform any exceptions thrown by an `ExceptT` computation using the given function.
withExceptT :: forall e e' m a. (Functor m) => (e -> e') -> ExceptT e m a -> ExceptT e' m a
withExceptT f = ExceptT <<< (<$>) (mapLeft f) <<< runExceptT
where
mapLeft _ (Right x) = Right x
mapLeft f (Left x) = Left (f x)

-- | Transform the unwrapped computation using the given function.
mapExceptT :: forall e e' m n a b. (m (Either e a) -> n (Either e' b)) -> ExceptT e m a -> ExceptT e' n b
mapExceptT f m = ExceptT (f (runExceptT m))

instance functorExceptT :: (Functor m) => Functor (ExceptT e m) where
(<$>) f = mapExceptT ((<$>) ((<$>) f))

instance applyExceptT :: (Apply m) => Apply (ExceptT e m) where
(<*>) (ExceptT f) (ExceptT x) =
let f' = (<*>) <$> f
x' = f' <*> x
in ExceptT x'

instance applicativeExceptT :: (Applicative m) => Applicative (ExceptT e m) where
pure = ExceptT <<< pure <<< Right

instance bindExceptT :: (Monad m) => Bind (ExceptT e m) where
(>>=) m k = ExceptT (runExceptT m >>=
either (return <<< Left) (runExceptT <<< k))

instance monadExceptT :: (Monad m) => Monad (ExceptT e m)

instance altExceptT :: (Semigroup e, Monad m) => Alt (ExceptT e m) where
(<|>) m n = ExceptT $ do
rm <- runExceptT m
case rm of
Right x -> pure (Right x)
Left err -> do
rn <- runExceptT n
case rn of
Right x -> pure (Right x)
Left err' -> pure (Left (err <> err'))

instance plusExceptT :: (Monoid e, Monad m) => Plus (ExceptT e m) where
empty = throwE mempty

instance alternativeExceptT :: (Monoid e, Monad m) => Alternative (ExceptT e m)

instance monadPlusExceptT :: (Monoid e, Monad m) => MonadPlus (ExceptT e m)

-- | Throw an exception in an `ExceptT` computation.
throwE :: forall e m a. (Applicative m) => e -> ExceptT e m a
throwE = ExceptT <<< pure <<< Left

-- | Catch an exception in an `ExceptT` computation.
catchE :: forall e e' m a. (Monad m) => ExceptT e m a -> (e -> ExceptT e' m a) -> ExceptT e' m a
catchE m handler = ExceptT (runExceptT m >>= either (runExceptT <<< handler) (pure <<< Right))

0 comments on commit 8340a89

Please sign in to comment.