-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add sequenceEitherT #113
Add sequenceEitherT #113
Conversation
I'm ok with this. I can see that being useful. Hell I've even worked around this issue (twice) in Blowfish by returning an However, since it is going into one of our base libraries, I'd like to get some more eyes on it. |
I am good with code and implementation, but would rather naming reflect sequence then fold, I would expect |
@@ -204,3 +211,28 @@ joinErrorsEither = | |||
tryEitherT :: (Functor m, MonadCatch m, Exception e) => (e -> x) -> m a -> EitherT x m a | |||
tryEitherT handler = firstEitherT handler . newEitherT . try | |||
{-# INLINE tryEitherT #-} | |||
|
|||
-- | Lift an 'Either' into 'Errors'. | |||
hoistErrors :: Either e a -> Errors e a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This name doesn't really match the naming / usage of the other two hoist functions:
hoistEither :: Monad m => Either x a -> EitherT x m a
hoistMaybe :: Monad m => x -> Maybe a -> EitherT x m a
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not exported (maybe it should be?), but i'll rename it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given:
Control.Applicative.Lift.runErrors :: Errors e a -> Either e a
Maybe mkErrors
?
|
||
-- | Like 'sequence', but folding/accumulating all errors in case of a 'Left'. | ||
foldEither :: (Monoid e, Traversable f) => f (Either e a) -> Either e (f a) | ||
foldEither = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The type of this is similar to sequence:
sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)
Would prefer something like:
sequenceEither :: (Traversable t, Monoid x) => t (Either x a) -> Either x (t a)
(Also x
for the Left
type variable to be consistent with the rest of the module)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or perhaps mconcatEither
, not sure, but fold I would expect to take an argument
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've been calling it sequenceErrors
in my code, but proposed fold
as it's essentially a (monoidal) fold
of the left
. Names are hard.
Anyone mind |
|
8d8d1e3
to
d88cdd0
Compare
|
||
-- | Lift an 'Either' into 'Errors'. | ||
eitherErrors :: Either e a -> Errors e a | ||
eitherErrors e = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep, good with this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Export y/n?
Honestly the Errors
type is only mildly useful because it's limited to applicative. It's also a type synonym, so I prefer not to use it directly.
If you happen to want to use it, you'd probably want this function, else you have to learn how Lift works.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
n
I'd be happy to not export it, as your other functions don't mention Errors
at all
{-# INLINE eitherErrors #-} | ||
|
||
-- | Like 'sequence', but folding/accumulating all errors in case of a 'Left'. | ||
sequenceEither :: (Monoid x, Traversable f) => f (Either x a) -> Either x (f a) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/f/t/
d88cdd0
to
0419916
Compare
📻 |
These are combinators for running a batch of Either expressions independently, folding the error messages together if any of them fail.
I have been pasting
foldEither
around the place quite a bit lately, and recently neededfoldEitherT
, so I thought they might be general enough to propose here.You can generalise to Semigroup but that would require reimplementing
Errors
, which is a handy validation type we get for free fromtransformers
.! @jystic @erikd-ambiata