LanguageExt 将 eithers 的列表折叠为 one either
LanguageExt Fold list of eithers to one either
我有一个执行一组查询的函数,每个查询 returning 一个 Either<Error, Result>
。我将这些收集到 List<>
。我想将这些单独的 return 值折叠在一起,以便整体 return 结果是 Either<Error, List<Result>>
。我已经走到这一步了;
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);
}
我相信它应该可以工作,但不是特别优雅。必须有更好的方法来做到这一点(即更多的单子)。有什么线索吗?
您应该将 System.Collections.Generic.List
替换为其中一种 LanguageExt 数据类型,例如Seq
或 Lst
或 Arr
...
为了便于说明,我在这里使用了 Seq
。您也可以使用 ToSeq()
扩展名将 IEnumerable
转换为 Seq
。
然后你可以像这里一样使用 Sequence
没有任何麻烦:
class Error
{
string Message { get; set; }
Seq<Error> ChildErrors { get; set; }
}
class Result
{
}
private static Either<Error, Result> GetResultForQuery(string query) =>
throw new NotImplementedException();
Either<Error, Seq<Result>> GetResults(Seq<string> queries)
{
Seq<Either<Error, Result>> internalResults = queries.Map(GetResultForQuery);
return internalResults.Sequence();
}
Either<Error, Seq<Result>> GetResults2(Seq<string> queries) =>
queries.Map(GetResultForQuery).Sequence();
GetResults2 只是 GetResults 的一个简短版本。
我有一个执行一组查询的函数,每个查询 returning 一个 Either<Error, Result>
。我将这些收集到 List<>
。我想将这些单独的 return 值折叠在一起,以便整体 return 结果是 Either<Error, List<Result>>
。我已经走到这一步了;
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);
}
我相信它应该可以工作,但不是特别优雅。必须有更好的方法来做到这一点(即更多的单子)。有什么线索吗?
您应该将 System.Collections.Generic.List
替换为其中一种 LanguageExt 数据类型,例如Seq
或 Lst
或 Arr
...
为了便于说明,我在这里使用了 Seq
。您也可以使用 ToSeq()
扩展名将 IEnumerable
转换为 Seq
。
然后你可以像这里一样使用 Sequence
没有任何麻烦:
class Error
{
string Message { get; set; }
Seq<Error> ChildErrors { get; set; }
}
class Result
{
}
private static Either<Error, Result> GetResultForQuery(string query) =>
throw new NotImplementedException();
Either<Error, Seq<Result>> GetResults(Seq<string> queries)
{
Seq<Either<Error, Result>> internalResults = queries.Map(GetResultForQuery);
return internalResults.Sequence();
}
Either<Error, Seq<Result>> GetResults2(Seq<string> queries) =>
queries.Map(GetResultForQuery).Sequence();
GetResults2 只是 GetResults 的一个简短版本。