Drafting Scalaz 7 Check

I would like to make checks that return Scalaz 7 Validations. I made a simple example of parsing a sequence of words and building a Person object from them. The analysis can be unsuccessful at many stages, in which case we will not be able to quickly, with the error message of what was the error. The example below is complete and stupid, as it is, but as close to what I want to achieve as I could provide.

Looking at my understanding below, it seems like there should be a better way to make checks than this.

  • Initial sequence varies multiple times from sequp seq2to seq3. When called, for example lastNameValidation, it must be explicitly called using seq2, although it is called immediately after seq2 = onlyShort(seq).
  • I read about the composition of the Claysley arrow, when you can compose A => M[B]and B => M[C]to get the arrow A => M[C](where Mis the monad). However, I do not always put things together in such a way that the next step will reuse the calculations from the previous one. This, and I could not get a Claysley arrow composition with Scalaz 7.

the code:

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

Any advice on fairy tales / functional gurus is very welcome!

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)
+3
source share

All Articles