Use of Validation
import scalaz._
import Scalaz._
def convertToInt(s:String):Validation[String, Int] = {
try{
Success(s.toInt)
}catch {
case ex:NumberFormatException => {
println(ex)
Failure(ex.getMessage)
}
}
}
val p:Option[Int] = convertToInt("sd1").fold( err => None, value => Some(value))
//For comprehension breaks if there is any failure in the middle.
import scalaz._
import Scalaz._
val p = -\/("Failed")
val p1 = -\/("Failed again")
val q = \/-("Success")
val q1 = \/-("Success again")
//Once it thorws exception in the middle of for-comprehension.
//it never gets executed.
//Right biased
for{
a <- q
c <- p
b <- q1
}yield(a,b) //scalaz.\/[String,(String, String)] = -\/(Failed)
//To change that, use toRightDisjunction.The drawback is we can get only first error.
case class ModifiedPerson(fname:String, lname:String, address:String)
val p7:Person = Person("Iniyan",None)
val res: \/[String,(ModifiedPerson)] = for{
fname <- Some("Mr." + p7.firstName).toRightDisjunction("FirstName shouldn't be empty")
lname <- p7.lastName.toRightDisjunction("Provide last name")
address <- p7.address.toRightDisjunction("Provide Address")
}yield(ModifiedPerson(fname, lname, address))
res //prints scalaz.\/[String,ModifiedPerson] = -\/(Provide last name)
//To get all the errors use, Validation.
import scalaz.ValidationNel
import scalaz._
import Scalaz._
sealed abstract class PersonError extends Product with Serializable
final case class MustHaveLastName(id:String) extends PersonError {
override def toString: String = s"${id} should have last name"
}
final case class MustHaveAddress(id:String) extends PersonError {
override def toString: String = s"${id} should have address"
}
case class Person(id:String, firstName:String, lastName:Option[String]=None,address:Option[String]=None)
case class ModifiedPerson(id:String, fname:String, lname:String, address:String)
def checkLastName(id:String,lname:Option[String]):ValidationNel[PersonError,String] = {
lname match {
case Some(value) => value.success
case None => MustHaveLastName(id).failureNel
}
}
def checkAddress(id:String, address:Option[String]):ValidationNel[PersonError,String] = {
address match {
case Some(value) => value.success
case None => MustHaveAddress(id).failureNel
}
}
def constructModPerson(p:Person):Validation[NonEmptyList[PersonError], ModifiedPerson] = {
(checkLastName(p.id, p.lastName) |@| checkAddress(p.id,p.address) ){ (l, a) => new ModifiedPerson(p.id, "Mr." + p.firstName,l, a) }
}
//val p8 = constructModPerson(Person("Iniyan",Some("Paramasivam"),Some("USA")))
val p8 = constructModPerson(Person("1","Iniyan"))
val p9:Option[ModifiedPerson] = p8.fold(f => {
println("Error is " +f.list.mkString(","))
None
}, person => Some(person))
//Result:
//p8: scalaz.Validation[scalaz.NonEmptyList[PersonError],ModifiedPerson] = Failure(NonEmptyList(1 should have last name, 1 should have address))
//Error is 1 should have last name,1 should have address
//p9: Option[ModifiedPerson] = None