diff --git a/core/src/main/scala/cats/data/Kleisli.scala b/core/src/main/scala/cats/data/Kleisli.scala index d88556791a..d58fc60d19 100644 --- a/core/src/main/scala/cats/data/Kleisli.scala +++ b/core/src/main/scala/cats/data/Kleisli.scala @@ -3,15 +3,24 @@ package data import cats.{Contravariant, Id} import cats.arrow._ +import cats.evidence.As /** * Represents a function `A => F[B]`. */ final case class Kleisli[F[_], -A, B](run: A => F[B]) { self => - def ap[C, AA <: A](f: Kleisli[F, AA, B => C])(implicit F: Apply[F]): Kleisli[F, AA, C] = + private[data] def ap[C, AA <: A](f: Kleisli[F, AA, B => C])(implicit F: Apply[F]): Kleisli[F, AA, C] = Kleisli(a => F.ap(f.run(a))(run(a))) + def ap[C, D, AA <: A](f: Kleisli[F, AA, C])(implicit F: Apply[F], ev: B As (C => D)): Kleisli[F, AA, D] = { + Kleisli { a => + val fb: F[C => D] = F.map(run(a))(ev.coerce) + val fc: F[C] = f.run(a) + F.ap(fb)(fc) + } + } + /** * Performs [[local]] and [[map]] simultaneously. */ @@ -620,7 +629,7 @@ private[data] trait KleisliApply[F[_], A] extends Apply[Kleisli[F, A, *]] with K implicit def F: Apply[F] override def ap[B, C](f: Kleisli[F, A, B => C])(fa: Kleisli[F, A, B]): Kleisli[F, A, C] = - fa.ap(f) + f.ap(fa) override def product[B, C](fb: Kleisli[F, A, B], fc: Kleisli[F, A, C]): Kleisli[F, A, (B, C)] = Kleisli(a => F.product(fb.run(a), fc.run(a)))