package scalaz.example
import scalaz._
import collection.immutable.List
import collection.Traversable
object ExampleValidation {
def main(args: Array[String]) = run
import Scalaz._
def run {
failure[String, Int]("error") assert_=== "error".fail[Int]
success[String, Int](0) assert_=== 0.success[String]
validation[String, Int](Left("error")) assert_=== "error".fail[Int]
validation[String, Int](Right(0)) assert_=== 0.success[String]
val s: Validation[String, Int] = 1.success
val f: Validation[String, Int] = "error".fail
s.toOption assert_=== some(1)
s.fail.toOption assert_=== none[String]
f.toOption assert_=== none[Int]
f.fail.toOption assert_=== some("error")
val result: String = s.fold(e => "got error: " + e, s => "got success: " + s.toString)
s match {
case Success(a) => "success"
case Failure(e) => "fail"
}
(f | 1) assert_=== 1
val k3 = (f <**> f){ _ + _ }
k3.fail.toOption assert_=== some("errorerror")
val fNel: ValidationNEL[String, Int] = f.liftFailNel
val k4 = (fNel <**> fNel){ _ + _ }
k4.fail.toOption assert_=== some(nel("error", "error"))
person
parseNumbers
}
def person {
sealed trait Name extends NewType[String]
object Name {
def apply(s: String): Validation[String, Name] = if (s.headOption.exists(_.isUpper))
(new Name {val value = s}).success
else
"Name must start with a capital letter".fail
}
sealed trait Age extends NewType[Int]
object Age {
def apply(a: Int): Validation[String, Age] = if (0 to 130 contains a)
(new Age {val value = a}).success
else
"Age must be in range".fail
}
case class Person(name: Name, age: Age)
def mkPerson(name: String, age: Int) = (Name(name).liftFailNel ⊛ Age(age).liftFailNel){ (n, a) => Person(n, a)}
mkPerson("Bob", 31).isSuccess assert_=== true
mkPerson("bob", 131).fail.toOption assert_=== some(nel("Name must start with a capital letter", "Age must be in range"))
}
def parseNumbers {
def only[A](as: Traversable[A]): Validation[String, A] = {
val firstTwo = as.take(2).toSeq
validation((firstTwo.size != 1) either "required exactly one element" or firstTwo.head)
}
def empty[A](as: Traversable[A]): Validation[String, Unit] =
validation(!as.isEmpty either "expected an empty collection" or ())
val x: ValidationNEL[String, Int] = only(Seq(1)).liftFailNel <* empty(Seq.empty).liftFailNel
x assert_=== 1.successNel[String]
val badInput = """42
|aasf
|314
|xxx""".stripMargin
parse(badInput) assert_=== nel("java.lang.NumberFormatException: For input string: \"aasf\"",
"java.lang.NumberFormatException: For input string: \"xxx\"").fail[List[Int]]
val validInput = """42
|314""".stripMargin
parse(validInput) assert_=== List(42, 314).successNel[String]
}
def parse(text: String): ValidationNEL[String, List[Int]] = {
val lines = text.lines.toList
def parseInt(s: String): ValidationNEL[String, Int] = {
val projection: FailProjection[String, Int] = s.parseInt.fail ∘ (_.toString)
projection.lift[NonEmptyList, String]
}
val listVals: List[ValidationNEL[String, Int]] = lines.map(parseInt(_))
listVals.sequence[({type λ[α]=ValidationNEL[String, α]})#λ, Int]
}
}