Reputation: 533
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
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
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