From fe3d57cb0d6b92e891037a4f8c5c58907878a6cd Mon Sep 17 00:00:00 2001 From: Aleksey Troitskiy Date: Fri, 12 Jul 2019 18:02:30 +0300 Subject: [PATCH] fix #2940 --- free/src/main/scala/cats/free/Cofree.scala | 2 +- free/src/test/scala/cats/free/CofreeSuite.scala | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/free/src/main/scala/cats/free/Cofree.scala b/free/src/main/scala/cats/free/Cofree.scala index 36c4893a11..051c916d1a 100644 --- a/free/src/main/scala/cats/free/Cofree.scala +++ b/free/src/main/scala/cats/free/Cofree.scala @@ -80,7 +80,7 @@ object Cofree extends CofreeInstances { * A stack-safe algebraic recursive fold out of the cofree comonad. */ def cata[F[_], A, B](cof: Cofree[F, A])(folder: (A, F[B]) => Eval[B])(implicit F: Traverse[F]): Eval[B] = - F.traverse(cof.tailForced)(cata(_)(folder)).flatMap(folder(cof.head, _)) + F.traverse(cof.tailForced)(c => Eval.defer(cata(c)(folder))).flatMap(folder(cof.head, _)) /** * A monadic recursive fold out of the cofree comonad into a monad which can express Eval's stack-safety. diff --git a/free/src/test/scala/cats/free/CofreeSuite.scala b/free/src/test/scala/cats/free/CofreeSuite.scala index 6bbf13c6d9..14fe7f94a2 100644 --- a/free/src/test/scala/cats/free/CofreeSuite.scala +++ b/free/src/test/scala/cats/free/CofreeSuite.scala @@ -108,6 +108,19 @@ class CofreeSuite extends CatsSuite { cata should ===(nelUnfoldedHundred) } + test("Cofree.cata is stack-safe") { + val unfolded = Cofree.unfold[Option, Int](0)(i => if (i == 50000) None else Some(i + 1)) + val sum = List.tabulate(50000)(identity).sum + val cata = + Cofree + .cata[Option, Int, Int](unfolded)( + (i, lb) => Eval.now(lb.fold(0)(_ + i)) + ) + .value + + cata should ===(sum) + } + test("Cofree.cataM") { type EvalOption[A] = OptionT[Eval, A]