diff --git a/core/src/main/scala/cats/data/Ior.scala b/core/src/main/scala/cats/data/Ior.scala index 6ffa11e82b..97d6afa780 100644 --- a/core/src/main/scala/cats/data/Ior.scala +++ b/core/src/main/scala/cats/data/Ior.scala @@ -145,6 +145,31 @@ object Ior extends IorInstances with IorFunctions { } private[data] sealed abstract class IorInstances extends IorInstances0 { + + implicit val catsBitraverseForIor: Bitraverse[Ior] = new Bitraverse[Ior] { + + def bitraverse[G[_], A, B, C, D](fab: Ior[A, B])(f: A => G[C], g: B => G[D])(implicit G: Applicative[G]): G[Ior[C, D]] = + fab match { + case Ior.Left(a) => G.map(f(a))(Ior.Left(_)) + case Ior.Right(b) => G.map(g(b))(Ior.Right(_)) + case Ior.Both(a, b) => G.map2(f(a), g(b))(Ior.Both(_, _)) + } + + def bifoldLeft[A, B, C](fab: Ior[A, B], c: C)(f: (C, A) => C, g: (C, B) => C): C = + fab match { + case Ior.Left(a) => f(c, a) + case Ior.Right(b) => g(c, b) + case Ior.Both(a, b) => g(f(c, a), b) + } + + def bifoldRight[A, B, C](fab: Ior[A, B], c: Eval[C])(f: (A, Eval[C]) => Eval[C], g: (B, Eval[C]) => Eval[C]): Eval[C] = + fab match { + case Ior.Left(a) => f(a, c) + case Ior.Right(b) => g(b, c) + case Ior.Both(a, b) => g(b, f(a, c)) + } + } + implicit def catsDataEqForIor[A: Eq, B: Eq]: Eq[A Ior B] = new Eq[A Ior B] { def eqv(x: A Ior B, y: A Ior B): Boolean = x === y } diff --git a/tests/src/test/scala/cats/tests/IorSuite.scala b/tests/src/test/scala/cats/tests/IorSuite.scala index 81b93be4fd..ac84db49ca 100644 --- a/tests/src/test/scala/cats/tests/IorSuite.scala +++ b/tests/src/test/scala/cats/tests/IorSuite.scala @@ -2,7 +2,7 @@ package cats package tests import cats.kernel.laws.discipline.SemigroupTests -import cats.laws.discipline.{BifunctorTests, SemigroupalTests, MonadErrorTests, SerializableTests, TraverseTests} +import cats.laws.discipline.{BifunctorTests, BitraverseTests, SemigroupalTests, MonadErrorTests, SerializableTests, TraverseTests} import cats.data.{Ior, NonEmptyList, EitherT} import cats.laws.discipline.arbitrary._ import org.scalacheck.Arbitrary._ @@ -23,6 +23,9 @@ class IorSuite extends CatsSuite { checkAll("Traverse[String Ior ?]", SerializableTests.serializable(Traverse[String Ior ?])) checkAll("? Ior ?", BifunctorTests[Ior].bifunctor[Int, Int, Int, String, String, String]) + checkAll("Ior[?, ?]", BitraverseTests[Ior].bitraverse[Option, Int, Int, Int, String, String, String]) + checkAll("Bitraverse[Ior]", SerializableTests.serializable(Bitraverse[Ior])) + checkAll("Semigroup[Ior[A: Semigroup, B: Semigroup]]", SemigroupTests[Ior[List[Int], List[Int]]].semigroup) checkAll("SerializableTest Semigroup[Ior[A: Semigroup, B: Semigroup]]", SerializableTests.serializable(Semigroup[Ior[List[Int], List[Int]]]))