我想撰写一些返回Scalaz 7 Validation
的检查。我做了一个简单的例子,解析一系列单词并从中构造一个Person对象。解析可能会在很多步骤中失败,在这种情况下我们会快速失败,并显示失败的错误消息。下面的例子是完全弥补和愚蠢的,但是尽可能接近我想要达到的目标。
看看下面的理解,似乎必须有更好的方法来构建验证。
seq
更改为seq2
到seq3
。在调用示例lastNameValidation
时,需要使用seq2
显式调用它,即使它在seq2 = onlyShort(seq)
之后立即调用。A => M[B]
和B => M[C]
来获得箭头A => M[C]
(其中M
是monad)。但是,我并不总是以这样的方式组合事物,即下一步将重复使用前一步的计算。那,并且我无法使用Scalaz 7获得Kleisli箭头组合。代码:
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)