如何用scalaz实现这样的行为:
"Fail1".failNel[Int] and "Fail2".failNel[Int] to Failure("Fail1", "Fail2")
"Fail1".failNel[Int] and 100.successNel[String] to Success(100)
Run Code Online (Sandbox Code Playgroud)
我的解决方案看起来很复杂,我想存在一些其他方式来做succint:
def aggregateErrorsOrSuccess(v1: ValidationNEL[String, Int],
v2: ValidationNEL[String, Int]) = {
v2.fold(
nl => (nl.fail[Int] |@| v1) {(i1, i2) => (/*actually should never happen*/)},
res => res.successNel[String]
)
}
Run Code Online (Sandbox Code Playgroud)
=====================
第二个解决方案:
implicit def nel2list[T](nl: NonEmptyList[T]) = nl.head :: nl.tail;
implicit def ValidationNELPlus[X]: Plus[({type ?[?]=ValidationNEL[X, ?]})#?] = new Plus[({type ?[?]=ValidationNEL[X, ?]})#?] {
def plus[A](a1: ValidationNEL[X, A], a2: => ValidationNEL[X, A]) = a1 match {
case Success(_) => a1
case Failure(f1) => a2 match {
case Success(_) => a2
case Failure(f2) => (f1 <::: f2).fail[A]
}
}
}
Run Code Online (Sandbox Code Playgroud)
像这样使用它:
val sum = v1 <+> v2
Run Code Online (Sandbox Code Playgroud)
实际上,您可以使用>>*<<(紧急退出?)方法,Validation该方法接近您的第二个解决方案.但是它也会尝试聚合成功,你可能想要调整一下.
def >>*<<[EE >: E: Semigroup, AA >: A: Semigroup](x: Validation[EE, AA]): Validation[EE, AA] = (this, x) match {
case (Success(a1), Success(a2)) => Success((a1: AA) ? a2)
case (Success(a1), Failure(_)) => Success(a1)
case (Failure(_), Success(a2)) => Success(a2)
case (Failure(e1), Failure(e2)) => Failure((e1: EE) ? e2)
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
661 次 |
| 最近记录: |