从聚合的 ValidationNel 访问成功和失败
Access both the success and the failure from an aggregated ValidationNel
是否可以使用 ValidationNel 来 return 错误和成功的混合?
举个例子:
def f(i: Int) =
if (i > 2) i.successNel
else "something wrong".failureNel
List(1, 2, 3).traverseU(f) // Failure(NonEmptyList(something wrong, something wrong))
借用 How to use Scalaz's traverse and traverseU with Either 我们得到了两次失败 (1,2) 和一次成功 (3)。由于我们有超过 0 次失败,结果是失败,但是有什么方法可以从 3 中获得成功,还是只是被丢弃了?
编辑:看 for separate
from MonadPlus
.
与 Try
、Either
或 scalaz 的析取 \/
相比,您使用 Validation[E, X]
并因此也使用 ValidationNel[E, X]
来累积错误给你第一个失败。
traverse
函数是map
和sequence
的组合。
List(1, 2, 3).map(f).sequenceU == List(1, 2, 3).traverseU(f)
如果我们查看映射后的中间结果:
List(1, 2, 3).map(f)
// List[scalaz.Validation[scalaz.NonEmptyList[String],Int]] =
// List(Failure(NonEmptyList(something wrong)),
// Failure(NonEmptyList(something wrong)),
// Success(3))
我们可以看到我们的中间结果是 Validation[NonEmptyList[String], Int]]
类型,等于 ValidationNel[String, Int]
.
如果我们再看最后一步(sequence
) :
sequence
是一个将 monad 翻转过来的函数 (F[G[_]] => G[F[_]]
),在这种情况下我们从 List[ValidationNel[String, Int]]
到 ValidationNel[String, List[Int]]
.
Validation
的上下文是我们想知道我们的函数是否成功,如果失败则累积所有错误。
因此,使用 sequence
我们会丢失有关列表中哪些元素成功的信息。
如果你真的想同时获得成功和失败,更简洁的方法是使用 .separate
import scalaz.syntax.validation._
import scalaz.syntax.monadPlus._
import scalaz.std.list._
@ val a = "yeah".success[Int]
a: Validation[Int, String] = Success(yeah)
@ val b = "wot".success[Int]
b: Validation[Int, String] = Success(wot)
@ val c = 10.failure[String]
c: Validation[Int, String] = Failure(10)
@ List(a,b,c).separate
res6: (List[Int], List[String]) = (List(10), List("yeah", "wot"))
是否可以使用 ValidationNel 来 return 错误和成功的混合?
举个例子:
def f(i: Int) =
if (i > 2) i.successNel
else "something wrong".failureNel
List(1, 2, 3).traverseU(f) // Failure(NonEmptyList(something wrong, something wrong))
借用 How to use Scalaz's traverse and traverseU with Either 我们得到了两次失败 (1,2) 和一次成功 (3)。由于我们有超过 0 次失败,结果是失败,但是有什么方法可以从 3 中获得成功,还是只是被丢弃了?
编辑:看separate
from MonadPlus
.
与 Try
、Either
或 scalaz 的析取 \/
相比,您使用 Validation[E, X]
并因此也使用 ValidationNel[E, X]
来累积错误给你第一个失败。
traverse
函数是map
和sequence
的组合。
List(1, 2, 3).map(f).sequenceU == List(1, 2, 3).traverseU(f)
如果我们查看映射后的中间结果:
List(1, 2, 3).map(f)
// List[scalaz.Validation[scalaz.NonEmptyList[String],Int]] =
// List(Failure(NonEmptyList(something wrong)),
// Failure(NonEmptyList(something wrong)),
// Success(3))
我们可以看到我们的中间结果是 Validation[NonEmptyList[String], Int]]
类型,等于 ValidationNel[String, Int]
.
如果我们再看最后一步(sequence
) :
sequence
是一个将 monad 翻转过来的函数 (F[G[_]] => G[F[_]]
),在这种情况下我们从List[ValidationNel[String, Int]]
到ValidationNel[String, List[Int]]
.Validation
的上下文是我们想知道我们的函数是否成功,如果失败则累积所有错误。
因此,使用 sequence
我们会丢失有关列表中哪些元素成功的信息。
如果你真的想同时获得成功和失败,更简洁的方法是使用 .separate
import scalaz.syntax.validation._
import scalaz.syntax.monadPlus._
import scalaz.std.list._
@ val a = "yeah".success[Int]
a: Validation[Int, String] = Success(yeah)
@ val b = "wot".success[Int]
b: Validation[Int, String] = Success(wot)
@ val c = 10.failure[String]
c: Validation[Int, String] = Failure(10)
@ List(a,b,c).separate
res6: (List[Int], List[String]) = (List(10), List("yeah", "wot"))