Skip to content

Commit

Permalink
Make Free.foldMap stack-safe.
Browse files Browse the repository at this point in the history
Fixes typelevel#721.

The fix is possible by strengthening constraints on the target monad
from Monad to MonadRec.
  • Loading branch information
TomasMikula committed May 31, 2016
1 parent 04b2501 commit 07de292
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 7 deletions.
12 changes: 6 additions & 6 deletions free/src/main/scala/cats/free/Free.scala
Original file line number Diff line number Diff line change
Expand Up @@ -135,12 +135,12 @@ sealed abstract class Free[S[_], A] extends Product with Serializable {
* Run to completion, mapping the suspension with the given transformation at each step and
* accumulating into the monad `M`.
*/
final def foldMap[M[_]](f: FunctionK[S,M])(implicit M: Monad[M]): M[A] =
step match {
case Pure(a) => M.pure(a)
case Suspend(s) => f(s)
case Gosub(c, g) => M.flatMap(c.foldMap(f))(cc => g(cc).foldMap(f))
}
final def foldMap[M[_]](f: FunctionK[S,M])(implicit M: MonadRec[M]): M[A] =
M.tailRecM(this)(_.step match {
case Pure(a) => M.pure(Xor.right(a))
case Suspend(sa) => M.map(f(sa))(Xor.right)
case Gosub(c, g) => M.map(c.foldMap(f))(cc => Xor.left(g(cc)))
})

/**
* Compile your Free into another language by changing the suspension functor
Expand Down
2 changes: 1 addition & 1 deletion free/src/test/scala/cats/free/FreeTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class FreeTests extends CatsSuite {
fa should === (Free.pure[Option, Int](n))
}

ignore("foldMap is stack safe") {
test("foldMap is stack safe") {
trait FTestApi[A]
case class TB(i: Int) extends FTestApi[Int]

Expand Down

0 comments on commit 07de292

Please sign in to comment.