【问题标题】:Convert Either<Error,Option<X>> to Option<Either<Error, X>> in c# LanguageExt在 c# LanguageExt 中将 Either<Error,Option<X>> 转换为 Option<Either<Error, X>>
【发布时间】:2020-06-18 00:09:26
【问题描述】:

我正在使用 C# LanguageExt https://github.com/louthy/language-ext

我有一个类 MyDto 从一些 Json 中解析出来。解析函数返回Either&lt;Error, Mydto&gt;。 如果 dto 匹配给定的规则,或者它是一个错误,那么我想取回结果,否则,什么都没有。

最后的结果应该是Option&lt;Either&lt;Error, Mydto&gt;&gt;类型。

我最终得到了这样的东西

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)

但它返回Either&lt;Error, Option&lt;MyDto&gt;&gt;,如果此时我能够将选项带出,那看起来还不错。不幸的是,我找不到任何可以做到这一点的东西。

有什么东西存在吗?还是有更好的方法来实现我的目的?

也许像

 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

感谢您对此的任何建议。

【问题讨论】:

    标签: c# functional-programming optional either language-ext


    【解决方案1】:

    好的,下面是三个代码解决方案:

    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 的行)。您应该根据您希望在程序中拥有/传递的类型来选择您需要的版本。

    如果您不太关心“条件失败”和“异常”之间的区别,那么版本 1(底部)可能没问题(避免类型嵌套)。但我个人更喜欢后一种解决方案。您可以根据需要使用.Sequence() 在它们之间切换。

    【讨论】:

    • 非常感谢您的回答!可能序列是我一直在寻找的。我会在星期一试一试。谢谢
    猜你喜欢
    • 2018-06-23
    • 1970-01-01
    • 2016-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-14
    相关资源
    最近更新 更多