ScalazValidation
型を返す関数を簡単にチェーンできるようにするためのコードを書こうとしています。私が書き込もうとしているメソッドの1つは、これからValidation.flatMap
呼び出す(検証の短絡)に類似していますandPipe
。|@|
もう1つは、 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
}
}