I am using a method in a library that returns a TryAsync<Unit>
(dumb stupid implementation to show the signature)...
public TryAsync<Unit> DoLibraryStuffAsync() =>
TryAsync(unit);
I want to call this, and return a Task<Either<string, Unit>>
, where the string
would contain the error message. I have got as far as this...
private async Task<Either<string, Unit>> DoMyStuffAsync() =>
(await DoLibraryStuffAsync())
.Match(_ => unit,
ex => $"Ex: {ex.Message}");
However, this gives a compiler error on both of the branches in Match
...
Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement
Hovering over Match
, I can see that the compiler has picked up on the overload that takes Func
s, so I would have expected to be able to return either a string
or unit
...
Anyone able to explain what I'm doing wrong, and how I fix it?
Whilst I can't offer a full explanation of the problem (as I don't completely understand it myself!), I can suggest how to fix it.
I think the problem is that the compiler can't work out exactly what you're returning (no, I'm not sure why either!), but if you make it explicit, I think it will work...
private async Task<Either<string, Unit>> DoMyStuffAsync() =>
(await DoLibraryStuffAsync())
.Match(_ => Right<string, Unit>(unit),
ex => $"Ex: {ex.Message}");
I would hope that someone can come along and explain to both of us why we need to do this, but at least this should get you going.
Update
OK, I discussed this with someone who understands this stuff better than I do (which is most people actually), and I think I have an idea why you got a compiler error.
Consider the following silly method...
Either<string, int> Jim() {
Random r = new();
return r.Next() % 100 > 50 ? 1 : "jim";
}
This compiles without needing to cast explicitly to an Either
because both types that can be returned are in the same bit of code (ie the return
statement).
In your code, the two Funcs
that you passed to Match
were in separate pieces of code, so the compiler couldn't put them together and work out what the return type should be. I think this is because, although we humans can understand that both Func
s passed Match
produce a return value for the same method, the compiler doesn't know that. It has no idea what Match
does.
Not sure that's completely clear, but I think it gives some idea why you needed to cast at least one of the return values.