我开始使用Scalaz 7 Validation和/或disjunction处理可能失败的操作列表并管理其结果。
对于这种用例,有两个记录良好的案例:
1 /您想检查某些条件的列表,并累积每个错误(如果有的话)。在这里,你总是走到列表的末尾,如果有任何错误,你就会失败作为全局结果。 这是一个适用于工作的应用程序。
2 /您想要执行可能失败的几个步骤,并在第一个失败时停止。 在这里,我们有一个单调,在Scala中很好地理解。
所以,我有两个在同一行中的其他用例,但似乎在任何先例都不是很好: 我想处理一个步骤列表,可能会失败,并累积错误和成功结果(例如:它是文件修改列表,错误可能发生,因为那是外部世界,成功是我想要保留的补丁)。
两个用例的区别仅在于我想提前停止(在第一个错误上)或者到列表的末尾。
好的,那对此是什么意思?
(写这个问题让我觉得它只是一个简单的foldLeft,是吗?我会让这里的问题验证,如果有人想知道的话)
答案 0 :(得分:5)
查看Validation#append
或其别名Validation#+|+
。给定两个验证,如果两者都成功,则返回附加值的成功。如果两者都失败,则返回附加值的失败。否则,它返回成功的值。这需要成功类型的隐式Semigroup实例。
答案 1 :(得分: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))
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))
答案 2 :(得分:1)
您需要的是将Either[E, A]
转换为Writer[List[E], A]
。 Writer
monad会记录您遇到的错误。
答案 3 :(得分:0)
听起来你想要一对(SomveValue, List[T])
,其中T
是你的'失败',虽然我称之为'警告'或'记录',因为你仍然得到一个结果,所以它不是真的故障。
不知道Scalaz是否对此有任何想法。