Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Override some methods in Kleisli instances #1618

Merged
merged 2 commits into from
Apr 21, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
189 changes: 82 additions & 107 deletions core/src/main/scala/cats/data/Kleisli.scala
Original file line number Diff line number Diff line change
Expand Up @@ -82,17 +82,17 @@ private[data] sealed trait KleisliFunctions {

private[data] sealed abstract class KleisliInstances extends KleisliInstances0 {

implicit def catsDataMonoidForKleisli[F[_], A, B](implicit M: Monoid[F[B]]): Monoid[Kleisli[F, A, B]] =
new KleisliMonoid[F, A, B] { def FB: Monoid[F[B]] = M }
implicit def catsDataMonoidForKleisli[F[_], A, B](implicit FB0: Monoid[F[B]]): Monoid[Kleisli[F, A, B]] =
new KleisliMonoid[F, A, B] { def FB: Monoid[F[B]] = FB0 }

implicit def catsDataMonoidKForKleisli[F[_]](implicit M: Monad[F]): MonoidK[λ[α => Kleisli[F, α, α]]] =
Category[Kleisli[F, ?, ?]].algebraK

implicit val catsDataMonoidKForKleisliId: MonoidK[λ[α => Kleisli[Id, α, α]]] =
catsDataMonoidKForKleisli[Id]

implicit def catsDataArrowForKleisli[F[_]](implicit ev: Monad[F]): Arrow[Kleisli[F, ?, ?]] =
new KleisliArrow[F] { def F: Monad[F] = ev }
implicit def catsDataArrowForKleisli[F[_]](implicit M: Monad[F]): Arrow[Kleisli[F, ?, ?]] =
new KleisliArrow[F] { def F: Monad[F] = M }

implicit val catsDataArrowForKleisliId: Arrow[Kleisli[Id, ?, ?]] =
catsDataArrowForKleisli[Id]
Expand All @@ -102,7 +102,7 @@ private[data] sealed abstract class KleisliInstances extends KleisliInstances0 {

implicit def catsDataContravariantForKleisli[F[_], C]: Contravariant[Kleisli[F, ?, C]] =
new Contravariant[Kleisli[F, ?, C]] {
override def contramap[A, B](fa: Kleisli[F, A, C])(f: (B) => A): Kleisli[F, B, C] =
override def contramap[A, B](fa: Kleisli[F, A, C])(f: B => A): Kleisli[F, B, C] =
fa.local(f)
}

Expand All @@ -113,114 +113,70 @@ private[data] sealed abstract class KleisliInstances extends KleisliInstances0 {
def liftT[M[_], B](ma: M[B])(implicit ev: Trivial): Kleisli[M, A, B] = Kleisli.lift(ma)
}

implicit def catsDataApplicativeErrorForKleisli[F[_], A, E](implicit AE: ApplicativeError[F, E]): ApplicativeError[Kleisli[F, A, ?], E]
= new KleisliApplicativeError[F, A, E] { implicit def AF: ApplicativeError[F, E] = AE }
implicit def catsDataApplicativeErrorForKleisli[F[_], A, E](implicit AE: ApplicativeError[F, E]): ApplicativeError[Kleisli[F, A, ?], E] =
new KleisliApplicativeError[F, A, E] { def F: ApplicativeError[F, E] = AE }
}

private[data] sealed abstract class KleisliInstances0 extends KleisliInstances1 {

implicit def catsDataMonadErrorForKleisli[F[_], A, E](
implicit me: MonadError[F, E]
): MonadError[Kleisli[F, A, ?], E] with MonadReader[Kleisli[F, A, ?], A] = {
new KleisliApplicativeError[F, A, E]
with KleisliMonadReader[F, A]
with MonadError[Kleisli[F, A, ?], E] {
override def M: Monad[F] = me
override def AF: ApplicativeError[F, E] = me
}
}
implicit def catsDataMonadErrorForKleisli[F[_], A, E](implicit ME: MonadError[F, E]): MonadError[Kleisli[F, A, ?], E] =
new KleisliMonadError[F, A, E] { def F: MonadError[F, E] = ME }
}

private[data] sealed abstract class KleisliInstances1 extends KleisliInstances2 {

implicit def catsDataMonadReaderForKleisli[F[_]: Monad, A](implicit m: Monad[F]): MonadReader[Kleisli[F, A, ?], A] = {
new KleisliMonadReader[F, A] {
override def M: Monad[F] = m
}
}
implicit def catsDataMonadReaderForKleisli[F[_], A](implicit M: Monad[F]): MonadReader[Kleisli[F, A, ?], A] =
new KleisliMonadReader[F, A] { def F: Monad[F] = M }
}

private[data] sealed abstract class KleisliInstances2 extends KleisliInstances3 {
implicit def catsDataChoiceForKleisli[F[_]](implicit ev: Monad[F]): Choice[Kleisli[F, ?, ?]] =
new Choice[Kleisli[F, ?, ?]] {
def id[A]: Kleisli[F, A, A] = Kleisli(ev.pure)

def choice[A, B, C](f: Kleisli[F, A, C], g: Kleisli[F, B, C]): Kleisli[F, Either[A, B], C] =
Kleisli(_.fold(f.run, g.run))

def compose[A, B, C](f: Kleisli[F, B, C], g: Kleisli[F, A, B]): Kleisli[F, A, C] =
f.compose(g)
}
implicit def catsDataChoiceForKleisli[F[_]](implicit M: Monad[F]): Choice[Kleisli[F, ?, ?]] =
new KleisliChoice[F] { def F: Monad[F] = M }

implicit val catsDataChoiceForKleisliId: Choice[Kleisli[Id, ?, ?]] =
catsDataChoiceForKleisli[Id]

implicit def catsDataSplitForKleisli[F[_]](implicit ev: FlatMap[F]): Split[Kleisli[F, ?, ?]] =
new KleisliSplit[F] { def F: FlatMap[F] = ev }
implicit def catsDataSplitForKleisli[F[_]](implicit FM: FlatMap[F]): Split[Kleisli[F, ?, ?]] =
new KleisliSplit[F] { def F: FlatMap[F] = FM }

implicit def catsDataStrongForKleisli[F[_]](implicit ev: Functor[F]): Strong[Kleisli[F, ?, ?]] =
new KleisliStrong[F] { def F: Functor[F] = ev }
implicit def catsDataStrongForKleisli[F[_]](implicit F0: Functor[F]): Strong[Kleisli[F, ?, ?]] =
new KleisliStrong[F] { def F: Functor[F] = F0 }

implicit def catsDataFlatMapForKleisli[F[_], A](implicit ev: FlatMap[F]): FlatMap[Kleisli[F, A, ?]] =
new KleisliFlatMap[F, A] { def FM: FlatMap[F] = ev }
implicit def catsDataFlatMapForKleisli[F[_], A](implicit FM: FlatMap[F]): FlatMap[Kleisli[F, A, ?]] =
new KleisliFlatMap[F, A] { def F: FlatMap[F] = FM }

implicit def catsDataSemigroupForKleisli[F[_], A, B](implicit M: Semigroup[F[B]]): Semigroup[Kleisli[F, A, B]] =
new KleisliSemigroup[F, A, B] { def FB: Semigroup[F[B]] = M }
implicit def catsDataSemigroupForKleisli[F[_], A, B](implicit FB0: Semigroup[F[B]]): Semigroup[Kleisli[F, A, B]] =
new KleisliSemigroup[F, A, B] { def FB: Semigroup[F[B]] = FB0 }

implicit def catsDataSemigroupKForKleisli[F[_]](implicit ev: FlatMap[F]): SemigroupK[λ[α => Kleisli[F, α, α]]] =
implicit def catsDataSemigroupKForKleisli[F[_]](implicit FM: FlatMap[F]): SemigroupK[λ[α => Kleisli[F, α, α]]] =
Compose[Kleisli[F, ?, ?]].algebraK
}

private[data] sealed abstract class KleisliInstances3 extends KleisliInstances4 {
implicit def catsDataApplicativeForKleisli[F[_], A](implicit A : Applicative[F]): Applicative[Kleisli[F, A, ?]] = new KleisliApplicative[F, A] {
implicit def F: Applicative[F] = A
}
implicit def catsDataApplicativeForKleisli[F[_], A](implicit A: Applicative[F]): Applicative[Kleisli[F, A, ?]] =
new KleisliApplicative[F, A] { def F: Applicative[F] = A }
}

private[data] sealed abstract class KleisliInstances4 extends KleisliInstances5 {
implicit def catsDataApplyForKleisli[F[_]: Apply, A]: Apply[Kleisli[F, A, ?]] = new Apply[Kleisli[F, A, ?]] {
def ap[B, C](f: Kleisli[F, A, B => C])(fa: Kleisli[F, A, B]): Kleisli[F, A, C] =
fa.ap(f)

override def product[B, C](fb: Kleisli[F, A, B], fc: Kleisli[F, A, C]): Kleisli[F, A, (B, C)] =
Kleisli(a => Apply[F].product(fb.run(a), fc.run(a)))

def map[B, C](fa: Kleisli[F, A, B])(f: B => C): Kleisli[F, A, C] =
fa.map(f)
}
implicit def catsDataApplyForKleisli[F[_], A](implicit A: Apply[F]): Apply[Kleisli[F, A, ?]] =
new KleisliApply[F, A] { def F: Apply[F] = A }
}

private[data] sealed abstract class KleisliInstances5 {
implicit def catsDataFunctorForKleisli[F[_]: Functor, A]: Functor[Kleisli[F, A, ?]] = new Functor[Kleisli[F, A, ?]] {
def map[B, C](fa: Kleisli[F, A, B])(f: B => C): Kleisli[F, A, C] =
fa.map(f)
}
implicit def catsDataFunctorForKleisli[F[_], A](implicit F0: Functor[F]): Functor[Kleisli[F, A, ?]] =
new KleisliFunctor[F, A] { def F: Functor[F] = F0 }
}

private trait KleisliArrow[F[_]] extends Arrow[Kleisli[F, ?, ?]] with KleisliSplit[F] with KleisliStrong[F] {
private trait KleisliArrow[F[_]] extends Arrow[Kleisli[F, ?, ?]] with KleisliSplit[F] with KleisliStrong[F] with KleisliCategory[F] {
implicit def F: Monad[F]

def lift[A, B](f: A => B): Kleisli[F, A, B] =
Kleisli(a => F.pure(f(a)))

def id[A]: Kleisli[F, A, A] =
Kleisli(a => F.pure(a))

override def second[A, B, C](fa: Kleisli[F, A, B]): Kleisli[F, (C, A), (C, B)] =
super[KleisliStrong].second(fa)

override def split[A, B, C, D](f: Kleisli[F, A, B], g: Kleisli[F, C, D]): Kleisli[F, (A, C), (B, D)] =
super[KleisliSplit].split(f, g)
}

private trait KleisliSplit[F[_]] extends Split[Kleisli[F, ?, ?]] {
private trait KleisliSplit[F[_]] extends Split[Kleisli[F, ?, ?]] with KleisliCompose[F] {
implicit def F: FlatMap[F]

def split[A, B, C, D](f: Kleisli[F, A, B], g: Kleisli[F, C, D]): Kleisli[F, (A, C), (B, D)] =
override def split[A, B, C, D](f: Kleisli[F, A, B], g: Kleisli[F, C, D]): Kleisli[F, (A, C), (B, D)] =
Kleisli{ case (a, c) => F.flatMap(f.run(a))(b => F.map(g.run(c))(d => (b, d))) }

def compose[A, B, C](f: Kleisli[F, B, C], g: Kleisli[F, A, B]): Kleisli[F, A, C] =
f.compose(g)
}

private trait KleisliStrong[F[_]] extends Strong[Kleisli[F, ?, ?]] {
Expand All @@ -238,10 +194,28 @@ private trait KleisliStrong[F[_]] extends Strong[Kleisli[F, ?, ?]] {
def first[A, B, C](fa: Kleisli[F, A, B]): Kleisli[F, (A, C), (B, C)] =
fa.first[C]

def second[A, B, C](fa: Kleisli[F, A, B]): Kleisli[F, (C, A), (C, B)] =
override def second[A, B, C](fa: Kleisli[F, A, B]): Kleisli[F, (C, A), (C, B)] =
fa.second[C]
}

private trait KleisliChoice[F[_]] extends Choice[Kleisli[F, ?, ?]] with KleisliCategory[F] {
def choice[A, B, C](f: Kleisli[F, A, C], g: Kleisli[F, B, C]): Kleisli[F, Either[A, B], C] =
Kleisli(_.fold(f.run, g.run))
}

private trait KleisliCategory[F[_]] extends Category[Kleisli[F, ?, ?]] with KleisliCompose[F] {
implicit def F: Monad[F]

def id[A]: Kleisli[F, A, A] = Kleisli.ask[F, A]
}

private trait KleisliCompose[F[_]] extends Compose[Kleisli[F, ?, ?]] {
implicit def F: FlatMap[F]

def compose[A, B, C](f: Kleisli[F, B, C], g: Kleisli[F, A, B]): Kleisli[F, A, C] =
f.compose(g)
}

private trait KleisliSemigroup[F[_], A, B] extends Semigroup[Kleisli[F, A, B]] {
implicit def FB: Semigroup[F[B]]

Expand All @@ -255,63 +229,64 @@ private trait KleisliMonoid[F[_], A, B] extends Monoid[Kleisli[F, A, B]] with Kl
override def empty: Kleisli[F, A, B] = Kleisli[F, A, B](a => FB.empty)
}

private trait KleisliApplicativeError[F[_], A, E] extends KleisliApplicative[F, A] with ApplicativeError[Kleisli[F, A, ?], E] {
type K[T] = Kleisli[F, A, T]
private trait KleisliMonadError[F[_], A, E] extends MonadError[Kleisli[F, A, ?], E] with KleisliApplicativeError[F, A, E] with KleisliMonadReader[F, A] {
def F: MonadError[F, E]
}

implicit def AF: ApplicativeError[F, E]
private trait KleisliApplicativeError[F[_], A, E] extends ApplicativeError[Kleisli[F, A, ?], E] with KleisliApplicative[F, A] {
type K[T] = Kleisli[F, A, T]

implicit def F: Applicative[F] = AF
implicit def F: ApplicativeError[F, E]

def raiseError[B](e: E): K[B] = Kleisli(_ => AF.raiseError(e))
def raiseError[B](e: E): K[B] = Kleisli(_ => F.raiseError(e))

def handleErrorWith[B](kb: K[B])(f: E => K[B]): K[B] = Kleisli { a: A =>
AF.handleErrorWith(kb.run(a))((e: E) => f(e).run(a))
F.handleErrorWith(kb.run(a))((e: E) => f(e).run(a))
}

}

private trait KleisliMonadReader[F[_], A] extends KleisliFlatMap[F, A] with KleisliApplicative[F, A] with MonadReader[Kleisli[F, A, ?], A] {

def M: Monad[F]

override def F: Applicative[F] = M
override def FM: FlatMap[F] = M

val ask: Kleisli[F, A, A] = Kleisli(M.pure)
private trait KleisliMonadReader[F[_], A] extends MonadReader[Kleisli[F, A, ?], A] with KleisliMonad[F, A] {
implicit def F: Monad[F]

def local[B](f: A => A)(fa: Kleisli[F, A, B]): Kleisli[F, A, B] =
Kleisli(f.andThen(fa.run))
val ask: Kleisli[F, A, A] = Kleisli.ask[F, A]

override def ap[B, C](f: Kleisli[F, A, B => C])(fa: Kleisli[F, A, B]): Kleisli[F, A, C] =
super[KleisliApplicative].ap(f)(fa)
def local[B](f: A => A)(fa: Kleisli[F, A, B]): Kleisli[F, A, B] = Kleisli.local(f)(fa)
}

private trait KleisliFlatMap[F[_], A] extends FlatMap[Kleisli[F, A, ?]] {
private trait KleisliMonad[F[_], A] extends Monad[Kleisli[F, A, ?]] with KleisliFlatMap[F, A] with KleisliApplicative[F, A] {
implicit def F: Monad[F]
}

implicit def FM: FlatMap[F]
private trait KleisliFlatMap[F[_], A] extends FlatMap[Kleisli[F, A, ?]] with KleisliApply[F, A] {
implicit def F: FlatMap[F]

def flatMap[B, C](fa: Kleisli[F, A, B])(f: B => Kleisli[F, A, C]): Kleisli[F, A, C] =
fa.flatMap(f)

def map[B, C](fa: Kleisli[F, A, B])(f: B => C): Kleisli[F, A, C] =
fa.map(f)

def tailRecM[B, C](b: B)(f: B => Kleisli[F, A, Either[B, C]]): Kleisli[F, A, C] =
Kleisli[F, A, C]({ a => FlatMap[F].tailRecM(b) { f(_).run(a) } })
Kleisli[F, A, C]({ a => F.tailRecM(b) { f(_).run(a) } })
}

private trait KleisliApplicative[F[_], A] extends Applicative[Kleisli[F, A, ?]] {
private trait KleisliApplicative[F[_], A] extends Applicative[Kleisli[F, A, ?]] with KleisliApply[F, A] {
implicit def F: Applicative[F]

def pure[B](x: B): Kleisli[F, A, B] =
Kleisli.pure[F, A, B](x)
}

def ap[B, C](f: Kleisli[F, A, B => C])(fa: Kleisli[F, A, B]): Kleisli[F, A, C] =
fa.ap(f)
private trait KleisliApply[F[_], A] extends Apply[Kleisli[F, A, ?]] with KleisliFunctor[F, A] {
implicit def F: Apply[F]

override def map[B, C](fb: Kleisli[F, A, B])(f: B => C): Kleisli[F, A, C] =
fb.map(f)
override def ap[B, C](f: Kleisli[F, A, B => C])(fa: Kleisli[F, A, B]): Kleisli[F, A, C] =
fa.ap(f)

override def product[B, C](fb: Kleisli[F, A, B], fc: Kleisli[F, A, C]): Kleisli[F, A, (B, C)] =
Kleisli(a => Applicative[F].product(fb.run(a), fc.run(a)))
Kleisli(a => F.product(fb.run(a), fc.run(a)))
}

private trait KleisliFunctor[F[_], A] extends Functor[Kleisli[F, A, ?]] {
implicit def F: Functor[F]

override def map[B, C](fa: Kleisli[F, A, B])(f: B => C): Kleisli[F, A, C] =
fa.map(f)
}
8 changes: 8 additions & 0 deletions tests/src/test/scala/cats/tests/KleisliTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ class KleisliTests extends CatsSuite {
kleisliEq

implicit val eitherTEq = EitherT.catsDataEqForEitherT[Kleisli[Option, Int, ?], Unit, Int]
implicit val eitherTEq2 = EitherT.catsDataEqForEitherT[Reader[Int, ?], Unit, Int]

implicit val iso = CartesianTests.Isomorphisms.invariant[Kleisli[Option, Int, ?]]
implicit val iso2 = CartesianTests.Isomorphisms.invariant[Reader[Int, ?]]

checkAll("Kleisli[Option, Int, Int] with Unit", ApplicativeErrorTests[Kleisli[Option, Int, ?], Unit].applicativeError[Int, Int, Int])
checkAll("ApplicativeError[Kleisli[Option, Int, Int], Unit]", SerializableTests.serializable(ApplicativeError[Kleisli[Option, Int, ?], Unit]))
Expand Down Expand Up @@ -49,6 +51,12 @@ class KleisliTests extends CatsSuite {
checkAll("MonadReader[Kleisli[Option, ?, ?], Int]", SerializableTests.serializable(MonadReader[Kleisli[Option, Int, ?], Int]))
}

{
implicit val catsDataMonadReaderForReader = Kleisli.catsDataMonadReaderForKleisliId[Int]
checkAll("Reader[Int, Int]", MonadReaderTests[Reader[Int, ?], Int].monadReader[Int, Int, Int])
checkAll("MonadReader[Reader[?, ?], Int]", SerializableTests.serializable(MonadReader[Reader[Int, ?], Int]))
}

{
implicit val kleisliSplit = Kleisli.catsDataSplitForKleisli[Option]
checkAll("Kleisli[Option, Int, Int]", SplitTests[Kleisli[Option, ?, ?]].split[Int, Int, Int, Int, Int, Int])
Expand Down