License | BSD |
---|---|

Maintainer | wren@community.haskell.org |

Stability | provisional |

Portability | semi-portable (CPP, Rank2Types, MPTCs, FlexibleInstances) |

Safe Haskell | Safe-Inferred |

Language | Haskell98 |

A continuation-passing variant of `Either`

for short-circuiting
at failure. This code is based on Control.Monad.MaybeK.

## Synopsis

- data EitherK e a
- runEitherK :: EitherK e a -> Either e a
- toEitherK :: Either e a -> EitherK e a
- eitherK :: (e -> b) -> (a -> b) -> EitherK e a -> b
- throwEitherK :: e -> EitherK e a
- catchEitherK :: EitherK e a -> (e -> EitherK f a) -> EitherK f a
- data EitherKT e m a
- runEitherKT :: Applicative m => EitherKT e m a -> m (Either e a)
- toEitherKT :: Applicative m => Either e a -> EitherKT e m a
- liftEitherK :: Applicative m => EitherK e a -> EitherKT e m a
- lowerEitherK :: Applicative m => EitherKT e m a -> m (EitherK e a)
- throwEitherKT :: Applicative m => e -> EitherKT e m a
- catchEitherKT :: (Applicative m, Monad m) => EitherKT e m a -> (e -> EitherKT f m a) -> EitherKT f m a

# The short-circuiting monad

A continuation-passing encoding of `Either`

as an error monad;
also known as `Codensity (Either e)`

, if you're familiar with
that terminology. N.B., this is not the 2-continuation implementation
based on the Church encoding of `Either`

. The latter tends to
have worse performance than non-continuation based implementations.

This is generally more efficient than using `Either`

(or the
MTL's `Error`

) for two reasons. First is that it right associates
all binds, ensuring that bad associativity doesn't artificially
introduce midpoints in short-circuiting to the nearest handler.
Second is that it removes the need for intermediate case
expressions.

Another benefit over MTL's `Error`

is that it doesn't artificially
restrict the error type. In fact, there's no reason why `e`

must
denote "errors" per se. This could also denote computations
which short-circuit with the final answer, or similar methods
of non-local control flow.

N.B., the `Alternative`

and `MonadPlus`

instances are left-biased
in `a`

and monoidal in `e`

. Thus, they are not commutative.

#### Instances

MonadError e (EitherK e) Source # | |

Defined in Control.Monad.EitherK throwError :: e -> EitherK e a # catchError :: EitherK e a -> (e -> EitherK e a) -> EitherK e a # | |

Monad (EitherK e) Source # | |

Functor (EitherK e) Source # | |

Applicative (EitherK e) Source # | |

Monoid e => Alternative (EitherK e) Source # | |

Monoid e => MonadPlus (EitherK e) Source # | |

runEitherK :: EitherK e a -> Either e a Source #

Execute an `EitherK`

and return the concrete `Either`

encoding.

eitherK :: (e -> b) -> (a -> b) -> EitherK e a -> b Source #

A version of `either`

on `EitherK`

, for convenience. N.B.,
using this function inserts a case match, reducing the range of
short-circuiting.

throwEitherK :: e -> EitherK e a Source #

Throw an error in the `EitherK`

monad. This is identical to
`throwError`

.

catchEitherK :: EitherK e a -> (e -> EitherK f a) -> EitherK f a Source #

Handle errors in the `EitherK`

monad. N.B., this type is more
general than that of `catchError`

, allowing the type of the
errors to change.

# The short-circuiting monad transformer

A monad transformer version of `EitherK`

.

#### Instances

(Applicative m, Monad m) => MonadError e (EitherKT e m) Source # | |

Defined in Control.Monad.EitherK throwError :: e -> EitherKT e m a # catchError :: EitherKT e m a -> (e -> EitherKT e m a) -> EitherKT e m a # | |

MonadTrans (EitherKT e) Source # | |

Defined in Control.Monad.EitherK | |

Monad (EitherKT e m) Source # | |

Functor (EitherKT e m) Source # | |

Applicative (EitherKT e m) Source # | |

Defined in Control.Monad.EitherK | |

(Applicative m, Monad m, Monoid e) => Alternative (EitherKT e m) Source # | |

(Applicative m, Monad m, Monoid e) => MonadPlus (EitherKT e m) Source # | |

runEitherKT :: Applicative m => EitherKT e m a -> m (Either e a) Source #

Execute an `EitherKT`

and return the concrete `Either`

encoding.

toEitherKT :: Applicative m => Either e a -> EitherKT e m a Source #

Lift an `Either`

into an `EitherKT`

.

liftEitherK :: Applicative m => EitherK e a -> EitherKT e m a Source #

Lift an `EitherK`

into an `EitherKT`

.

lowerEitherK :: Applicative m => EitherKT e m a -> m (EitherK e a) Source #

Lower an `EitherKT`

into an `EitherK`

.

throwEitherKT :: Applicative m => e -> EitherKT e m a Source #

Throw an error in the `EitherKT`

monad. This is identical to
`throwError`

.

catchEitherKT :: (Applicative m, Monad m) => EitherKT e m a -> (e -> EitherKT f m a) -> EitherKT f m a Source #

Handle errors in the `EitherKT`

monad. N.B., this type is more
general than that of `catchError`

, allowing the type of the
errors to change.