Skip to content

Commit

Permalink
Some Kleisli instance cleanup (#2105)
Browse files Browse the repository at this point in the history
- Remove an irrelevant and unused `B` type parameter on
`catsDataCommutativeMonadForKleisli`.
- Upgrade `catsDataMonadForKleisliId` from `Monad` to `CommutativeMonad`
  - Note that while I had to add a mima exception for this, I think that
  it should be 100% binary compatible since its a member of a `sealed`
  and `private` abstract class and returns a subtype of what it was
  before.
- Add a `CommutativeFlatMap` instance for `Kleisli`
- Add a couple of implicit resolution tests for Kleisli that were
missing
  • Loading branch information
ceedubs authored and kailuowang committed Dec 14, 2017
1 parent d9c3c5b commit 86caa7e
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 6 deletions.
3 changes: 2 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,8 @@ def mimaSettings(moduleName: String) = Seq(
exclude[InheritedNewAbstractMethodProblem]("cats.instances.Function1Instances0.catsStdDistributiveForFunction1"),
exclude[InheritedNewAbstractMethodProblem]("cats.instances.Function1Instances0.catsStdDistributiveForFunction1"),
exclude[InheritedNewAbstractMethodProblem]("cats.instances.Function1Instances0.catsStdDistributiveForFunction1"),
exclude[ReversedMissingMethodProblem]("cats.kernel.instances.MapInstances.catsKernelStdCommutativeMonoidForMap")
exclude[ReversedMissingMethodProblem]("cats.kernel.instances.MapInstances.catsKernelStdCommutativeMonoidForMap"),
exclude[IncompatibleResultTypeProblem]("cats.data.KleisliInstances0.catsDataMonadForKleisliId")
)
}
)
Expand Down
15 changes: 12 additions & 3 deletions core/src/main/scala/cats/data/Kleisli.scala
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ private[data] sealed trait KleisliExplicitInstances {
}

private[data] sealed abstract class KleisliInstances extends KleisliInstances0 {
implicit def catsDataCommutativeMonadForKleisli[F[_], A, B](implicit F0: CommutativeMonad[F]): CommutativeMonad[Kleisli[F, A, ?]] =
implicit def catsDataCommutativeMonadForKleisli[F[_], A](implicit F0: CommutativeMonad[F]): CommutativeMonad[Kleisli[F, A, ?]] =
new KleisliMonad[F, A] with CommutativeMonad[Kleisli[F, A, ?]] {
implicit def F: Monad[F] = F0
}
Expand All @@ -143,8 +143,14 @@ private[data] sealed abstract class KleisliInstances0 extends KleisliInstances1
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 }

implicit def catsDataMonadForKleisliId[A]: Monad[Kleisli[Id, A, ?]] =
catsDataMonadForKleisli[Id, A]
implicit def catsDataMonadForKleisliId[A]: CommutativeMonad[Kleisli[Id, A, ?]] =
// In an ideal world this would just be `catsDataCommutativeMonadForKleisli[Id, A]`
// but that method is higher in the hierarchy than this one, and it would
// take a substantial amount of moving stuff around to make this happen
// in a binary-compatible way.
new KleisliMonad[Id, A] with CommutativeMonad[Kleisli[Id, A, ?]] {
implicit def F: Monad[Id] = catsInstancesForId
}

implicit def catsDataContravariantMonoidalForKleisli[F[_], A](implicit F0: ContravariantMonoidal[F]): ContravariantMonoidal[Kleisli[F, A, ?]] =
new KleisliContravariantMonoidal[F, A] { def F: ContravariantMonoidal[F] = F0 }
Expand Down Expand Up @@ -215,6 +221,9 @@ private[data] sealed abstract class KleisliInstances4 extends KleisliInstances5

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

implicit def catsDataCommutativeFlatMapForKleisli[F[_], A](implicit F0: CommutativeFlatMap[F]): CommutativeFlatMap[Kleisli[F, A, ?]] =
new KleisliFlatMap[F, A] with CommutativeFlatMap[Kleisli[F, A, ?]] { val F: CommutativeFlatMap[F] = F0 }
}

private[data] sealed abstract class KleisliInstances5 extends KleisliInstances6 {
Expand Down
15 changes: 13 additions & 2 deletions tests/src/test/scala/cats/tests/KleisliSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import cats.laws.discipline.eq._
import org.scalacheck.Arbitrary
import cats.kernel.laws.discipline.{MonoidTests, SemigroupTests}
import cats.laws.discipline.{SemigroupKTests, MonoidKTests}
import Helpers.CSemi

class KleisliSuite extends CatsSuite {
implicit def kleisliEq[F[_], A, B](implicit A: Arbitrary[A], FB: Eq[F[B]]): Eq[Kleisli[F, A, B]] =
Expand All @@ -36,9 +37,15 @@ class KleisliSuite extends CatsSuite {
checkAll("Kleisli[Option, Int, Int]", SemigroupalTests[Kleisli[Option, Int, ?]].semigroupal[Int, Int, Int])
checkAll("Semigroupal[Kleisli[Option, Int, ?]]", SerializableTests.serializable(Semigroupal[Kleisli[Option, Int, ?]]))

checkAll("Kleisli[(CSemi, ?), Int, ?]", CommutativeFlatMapTests[Kleisli[(CSemi, ?), Int, ?]].commutativeFlatMap[Int, Int, Int])
checkAll("CommutativeFlatMap[Kleisli[(CSemi, ?), Int, ?]]",SerializableTests.serializable(CommutativeFlatMap[Kleisli[(CSemi, ?), Int, ?]]))

checkAll("Kleisli[Option, Int, ?]", CommutativeMonadTests[Kleisli[Option, Int, ?]].commutativeMonad[Int, Int, Int])
checkAll("CommutativeMonad[Kleisli[Option, Int, ?]]",SerializableTests.serializable(CommutativeMonad[Kleisli[Option, Int, ?]]))

checkAll("Kleisli[Id, Int, ?]", CommutativeMonadTests[Kleisli[Id, Int, ?]].commutativeMonad[Int, Int, Int])
checkAll("CommutativeMonad[Kleisli[Id, Int, ?]]",SerializableTests.serializable(CommutativeMonad[Kleisli[Id, Int, ?]]))

{
implicit val catsDataArrowForKleisli = Kleisli.catsDataArrowChoiceForKleisli[List]
checkAll("Kleisli[List, Int, Int]", ArrowTests[Kleisli[List, ?, ?]].arrow[Int, Int, Int, Int, Int, Int])
Expand Down Expand Up @@ -273,25 +280,27 @@ class KleisliSuite extends CatsSuite {
Apply[Kleisli[Id, Int, ?]]
Applicative[Kleisli[Id, Int, ?]]
Monad[Kleisli[Id, Int, ?]]
CommutativeMonad[Kleisli[Id, Int, ?]]
Monoid[Kleisli[Id, Int, String]]
Arrow[Kleisli[Id, ?, ?]]
CommutativeArrow[Kleisli[Id, ?, ?]]
Choice[Kleisli[Id, ?, ?]]
Strong[Kleisli[Id, ?, ?]]
FlatMap[Kleisli[Id, Int, ?]]
CommutativeFlatMap[Kleisli[Id, Int, ?]]
Semigroup[Kleisli[Id, Int, String]]

// using Reader alias instead of Kleisli with Id as F
Functor[Reader[Int, ?]]
Apply[Reader[Int, ?]]
Applicative[Reader[Int, ?]]
Monad[Reader[Int, ?]]
CommutativeMonad[Reader[Int, ?]]
Monoid[Reader[Int, String]]
Arrow[Reader[?, ?]]
CommutativeArrow[Reader[?, ?]]
Choice[Reader[?, ?]]
Strong[Reader[?, ?]]
FlatMap[Reader[Int, ?]]
CommutativeFlatMap[Reader[Int, ?]]
Semigroup[Reader[Int, String]]

// using IntReader alias instead of Kleisli with Id as F and A as Int
Expand All @@ -300,8 +309,10 @@ class KleisliSuite extends CatsSuite {
Apply[IntReader]
Applicative[IntReader]
Monad[IntReader]
CommutativeMonad[IntReader]
Monoid[IntReader[String]]
FlatMap[IntReader]
CommutativeFlatMap[IntReader]
Semigroup[IntReader[String]]

ApplicativeError[Kleisli[cats.data.Validated[Unit, ?], Int, ?], Unit]
Expand Down

0 comments on commit 86caa7e

Please sign in to comment.