通过嵌套的Option / Try monads进行Scala过滤

时间:2017-03-13 17:54:44

标签: scala monads

在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) <- c放在for语句中。这感觉就像一件我很遗憾的事情,但任何指导都会非常有价值。

非常感谢!

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

3 个答案:

答案 0 :(得分:4)

a.map(_._3).filter(_.isFailure)做什么?

编辑:看过编辑和你的评论后,我认为你也可以做到

val tries = for {
    x <- a
    z <- x
} yield z._3

tries.filter(_.isFailure)

答案 1 :(得分:3)

为了组合不同类型的“monad”,你需要所谓的monad变换器。简单地说,Scala不会让你在同一个混合中使用不同的monad类型进行理解 - 这是有道理的,因为对于map / flatMap / filter的组合只需要语法糖。

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

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

如果你真的不关心Try里面的内容那么好,但如果你这样做,那么在做Some(x)时你会小心丢失这些信息。如果模式匹配失败,那么您将获得None

我希望能帮助你。

答案 2 :(得分:2)

这会返回Array[Throwable]

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

或者,也许是一个没有结果的版本。

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