2012-11-19 64 views
9

कोई वास्तविक दुनिया उदाहरणों के साथ समझा सकता है scalaz.Validation के तरीकों के नीचे कैसे काम करता है? मेरा मतलब है loopSuccess और loopFailure। स्रोत कोड (scalaz7) सेकार्य scalaz कैसे काम करता है। प्रमाणीकरण loopSuccess और loopFailure

Snippetes:

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) 

साथी वस्तु:

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) 
    } 

} 

उत्तर

5

यह एक trampoline के समान है। 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 

loopFailure के लिए विफलता के साथ एक ही बात करता है और सफलता, उलट ताकि आप जब तक आप बाईं या एक सफलता लौट चालू रखने के: वहाँ 3 संभव अगले राज्य हैं।

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" 
} 
:

यहाँ loopSuccess उपयोग करने का एक उदाहरण है