Gabriella439 / Haskell-Pipes-Safe-Library

Safety for the pipes ecosystem
BSD 3-Clause "New" or "Revised" License
26 stars 21 forks source link

Added functions analogous to 'try' and 'tryJust' from Control.Exception #1

Closed k0001 closed 11 years ago

k0001 commented 11 years ago

Control.Exception exports two functions, try and tryJust, whose behaviour might be easily missed when using pipes-safe error handling facilities.

Here two functions are added:

I'm not particularly fond of their names—“ex” stands for “exception”, by the way—but at least they don't start with “try”, a prefix already used for different purposes in the same module. The name catchEither is arguably better, but then catchEitherJust is weird.

Each of these functions is added in a different commit.

k0001 commented 11 years ago

I'd like to add that I find exTry much more useful and general than exTryJust, so maybe there's no need to add both.

Gabriella439 commented 11 years ago

Give me some time to think about this because I just figured out an elegant solution to backtracking parsing and I'm writing it up.

Gabriella439 commented 11 years ago

So this is actually quite similar to a request I got for the errors library, where Paolo asked if I could add the equivalent of your exTry for EitherT:

exTry :: (Monad m) => EitherT e m r -> EitherT e m (Either e r)
exTry = lift . runEitherT

Note that you could implement your exTry the same way with a slight modification:

exTry = liftP . runEitherP

So the first reason I ended up not including the equivalent function in errors was because I considered this to be slightly too specialized in utility, and it's easy to achieve just by composing two easily available functions.

The second reason I didn't include it was because most of them time when people want this feature they actually want just runEitherP alone. When you relift the result of runEitherP back into EitherP you lose information in the types, specifically you no longer know that exTry itself won't fail, whereas if you use runEitherP alone the type communicates that the result of runEitherP is bound in a monad that does not itself permit failure.

This is why I prefer users to have to manually liftP the result of runEitherP rather than doing it automatically for them: I want the user to explicitly acknowledge that they are irreversibly losing that information from the type.

k0001 commented 11 years ago

I understand now what you mean, it makes sense. Thanks for the enlightenment. Also, it didn't occur to me that this could be accomplished by composing liftP and runEitherP. Just ignore this pull request then.