diff --git a/core/src/main/scala/cats/Reducible.scala b/core/src/main/scala/cats/Reducible.scala index 60d2cf15d7..b67ae82f80 100644 --- a/core/src/main/scala/cats/Reducible.scala +++ b/core/src/main/scala/cats/Reducible.scala @@ -181,8 +181,10 @@ import scala.annotation.implicitNotFound * available for `G` and want to take advantage of short-circuiting * the traversal. */ - def nonEmptyTraverse_[G[_], A, B](fa: F[A])(f: A => G[B])(implicit G: Apply[G]): G[Unit] = - G.void(reduceLeftTo(fa)(f)((x, y) => G.map2(x, f(y))((_, b) => b))) + def nonEmptyTraverse_[G[_], A, B](fa: F[A])(f: A => G[B])(implicit G: Apply[G]): G[Unit] = { + val f1 = f.andThen(G.void) + reduceRightTo(fa)(f1)((x, y) => G.map2Eval(f1(x), y)((_, b) => b)).value + } /** * Sequence `F[G[A]]` using `Apply[G]`. @@ -192,7 +194,7 @@ import scala.annotation.implicitNotFound * [[nonEmptyTraverse_]] documentation for a description of the differences. */ def nonEmptySequence_[G[_], A](fga: F[G[A]])(implicit G: Apply[G]): G[Unit] = - G.void(reduceLeft(fga)((x, y) => G.map2(x, y)((_, b) => b))) + nonEmptyTraverse_(fga)(identity) def toNonEmptyList[A](fa: F[A]): NonEmptyList[A] = reduceRightTo(fa)(a => NonEmptyList(a, Nil)) { (a, lnel) => diff --git a/tests/src/test/scala/cats/tests/ReducibleSuite.scala b/tests/src/test/scala/cats/tests/ReducibleSuite.scala index cc8c3b1104..656d916f94 100644 --- a/tests/src/test/scala/cats/tests/ReducibleSuite.scala +++ b/tests/src/test/scala/cats/tests/ReducibleSuite.scala @@ -92,7 +92,16 @@ class ReducibleSuiteAdditional extends CatsSuite { notAllEven.reduceMapA { a => out += a; if (a % 2 == 0) Some(a) else None } - assert(out.toList === (List(2, 4, 6, 9))) + 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.