@@ -38,8 +38,10 @@ sealed trait Hxl[F[_], A] {
3838 // Useful for combinators such as `flatTraverse`
3939 def monadic : HxlM [F , A ] = HxlM (this )
4040
41- def foldMap [G [_]](fk : Hxl .Compiler [F , G ])(implicit G : Monad [G ]): G [A ] =
42- this .tailRecM(fk(_))
41+ def foldMap [G [_]](fk : Hxl .Compiler [F , G ])(implicit G : Monad [G ]): G [A ] = {
42+ val full = Hxl .Compiler .fullCompiler(fk)
43+ this .tailRecM(full(_))
44+ }
4345
4446 // runs up to the first batch and optimizes it
4547 //
@@ -58,18 +60,34 @@ sealed trait Hxl[F[_], A] {
5860object Hxl {
5961 type Target [F [_], G [_], A ] = G [Either [Hxl [F , A ], A ]]
6062
61- type Compiler [F [_], G [_]] = Hxl [F , * ] ~> Target [F , G , * ]
63+ type Compiler [F [_], G [_]] = NonBind [F , * ] ~> Target [F , G , * ]
64+ object Compiler {
65+ def fullCompiler [F [_], G [_]](compiler : Compiler [F , G ])(implicit G : Applicative [G ]): Hxl [F , * ] ~> Target [F , G , * ] =
66+ new (Hxl [F , * ] ~> Target [F , G , * ]) {
67+ def apply [A ](fa : Hxl [F , A ]): Target [F , G , A ] = fa match {
68+ case nb : NonBind [F , A ] => compiler(nb)
69+ case andThen : AndThen [F , a, A ] =>
70+ val fb : G [Either [Hxl [F , a], a]] = G .unit *> apply(andThen.fa)
71+ fb.map {
72+ case Left (h) => Left (h.andThen(andThen.fb))
73+ case Right (a) => Left (andThen.fb(a))
74+ }
75+ }
76+ }
77+ }
78+
79+ sealed trait NonBind [F [_], A ] extends Hxl [F , A ]
6280
6381 // Almost a free monad
64- final case class Done [F [_], A ](value : A ) extends Hxl [F , A ] {
82+ final case class Done [F [_], A ](value : A ) extends NonBind [F , A ] {
6583 def mapK [G [_]: Functor ](fk : F ~> G ): Hxl [G , A ] = Done (value)
6684 def optimized (implicit F : Monad [F ]) = Left (this )
6785 }
68- final case class Run [F [_], A ](requests : Requests [F , A ]) extends Hxl [F , A ] {
86+ final case class Run [F [_], A ](requests : Requests [F , A ]) extends NonBind [F , A ] {
6987 def mapK [G [_]: Functor ](fk : F ~> G ): Hxl [G , A ] = Run (requests.mapK(fk))
7088 def optimized (implicit F : Monad [F ]) = Left (Run (requests.optimized))
7189 }
72- final case class LiftF [F [_], A ](unFetch : F [Hxl [F , A ]]) extends Hxl [F , A ] {
90+ final case class LiftF [F [_], A ](unFetch : F [Hxl [F , A ]]) extends NonBind [F , A ] {
7391 def mapK [G [_]: Functor ](fk : F ~> G ): Hxl [G , A ] =
7492 LiftF (fk(unFetch).map(_.mapK(fk)))
7593 def optimized (implicit F : Monad [F ]) =
@@ -88,18 +106,12 @@ object Hxl {
88106
89107 def parallelRunner [F [_]](implicit F : Parallel [F ]): Compiler [F , F ] = new Compiler [F , F ] {
90108 implicit val M : Monad [F ] = F .monad
91- override def apply [A ](fa : Hxl [F , A ]): F [Either [Hxl [F , A ], A ]] =
109+ override def apply [A ](fa : NonBind [F , A ]): F [Either [Hxl [F , A ], A ]] =
92110 M .unit >> {
93111 fa match {
94- case Done (a) => M .pure(Right (a))
95- // case Align(fa) => M.pure(Left(fa))
112+ case Done (a) => M .pure(Right (a))
96113 case LiftF (unFetch) => unFetch.map(Left (_))
97- case at : AndThen [F , a, A ] =>
98- apply(at.fa).map {
99- case Left (h) => Left (h.andThen(at.fb))
100- case Right (a) => Left (at.fb(a))
101- }
102- case bind : Run [F , A ] => Requests .run[F , A ](bind.requests).map(Right (_))
114+ case run : Run [F , A ] => Requests .run[F , A ](run.requests).map(Right (_))
103115 }
104116 }
105117 }
0 commit comments