The current implementation of the FlatMap.map2Eval is the following:
|
override def map2Eval[A, B, Z](fa: F[A], fb: Eval[F[B]])(f: (A, B) => Z): Eval[F[Z]] = |
|
Eval.now(flatMap(fa)(a => map(fb.value)(b => f(a, b)))) |
If that implementation is used inside Foldable.foldRight it blows the stack very easily:
val G = Applicative[OptionT[Id, *]]
Foldable[List]
.foldRight(List.range(0, 12345), Eval.now(OptionT.pure[Id](0L))) { (a, accEvalG) =>
G.pure(a).map2Eval(accEvalG) { _ + _ }
}
.value
Note: even though Applicative is summoned, since OptionT is a Monad, it implements FlatMap too. And since it doesn't override map2Eval, the one from FlatMap is used.
The current implementation of the
FlatMap.map2Evalis the following:cats/core/src/main/scala/cats/FlatMap.scala
Lines 116 to 117 in 8681c88
If that implementation is used inside
Foldable.foldRightit blows the stack very easily:Note: even though
Applicativeis summoned, sinceOptionTis aMonad, it implementsFlatMaptoo. And since it doesn't overridemap2Eval, the one fromFlatMapis used.