1

I'm prototyping language-ext and functional code style for a web server library to share between my projects. I really like binding of async steps using LINQ query syntax but I have now encountered this compiler issue: language-ext Task of Either with multiple from clauses.

To implement the suggested solution in that link, I would need to refactor this method:

private static async Task<Either<RouteError, object>> DispatchRequest<T>(
    IRequestDispatcher requestDispatcher,
    T request)
    where T : class, IRequest
{
    var result = await requestDispatcher.Send(request);
    return result.Match<Either<RouteError, object>>(
        Some: x => x,
        None: () => new NotFoundError(),
        Fail: ex => new InternalServerError(ex));
}

where requestDispatcher is an implementation of:

public interface IRequestDispatcher
{
    Task<OptionalResult<object>> Send<T>(T request) where T : IRequest;
}

What I need is a method with this signature instead, so that it can be more easily used in LINQ expressions:

private static EitherAsync<RouteError, object> DispatchRequest<T>(
    IRequestDispatcher requestDispatcher,
    T request)
    where T : class, IRequest
{ 
  // What should the implementation look like? 
} 

I can't figure out how to construct the method so that I can await and then return Left or Right based on the result. Everything I tried so far also looks ugly compared to the nice and clean original implementation with a Task return value.

jussi.mattila
  • 227
  • 3
  • 16

1 Answers1

2

It looks like Send returns a TryOption? If so, then you can do this:

private static EitherAsync<RouteError, object> DispatchRequest<T>(
    IRequestDispatcher requestDispatcher, T request)
    where T : class, IRequest =>
        Send(request)
            .ToAsync();
            .Match(Some: Right<RouteError, object>,
                   None: () => Left<RouteError, object>(new NotFoundError()),
                   Fail: ex => Left<RouteError, object>(new InternalServerError(ex)))
            .ToAsync();

What that does is converts the TryOption to TryOptionAsync by calling ToAsync on the Task<TryOption<object>>, and then matches on that TryOptionAsync to return an Task<Either<RouteError, object>> and then finally calls ToAsync() on that to convert the Task to an EitherAsync.

louthster
  • 1,560
  • 9
  • 20
  • Sorry, I forgot to include the signature of the request dispatcher interface in my question. It is now added to the question. What `Send` returns is actually `Task>`. If that is not recommended, I can change that as well. – jussi.mattila Dec 11 '18 at 19:24