编写Scalaz 7验证

时间:2014-02-20 01:14:49

标签: scala scalaz

我想撰写一些返回Scalaz 7 Validation的检查。我做了一个简单的例子,解析一系列单词并从中构造一个Person对象。解析可能会在很多步骤中失败,在这种情况下我们会快速失败,并显示失败的错误消息。下面的例子是完全弥补和愚蠢的,但是尽可能接近我想要达到的目标。

看看下面的理解,似乎必须有更好的方法来构建验证。

  1. 初始序列更改了几次,从seq更改为seq2seq3。在调用示例lastNameValidation时,需要使用seq2显式调用它,即使它在seq2 = onlyShort(seq)之后立即调用。
  2. 我读到有关Kleisli箭头构图的内容,当人们可以撰写A => M[B]B => M[C]来获得箭头A => M[C](其中M是monad)。但是,我并不总是以这样的方式组合事物,即下一步将重复使用前一步的计算。那,并且我无法使用Scalaz 7获得Kleisli箭头组合。
  3. 代码:

    import scalaz._, Scalaz._
    
    case class Address(streetName: String, streetNumber: Int)
    case class Person(name: String, lastName: String, age: Int, address: Address)
    
    def nameValidation(seq: List[String]) = seq.find(Set("John", "Carol", "Susan").contains(_)).toSuccess("Name not found")
    def lastNameValidation(seq: List[String]) = seq.find(Set("Kennedy", "Hardy", "Taplin").contains(_)).toSuccess("Last name not found")
    def lengthValidation(lastName: String) = lastName.size.success[String]
    def dyValidation(lastName: String) = if (!lastName.contains("dy")) Failure("Not the person") else Success(123)
    def streetNumberValidation(seq: List[String]) = seq.find(_.forall(_.isDigit)).map(_.toInt).toSuccess("Could not extract street number")
    def streetValidation(seq: List[String]) = seq.find(Set("Bush Street", "Pine Street", "Market Street").contains(_)).toSuccess("Street not found")
    
    def onlyShort(seq: List[String]) = seq.filter(_.size < 15)
    def omitGarbage(seq: List[String]) = seq.filter(_ != "garbage")
    
    def createPerson(seq: List[String]) = for {
      name <- nameValidation(seq)
      seq2 = onlyShort(seq)
      lastName <- lastNameValidation(seq2)
      length <- lengthValidation(lastName)
      dy <- dyValidation(lastName)
      seq3 = omitGarbage(seq2)
      streetNumber <- streetNumberValidation(seq3)
      street <- streetValidation(seq3)
    } yield Person(name, lastName, 80, Address(street, streetNumber))
    
    createPerson(List("255", "a very long string", "Bush Street", "Hardy", "San Francisco", "John", "garbage"))
    
    createPerson(List("a very long string", "Bush Street", "Hardy", "San Francisco", "John", "garbage"))
    

    非常欢迎任何scalaz / functional guru的建议!

    REPL:

    scala> import scalaz._, Scalaz._
    import scalaz._
    import Scalaz._
    
    scala> case class Address(streetName: String, streetNumber: Int)
    defined class Address
    
    scala> case class Person(name: String, lastName: String, age: Int, address: Address)
    defined class Person
    
    scala> def nameValidation(seq: List[String]) = seq.find(Set("John", "Carol", "Susan").contains(_)).toSuccess("Name not found")
    nameValidation: (seq: List[String])scalaz.Validation[java.lang.String,String]
    
    scala> def lastNameValidation(seq: List[String]) = seq.find(Set("Kennedy", "Hardy", "Taplin").contains(_)).toSuccess("Last name not found")
    lastNameValidation: (seq: List[String])scalaz.Validation[java.lang.String,String]
    
    scala> def lengthValidation(lastName: String) = lastName.size.success[String]
    lengthValidation: (lastName: String)scalaz.Validation[String,Int]
    
    scala> def dyValidation(lastName: String) = if (!lastName.contains("dy")) Failure("Not the person") else Success(123)
    dyValidation: (lastName: String)Product with Serializable with scalaz.Validation[java.lang.String,Int]
    
    scala> def streetNumberValidation(seq: List[String]) = seq.find(_.forall(_.isDigit)).map(_.toInt).toSuccess("Could not extract street number")
    streetNumberValidation: (seq: List[String])scalaz.Validation[java.lang.String,Int]
    
    scala> def streetValidation(seq: List[String]) = seq.find(Set("Bush Street", "Pine Street", "Market Street").contains(_)).toSuccess("Street not found")
    streetValidation: (seq: List[String])scalaz.Validation[java.lang.String,String]
    
    scala> def onlyShort(seq: List[String]) = seq.filter(_.size < 15)
    onlyShort: (seq: List[String])List[String]
    
    scala> def omitGarbage(seq: List[String]) = seq.filter(_ != "garbage")
    omitGarbage: (seq: List[String])List[String]
    
    scala> def createPerson(seq: List[String]) = for {
         |   name <- nameValidation(seq)
         |   seq2 = onlyShort(seq)
         |   lastName <- lastNameValidation(seq2)
         |   length <- lengthValidation(lastName)
         |   dy <- dyValidation(lastName)
         |   seq3 = omitGarbage(seq2)
         |   streetNumber <- streetNumberValidation(seq3)
         |   street <- streetValidation(seq3)
         | } yield Person(name, lastName, 80, Address(street, streetNumber))
    createPerson: (seq: List[String])scalaz.Validation[java.lang.String,Person]
    
    scala> createPerson(List("255", "a very long string", "Bush Street", "Hardy", "San Francisco", "John", "garbage"))
    res19: scalaz.Validation[java.lang.String,Person] = Success(Person(John,Hardy,80,Address(Bush Street,255)))
    
    scala> createPerson(List("a very long string", "Bush Street", "Hardy", "San Francisco", "John", "garbage"))
    res20: scalaz.Validation[java.lang.String,Person] = Failure(Could not extract street number)
    

0 个答案:

没有答案