Carlos Rodriguez
Carlos Rodriguez

Reputation: 533

Chain asynchronous operations that return Either using Language-Ext in C#

I am using the Language-Ext library for C# and I am trying to chain asynchronous operations that return an Either type. Let's say that I have three functions that would return an integer if they succeed and a string if the fail, and another function that sums the result of the previous three functions. In the sample implementations below Op3 fails and returns a string.

public static async Task<Either<string, int>> Op1()
{
    return await Task.FromResult(1);
}

public static async Task<Either<string, int>> Op2()
{
    return await Task.FromResult(2);
}

public static async Task<Either<string, int>> Op3()
{
    return await Task.FromResult("error");
}

public static async Task<Either<string, int>> Calculate(int x, int y, int z)
{
    return await Task.FromResult(x + y + z);
}

I want to chain these operations and I am trying to do it like this:

var res = await (from x in Op1()
                 from y in Op2()
                 from z in Op3()
                 from w in Calculate(x, y, z)
                 select w);

But we the code does not compile because I get the error cannot convert from 'LanguageExt.Either<string, int>' to 'int' for the arguments of Calculate. How should I chain these functions?

Upvotes: 6

Views: 3944

Answers (2)

louthster
louthster

Reputation: 1652

The problem is that the LINQ query can't work out which version of SelectMany to use, because x isn't used in the second line. You can get around this by converting your Task<Either<L, R>> to EitherAsync<L, R>:

    public static async Task<int> M()
    {
        var res = from x in Op1().ToAsync()
                  from y in Op2().ToAsync()
                  from z in Op3().ToAsync()
                  from w in Calculate(x, y, z).ToAsync()
                  select w;

        return await res.IfLeft(0);
    }

Or, instead of returning Task<Either<L, R>> return EitherAsync<L, R>:

    public static EitherAsync<string, int> Op1() =>
        1;

    public static EitherAsync<string, int> Op2() =>
        2;

    public static EitherAsync<string, int> Op3() =>
        3;

    public static EitherAsync<string, int> Calculate(int x, int y, int z) =>
        x + y + z;

    public static async Task<int> M()
    {
        var res = from x in Op1()
                  from y in Op2()
                  from z in Op3()
                  from w in Calculate(x, y, z)
                  select w;

        return await res.IfLeft(0);
    }

Upvotes: 5

Radin Gospodinov
Radin Gospodinov

Reputation: 2323

x, y and z are not of type int, but of Either<string, int> change Calculate(int x, int y, int z) to accept instances of Either calls: Calculate(Either<string, int> x, Either<string, int> y, Either<string, int>z), or pass

x.{The int getter property}

Upvotes: 0

Related Questions