Skip to content
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

Missing extension methods for Either.MatchAsync (Want permission to open PR) #1152

Open
z93blom opened this issue Dec 1, 2022 · 0 comments

Comments

@z93blom
Copy link

z93blom commented Dec 1, 2022

I find myself using Task<Either<L,R>> quite a lot to handle return values for web calls.

I've discovered the BindAsync extension method for Task<Either<L,R> which helps to chain calls without having to put lots of awaits in between calls:.

Example without overload (All methods return some form of Task<Either<L,R> or just a plain Either<L,R>):

HttpRequest req;
var result = await (await (ReadBody(req))
  .Bind(body => Parse(body))
  .BindAsync(async model => await SendToAsyncService(model))
  .Match(ok => OkResult(), err => ErrorResult(err))

return result

The problem with this code is the stacking of the awaits/ extra parenthesis at the top of the function to "transform" a Task<Either<L,R> to a Either<L,R>. This becomes more apparent the more asynchronous calls you have (the above example had just two asynchronous calls - as most I had four. Finding the matching parentheses became cumbersome.

Enter overload for BindAsync for a Task<Either<L,R>>available in EitherExtensions:

HttpRequest req;
var result = (await ReadBody(req)
  .BindAsync(body => Parse(body))
  .BindAsync(model => SendToAsyncService(model)))
  .Match(ok => OkResult(), err => ErrorResult(err))

return result

This is more like it. It allows me to chain the Bind chain into BindAsync all the way through, and just put a single await at the top of the call stack.

However - when I need to transform the Task<Either<L,R>> into an actual result to send back to the caller, I find myself missing the same convenience method available as a MatchAsync, and having to go back and transform the Task<Either<L,R> into an Either<L,R> before calling .Match on it.

Looking at the implementation for BindAsync I think the implementation should be fairly straight-forward and without any pitfalls.
I would be willing to create a PR for the extension methods needed if the project maintainers think it fits into the project.
I would assume the following overloads to be relevant:

public static Task<R2> MatchAsync<L, R, R2>(this Task<Either<L, R>> self, Func<R, R2> right, Func<L, R2> left)
public static Task<R2> MatchAsync<L, R, R2>(this Task<Either<L, R>> self, Func<R, Task<R2>> right, Func<L, R2> left)
public static Task<R2> MatchAsync<L, R, R2>(this Task<Either<L, R>> self, Func<R, R2> right, Func<L, Task<R2>> left)
public static Task<R2> MatchAsync<L, R, R2>(this Task<Either<L, R>> self, Func<R, Task<R2>> right, Func<L, Task<R2>> left)

The different overloads handle all cases of the supplied functions being synchronous or asynchronous (Task based).

@z93blom z93blom changed the title Missing extension methods for Either.MatchAsync Missing extension methods for Either.MatchAsync (Want permission to open PR) Jan 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant