diff --git a/core/src/main/scala/cats/data/Validated.scala b/core/src/main/scala/cats/data/Validated.scala index d8a1f2c44a..5ce16997e9 100644 --- a/core/src/main/scala/cats/data/Validated.scala +++ b/core/src/main/scala/cats/data/Validated.scala @@ -27,6 +27,11 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable { */ def getOrElse[B >: A](default: => B): B = fold(_ => default, identity) + /** + * Return the Valid value, or the result of f if Invalid + */ + def valueOr[B >: A](f: E => B): B = fold(f, identity) + /** * Is this Valid and matching the given predicate */ @@ -203,6 +208,8 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable { case Invalid(e) => Valid(e) } + def merge[EE >: E](implicit ev: A <:< EE): EE = fold(identity, ev.apply) + /** * Ensure that a successful result passes the given predicate, * falling back to an Invalid of `onFailure` if the predicate diff --git a/tests/src/test/scala/cats/tests/ValidatedTests.scala b/tests/src/test/scala/cats/tests/ValidatedTests.scala index 22cc72fb6f..1c1f2365c9 100644 --- a/tests/src/test/scala/cats/tests/ValidatedTests.scala +++ b/tests/src/test/scala/cats/tests/ValidatedTests.scala @@ -114,6 +114,12 @@ class ValidatedTests extends CatsSuite { } } + test("valueOr consistent with swap then map then merge") { + forAll { (v: Validated[String, Int], f: String => Int) => + v.valueOr(f) should === (v.swap.map(f).merge) + } + } + test("toEither then fromEither is identity") { forAll { (v: Validated[String, Int]) => Validated.fromEither(v.toEither) should === (v)