Copyright | (c) Ben Weitzman 2018 |
---|---|

License | MIT |

Maintainer | ben@costarastrolgoy.com |

Stability | experimental |

Portability | POSIX |

Safe Haskell | None |

Language | Haskell2010 |

The `Catching`

effect allows a way to keep track of effects that we might expect to throw
exceptions during their handling, but whose signatures don't indicate this.

As an example, consider an effect `Div`

that divides numbers:

data Div a where Div :: Int -> Int -> Div Int

The keen programmer is aware that this can throw an error. However, suppose that there is reason to believe that
this effect will be rarely used in a way that fails. Adding an indicator to the interface (such as by saying `Div :: Int -> Int -> Div (Maybe Int)`

) makes using this effect more annoying most of the time.

Nevertheless, it should be possible to handle this case when we want to. This is where `Catching`

can help.

## Synopsis

- data Catching f e a
- catching :: forall e f a r. (Exception e, Member (Catching f e) r) => Eff '[f] a -> Eff r (Either e a)
- runCatching :: forall e r v f. (Member IO r, LastMember IO (f ': r)) => (forall a q. Member IO q => Eff (f ': q) a -> Eff q a) -> Eff (Catching f e ': (f ': r)) v -> Eff r v
- runCatching2 :: forall e r v f g. (Member IO r, Member IO (f ': r), LastMember IO (f ': (g ': r))) => (forall a q. Member g q => Eff (f ': q) a -> Eff q a) -> (forall a q. Member IO q => Eff (g ': q) a -> Eff q a) -> Eff (Catching f e ': (f ': (g ': r))) v -> Eff r v

# Documentation

The `Catching`

effect is parameterized by the effect it is handling and the type of exceptions it will
attempt to handle (e.g. `Catching Div ArithException`

)

catching :: forall e f a r. (Exception e, Member (Catching f e) r) => Eff '[f] a -> Eff r (Either e a) Source #

`catching`

will turn an effectful computation producing an `a`

and using effect `f`

into one that produces
an `Either e a`

. This allows any exception that is thrown during normal handling of `f`

be handled explicitly.

runCatching :: forall e r v f. (Member IO r, LastMember IO (f ': r)) => (forall a q. Member IO q => Eff (f ': q) a -> Eff q a) -> Eff (Catching f e ': (f ': r)) v -> Eff r v Source #

runCatching2 :: forall e r v f g. (Member IO r, Member IO (f ': r), LastMember IO (f ': (g ': r))) => (forall a q. Member g q => Eff (f ': q) a -> Eff q a) -> (forall a q. Member IO q => Eff (g ': q) a -> Eff q a) -> Eff (Catching f e ': (f ': (g ': r))) v -> Eff r v Source #

`runCatching2`

can catch exceptions in effects that don't interpret directly to `IO`

but instead
go through an intermediary effect. In this case, three effects will be handled in one go:

- The effect
`f`

that is being called and is expected to be the source of an exception - The effect
`g`

which is not being called directly but is called instead by the handler`f`

- The effect
`Catching f e`