From 80036f0dade1e5ba51c4366e358f0786132d04d6 Mon Sep 17 00:00:00 2001 From: takayahilton Date: Tue, 4 Aug 2020 15:25:11 +0900 Subject: [PATCH] Enable breakout in Reducible[NonEmptyVector].reduceMapA can breakout --- .../main/scala/cats/data/NonEmptyChain.scala | 2 +- .../scala/cats/tests/ReducibleSuite.scala | 59 ++++++++----------- 2 files changed, 25 insertions(+), 36 deletions(-) diff --git a/core/src/main/scala/cats/data/NonEmptyChain.scala b/core/src/main/scala/cats/data/NonEmptyChain.scala index 7a5c235921..37b445538a 100644 --- a/core/src/main/scala/cats/data/NonEmptyChain.scala +++ b/core/src/main/scala/cats/data/NonEmptyChain.scala @@ -441,7 +441,7 @@ sealed abstract private[data] class NonEmptyChainInstances extends NonEmptyChain def reduceLeftTo[A, B](fa: NonEmptyChain[A])(f: A => B)(g: (B, A) => B): B = fa.reduceLeftTo(f)(g) def reduceRightTo[A, B](fa: NonEmptyChain[A])(f: A => B)(g: (A, cats.Eval[B]) => cats.Eval[B]): cats.Eval[B] = - Eval.defer(fa.reduceRightTo(a => Eval.now(f(a))) { (a, b) => + Eval.defer(fa.reduceRightTo(a => Eval.later(f(a))) { (a, b) => Eval.defer(g(a, b)) }) diff --git a/tests/src/test/scala/cats/tests/ReducibleSuite.scala b/tests/src/test/scala/cats/tests/ReducibleSuite.scala index 656d916f94..93f8e74788 100644 --- a/tests/src/test/scala/cats/tests/ReducibleSuite.scala +++ b/tests/src/test/scala/cats/tests/ReducibleSuite.scala @@ -16,22 +16,6 @@ import org.scalacheck.Prop._ class ReducibleSuiteAdditional extends CatsSuite { - test("Reducible[NonEmptyList].reduceLeftM stack safety") { - def nonzero(acc: Long, x: Long): Option[Long] = - if (x == 0) None else Some(acc + x) - - val n = 100000L - val expected = n * (n + 1) / 2 - val actual = (1L to n).toList.toNel.flatMap(_.reduceLeftM(Option.apply)(nonzero)) - assert(actual === (Some(expected))) - } - - test("Reducible[NonEmptyList].reduceRightTo stack safety") { - val n = 100000L - val actual = (1L to n).toList.toNel.get.reduceRightTo(identity) { case (a, r) => r.map(_ + a) }.value - assert(actual === ((1L to n).sum)) - } - // exists method written in terms of reduceRightTo def contains[F[_]: Reducible, A: Eq](as: F[A], goal: A): Eval[Boolean] = as.reduceRightTo(_ === goal) { (a, lb) => @@ -85,25 +69,7 @@ class ReducibleSuiteAdditional extends CatsSuite { val large = NonEmptyList(1, (2 to 10000).toList) assert(contains(large, 10000).value) } - - test("Reducible[NonEmptyList].reduceMapA can breakout") { - val notAllEven = NonEmptyList.of(2, 4, 6, 9, 10, 12, 14) - val out = mutable.ListBuffer[Int]() - - notAllEven.reduceMapA { a => out += a; if (a % 2 == 0) Some(a) else None } - - assert(out.toList === List(2, 4, 6, 9)) - } - - test("Reducible[NonEmptyList].nonEmptyTraverse_ can breakout") { - val notAllEven = NonEmptyList.of(2, 4, 6, 9, 10, 12, 14) - val out = mutable.ListBuffer[Int]() - - notAllEven.nonEmptyTraverse_ { a => out += a; if (a % 2 == 0) Some(a) else None } - - assert(out.toList === List(2, 4, 6, 9)) - } - + // A simple non-empty stream with lazy `foldRight` and `reduceRightTo` implementations. case class NES[A](h: A, t: Stream[A]) { def toStream: Stream[A] = h #:: t @@ -157,6 +123,12 @@ abstract class ReducibleSuite[F[_]: Reducible](name: String)(implicit def range(start: Long, endInclusive: Long): F[Long] def fromValues[A](el: A, els: A*): F[A] + test(s"Reducible[$name].reduceRightTo stack safety") { + val n = 100000L + val actual = range(1L, n).reduceRightTo(identity) { case (a, r) => r.map(_ + a) }.value + assert(actual === (1L to n).sum) + } + test(s"Reducible[$name].reduceLeftM stack safety") { def nonzero(acc: Long, x: Long): Option[Long] = if (x == 0) None else Some(acc + x) @@ -226,4 +198,21 @@ abstract class ReducibleSuite[F[_]: Reducible](name: String)(implicit } } + test(s"Reducible[$name].reduceMapA can breakout") { + val notAllEven = fromValues(2, 4, 6, 9, 10, 12, 14) + val out = mutable.ListBuffer[Int]() + + notAllEven.reduceMapA { a => out += a; if (a % 2 == 0) Some(a) else None } + + assert(out.toList === List(2, 4, 6, 9)) + } + + test(s"Reducible[$name].reduceRightTo can breakout") { + val notAllEven = fromValues(2, 4, 6, 9, 10, 12, 14) + val out = mutable.ListBuffer[Int]() + + notAllEven.reduceRightTo(identity) { case (a, r) => out += a; if (a % 2 == 0) r.map(_ + a) else Eval.now(0) }.value + + assert(out.toList === List(2, 4, 6, 9)) + } }