diff --git a/core/src/main/scala/cats/Align.scala b/core/src/main/scala/cats/Align.scala index 884bda6ece..4100a4a419 100644 --- a/core/src/main/scala/cats/Align.scala +++ b/core/src/main/scala/cats/Align.scala @@ -17,30 +17,64 @@ import cats.data.Ior /** * Pairs elements of two structures along the union of their shapes, using `Ior` to hold the results. * - * Align[List].align(List(1, 2), List(10, 11, 12)) = List(Ior.Both(1, 10), Ior.Both(2, 11), Ior.Right(12)) + * Example: + * {{{ + * scala> import cats.implicits._ + * scala> import cats.data.Ior + * scala> Align[List].align(List(1, 2), List(10, 11, 12)) + * res0: List[Ior[Int, Int]] = List(Both(1,10), Both(2,11), Right(12)) + * }}} */ def align[A, B](fa: F[A], fb: F[B]): F[Ior[A, B]] /** * Combines elements similarly to `align`, using the provided function to compute the results. + * + * Example: + * {{{ + * scala> import cats.implicits._ + * scala> Align[List].alignWith(List(1, 2), List(10, 11, 12))(_.mergeLeft) + * res0: List[Int] = List(1, 2, 12) + * }}} */ def alignWith[A, B, C](fa: F[A], fb: F[B])(f: Ior[A, B] => C): F[C] = functor.map(align(fa, fb))(f) /** * Align two structures with the same element, combining results according to their semigroup instances. + * + * Example: + * {{{ + * scala> import cats.implicits._ + * scala> Align[List].alignCombine(List(1, 2), List(10, 11, 12)) + * res0: List[Int] = List(11, 13, 12) + * }}} */ def alignCombine[A: Semigroup](fa1: F[A], fa2: F[A]): F[A] = alignWith(fa1, fa2)(_.merge) /** * Same as `align`, but forgets from the type that one of the two elements must be present. + * + * Example: + * {{{ + * scala> import cats.implicits._ + * scala> Align[List].padZip(List(1, 2), List(10)) + * res0: List[(Option[Int], Option[Int])] = List((Some(1),Some(10)), (Some(2),None)) + * }}} */ def padZip[A, B](fa: F[A], fb: F[B]): F[(Option[A], Option[B])] = alignWith(fa, fb)(_.pad) /** * Same as `alignWith`, but forgets from the type that one of the two elements must be present. + * + * Example: + * {{{ + * scala> import cats.implicits._ + * scala> Align[List].padZipWith(List(1, 2), List(10, 11, 12))(_ |+| _) + * res0: List[Option[Int]] = List(Some(11), Some(13), Some(12)) + * }}} */ def padZipWith[A, B, C](fa: F[A], fb: F[B])(f: (Option[A], Option[B]) => C): F[C] = alignWith(fa, fb)(ior => Function.tupled(f)(ior.pad)) diff --git a/tests/src/test/scala/cats/tests/EitherSuite.scala b/tests/src/test/scala/cats/tests/EitherSuite.scala index 3544434b71..3d6007516d 100644 --- a/tests/src/test/scala/cats/tests/EitherSuite.scala +++ b/tests/src/test/scala/cats/tests/EitherSuite.scala @@ -5,6 +5,7 @@ import cats.data.{EitherT, NonEmptyChain, NonEmptyList, NonEmptySet, Validated} import cats.laws.discipline._ import cats.kernel.laws.discipline.{EqTests, MonoidTests, OrderTests, PartialOrderTests, SemigroupTests} import org.scalatest.funsuite.AnyFunSuiteLike +import cats.laws.discipline.arbitrary._ import scala.util.Try @@ -17,6 +18,9 @@ class EitherSuite extends CatsSuite { checkAll("Either[Int, Int]", SemigroupalTests[Either[Int, *]].semigroupal[Int, Int, Int]) checkAll("Semigroupal[Either[Int, *]]", SerializableTests.serializable(Semigroupal[Either[Int, *]])) + checkAll("Either[Int, Int]", AlignTests[Either[Int, *]].align[Int, Int, Int, Int]) + checkAll("Align[Either[Int, *]]", SerializableTests.serializable(Align[Either[Int, *]])) + implicit val eq0 = EitherT.catsDataEqForEitherT[Either[Int, *], Int, Int] checkAll("Either[Int, Int]", MonadErrorTests[Either[Int, *], Int].monadError[Int, Int, Int])