Scalaz在错误和成功方面都有积累的东西吗?

fan*_*f42 5 monads scala fold scalaz applicative

我开始使用Scalaz 7 Validation和/或disjunction来处理可能失败的操作列表并管理它们的结果.

对于这种用例,有两个记录良好的案例:

1 /您想检查某些条件的列表,并累积每个错误(如果有的话).在这里,你总是走到列表的末尾,如果有任何错误,你就会失败作为全局结果.这是一个适用于工作的应用程序.

2 /您希望执行可能失败的几个步骤,并在第一个失败时停止.在这里,我们有一个单调,在Scala中很好地理解.

所以,我有两个在同一行中的其他用例,但似乎在任何先例都不是很好:我想处理一个步骤列表,可能失败,并累积错误和成功结果(例如:它是一个对文件进行修改的列表,可能会发生错误,因为这是外部世界,而成功是我希望以后保留的补丁.

两个用例的区别仅在于我想提前停止(在第一个错误上)或者到列表的末尾.

那么,那是正确的呢?

(写这个问题让我觉得它只是一个简单的foldLeft,是吗?我会让这里的问题验证,如果有人想知道的话)

mpi*_*ist 5

看看Validation#append或别名Validation#+|+.给定两个验证,如果两者都成功,则返回附加值的成功.如果两者都失败,则返回附加值的失败.否则,它返回成功的值.这需要成功类型的隐式Semigroup实例.


fol*_*one 4

我会做这样的事情:

scala> List(1.success[String], 2.success[String], "3".failure[Int], "4".failure[Int]).partition(_.isSuccess)
res2: (List[scalaz.Validation[java.lang.String,Int]], List[scalaz.Validation[java.lang.String,Int]]) = (List(Success(1), Success(2)),List(Failure(3), Failure(4)))

scala> val fun = (_:List[Validation[String, Int]]).reduceLeft(_ append _)
fun: List[scalaz.Validation[String,Int]] => scalaz.Validation[String,Int] = <function1>

scala> fun <-: res2 :-> fun
res3: (scalaz.Validation[String,Int], scalaz.Validation[String,Int]) = (Success(3),Failure(34))
Run Code Online (Sandbox Code Playgroud)

UPD:合并#129#130后,您可以更改fun(_:List[Validation[String, Int]]).concatenate(_:List[Validation[String, Int]]).suml

或者bimap像这样:

scala> List(1.success[String], 2.success[String], "3".failure[Int], "4".failure[Int]).partition(_.isSuccess).bimap(_.suml, _.suml)
res6: (scalaz.Validation[java.lang.String,Int], scalaz.Validation[java.lang.String,Int]) = (Success(3),Failure(34))
Run Code Online (Sandbox Code Playgroud)