在 c# LanguageExt 中将 Either<Error,Option<X>> 转换为 Option<Either<Error, X>>
Convert Either<Error,Option<X>> to Option<Either<Error, X>> in c# LanguageExt
我正在使用 C# LanguageExt https://github.com/louthy/language-ext
我有一个 class MyDto
从一些 Json 解析出来的。解析函数 returns Either<Error, Mydto>
。
如果dto匹配给定的规则,或者是一个错误,那么我想取回结果,否则,什么都没有。
最终结果应该是 Option<Either<Error, Mydto>>
.
类型
我最终得到了这样的结果
Option<Either<Error, MyDto>> finalResult =
MyDto.From("some json") // Returns Either<Error, MyDto>
.Right(dto => (dto.Equals("something")
? Some<Either<Error, IDhResponse>>(Right(dto))
: None))
.Left(error => Some<Either<Error, IDhResponse>>(Left(error)));
我不太喜欢它,因为它重复太多。
然后我尝试了这个
MyDto.From("some json") // Returns Either<Error, MyDto>
.Map(dto => dto.Equals("something")
? Some(dto)
: None)
但是 returns Either<Error, Option<MyDto>>
如果此时我能够将 Option 带出,那看起来还不错。不幸的是,我找不到任何相关的东西。
有什么东西存在吗?或者有更好的方法来实现我的目的?
可能是
MyDto.From("some json") // Returns Either<Error, MyDto>
.Where(dto => dto.Equals("something")) // Only applies to Right branch and wrap everything in Option when fails
感谢您对此的任何建议。
好的,下面是三个代码解决方案:
Either<Exception, int> resultOfParsing = Right(10); // Left(new Exception("error"))
// version 1: make use of "bottom" state:
Either<Exception, int> filterResultUsingBottom = resultOfParsing.Filter(i => i > 5);
var textResultUsingBottom = filterResultUsingBottom.Match(i => $"success: {i}", exception => $"error: {exception.Message}", () => "condition: false");
// version 2: inner option
Either<Exception, Option<int>> filterResultInnerOption = resultOfParsing
.Map(i => Some(i))
.FilterT(i => i > 5);
var textResultInnerOption = filterResultInnerOption.Match(noError =>
noError.Match(i => $"success: {i}", () => "condition: false"),
exception => $"error: {exception.Message}");
// version 3: outer option
Option<Either<Exception, int>> filterResultOuterOption = filterResultInnerOption.Sequence();
var textResultOuterOption = filterResultOuterOption.Match(noConditionFail =>
noConditionFail.Match(i => $"success: {i}", exception => $"error: {exception.Message}"),
() => "condition: false");
如您所见,所有版本都可以以类似的方式使用(Match
行)。你应该select你需要的版本取决于你想要在你的程序中拥有/传递的类型。
如果您不太关心 "condition failed" 和 "exception" 之间的区别,那么版本 1(底部)可能没问题(避免类型嵌套)。但我个人更喜欢后一种方案。您可以根据需要使用 .Sequence()
在它们之间切换。
我正在使用 C# LanguageExt https://github.com/louthy/language-ext
我有一个 class MyDto
从一些 Json 解析出来的。解析函数 returns Either<Error, Mydto>
。
如果dto匹配给定的规则,或者是一个错误,那么我想取回结果,否则,什么都没有。
最终结果应该是 Option<Either<Error, Mydto>>
.
我最终得到了这样的结果
Option<Either<Error, MyDto>> finalResult =
MyDto.From("some json") // Returns Either<Error, MyDto>
.Right(dto => (dto.Equals("something")
? Some<Either<Error, IDhResponse>>(Right(dto))
: None))
.Left(error => Some<Either<Error, IDhResponse>>(Left(error)));
我不太喜欢它,因为它重复太多。
然后我尝试了这个
MyDto.From("some json") // Returns Either<Error, MyDto>
.Map(dto => dto.Equals("something")
? Some(dto)
: None)
但是 returns Either<Error, Option<MyDto>>
如果此时我能够将 Option 带出,那看起来还不错。不幸的是,我找不到任何相关的东西。
有什么东西存在吗?或者有更好的方法来实现我的目的?
可能是
MyDto.From("some json") // Returns Either<Error, MyDto>
.Where(dto => dto.Equals("something")) // Only applies to Right branch and wrap everything in Option when fails
感谢您对此的任何建议。
好的,下面是三个代码解决方案:
Either<Exception, int> resultOfParsing = Right(10); // Left(new Exception("error"))
// version 1: make use of "bottom" state:
Either<Exception, int> filterResultUsingBottom = resultOfParsing.Filter(i => i > 5);
var textResultUsingBottom = filterResultUsingBottom.Match(i => $"success: {i}", exception => $"error: {exception.Message}", () => "condition: false");
// version 2: inner option
Either<Exception, Option<int>> filterResultInnerOption = resultOfParsing
.Map(i => Some(i))
.FilterT(i => i > 5);
var textResultInnerOption = filterResultInnerOption.Match(noError =>
noError.Match(i => $"success: {i}", () => "condition: false"),
exception => $"error: {exception.Message}");
// version 3: outer option
Option<Either<Exception, int>> filterResultOuterOption = filterResultInnerOption.Sequence();
var textResultOuterOption = filterResultOuterOption.Match(noConditionFail =>
noConditionFail.Match(i => $"success: {i}", exception => $"error: {exception.Message}"),
() => "condition: false");
如您所见,所有版本都可以以类似的方式使用(Match
行)。你应该select你需要的版本取决于你想要在你的程序中拥有/传递的类型。
如果您不太关心 "condition failed" 和 "exception" 之间的区别,那么版本 1(底部)可能没问题(避免类型嵌套)。但我个人更喜欢后一种方案。您可以根据需要使用 .Sequence()
在它们之间切换。