In cats , when Monad is created using the Monad attribute, an implementation of the tailRecM method must be provided.
I have a script below that I found impossible to provide for a recursive tailRecM tail tailRecM
sealed trait Tree[+A] final case class Branch[A](left: Tree[A], right: Tree[A]) extends Tree[A] final case class Leaf[A](value: A) extends Tree[A] implicit val treeMonad = new Monad[Tree] { override def pure[A](value: A): Tree[A] = Leaf(value) override def flatMap[A, B](initial: Tree[A])(func: A => Tree[B]): Tree[B] = initial match { case Branch(l, r) => Branch(flatMap(l)(func), flatMap(r)(func)) case Leaf(value) => func(value) } //@tailrec override def tailRecM[A, B](a: A)(func: (A) => Tree[Either[A, B]]): Tree[B] = { func(a) match { case Branch(l, r) => Branch( flatMap(l) { case Right(l) => pure(l) case Left(l) => tailRecM(l)(func) }, flatMap(r){ case Right(r) => pure(r) case Left(r) => tailRecM(r)(func) } ) case Leaf(Left(value)) => tailRecM(value)(func) case Leaf(Right(value)) => Leaf(value) } } }
1) According to the above example, how can this tailRecM method be used to optimize the call to the flatMap method? Is overriding / changing the flatMap method to tailRecM at compile time?
2) If tailRecM not tail recursive as described above, will it still be more efficient than using the original flatMap method?
Share your thoughts.
scala functional-programming recursion scala-cats
tharindu_DG
source share