I have a function that performs a set of queries, each returning an Either<Error, Result>. I collect these into a List<>. I want to fold these individual return values together so that the overall return result is a Either<Error, List<Result>>. I got this far;
class Error
{
string Message { get; set; }
List<Error> ChildErrors { get; set; }
}
class Result
{
}
Either<Error, List<Result>> GetResults(List<string> queries)
{
var internalResults = new List<Either<Error, Result>>();
foreach (string query in queries)
{
internalResults.Add(GetResultForQuery(query));
}
var initialState = (new List<Error>(), new List<Result>());
(List<Error> errors, List<Result> events) =
internalResults.Fold(initialState, (state, item) =>
{
(List<Error> err, List<Result> res) = state;
item.Right(i => res.Add(i)).Left(e => err.Add(e));
return (err, res);
});
if (errors.Count > 0)
{
var groupedError = new Error {
Message = "One or more problems encountered",
ChildErrors = errors
};
return Left<Error, List<Result>>(groupedError);
}
return Right<Error, List<Result>>(events);
}
I believe it should work but it is not particularly elegant. There must be a better way to do it (i.e. more monadic). Any clues?
You should replace
System.Collections.Generic.Listby one of the LanguageExt data types, e.g.SeqorLstorArr...I used
Seqhere for illustration purposes. You can convert aIEnumerabletoSeqby usingToSeq()extension, too.Then you can use
Sequencelike here without any hassle:GetResults2 is just a short version of GetResults.