Skip to content

Commit

Permalink
Add Cofree.ana (Cofree.unfold but with fused map)
Browse files Browse the repository at this point in the history
  • Loading branch information
andyscott committed Jul 16, 2018
1 parent 186dbab commit 14b03e0
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 2 deletions.
7 changes: 5 additions & 2 deletions free/src/main/scala/cats/free/Cofree.scala
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,11 @@ object Cofree extends CofreeInstances {

/** Cofree anamorphism, lazily evaluated. */
def unfold[F[_], A](a: A)(f: A => F[A])(implicit F: Functor[F]): Cofree[F, A] =
Cofree[F, A](a, Eval.later(F.map(f(a))(unfold(_)(f))))
ana(a)(f, identity)

/** Cofree anamorphism with a fused map, lazily evaluated. */
def ana[F[_], A, C](a: A)(coalg: A => F[A], f: A => C)(implicit F: Functor[F]): Cofree[F, C] =
Cofree[F, C](f(a), Eval.later(F.map(coalg(a))(ana(_)(coalg, f))))

/**
* A stack-safe algebraic recursive fold out of the cofree comonad.
Expand Down Expand Up @@ -148,4 +152,3 @@ private trait CofreeTraverse[F[_]] extends Traverse[Cofree[F, ?]] with CofreeRed
G.map2(f(fa.head), F.traverse(fa.tailForced)(traverse(_)(f)))((h, t) => Cofree[F, B](h, Eval.now(t)))

}

6 changes: 6 additions & 0 deletions free/src/test/scala/cats/free/CofreeSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ class CofreeSuite extends CatsSuite {
cofNelToNel(unfoldedHundred) should ===(nelUnfoldedHundred)
}

test("Cofree.ana") {
val unfoldedHundred: CofreeNel[String] = Cofree.ana[Option, Int, String](0)(i => if (i == 100) None else Some(i + 1), _.toString)
val nelUnfoldedHundred: NonEmptyList[String] = NonEmptyList.fromListUnsafe(List.tabulate(101)(_.toString))
cofNelToNel(unfoldedHundred) should ===(nelUnfoldedHundred)
}

test("Cofree.tailForced") {
val spooky = new Spooky
val incrementor =
Expand Down

0 comments on commit 14b03e0

Please sign in to comment.