我正在尝试编写一些代码来轻松链接返回 ScalazValidation
类型的函数。我正在尝试编写的一种方法类似于Validation.flatMap
我将调用的 (Short circuit that validation) andPipe
。另一个类似于|@|
on ApplicativeBuilder
(累积错误),除了它只返回最终Success
类型,我将调用它andPass
假设我有功能:
def allDigits: (String) => ValidationNEL[String, String]
def maxSizeOfTen: (String) => ValidationNEL[String, String]
def toInt: (String) => ValidationNEL[String, Int]
例如,我想首先将输入字符串传递给 allDigits 和 maxSizeOf10。如果有故障,它应该通过不调用 toInt 函数来短路并返回发生的一个或两个故障。如果成功,我想将 Success 值传递给 toInt 函数。从那里开始,它要么成功,输出值为 Int,要么失败,仅返回来自 toInt 的验证失败。
def intInput: (String) => ValidationNEL[String,Int] = (allDigits andPass maxSizeOfTen) andPipe toInt
如果没有下面的附加实现,有没有办法做到这一点?
这是我的实现:
trait ValidationFuncPimp[E,A,B] {
val f: (A) => Validation[E, B]
/** If this validation passes, pass to f2, otherwise fail without accumulating. */
def andPipe[C](f2: (B) => Validation[E,C]): (A) => Validation[E,C] = (a: A) => {
f(a) match {
case Success(x) => f2(x)
case Failure(x) => Failure(x)
}
}
/** Run this validation and the other validation, Success only if both are successful. Fail accumulating errors. */
def andPass[D](f2: (A) => Validation[E,D])(implicit S: Semigroup[E]): (A) => Validation[E,D] = (a:A) => {
(f(a), f2(a)) match {
case (Success(x), Success(y)) => Success(y)
case (Failure(x), Success(y)) => Failure(x)
case (Success(x), Failure(y)) => Failure(y)
case (Failure(x), Failure(y)) => Failure(S.append(x, y))
}
}
}
implicit def toValidationFuncPimp[E,A,B](valFunc : (A) => Validation[E,B]): ValidationFuncPimp[E,A,B] = {
new ValidationFuncPimp[E,A,B] {
val f = valFunc
}
}