【问题标题】:Scala filter by nested Option/Try monadsScala 过滤器通过嵌套的 Option/Try monads
【发布时间】:2019-05-13 16:07:12
【问题描述】:

在 Scala 中,我有一个 Array[Option[(String,String,Try[String])]],并希望找到所有的失败错误代码。

如果内部 monad 是一个 Option[String] 而不是,我可以访问 Some(x) 的内容,而无需理解,就像这样:

for {
  Some(row) <- row 
  (a,b,c) = row 
  x <- c
} yield x

但如果内部 monad 是失败的,那么我很难看到如何对其进行模式匹配,因为我不能将 Failure(x) &lt;- c 放在 for 语句中。这感觉就像我错过了一件非常简单的事情,但任何指导都会非常有价值。

非常感谢!

EDIT - 错误指定了数组。它实际上是一个 option-tuple3s 的数组,而不仅仅是 tuple3s。

【问题讨论】:

    标签: scala monads


    【解决方案1】:

    a.map(_._3).filter(_.isFailure) 会吗?

    编辑:看到编辑和您的评论后,我认为您也可以这样做

    val tries = for {
        x <- a
        z <- x
    } yield z._3
    
    tries.filter(_.isFailure)
    

    【讨论】:

    • 谢谢。这正是我通过过度思考理解和匹配协议而错过的简单答案。我必须在开始时添加一个 flatMap 以删除该选项(请参阅编辑)。
    • 哦,等等...没有看到您的编辑...您必须执行类似a.flatMap(x =&gt; x.map(_._3)).filter(_.isFailure)的操作?
    • 没错。我只需要删除选项部分。我认为使用 Either monad 可能有更好的方法,但它正在工作,我不想重新设计整个解决方案以使其更清洁。
    【解决方案2】:

    为了组合不同类型的“monad”,您需要使用所谓的 monad 转换器。简而言之,Scala 不允许您在同一个 for 理解中混合不同的 monad 类型 - 这是有道理的,因为 for 理解只是 map / flatMap / filter 组合的语法糖。

    假设第一个始终是 Option,那么您可以将 Try 转换为 Option 并获得所需的结果:

    for {
      Some((a, b, c)) <- row
      x               <- c.toOption
    } yield x
    

    如果您并不真正关心 Try 内部的内容,那很好,但如果您这样做,请注意在执行 Some(x) 时会丢失该信息。如果模式匹配失败,那么你会得到一个None

    希望对你有帮助。

    【讨论】:

    • 我没想到。关于单子组合限制的好点。我确实需要失败内容,所以这对我不起作用,但知道它非常有帮助。谢谢。
    • 我建议在这种情况下使用模式匹配,这是最干净的解决方案:)
    【解决方案3】:

    这会返回一个Array[Throwable]

    for {
      (_,_,Failure(e)) <- rows
    } yield e
    

    或者,也许是未加糖的版本。

    rows.collect{case (_,_,Failure(e)) => e}
    

    【讨论】:

      猜你喜欢
      • 2021-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-17
      • 2014-10-27
      • 2015-07-21
      • 2017-07-27
      相关资源
      最近更新 更多