tweag/capability

Add Error capability

aherrmann opened this issue · 1 comments

As requested in #17 (comment) .

Some points for discussion:

  1. Is a tag meaningful and useful?
    It could be used to select a layer in a transformer stack. E.g.
    example :: ExampleM ()
    example = do
      let catchIO = catch @"io"
      throw @"either" MyException
        `catchIO` \MyExcetion -> pure ()
    
    newtype ExampleM a = ExampleM (ExceptT MyException IO)
  2. Should we follow Control.Monad.Catch and have separate capabilities for throw/catch/mask, or rather one class for all?
    Separate classes seem more flexible. E.g. throw works in cases where mask doesn't.
  3. Should the error type be an index to HasError?
    If HasError should cover e.g. ExceptT then, it seems, the answer should be yes.
    The general IO case could be covered with a synonym HasError_ where e ~ SomeException.

cc @aspiwack

Is a tag meaningful and useful?

Yes, because just as state and reader compose with lenses, exceptions compose with prisms.

So that if you have a bunch of your program which can throw (and presumably catch) PuddingException-s and another bit throws PoundCakeException-s, then you can implement that as one

Either CakeException

data CakeException = Pudding PuddingException | PoundCake PoundCakeException

I'm not sure how to best do the interaction with IO, however. Maybe by making a special type of exception TaggedException tag e which is a newtype for e?

Should we follow Control.Monad.Catch and have separate capabilities for throw/catch/mask, or rather one class for all?

I have no opinion on this one.

Should the error type be an index to HasError

Yes.

The general IO case could be covered with a synonym HasError_ where e ~ SomeException.

Well, you can also implement HasError tag AnotherExceptionType with IO.