-
Notifications
You must be signed in to change notification settings - Fork 52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
stackoverflow on fib(1500) #95
Comments
This is expected (and unfortunately not easily solved!). The recursion schemes using |
You can trampoline the As an aside, there doesn’t seem to be a link to the site from the README. |
@sellout seems it doesn't work: (matryoshka + scalaz) def expr[T](n: Int)(implicit T: Corecursive.Aux[T, Option]): Trampoline[T] = {
n match {
case 0 => Trampoline.delay(none[T].embed)
case m => Trampoline.suspend(expr(m - 1).map(some(_).embed))
}
}
val e = expr[Fix[Option]](500).cataM[Trampoline, Int] { x => Trampoline.done(0) }
println(e.run) e.run throws stack overflow exception. |
@chenharryhua You can’t do it with So you have to use |
Thanks, @sellout . very helpful. by using hyloM, the stack overflow issue is gone. I wonder if it is because holyM does not build up the structure at all. |
Note, cats has the Defer type class which generalizes Eval.defer to the many structures that support it. You could make a variant of cataM that uses defer with pure that should be stack safe. |
This sounds great!
Defer is a new addition (by you?) if I'm not mistaken?
|
It is. It may be useful in a few other locations to make generic stack
safety work. Might be good to collect examples of blowing the stack and try
to burn them down.
|
But... were you offering to submit a pull request to leverage defer? 😁 |
Hello! Thanks for the great lib, I'm pretty new to recursion schema and all the fancy names and I'm just trying to poke around... Since matryoshka looks like it's EOL I was trying to re-implement the examples using droste and eventually open a pr (if you think it would be useful), but I hit a Would you mind to give me some hints on how to fix it? My understanding is that Thanks in advance import cats.{ Applicative, Functor, Traverse }
import higherkindness.droste.data.Fix
import higherkindness.droste.util.DefaultTraverse
import higherkindness.droste.{ Algebra, Coalgebra, scheme }
// https://github.com/precog/matryoshka/blob/master/tests/shared/src/test/scala/matryoshka/example/nat.scala
object nat {
import cats.syntax.functor.toFunctorOps
sealed trait Nat[+A]
final case object Zero extends Nat[Nothing]
final case class Succ[A](previous: A) extends Nat[A]
implicit val natFunctor: Functor[Nat] = new Functor[Nat] {
override def map[A, B](fa: Nat[A])(f: A => B): Nat[B] =
fa match {
case Zero => Zero
case Succ(previous) => Succ(f(previous))
}
}
val toNat: Coalgebra[Nat, Int] = Coalgebra {
case 0 => Zero
case previous => Succ(previous - 1)
}
val toInt: Algebra[Nat, Int] = Algebra {
case Zero => 0
case Succ(previous) => previous + 1
}
// required by hyloM
implicit val natTraverse: Traverse[Nat] = new DefaultTraverse[Nat] {
override def traverse[G[_]: Applicative, A, B](fa: Nat[A])(f: A => G[B]): G[Nat[B]] = fa match {
case Zero => Applicative[G].pure(Zero) // <<<<<<<<<< cause of StackOverflowError
case Succ(previous) => f(previous) map (Succ(_))
}
}
val intToNat: Int => Fix[Nat] = scheme.ana(toNat)
val natToInt: Fix[Nat] => Int = scheme.cata(toInt)
val intToNatToInt: Int => Int = scheme.hylo(toInt, toNat)
val intToNatToIntStackSafe: Int => Int = scheme.hyloM(toInt.lift, toNat.lift)
} and here the tests import org.scalacheck.Gen
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpecLike
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
final class NatProp extends AnyWordSpecLike with ScalaCheckPropertyChecks with Matchers {
"Nat" should {
// expected to throw StackOverflowError
"verify hylo" in {
forAll(Gen.chooseNum(0, Int.MaxValue)) { n => intToNatToInt(n) shouldBe natToInt(intToNat(n)) }
}
// should work when fixed
"verify hyloM" in {
forAll(Gen.chooseNum(0, Int.MaxValue)) { n => intToNatToIntStackSafe(n) shouldBe n }
}
}
} |
Running the example on the homepage triggers stack overflow exception.
The text was updated successfully, but these errors were encountered: