Skip to content

Commit 580fb54

Browse files
committed
make applicative stack safe
1 parent 757c110 commit 580fb54

File tree

1 file changed

+9
-6
lines changed

1 file changed

+9
-6
lines changed

modules/core/src/main/scala/hxl/Hxl.scala

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,9 @@ object Hxl {
155155
): Applicative[Hxl[F, *]] = {
156156
implicit def self: Applicative[Hxl[F, *]] = applicativeInstance[F, G](fg, gf)
157157
type H[A] = Hxl[F, A]
158+
def suspend[A](ha: => H[A]): H[A] = LiftF[F, A](
159+
gf(Applicative[G].unit.map(_ => ha))
160+
)
158161
new Applicative[H] {
159162
def pure[A](x: A): H[A] = Done(x)
160163
def ap[A, B](ff: H[A => B])(fa: H[A]): H[B] = {
@@ -164,21 +167,21 @@ object Hxl {
164167
case (h, LiftF(fa)) => LiftF(fa.map(h <*> _))
165168
case (at: AndThen[F, a1, A => B], ab: AndThen[F, a2, A]) =>
166169
AndThen[F, (a1, a2), B](
167-
self.tuple2(at.fa, ab.fa),
168-
{ case (a1, a2) => at.fb(a1).ap(ab.fb(a2)) }
170+
suspend(self.tuple2(at.fa, ab.fa)),
171+
{ case (a1, a2) => suspend(at.fb(a1).ap(ab.fb(a2))) }
169172
)
170173

171174
// flatMap <*> batch -> move batch into left side of flatMap
172175
// to be optimistic. The choice is arbitrary.
173176
case (at: AndThen[F, a, A => B], fb) =>
174177
AndThen[F, (a, A), B](
175-
(at.fa, fb).tupled,
176-
{ case (a, a2) => self.ap(at.fb(a))(Done(a2)) }
178+
suspend((at.fa, fb).tupled),
179+
{ case (a, a2) => suspend(self.ap(at.fb(a))(Done(a2))) }
177180
)
178181
case (fa, ab: AndThen[F, a, A]) =>
179182
AndThen[F, (A => B, a), B](
180-
(fa, ab.fa).tupled,
181-
{ case (f, a2) => self.ap(Done(f))(ab.fb(a2)) }
183+
suspend((fa, ab.fa).tupled),
184+
{ case (f, a2) => suspend(self.ap(Done(f))(ab.fb(a2))) }
182185
)
183186

184187
case (Done(f), Done(a)) => Done(f(a))

0 commit comments

Comments
 (0)