paw*_*icz 9 scala scalaz scalaz7
有人可以解释现实世界的例子如何在下面的方法工作scalaz.Validation
?我的意思是loopSuccess
和loopFailure
.
来自源代码的片段(scalaz7):
scalaz.Validation:
/** Spin in tail-position on the success value of this validation. */
def loopSuccess[EE >: E, AA >: A, X](success: AA => X \/ Validation[EE, AA], failure: EE => X): X =
Validation.loopSuccess(this, success, failure)
/** Spin in tail-position on the failure value of this validation. */
def loopFailure[EE >: E, AA >: A, X](success: AA => X, failure: EE => X \/ Validation[EE, AA]): X =
Validation.loopFailure(this, success, failure)
Run Code Online (Sandbox Code Playgroud)
伴随对象:
object Validation extends ValidationFunctions with ValidationInstances {
/** Spin in tail-position on the success value of the given validation. */
@annotation.tailrec
final def loopSuccess[E, A, X](d: Validation[E, A], success: A => X \/ Validation[E, A], failure: E => X): X =
d match {
case Failure(e) => failure(e)
case Success(a) => success(a) match {
case -\/(x) => x
case \/-(q) => loopSuccess(q, success, failure)
}
}
/** Spin in tail-position on the failure value of the given validation. */
@annotation.tailrec
final def loopFailure[E, A, X](d: Validation[E, A], success: A => X, failure: E => X \/ Validation[E, A]): X =
d match {
case Failure(e) => failure(e) match {
case -\/(x) => x
case \/-(q) => loopFailure(q, success, failure)
}
case Success(a) => success(a)
}
}
Run Code Online (Sandbox Code Playgroud)
这类似于蹦床.对于loopSuccess,您提供一个初始值,以及一个将您带到下一个状态的函数.有三种可能的下一个状态:
X.left // stop processing with X as the result
Success(a).right // no result, run the next iteration with this value
Failure(e).right // stop processing, run the failure function on this result and return it
Run Code Online (Sandbox Code Playgroud)
对于loopFailure,在失败和成功相反的情况下执行相同的操作,因此您将继续运行,直到您返回左侧或成功.
以下是使用loopSuccess的示例:
import scalaz._
import Scalaz._
object TestLoopSuccess extends App {
// check if a number divides another, returning a Failure for division by zero
val divides : Int => Int => Validation[String,Boolean] = { div => num =>
if(div == 0) "division by zero".failure
else (num % div == 0).success
}
val allDivide : Int => List[Int] => String \/ Validation[Int,List[Int]] = { div => nums =>
nums match {
// empty list means we are done, so we return a left
case Nil => "All numbers divide".left
// process the head of the list and return a right
case x::xs => divides(div)(x).flatMap { divides =>
if(divides)
// head divides, so process more of the list
xs.success
else
// head does not divide, so we are done
"%d is not a multiple of %d".format(x,div).failure
}.right
}
}
println(Validation.loopSuccess(List(2,4,6,8).success[String], allDivide(0), identity[String])) // "division by zero"
println(Validation.loopSuccess(List(2,4,6,8).success[String], allDivide(2), identity[String])) // "All numbers divide"
println(Validation.loopSuccess(List(2,4,7,8).success[String], allDivide(2), identity[String])) // "7 is not a multiple of 2"
}
Run Code Online (Sandbox Code Playgroud)