Permalink
Browse files

Encourage the combination of NonEmptyList and Validation with a type …

…alias ValidationNEL, FailProjection.liftNel, and Identity.{failNel, successNel}. The example could do with a bit more work, maybe in combination with a BFFG presentation :)
  • Loading branch information...
retronym committed Feb 28, 2010
1 parent c0fd2a6 commit f2dc9fa2103e29f161920168ee6ca914660b2efa
@@ -110,7 +110,11 @@ sealed trait Identity[A] extends PimpedType[A] {
def success[X]: Validation[X, A] = Scalaz.success(value)
- def fail[X]: Validation[A, X] = Scalaz.failure(value)
+ def successNel[X]: ValidationNEL[X, A] = success
+
+ def fail[X]: Validation[A, X] = failure(value)
+
+ def failNel[X]: ValidationNEL[A, X] = failure(wrapNel)
def some: Option[A] = Some(value)
@@ -77,6 +77,8 @@ sealed trait FailProjection[+E, +A] {
case Failure(e) => Failure((e: EE) η)
}
+ def liftNel: Validation[NonEmptyList[E], A] = lift[NonEmptyList, E]
+
def |||[EE >: E](f: A => EE): EE = validation match {
case Success(a) => f(a)
case Failure(e) => e
@@ -96,6 +98,8 @@ sealed trait FailProjection[+E, +A] {
}
trait Validations {
+ type ValidationNEL[E, X] = Validation[NonEmptyList[E], X]
+
def success[E, A](a: A): Validation[E, A] = Success(a)
def failure[E, A](e: E): Validation[E, A] = Failure(e)
@@ -0,0 +1,46 @@
+package scalaz
+
+import collection.immutable.List
+import collection.Traversable
+
+object ExampleValidation {
+ def main(args: Array[String]) = run
+
+ import Scalaz._
+
+ def run {
+ 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 ())
+
+ // Combine two validations with the Validation Applicative Functor, using only the success
+ // values from the first.
+ val x: ValidationNEL[String, Int] = only(Seq(1)).fail.liftNel <* empty(Seq.empty).fail.liftNel
+ x assert_≟ 1.successNel[String]
+
+ val badInput = """42
+ |aasf
+ |314
+ |xxx""".stripMargin
+ parse(badInput) assert_≟ nel1("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]
+ }
+
+ /**
+ * Parse text containing a list of integers, each on a separate line.
+ */
+ def parse(text: String): ValidationNEL[String, List[Int]] = {
+ val lines = text.lines.toList
+ def parseInt(s: String): ValidationNEL[String, Int] = (s.parseInt.fail ∘ (_.toString)).lift
+ val listVals: List[ValidationNEL[String, Int]] = lines.map(parseInt(_))
+ // Sequence the List using the Validation Applicative Functor.
+ listVals.sequence[PartialApply1Of2[ValidationNEL, String]#Apply, Int]
+ }
+}

0 comments on commit f2dc9fa

Please sign in to comment.