Skip to content

Commit

Permalink
Enable breakout in Reducible[NonEmptyVector].reduceMapA can breakout
Browse files Browse the repository at this point in the history
  • Loading branch information
takayahilton committed Aug 6, 2020
1 parent 4cb93fb commit 80036f0
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 36 deletions.
2 changes: 1 addition & 1 deletion core/src/main/scala/cats/data/NonEmptyChain.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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))
})

Expand Down
59 changes: 24 additions & 35 deletions tests/src/test/scala/cats/tests/ReducibleSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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) =>
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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))
}
}

0 comments on commit 80036f0

Please sign in to comment.