Last active
November 20, 2015 15:45
-
-
Save jayhutfles/deca344c8be2f853b2b4 to your computer and use it in GitHub Desktop.
Differences between Xor and Validated in Cats
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import cats._ | |
import cats.data._ | |
import cats.std.all._ | |
import cats.syntax.apply._ | |
object ValidationExamples { | |
type WhyNot = List[String] | |
type Good[A] = Xor[WhyNot, A] | |
type Proven[A] = Validated[WhyNot, A] | |
trait TryingGood { | |
def a(s: String): Good[Int] | |
def b(s: String): Good[Int] | |
def c(s: String): Good[(Int, Int)] = (a(s) |@| b(s)) map { (_, _) } | |
def l(s: String): Good[Int] = a(s) <* b(s) | |
def r(s: String): Good[Int] = a(s) *> b(s) | |
} | |
trait TryingProven { | |
def a(s: String): Proven[Int] | |
def b(s: String): Proven[Int] | |
def c(s: String): Proven[(Int, Int)] = (a(s) |@| b(s)) map { (_, _) } | |
def l(s: String): Proven[Int] = a(s) <* b(s) | |
def r(s: String): Proven[Int] = a(s) *> b(s) | |
} | |
object GoodTry extends TryingGood { | |
def a(s: String) = if (s.length % 2 == 0) Xor.right(s.length) else Xor.left(List("string '" + s + "' has odd length")) | |
def b(s: String) = try { Xor.right(s.toInt) } catch { case e: NumberFormatException => Xor.left(List("can't parse to Int")) } | |
} | |
object ProvenTry extends TryingProven { | |
def a(s: String) = if (s.length % 2 == 0) Validated.valid(s.length) else Validated.invalid(List("string '" + s + "' has odd length")) | |
def b(s: String) = try { Validated.valid(s.toInt) } catch { case e: NumberFormatException => Validated.invalid(List("can't parse to Int")) } | |
} | |
val inputs = List("12", "1", "ab", "a") | |
val goodTuple = inputs.map(GoodTry.c(_)) | |
// "12" => Right((2,12)) | |
// "1" => Left(List(string '1' has odd length)) // FIRST FAILURE | |
// "ab" => Left(List(can't parse to Int)) // SECOND FAILURE | |
// "a" => Left(List(string 'a' has odd length)) // JUST THE FIRST OF THE TWO FAILURES | |
val goodLeft = inputs.map(GoodTry.l(_)) | |
// "12" => Right(2) // JUST THE LEFT OF THE TWO COMPOSED APPLICATIVES | |
// "1" => Left(List(string '1' has odd length)) // FIRST FAILURE | |
// "ab" => Left(List(can't parse to Int)) // SECOND FAILURE | |
// "a" => Left(List(string 'a' has odd length)) // JUST THE FIRST OF THE TWO FAILURES | |
val goodRight = inputs.map(GoodTry.r(_)) | |
// "12" => Right(12) // JUST THE RIGHT OF THE TWO COMPOSED APPLICATIVES | |
// "1" => Left(List(string '1' has odd length)) // FIRST FAILURE | |
// "ab" => Left(List(can't parse to Int)) // SECOND FAILURE | |
// "a" => Left(List(string 'a' has odd length)) // JUST THE FIRST OF THE TWO FAILURES | |
val provenTuple = inputs.map(ProvenTry.c(_)) | |
// "12" => Valid((2,12)) | |
// "1" => Invalid(List(string '1' has odd length)) // FIRST FAILURE | |
// "ab" => Invalid(List(can't parse to Int)) // SECOND FAILURE | |
// "a" => Invalid(List(string 'a' has odd length, can't parse to Int)) // BOTH FAILURES | |
val provenLeft = inputs.map(ProvenTry.l(_)) | |
// "12" => Valid(2) // JUST THE LEFT OF THE TWO COMPOSED APPLICATIVES | |
// "1" => Invalid(List(string '1' has odd length)) // FIRST FAILURE | |
// "ab" => Invalid(List(can't parse to Int)) // SECOND FAILURE | |
// "a" => Invalid(List(string 'a' has odd length, can't parse to Int)) // BOTH FAILURES | |
val provenRight = inputs.map(ProvenTry.r(_)) | |
// "12" => Valid(12) // JUST THE RIGHT OF THE TWO COMPOSED APPLICATIVES | |
// "1" => Invalid(List(string '1' has odd length)) // FIRST FAILURE | |
// "ab" => Invalid(List(can't parse to Int)) // SECOND FAILURE | |
// "a" => Invalid(List(string 'a' has odd length, can't parse to Int)) // BOTH FAILURES | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment