From 4d548a91537a2bcebd48b3b1c90c3d5822fb5b0b Mon Sep 17 00:00:00 2001 From: Erik Osheim Date: Wed, 1 Jun 2016 23:53:36 -0400 Subject: [PATCH 01/36] Some clean up for Free (and friends). This commit does a bunch of small things: * Introduces `foldLeftM` and `runTailRec` * Renames `mapSuspension` to `compile` * Removes `Applicative[F]` requirement from `Free.suspend` * Adds some new comments * Moves the Free companion to the end of the file * Minor formatting changes I think all of these are good, but I'm happy to revert any of them that seem like they are bad news. The main reason I removed `mapSuspension` is that its description was written using "compile" which seems like a more evocative name (there are already several "map" variants). --- free/src/main/scala/cats/free/Free.scala | 171 ++++++++++++------ .../src/main/scala/cats/free/Trampoline.scala | 2 - free/src/test/scala/cats/free/FreeTests.scala | 8 +- 3 files changed, 117 insertions(+), 64 deletions(-) diff --git a/free/src/main/scala/cats/free/Free.scala b/free/src/main/scala/cats/free/Free.scala index 93159b07b9..beb7310ad0 100644 --- a/free/src/main/scala/cats/free/Free.scala +++ b/free/src/main/scala/cats/free/Free.scala @@ -6,55 +6,6 @@ import scala.annotation.tailrec import cats.data.Xor, Xor.{Left, Right} import cats.arrow.FunctionK -object Free { - /** - * Return from the computation with the given value. - */ - private final case class Pure[S[_], A](a: A) extends Free[S, A] - - /** Suspend the computation with the given suspension. */ - private final case class Suspend[S[_], A](a: S[A]) extends Free[S, A] - - /** Call a subroutine and continue with the given function. */ - private final case class Gosub[S[_], B, C](c: Free[S, C], f: C => Free[S, B]) extends Free[S, B] - - /** - * Suspend a value within a functor lifting it to a Free. - */ - def liftF[F[_], A](value: F[A]): Free[F, A] = Suspend(value) - - /** Suspend the Free with the Applicative */ - def suspend[F[_], A](value: => Free[F, A])(implicit F: Applicative[F]): Free[F, A] = - liftF(F.pure(())).flatMap(_ => value) - - /** Lift a pure value into Free */ - def pure[S[_], A](a: A): Free[S, A] = Pure(a) - - final class FreeInjectPartiallyApplied[F[_], G[_]] private[free] { - def apply[A](fa: F[A])(implicit I : Inject[F, G]): Free[G, A] = - Free.liftF(I.inj(fa)) - } - - def inject[F[_], G[_]]: FreeInjectPartiallyApplied[F, G] = new FreeInjectPartiallyApplied - - /** - * `Free[S, ?]` has a monad for any type constructor `S[_]`. - */ - implicit def freeMonad[S[_]]: MonadRec[Free[S, ?]] = - new MonadRec[Free[S, ?]] { - def pure[A](a: A): Free[S, A] = Free.pure(a) - override def map[A, B](fa: Free[S, A])(f: A => B): Free[S, B] = fa.map(f) - def flatMap[A, B](a: Free[S, A])(f: A => Free[S, B]): Free[S, B] = a.flatMap(f) - def tailRecM[A, B](a: A)(f: A => Free[S, A Xor B]): Free[S, B] = - f(a).flatMap(_ match { - case Xor.Left(a1) => tailRecM(a1)(f) // recursion OK here, since Free is lazy - case Xor.Right(b) => pure(b) - }) - } -} - -import Free._ - /** * A free operational monad for some functor `S`. Binding is done * using the heap instead of the stack, allowing tail-call @@ -62,6 +13,8 @@ import Free._ */ sealed abstract class Free[S[_], A] extends Product with Serializable { + import Free.{ Pure, Suspend, Gosub } + final def map[B](f: A => B): Free[S, B] = flatMap(a => Pure(f(a))) @@ -115,7 +68,12 @@ sealed abstract class Free[S[_], A] extends Product with Serializable { loop(this) } - final def run(implicit S: Comonad[S]): A = go(S.extract) + /** + * Run to completion, using the given comonad to extract the + * resumption. + */ + final def run(implicit S: Comonad[S]): A = + go(S.extract) /** * Run to completion, using a function that maps the resumption @@ -129,13 +87,39 @@ sealed abstract class Free[S[_], A] extends Product with Serializable { runM2(this) } + /** + * Run to completion, using monadic recursion to evaluate the + * resumption in the context of `S`. + */ + final def runTailRec(implicit S: MonadRec[S]): S[A] = { + def step(rma: Free[S, A]): S[Xor[Free[S, A], A]] = + rma match { + case Pure(a) => + S.pure(Xor.right(a)) + case Suspend(ma) => + S.map(ma)(Xor.right(_)) + case Gosub(curr, f) => + curr match { + case Pure(x) => + S.pure(Xor.left(f(x))) + case Suspend(mx) => + S.map(mx)(x => Xor.left(f(x))) + case Gosub(prev, g) => + S.pure(Xor.left(prev.flatMap(w => g(w).flatMap(f)))) + } + } + S.tailRecM(this)(step) + } + /** * Catamorphism for `Free`. * - * Run to completion, mapping the suspension with the given transformation at each step and - * accumulating into the monad `M`. + * Run to completion, mapping the suspension with the given + * transformation at each step and accumulating into the monad `M`. + * + * This method uses `MonadRec[M]` to provide stack-safety. */ - final def foldMap[M[_]](f: FunctionK[S,M])(implicit M: MonadRec[M]): M[A] = + final def foldMap[M[_]](f: FunctionK[S, M])(implicit M: MonadRec[M]): M[A] = M.tailRecM(this)(_.step match { case Pure(a) => M.pure(Xor.right(a)) case Suspend(sa) => M.map(f(sa))(Xor.right) @@ -143,17 +127,88 @@ sealed abstract class Free[S[_], A] extends Product with Serializable { }) /** - * Compile your Free into another language by changing the suspension functor - * using the given natural transformation. - * Be careful if your natural transformation is effectful, effects are applied by mapSuspension. + * Compile your free monad into another language by changing the + * suspension functor using the given natural transformation `f`. + * + * If your natural transformation is effectful, be careful. These + * effects will be applied by `compile`. */ - final def mapSuspension[T[_]](f: FunctionK[S,T]): Free[T, A] = + final def compile[T[_]](f: FunctionK[S, T]): Free[T, A] = foldMap[Free[T, ?]] { new FunctionK[S, Free[T, ?]] { def apply[B](fa: S[B]): Free[T, B] = Suspend(f(fa)) } }(Free.freeMonad) +} - final def compile[T[_]](f: FunctionK[S,T]): Free[T, A] = mapSuspension(f) +object Free { + + /** + * Return from the computation with the given value. + */ + private[free] final case class Pure[S[_], A](a: A) extends Free[S, A] + + /** Suspend the computation with the given suspension. */ + private[free] final case class Suspend[S[_], A](a: S[A]) extends Free[S, A] + + /** Call a subroutine and continue with the given function. */ + private[free] final case class Gosub[S[_], B, C](c: Free[S, C], f: C => Free[S, B]) extends Free[S, B] + + /** + * Lift a pure `A` value into the free monad. + */ + def pure[S[_], A](a: A): Free[S, A] = Pure(a) + + /** + * Lift an `F[A]` value into the free monad. + */ + def liftF[F[_], A](value: F[A]): Free[F, A] = Suspend(value) + + /** + * Suspend the creation of a `Free[F, A]` value. + */ + def suspend[F[_], A](value: => Free[F, A]): Free[F, A] = + pure(()).flatMap(_ => value) + + /** + * This method is used to defer the application of an Inject[F, G] + * instance. The actual work happens in + * `FreeInjectPartiallyApplied#apply`. + * + * This method exists to allow the `F` and `G` parameters to be + * bound independently of the `A` parameter below. + */ + def inject[F[_], G[_]]: FreeInjectPartiallyApplied[F, G] = + new FreeInjectPartiallyApplied + + /** + * Pre-application of an injection to a `F[A]` value. + */ + final class FreeInjectPartiallyApplied[F[_], G[_]] private[free] { + def apply[A](fa: F[A])(implicit I: Inject[F, G]): Free[G, A] = + Free.liftF(I.inj(fa)) + } + + /** + * `Free[S, ?]` has a monad for any type constructor `S[_]`. + */ + implicit def freeMonad[S[_]]: MonadRec[Free[S, ?]] = + new MonadRec[Free[S, ?]] { + def pure[A](a: A): Free[S, A] = Free.pure(a) + override def map[A, B](fa: Free[S, A])(f: A => B): Free[S, B] = fa.map(f) + def flatMap[A, B](a: Free[S, A])(f: A => Free[S, B]): Free[S, B] = a.flatMap(f) + def tailRecM[A, B](a: A)(f: A => Free[S, A Xor B]): Free[S, B] = + f(a).flatMap(_ match { + case Left(a1) => tailRecM(a1)(f) // recursion OK here, since Free is lazy + case Right(b) => pure(b) + }) + } + + /** + * Perform a stack-safe monadic fold from the source context `F` + * into the target monad `G`. + */ + def foldLeftM[F[_], G[_]: MonadRec, A, B](fa: F[A], z: B)(f: (B, A) => G[B])(implicit F: Foldable[F]): G[B] = + F.foldM[Free[G, ?], A, B](fa, z) { (b, a) => Free.liftF(f(b, a)) }.runTailRec } diff --git a/free/src/main/scala/cats/free/Trampoline.scala b/free/src/main/scala/cats/free/Trampoline.scala index 663fd32080..8e9f45a923 100644 --- a/free/src/main/scala/cats/free/Trampoline.scala +++ b/free/src/main/scala/cats/free/Trampoline.scala @@ -1,8 +1,6 @@ package cats package free -import cats.std.function.catsStdBimonadForFunction0 - // To workaround SI-7139 `object Trampoline` needs to be defined inside the package object // together with the type alias. private[free] abstract class TrampolineFunctions { diff --git a/free/src/test/scala/cats/free/FreeTests.scala b/free/src/test/scala/cats/free/FreeTests.scala index 09288b275c..30aa25cfce 100644 --- a/free/src/test/scala/cats/free/FreeTests.scala +++ b/free/src/test/scala/cats/free/FreeTests.scala @@ -18,9 +18,9 @@ class FreeTests extends CatsSuite { checkAll("Free[Option, ?]", MonadRecTests[Free[Option, ?]].monadRec[Int, Int, Int]) checkAll("MonadRec[Free[Option, ?]]", SerializableTests.serializable(MonadRec[Free[Option, ?]])) - test("mapSuspension id"){ + test("compile id"){ forAll { x: Free[List, Int] => - x.mapSuspension(FunctionK.id[List]) should === (x) + x.compile(FunctionK.id[List]) should === (x) } } @@ -36,9 +36,9 @@ class FreeTests extends CatsSuite { val _ = Free.suspend(yikes[Option, Int]) } - test("mapSuspension consistent with foldMap"){ + test("compile consistent with foldMap"){ forAll { x: Free[List, Int] => - val mapped = x.mapSuspension(headOptionU) + val mapped = x.compile(headOptionU) val folded = mapped.foldMap(FunctionK.id[Option]) folded should === (x.foldMap(headOptionU)) } From b7afcb161d2e6a10ad4f4b03ef0c73e89ead9dd7 Mon Sep 17 00:00:00 2001 From: Erik Osheim Date: Thu, 2 Jun 2016 00:33:38 -0400 Subject: [PATCH 02/36] Add tests for new Free methods. --- free/src/main/scala/cats/free/Free.scala | 4 ++++ free/src/test/scala/cats/free/FreeTests.scala | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/free/src/main/scala/cats/free/Free.scala b/free/src/main/scala/cats/free/Free.scala index beb7310ad0..5056bf15bd 100644 --- a/free/src/main/scala/cats/free/Free.scala +++ b/free/src/main/scala/cats/free/Free.scala @@ -207,6 +207,10 @@ object Free { /** * Perform a stack-safe monadic fold from the source context `F` * into the target monad `G`. + * + * This method can express short-circuiting semantics, but like + * other left folds will traverse the entire `F[A]` structure. This + * means it is not suitable for potentially infinite structures. */ def foldLeftM[F[_], G[_]: MonadRec, A, B](fa: F[A], z: B)(f: (B, A) => G[B])(implicit F: Foldable[F]): G[B] = F.foldM[Free[G, ?], A, B](fa, z) { (b, a) => Free.liftF(f(b, a)) }.runTailRec diff --git a/free/src/test/scala/cats/free/FreeTests.scala b/free/src/test/scala/cats/free/FreeTests.scala index 30aa25cfce..3e026cbe5a 100644 --- a/free/src/test/scala/cats/free/FreeTests.scala +++ b/free/src/test/scala/cats/free/FreeTests.scala @@ -72,6 +72,25 @@ class FreeTests extends CatsSuite { assert(10000 == a(0).foldMap(runner)) } + + test(".runTailRec") { + val r = Free.pure[List, Int](12358) + def recurse(r: Free[List, Int], n: Int): Free[List, Int] = + if (n > 0) recurse(r.flatMap(x => Free.pure(x + 1)), n - 1) else r + val res = recurse(r, 100000).runTailRec + assert(res == List(112358)) + } + + test(".foldLeftM") { + // you can see .foldLeftM traversing the entire structure by + // changing the constant argument to .take and observing the time + // this test takes. + val ns = Stream.from(1).take(1000) + val res = Free.foldLeftM[Stream, Xor[Int, ?], Int, Int](ns, 0) { (sum, n) => + if (sum >= 2) Xor.left(sum) else Xor.right(sum + n) + } + assert(res == Xor.left(3)) + } } object FreeTests extends FreeTestsInstances { From 3eca17fd1f05d861599ce6a697d96ae8a6c5b762 Mon Sep 17 00:00:00 2001 From: Cody Allen Date: Fri, 3 Jun 2016 07:53:30 -0400 Subject: [PATCH 03/36] Add a short-circuiting implementation of foldLeftM I don't like the Eval.value calls, but I don't know of a way around them. The unit tests suggest that they aren't a problem due to the nature of `Free.runTailRec` and `FlatMapRec.tailRecM`. --- free/src/main/scala/cats/free/Free.scala | 11 +++++++---- free/src/test/scala/cats/free/FreeTests.scala | 8 ++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/free/src/main/scala/cats/free/Free.scala b/free/src/main/scala/cats/free/Free.scala index 5056bf15bd..02f8fe9f6a 100644 --- a/free/src/main/scala/cats/free/Free.scala +++ b/free/src/main/scala/cats/free/Free.scala @@ -208,11 +208,14 @@ object Free { * Perform a stack-safe monadic fold from the source context `F` * into the target monad `G`. * - * This method can express short-circuiting semantics, but like - * other left folds will traverse the entire `F[A]` structure. This - * means it is not suitable for potentially infinite structures. + * This method can express short-circuiting semantics. Even when + * `fa` is an infinite structure, this method can potentially + * terminate if the `foldRight` implementation for `F` and the + * `tailRecM` implementation for `G` are sufficiently lazy. */ def foldLeftM[F[_], G[_]: MonadRec, A, B](fa: F[A], z: B)(f: (B, A) => G[B])(implicit F: Foldable[F]): G[B] = - F.foldM[Free[G, ?], A, B](fa, z) { (b, a) => Free.liftF(f(b, a)) }.runTailRec + unsafeFoldLeftM[F, Free[G, ?], A, B](fa, z) { (b, a) => Free.liftF(f(b, a)) }.runTailRec + private def unsafeFoldLeftM[F[_], G[_], A, B](fa: F[A], z: B)(f: (B, A) => G[B])(implicit F: Foldable[F], G: Monad[G]): G[B] = + F.foldRight[A, B => G[B]](fa, Always(G.pure(_)))((a, lb) => Always((w: B) => G.flatMap(f(w, a))(lb.value))).value(z) } diff --git a/free/src/test/scala/cats/free/FreeTests.scala b/free/src/test/scala/cats/free/FreeTests.scala index 3e026cbe5a..b7e64994dc 100644 --- a/free/src/test/scala/cats/free/FreeTests.scala +++ b/free/src/test/scala/cats/free/FreeTests.scala @@ -91,6 +91,14 @@ class FreeTests extends CatsSuite { } assert(res == Xor.left(3)) } + + test(".foldLeftM short-circuiting") { + val ns = Stream.continually(1) + val res = Free.foldLeftM[Stream, Xor[Int, ?], Int, Int](ns, 0) { (sum, n) => + if (sum >= 100000) Xor.left(sum) else Xor.right(sum + n) + } + assert(res == Xor.left(100000)) + } } object FreeTests extends FreeTestsInstances { From 861361c4a2156da5f3be26aa3cdb57c31dd93fb9 Mon Sep 17 00:00:00 2001 From: Erik Osheim Date: Sun, 5 Jun 2016 00:09:09 -0400 Subject: [PATCH 04/36] Fix merge conflict. --- free/src/main/scala/cats/free/Free.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/free/src/main/scala/cats/free/Free.scala b/free/src/main/scala/cats/free/Free.scala index 7e7abfb55f..6d8aa5a017 100644 --- a/free/src/main/scala/cats/free/Free.scala +++ b/free/src/main/scala/cats/free/Free.scala @@ -139,6 +139,9 @@ sealed abstract class Free[S[_], A] extends Product with Serializable { def apply[B](fa: S[B]): Free[T, B] = Suspend(f(fa)) } }(Free.freeMonad) + + override def toString(): String = + "Free(...)" } object Free { @@ -214,6 +217,4 @@ object Free { */ def foldLeftM[F[_], G[_]: MonadRec, A, B](fa: F[A], z: B)(f: (B, A) => G[B])(implicit F: Foldable[F]): G[B] = F.foldM[Free[G, ?], A, B](fa, z) { (b, a) => Free.liftF(f(b, a)) }.runTailRec - - override def toString(): String = "Free(...)" } From 39fbd284e091d767482eda4bb0652aee6e81f2ad Mon Sep 17 00:00:00 2001 From: David Gregory Date: Fri, 11 Mar 2016 08:12:54 +0000 Subject: [PATCH 05/36] Adding more contravariant instances --- core/src/main/scala/cats/data/Cokleisli.scala | 7 +++- core/src/main/scala/cats/data/Func.scala | 13 ++++++++ core/src/main/scala/cats/data/Prod.scala | 12 +++++++ core/src/main/scala/cats/data/WriterT.scala | 18 +++++++++- .../scala/cats/functor/Contravariant.scala | 20 +++++++++++ .../cats/laws/discipline/Arbitrary.scala | 13 ++++++++ .../main/scala/cats/laws/discipline/Eq.scala | 33 +++++++++++++++++++ .../scala/cats/tests/CokleisliTests.scala | 5 ++- .../scala/cats/tests/CoproductTests.scala | 12 +------ .../src/test/scala/cats/tests/FuncTests.scala | 7 ++++ .../cats/tests/KernelContravariantTests.scala | 15 +++++++++ .../src/test/scala/cats/tests/ProdTests.scala | 5 +++ .../test/scala/cats/tests/WriterTTests.scala | 7 +++- 13 files changed, 152 insertions(+), 15 deletions(-) create mode 100644 tests/src/test/scala/cats/tests/KernelContravariantTests.scala diff --git a/core/src/main/scala/cats/data/Cokleisli.scala b/core/src/main/scala/cats/data/Cokleisli.scala index 6a9f5bcdd3..464b636bfb 100644 --- a/core/src/main/scala/cats/data/Cokleisli.scala +++ b/core/src/main/scala/cats/data/Cokleisli.scala @@ -2,7 +2,7 @@ package cats package data import cats.arrow.{Arrow, Split} -import cats.functor.Profunctor +import cats.functor.{Contravariant, Profunctor} import cats.{CoflatMap, Comonad, Functor, Monad} /** @@ -71,6 +71,11 @@ private[data] sealed abstract class CokleisliInstances0 { implicit def catsDataSemigroupKForCokleisli[F[_]](implicit ev: CoflatMap[F]): SemigroupK[λ[α => Cokleisli[F, α, α]]] = new CokleisliSemigroupK[F] { def F: CoflatMap[F] = ev } + + implicit def catsDataContravariantForCokleisli[F[_]: Functor, A]: Contravariant[Cokleisli[F, ?, A]] = + new Contravariant[Cokleisli[F, ?, A]] { + def contramap[B, C](fbc: Cokleisli[F, B, A])(f: C => B): Cokleisli[F, C, A] = fbc.lmap(f) + } } private trait CokleisliArrow[F[_]] extends Arrow[Cokleisli[F, ?, ?]] with CokleisliSplit[F] with CokleisliProfunctor[F] { diff --git a/core/src/main/scala/cats/data/Func.scala b/core/src/main/scala/cats/data/Func.scala index de64c0f941..f8c7e530e0 100644 --- a/core/src/main/scala/cats/data/Func.scala +++ b/core/src/main/scala/cats/data/Func.scala @@ -1,6 +1,8 @@ package cats package data +import cats.functor.Contravariant + /** * [[Func]] is a function `A => F[B]`. * @@ -50,6 +52,11 @@ private[data] abstract class FuncInstances1 { new FuncFunctor[F, C] { def F: Functor[F] = FF } + + implicit def catsDataContravariantForFunc[F[_], C](implicit FC: Contravariant[F]): Contravariant[λ[α => Func[F, α, C]]] = + new FuncContravariant[F, C] { + def F: Contravariant[F] = FC + } } sealed trait FuncFunctor[F[_], C] extends Functor[λ[α => Func[F, C, α]]] { @@ -58,6 +65,12 @@ sealed trait FuncFunctor[F[_], C] extends Functor[λ[α => Func[F, C, α]]] { fa.map(f)(F) } +sealed trait FuncContravariant[F[_], C] extends Contravariant[λ[α => Func[F, α, C]]] { + def F: Contravariant[F] + def contramap[A, B](fa: Func[F, A, C])(f: B => A): Func[F, B, C] = + Func.func(a => fa.run(f(a))) +} + sealed trait FuncApply[F[_], C] extends Apply[λ[α => Func[F, C, α]]] with FuncFunctor[F, C] { def F: Apply[F] def ap[A, B](f: Func[F, C, A => B])(fa: Func[F, C, A]): Func[F, C, B] = diff --git a/core/src/main/scala/cats/data/Prod.scala b/core/src/main/scala/cats/data/Prod.scala index 74f3139086..c7a0aaaa82 100644 --- a/core/src/main/scala/cats/data/Prod.scala +++ b/core/src/main/scala/cats/data/Prod.scala @@ -1,6 +1,8 @@ package cats package data +import cats.functor.Contravariant + /** * [[Prod]] is a product to two independent functor values. * @@ -55,6 +57,10 @@ private[data] sealed abstract class ProdInstances4 { def F: Functor[F] = FF def G: Functor[G] = GG } + implicit def catsDataContravariantForProd[F[_], G[_]](implicit FC: Contravariant[F], GC: Contravariant[G]): Contravariant[λ[α => Prod[F, G, α]]] = new ProdContravariant[F, G] { + def F: Contravariant[F] = FC + def G: Contravariant[G] = GC + } } sealed trait ProdFunctor[F[_], G[_]] extends Functor[λ[α => Prod[F, G, α]]] { @@ -63,6 +69,12 @@ sealed trait ProdFunctor[F[_], G[_]] extends Functor[λ[α => Prod[F, G, α]]] { override def map[A, B](fa: Prod[F, G, A])(f: A => B): Prod[F, G, B] = Prod(F.map(fa.first)(f), G.map(fa.second)(f)) } +sealed trait ProdContravariant[F[_], G[_]] extends Contravariant[λ[α => Prod[F, G, α]]] { + def F: Contravariant[F] + def G: Contravariant[G] + def contramap[A, B](fa: Prod[F, G, A])(f: B => A): Prod[F, G, B] = Prod(F.contramap(fa.first)(f), G.contramap(fa.second)(f)) +} + sealed trait ProdApply[F[_], G[_]] extends Apply[λ[α => Prod[F, G, α]]] with ProdFunctor[F, G] { def F: Apply[F] def G: Apply[G] diff --git a/core/src/main/scala/cats/data/WriterT.scala b/core/src/main/scala/cats/data/WriterT.scala index 9df6c5013a..37e7adddda 100644 --- a/core/src/main/scala/cats/data/WriterT.scala +++ b/core/src/main/scala/cats/data/WriterT.scala @@ -2,7 +2,7 @@ package cats package data import cats.kernel.std.tuple._ -import cats.functor.Bifunctor +import cats.functor.{Bifunctor, Contravariant} final case class WriterT[F[_], L, V](run: F[(L, V)]) { def written(implicit functorF: Functor[F]): F[L] = @@ -22,6 +22,11 @@ final case class WriterT[F[_], L, V](run: F[(L, V)]) { functorF.map(run) { z => (z._1, fn(z._2)) } } + def contramap[Z](fn: Z => V)(implicit F: Contravariant[F]): WriterT[F, L, Z] = + WriterT { + F.contramap(run) { z => (z._1, fn(z._2)) } + } + def flatMap[U](f: V => WriterT[F, L, U])(implicit flatMapF: FlatMap[F], semigroupL: Semigroup[L]): WriterT[F, L, U] = WriterT { flatMapF.flatMap(run) { lv => @@ -176,6 +181,10 @@ private[data] sealed abstract class WriterTInstances7 { new WriterTCoflatMap[F, L] { implicit val F0: Functor[F] = F } + + implicit def catsDataContravariantForWriterT[F[_], L](implicit F: Contravariant[F]): Contravariant[WriterT[F, L, ?]] = new WriterTContravariant[F, L] { + implicit val F0: Contravariant[F] = F + } } private[data] sealed trait WriterTFunctor[F[_], L] extends Functor[WriterT[F, L, ?]] { @@ -185,6 +194,13 @@ private[data] sealed trait WriterTFunctor[F[_], L] extends Functor[WriterT[F, L, fa.map(f) } +private[data] sealed trait WriterTContravariant[F[_], L] extends Contravariant[WriterT[F, L, ?]] { + implicit def F0: Contravariant[F] + + def contramap[A, B](fa: WriterT[F, L, A])(f: B => A): WriterT[F, L, B] = + fa.contramap(f) +} + private[data] sealed trait WriterTApply[F[_], L] extends WriterTFunctor[F, L] with Apply[WriterT[F, L, ?]] { override implicit def F0: Apply[F] implicit def L0: Semigroup[L] diff --git a/core/src/main/scala/cats/functor/Contravariant.scala b/core/src/main/scala/cats/functor/Contravariant.scala index cf231e38a2..59329b3b58 100644 --- a/core/src/main/scala/cats/functor/Contravariant.scala +++ b/core/src/main/scala/cats/functor/Contravariant.scala @@ -22,3 +22,23 @@ import simulacrum.typeclass val G = Functor[G] } } + +object Contravariant { + implicit val catsFunctorContravariantForPartialOrder: Contravariant[PartialOrder] = + new Contravariant[PartialOrder] { + /** Derive a `PartialOrder` for `B` given a `PartialOrder[A]` and a function `B => A`. + * + * Note: resulting instances are law-abiding only when the functions used are injective (represent a one-to-one mapping) + */ + def contramap[A, B](fa: PartialOrder[A])(f: B => A): PartialOrder[B] = fa.on(f) + } + + implicit val catsFunctorContravariantForOrder: Contravariant[Order] = + new Contravariant[Order] { + /** Derive an `Order` for `B` given an `Order[A]` and a function `B => A`. + * + * Note: resulting instances are law-abiding only when the functions used are injective (represent a one-to-one mapping) + */ + def contramap[A, B](fa: Order[A])(f: B => A): Order[B] = fa.on(f) + } +} diff --git a/laws/src/main/scala/cats/laws/discipline/Arbitrary.scala b/laws/src/main/scala/cats/laws/discipline/Arbitrary.scala index 7e823c6a06..e874bfc8d4 100644 --- a/laws/src/main/scala/cats/laws/discipline/Arbitrary.scala +++ b/laws/src/main/scala/cats/laws/discipline/Arbitrary.scala @@ -77,6 +77,19 @@ object arbitrary extends ArbitraryInstances0 { implicit def showArbitrary[A: Arbitrary]: Arbitrary[Show[A]] = Arbitrary(Show.fromToString[A]) + implicit def partialOrderArbitrary[A: Arbitrary]: Arbitrary[PartialOrder[A]] = + Arbitrary(Gen.oneOf( + PartialOrder.from[A]((_: A, _: A) => Double.NaN), + PartialOrder.from[A]((_: A, _: A) => -1.0), + PartialOrder.from[A]((_: A, _: A) => 0.0), + PartialOrder.from[A]((_: A, _: A) => 1.0))) + + implicit def orderArbitrary[A: Arbitrary]: Arbitrary[Order[A]] = + Arbitrary(Gen.oneOf( + Order.from[A]((_: A, _: A) => -1), + Order.from[A]((_: A, _: A) => 0), + Order.from[A]((_: A, _: A) => 1))) + implicit def function0Arbitrary[A: Arbitrary]: Arbitrary[() => A] = Arbitrary(getArbitrary[A].map(() => _)) diff --git a/laws/src/main/scala/cats/laws/discipline/Eq.scala b/laws/src/main/scala/cats/laws/discipline/Eq.scala index 432b1d7a80..ece842cc52 100644 --- a/laws/src/main/scala/cats/laws/discipline/Eq.scala +++ b/laws/src/main/scala/cats/laws/discipline/Eq.scala @@ -24,6 +24,39 @@ object eq { } } + /** + * Create an approximation of Eq[PartialOrder[A]] by generating 100 values for A + * and comparing the application of the two compare functions + */ + implicit def partialOrderEq[A](implicit arbA: Arbitrary[(A, A)], optIntEq: Eq[Option[Int]]): Eq[PartialOrder[A]] = new Eq[PartialOrder[A]] { + def eqv(f: PartialOrder[A], g: PartialOrder[A]): Boolean = { + val samples = List.fill(100)(arbA.arbitrary.sample).collect { + case Some(a) => a + case None => sys.error("Could not generate arbitrary values to compare two PartialOrder[A]") + } + samples.forall { + case (l, r) => optIntEq.eqv(f.tryCompare(l, r), g.tryCompare(l, r)) + } + } + } + + /** + * Create an approximation of Eq[Order[A]] by generating 100 values for A + * and comparing the application of the two compare functions + */ + implicit def orderEq[A](implicit arbA: Arbitrary[(A, A)], intEq: Eq[Int]): Eq[Order[A]] = new Eq[Order[A]] { + def eqv(f: Order[A], g: Order[A]): Boolean = { + val samples = List.fill(100)(arbA.arbitrary.sample).collect { + case Some(a) => a + case None => sys.error("Could not generate arbitrary values to compare two Order[A]") + } + samples.forall { + case (l, r) => intEq.eqv(f.compare(l, r), g.compare(l, r)) + } + } + } + + /** Create an approximation of Eq[Show[A]] by using function1Eq[A, String] */ implicit def showEq[A: Arbitrary]: Eq[Show[A]] = { val xyz = function1Eq[A, String] diff --git a/tests/src/test/scala/cats/tests/CokleisliTests.scala b/tests/src/test/scala/cats/tests/CokleisliTests.scala index 212de1f56b..a2781129e7 100644 --- a/tests/src/test/scala/cats/tests/CokleisliTests.scala +++ b/tests/src/test/scala/cats/tests/CokleisliTests.scala @@ -3,7 +3,7 @@ package tests import cats.arrow.{Arrow, Split} import cats.data.{Cokleisli, NonEmptyList} -import cats.functor.Profunctor +import cats.functor.{Contravariant, Profunctor} import cats.laws.discipline._ import cats.laws.discipline.arbitrary._ import cats.laws.discipline.eq._ @@ -32,6 +32,9 @@ class CokleisliTests extends SlowCatsSuite { checkAll("Cokleisli[Option, Int, Int]", SplitTests[Cokleisli[Option, ?, ?]].split[Int, Int, Int, Int, Int, Int]) checkAll("Split[Cokleisli[Option, ?, ?]", SerializableTests.serializable(Split[Cokleisli[Option, ?, ?]])) + checkAll("Cokleisli[Option, Int, Int]", ContravariantTests[Cokleisli[Option, ?, Int]].contravariant[Int, Int, Int]) + checkAll("Contravariant[Cokleisli[Option, ?, Int]]", SerializableTests.serializable(Contravariant[Cokleisli[Option, ?, Int]])) + { // Ceremony to help scalac to do the right thing, see also #267. type CokleisliNEL[A, B] = Cokleisli[NonEmptyList, A, B] diff --git a/tests/src/test/scala/cats/tests/CoproductTests.scala b/tests/src/test/scala/cats/tests/CoproductTests.scala index ff6a40e324..dc2e4c4d55 100644 --- a/tests/src/test/scala/cats/tests/CoproductTests.scala +++ b/tests/src/test/scala/cats/tests/CoproductTests.scala @@ -6,7 +6,7 @@ import cats.data.Coproduct import cats.functor.Contravariant import cats.laws.discipline._ import cats.laws.discipline.arbitrary._ -import org.scalacheck.Arbitrary +import cats.laws.discipline.eq._ class CoproductTests extends CatsSuite { @@ -31,16 +31,6 @@ class CoproductTests extends CatsSuite { checkAll("Coproduct[Option, Option, Int]", OrderLaws[Coproduct[Option, Option, Int]].eqv) checkAll("Eq[Coproduct[Option, Option, Int]]", SerializableTests.serializable(Eq[Coproduct[Option, Option, Int]])) - implicit def showEq[A](implicit arbA: Arbitrary[A], stringEq: Eq[String]): Eq[Show[A]] = new Eq[Show[A]] { - def eqv(f: Show[A], g: Show[A]): Boolean = { - val samples = List.fill(100)(arbA.arbitrary.sample).collect { - case Some(a) => a - case None => sys.error("Could not generate arbitrary values to compare two Show[A]") - } - samples.forall(s => stringEq.eqv(f.show(s), g.show(s))) - } - } - checkAll("Coproduct[Show, Show, ?]", ContravariantTests[Coproduct[Show, Show, ?]].contravariant[Int, Int, Int]) checkAll("Contravariant[Coproduct[Show, Show, ?]]", SerializableTests.serializable(Contravariant[Coproduct[Show, Show, ?]])) diff --git a/tests/src/test/scala/cats/tests/FuncTests.scala b/tests/src/test/scala/cats/tests/FuncTests.scala index fe1216e03a..1f779bd51f 100644 --- a/tests/src/test/scala/cats/tests/FuncTests.scala +++ b/tests/src/test/scala/cats/tests/FuncTests.scala @@ -2,6 +2,7 @@ package cats package tests import cats.data.{ Func, AppFunc } +import cats.functor.Contravariant import Func.appFunc import cats.laws.discipline._ import cats.laws.discipline.arbitrary._ @@ -37,6 +38,12 @@ class FuncTests extends CatsSuite { checkAll("Functor[Func[Option, Int, ?]]", SerializableTests.serializable(Functor[Func[Option, Int, ?]])) } + { + implicit val funcContravariant = Func.catsDataContravariantForFunc[Show, Int] + checkAll("Func[Show, Int, Int]", ContravariantTests[Func[Show, ?, Int]].contravariant[Int, Int, Int]) + checkAll("Contravariant[Func[Show, ?, Int]]", SerializableTests.serializable(Contravariant[Func[Show, ?, Int]])) + } + { implicit val appFuncApp = AppFunc.appFuncApplicative[Option, Int] implicit val iso = CartesianTests.Isomorphisms.invariant[AppFunc[Option, Int, ?]] diff --git a/tests/src/test/scala/cats/tests/KernelContravariantTests.scala b/tests/src/test/scala/cats/tests/KernelContravariantTests.scala new file mode 100644 index 0000000000..92be09409e --- /dev/null +++ b/tests/src/test/scala/cats/tests/KernelContravariantTests.scala @@ -0,0 +1,15 @@ +package cats +package tests + +import cats.functor.Contravariant +import cats.laws.discipline.arbitrary._ +import cats.laws.discipline.{ContravariantTests, SerializableTests} +import cats.laws.discipline.eq._ + +class KernelContravariantTests extends CatsSuite { + checkAll("Contravariant[PartialOrder]", ContravariantTests[PartialOrder].contravariant[Int, Int, Int]) + checkAll("Contravariant[PartialOrder]", SerializableTests.serializable(Contravariant[PartialOrder])) + + checkAll("Contravariant[Order]", ContravariantTests[Order].contravariant[Int, Int, Int]) + checkAll("Contravariant[Order]", SerializableTests.serializable(Contravariant[Order])) +} diff --git a/tests/src/test/scala/cats/tests/ProdTests.scala b/tests/src/test/scala/cats/tests/ProdTests.scala index d6e02e9d84..1d04e7bea4 100644 --- a/tests/src/test/scala/cats/tests/ProdTests.scala +++ b/tests/src/test/scala/cats/tests/ProdTests.scala @@ -2,8 +2,10 @@ package cats package tests import cats.data.Prod +import cats.functor.Contravariant import cats.laws.discipline._ import cats.laws.discipline.arbitrary._ +import cats.laws.discipline.eq._ class ProdTests extends CatsSuite { implicit val iso = CartesianTests.Isomorphisms.invariant[Prod[Option, List, ?]] @@ -13,6 +15,9 @@ class ProdTests extends CatsSuite { checkAll("Prod[Option, List, Int]", AlternativeTests[λ[α => Prod[Option, List, α]]].alternative[Int, Int, Int]) checkAll("Alternative[Prod[Option, List, Int]]", SerializableTests.serializable(Alternative[λ[α => Prod[Option, List, α]]])) + checkAll("Prod[Show, Order, Int]", ContravariantTests[λ[α => Prod[Show, Order, α]]].contravariant[Int, Int, Int]) + checkAll("Contravariant[Prod[Show, Order, Int]]", SerializableTests.serializable(Contravariant[λ[α => Prod[Show, Order, α]]])) + { implicit val monoidK = ListWrapper.monoidK checkAll("Prod[ListWrapper, ListWrapper, ?]", MonoidKTests[Prod[ListWrapper, ListWrapper, ?]].monoidK[Int]) diff --git a/tests/src/test/scala/cats/tests/WriterTTests.scala b/tests/src/test/scala/cats/tests/WriterTTests.scala index e567248e73..b3f7630403 100644 --- a/tests/src/test/scala/cats/tests/WriterTTests.scala +++ b/tests/src/test/scala/cats/tests/WriterTTests.scala @@ -2,9 +2,10 @@ package cats package tests import cats.data.{Writer, WriterT} -import cats.functor.Bifunctor +import cats.functor.{Bifunctor, Contravariant} import cats.laws.discipline._ import cats.laws.discipline.arbitrary._ +import cats.laws.discipline.eq._ import cats.kernel.laws.OrderLaws @@ -19,6 +20,10 @@ class WriterTTests extends CatsSuite { checkAll("WriterT[List, Int, Int]", OrderLaws[WriterT[List, Int, Int]].eqv) checkAll("Eq[WriterT[List, Int, Int]]", SerializableTests.serializable(Eq[WriterT[List, Int, Int]])) + + checkAll("WriterT[Show, Int, Int]", ContravariantTests[WriterT[Show, Int, ?]].contravariant[Int, Int, Int]) + checkAll("Contravariant[WriterT[Show, Int, Int]]", SerializableTests.serializable(Contravariant[WriterT[Show, Int, ?]])) + // check that this resolves Eq[Writer[Int, Int]] From 7e764dbd9b00328525efbbc9acea55b9ca82f875 Mon Sep 17 00:00:00 2001 From: Yilin Wei Date: Thu, 9 Jun 2016 22:27:23 +0100 Subject: [PATCH 06/36] XorTInstances + cleanup tests --- core/src/main/scala/cats/data/Xor.scala | 4 + core/src/main/scala/cats/data/XorT.scala | 63 ++++++++---- .../test/scala/cats/tests/ListWrapper.scala | 30 +++++- .../src/test/scala/cats/tests/XorTTests.scala | 96 ++++++++++++++----- 4 files changed, 147 insertions(+), 46 deletions(-) diff --git a/core/src/main/scala/cats/data/Xor.scala b/core/src/main/scala/cats/data/Xor.scala index bda34ec4a4..e6ac7cd517 100644 --- a/core/src/main/scala/cats/data/Xor.scala +++ b/core/src/main/scala/cats/data/Xor.scala @@ -179,6 +179,10 @@ sealed abstract class Xor[+A, +B] extends Product with Serializable { a => s"Xor.Left(${AA.show(a)})", b => s"Xor.Right(${BB.show(b)})" ) + + def ap[AA >: A, BB >: B, C](that: AA Xor (BB => C)): AA Xor C = flatMap( + a => that.map(f => f(a)) + ) } object Xor extends XorInstances with XorFunctions { diff --git a/core/src/main/scala/cats/data/XorT.scala b/core/src/main/scala/cats/data/XorT.scala index be129f4b6b..91b8109d8d 100644 --- a/core/src/main/scala/cats/data/XorT.scala +++ b/core/src/main/scala/cats/data/XorT.scala @@ -241,7 +241,7 @@ private[data] abstract class XorTInstances extends XorTInstances1 { val F0: Traverse[F] = F } - implicit def xortTransLift[E]: TransLift.Aux[XorT[?[_], E, ?], Functor] = + implicit def catsDataTransLiftForXorT[E]: TransLift.Aux[XorT[?[_], E, ?], Functor] = new TransLift[XorT[?[_], E, ?]] { type TC[M[_]] = Functor[M] @@ -249,6 +249,9 @@ private[data] abstract class XorTInstances extends XorTInstances1 { XorT(Functor[M].map(ma)(Xor.right)) } + implicit def catsMonoidForXorT[F[_], L, A](implicit F: Monoid[F[L Xor A]]): Monoid[XorT[F, L, A]] = + new XorTMonoid[F, L, A] { implicit val F0 = F } + } private[data] abstract class XorTInstances1 extends XorTInstances2 { @@ -258,7 +261,10 @@ private[data] abstract class XorTInstances1 extends XorTInstances2 { implicit val L0 = L new XorTMonadFilter[F, L] { implicit val F = F0; implicit val L = L0 } } - */ + */ + + implicit def catsSemigroupForXorT[F[_], L, A](implicit F: Semigroup[F[L Xor A]]): Semigroup[XorT[F, L, A]] = + new XorTSemigroup[F, L, A] { implicit val F0 = F } implicit def catsDataFoldableForXorT[F[_], L](implicit F: Foldable[F]): Foldable[XorT[F, L, ?]] = new XorTFoldable[F, L] { @@ -282,19 +288,11 @@ private[data] abstract class XorTInstances2 extends XorTInstances3 { } private[data] abstract class XorTInstances3 extends XorTInstances4 { - implicit def catsDataMonadErrorForXorT[F[_], L](implicit F: Monad[F]): MonadError[XorT[F, L, ?], L] = { - implicit val F0 = F + implicit def catsDataMonadErrorForXorT[F[_], L](implicit F0: Monad[F]): MonadError[XorT[F, L, ?], L] = new XorTMonadError[F, L] { implicit val F = F0 } - } - implicit def catsDataSemigroupKForXorT[F[_], L](implicit F: Monad[F]): SemigroupK[XorT[F, L, ?]] = - new SemigroupK[XorT[F,L,?]] { - def combineK[A](x: XorT[F,L,A], y: XorT[F, L, A]): XorT[F, L, A] = - XorT(F.flatMap(x.value) { - case l @ Xor.Left(_) => y.value - case r @ Xor.Right(_) => F.pure(r) - }) - } + implicit def catsDataSemigroupKForXorT[F[_], L](implicit F0: Monad[F]): SemigroupK[XorT[F, L, ?]] = + new XorTSemigroupK[F, L] { implicit val F = F0 } implicit def catsDataEqForXorT[F[_], L, R](implicit F: Eq[F[L Xor R]]): Eq[XorT[F, L, R]] = new XorTEq[F, L, R] { @@ -302,11 +300,42 @@ private[data] abstract class XorTInstances3 extends XorTInstances4 { } } -private[data] abstract class XorTInstances4 { - implicit def catsDataFunctorForXorT[F[_], L](implicit F: Functor[F]): Functor[XorT[F, L, ?]] = { - implicit val F0 = F +private[data] abstract class XorTInstances4 extends XorTInstances5 { + implicit def catsDataApplicativeForXorT[F[_], L](implicit F0: Applicative[F]): Applicative[XorT[F, L, ?]] = + new XorTApplicative[F, L] { implicit val F = F0 } +} + +private[data] abstract class XorTInstances5 { + implicit def catsDataFunctorForXorT[F[_], L](implicit F0: Functor[F]): Functor[XorT[F, L, ?]] = new XorTFunctor[F, L] { implicit val F = F0 } - } + +} + +private[data] trait XorTSemigroup[F[_], L, A] extends Semigroup[XorT[F, L, A]] { + implicit val F0: Semigroup[F[L Xor A]] + def combine(x: XorT[F, L ,A], y: XorT[F, L , A]): XorT[F, L , A] = + XorT(F0.combine(x.value, y.value)) +} + +private[data] trait XorTMonoid[F[_], L, A] extends Monoid[XorT[F, L, A]] with XorTSemigroup[F, L, A] { + implicit val F0: Monoid[F[L Xor A]] + def empty: XorT[F, L, A] = XorT(F0.empty) +} + +private[data] trait XorTApplicative[F[_], L] extends Applicative[XorT[F, L, ?]] with XorTFunctor[F, L] { + implicit val F: Applicative[F] + def pure[A](a: A): XorT[F, L, A] = XorT(F.pure(Xor.right(a))) + def ap[A, B](x: XorT[F, L, A => B])(y: XorT[F, L, A]): XorT[F, L, B] = + XorT(F.ap(F.map(y.value)(_.ap[L, A, B] _))(x.value)) +} + +private[data] trait XorTSemigroupK[F[_], L] extends SemigroupK[XorT[F, L, ?]] { + implicit val F: Monad[F] + def combineK[A](x: XorT[F,L,A], y: XorT[F, L, A]): XorT[F, L, A] = + XorT(F.flatMap(x.value) { + case l @ Xor.Left(_) => y.value + case r @ Xor.Right(_) => F.pure(r) + }) } private[data] trait XorTFunctor[F[_], L] extends Functor[XorT[F, L, ?]] { diff --git a/tests/src/test/scala/cats/tests/ListWrapper.scala b/tests/src/test/scala/cats/tests/ListWrapper.scala index 1536f25603..469e55d28e 100644 --- a/tests/src/test/scala/cats/tests/ListWrapper.scala +++ b/tests/src/test/scala/cats/tests/ListWrapper.scala @@ -44,14 +44,21 @@ object ListWrapper { def eqv[A : Eq]: Eq[ListWrapper[A]] = Eq[List[A]].on[ListWrapper[A]](_.list) - val foldable: Foldable[ListWrapper] = - new Foldable[ListWrapper] { - def foldLeft[A, B](fa: ListWrapper[A], b: B)(f: (B, A) => B): B = - Foldable[List].foldLeft(fa.list, b)(f) + val traverse: Traverse[ListWrapper] = { + val F = Traverse[List] + new Traverse[ListWrapper] { + def foldLeft[A, B](fa: ListWrapper[A], b: B)(f: (B, A) => B): B = + F.foldLeft(fa.list, b)(f) def foldRight[A, B](fa: ListWrapper[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = - Foldable[List].foldRight(fa.list, lb)(f) + F.foldRight(fa.list, lb)(f) + def traverse[G[_], A, B](fa: ListWrapper[A])(f: A => G[B])(implicit G0: Applicative[G]): G[ListWrapper[B]] = { + G0.map(F.traverse(fa.list)(f))(ListWrapper.apply) + } } + } + + val foldable: Foldable[ListWrapper] = traverse val functor: Functor[ListWrapper] = new Functor[ListWrapper] { @@ -85,6 +92,19 @@ object ListWrapper { } } + val monadRec: MonadRec[ListWrapper] = { + val M = MonadRec[List] + + new MonadRec[ListWrapper] { + def pure[A](x: A): ListWrapper[A] = ListWrapper(M.pure(x)) + def flatMap[A, B](fa: ListWrapper[A])(f: A => ListWrapper[B]): ListWrapper[B] = ListWrapper(M.flatMap(fa.list)(a => f(a).list)) + def tailRecM[A, B](a: A)(f: A => ListWrapper[cats.data.Xor[A,B]]): ListWrapper[B] = + ListWrapper(M.tailRecM(a)(a => f(a).list)) + } + } + + val flatMapRec: FlatMapRec[ListWrapper] = monadRec + val monad: Monad[ListWrapper] = monadCombine val applicative: Applicative[ListWrapper] = monadCombine diff --git a/tests/src/test/scala/cats/tests/XorTTests.scala b/tests/src/test/scala/cats/tests/XorTTests.scala index 80c96a6601..6851fbd929 100644 --- a/tests/src/test/scala/cats/tests/XorTTests.scala +++ b/tests/src/test/scala/cats/tests/XorTTests.scala @@ -8,52 +8,100 @@ import cats.laws.discipline.arbitrary._ import cats.kernel.laws.OrderLaws class XorTTests extends CatsSuite { - implicit val eq0 = XorT.catsDataEqForXorT[List, String, String Xor Int] - implicit val eq1 = XorT.catsDataEqForXorT[XorT[List, String, ?], String, Int](eq0) - implicit val iso = CartesianTests.Isomorphisms.invariant[XorT[List, String, ?]] - checkAll("XorT[List, String, Int]", MonadErrorTests[XorT[List, String, ?], String].monadError[Int, Int, Int]) - checkAll("MonadError[XorT[List, ?, ?]]", SerializableTests.serializable(MonadError[XorT[List, String, ?], String])) - checkAll("XorT[List, String, Int]", MonadRecTests[XorT[List, String, ?]].monadRec[Int, Int, Int]) - checkAll("MonadRec[XorT[List, String, ?]]", SerializableTests.serializable(MonadRec[XorT[List, String, ?]])) - checkAll("XorT[List, ?, ?]", BifunctorTests[XorT[List, ?, ?]].bifunctor[Int, Int, Int, String, String, String]) - checkAll("Bifunctor[XorT[List, ?, ?]]", SerializableTests.serializable(Bifunctor[XorT[List, ?, ?]])) - checkAll("XorT[List, ?, ?]", BitraverseTests[XorT[List, ?, ?]].bitraverse[Option, Int, Int, Int, String, String, String]) - checkAll("Bitraverse[XorT[List, ?, ?]]", SerializableTests.serializable(Bitraverse[XorT[List, ?, ?]])) - checkAll("XorT[List, Int, ?]", TraverseTests[XorT[List, Int, ?]].traverse[Int, Int, Int, Int, Option, Option]) - checkAll("Traverse[XorT[List, Int, ?]]", SerializableTests.serializable(Traverse[XorT[List, Int, ?]])) - checkAll("XorT[List, String, Int]", OrderLaws[XorT[List, String, Int]].order) - checkAll("Order[XorT[List, String, Int]]", SerializableTests.serializable(Order[XorT[List, String, Int]])) - checkAll("XorT[Option, ListWrapper[String], ?]", SemigroupKTests[XorT[Option, ListWrapper[String], ?]].semigroupK[Int]) - checkAll("SemigroupK[XorT[Option, ListWrapper[String], ?]]", SerializableTests.serializable(SemigroupK[XorT[Option, ListWrapper[String], ?]])) + implicit val iso = CartesianTests.Isomorphisms.invariant[XorT[ListWrapper, String, ?]](XorT.catsDataFunctorForXorT(ListWrapper.functor)) { - implicit val F = ListWrapper.foldable - checkAll("XorT[ListWrapper, Int, ?]", FoldableTests[XorT[ListWrapper, Int, ?]].foldable[Int, Int]) - checkAll("Foldable[XorT[ListWrapper, Int, ?]]", SerializableTests.serializable(Foldable[XorT[ListWrapper, Int, ?]])) + checkAll("XorT[Option, ListWrapper[String], ?]", SemigroupKTests[XorT[Option, ListWrapper[String], ?]].semigroupK[Int]) + checkAll("SemigroupK[XorT[Option, ListWrapper[String], ?]]", SerializableTests.serializable(SemigroupK[XorT[Option, ListWrapper[String], ?]])) + } + + { + implicit val F = ListWrapper.order[String Xor Int] + + checkAll("XorT[List, String, Int]", OrderLaws[XorT[ListWrapper, String, Int]].order) + checkAll("Order[XorT[List, String, Int]]", SerializableTests.serializable(Order[XorT[ListWrapper, String, Int]])) } { + //If a Functor for F is defined implicit val F = ListWrapper.functor + + checkAll("XorT[ListWrapper, ?, ?]", BifunctorTests[XorT[ListWrapper, ?, ?]].bifunctor[Int, Int, Int, String, String, String]) + checkAll("Bifunctor[XorT[ListWrapper, ?, ?]]", SerializableTests.serializable(Bifunctor[XorT[ListWrapper, ?, ?]])) checkAll("XorT[ListWrapper, Int, ?]", FunctorTests[XorT[ListWrapper, Int, ?]].functor[Int, Int, Int]) checkAll("Functor[XorT[ListWrapper, Int, ?]]", SerializableTests.serializable(Functor[XorT[ListWrapper, Int, ?]])) } + { + //If a Traverse for F is defined + implicit val F = ListWrapper.traverse + + checkAll("XorT[ListWrapper, Int, ?]", TraverseTests[XorT[ListWrapper, Int, ?]].traverse[Int, Int, Int, Int, Option, Option]) + checkAll("Traverse[XorT[ListWrapper, Int, ?]]", SerializableTests.serializable(Traverse[XorT[ListWrapper, Int, ?]])) + checkAll("XorT[ListWrapper, ?, ?]", BitraverseTests[XorT[ListWrapper, ?, ?]].bitraverse[Option, Int, Int, Int, String, String, String]) + checkAll("Bitraverse[XorT[ListWrapper, ?, ?]]", SerializableTests.serializable(Bitraverse[XorT[ListWrapper, ?, ?]])) + + } + + { + //if a Monad is defined + implicit val F = ListWrapper.monad + implicit val eq0 = XorT.catsDataEqForXorT[ListWrapper, String, String Xor Int] + implicit val eq1 = XorT.catsDataEqForXorT[XorT[ListWrapper, String, ?], String, Int](eq0) + + Functor[XorT[ListWrapper, String, ?]] + Applicative[XorT[ListWrapper, String, ?]] + Monad[XorT[ListWrapper, String, ?]] + + checkAll("XorT[ListWrapper, String, Int]", MonadErrorTests[XorT[ListWrapper, String, ?], String].monadError[Int, Int, Int]) + checkAll("MonadError[XorT[List, ?, ?]]", SerializableTests.serializable(MonadError[XorT[ListWrapper, String, ?], String])) + } + + { + //if a MonadRec is defined + implicit val F = ListWrapper.monadRec + + Functor[XorT[ListWrapper, String, ?]] + Applicative[XorT[ListWrapper, String, ?]] + Monad[XorT[ListWrapper, String, ?]] + + checkAll("XorT[ListWrapper, String, Int]", MonadRecTests[XorT[ListWrapper, String, ?]].monadRec[Int, Int, Int]) + checkAll("MonadRec[XorT[ListWrapper, String, ?]]", SerializableTests.serializable(MonadRec[XorT[ListWrapper, String, ?]])) + } + + { + //If an applicative is defined + implicit val F = ListWrapper.applicative + + Functor[XorT[ListWrapper, String, ?]] + + checkAll("XorT[ListWrapper, String, ?]", ApplicativeTests[XorT[ListWrapper, String, ?]].applicative[Int, Int, Int]) + checkAll("Applicative[XorT[ListWrapper, String, ?]]", SerializableTests.serializable(Applicative[XorT[ListWrapper, String, ?]])) + + } + + { + //If a foldable is defined + implicit val F = ListWrapper.foldable + + checkAll("XorT[ListWrapper, Int, ?]", FoldableTests[XorT[ListWrapper, Int, ?]].foldable[Int, Int]) + checkAll("Foldable[XorT[ListWrapper, Int, ?]]", SerializableTests.serializable(Foldable[XorT[ListWrapper, Int, ?]])) + } + { implicit val F = ListWrapper.partialOrder[String Xor Int] + checkAll("XorT[ListWrapper, String, Int]", OrderLaws[XorT[ListWrapper, String, Int]].partialOrder) checkAll("PartialOrder[XorT[ListWrapper, String, Int]]", SerializableTests.serializable(PartialOrder[XorT[ListWrapper, String, Int]])) } { implicit val F = ListWrapper.eqv[String Xor Int] + checkAll("XorT[ListWrapper, String, Int]", OrderLaws[XorT[ListWrapper, String, Int]].eqv) checkAll("Eq[XorT[ListWrapper, String, Int]]", SerializableTests.serializable(Eq[XorT[ListWrapper, String, Int]])) } - // make sure that the Monad and Traverse instances don't result in ambiguous - // Functor instances - Functor[XorT[List, Int, ?]] - test("toValidated") { forAll { (xort: XorT[List, String, Int]) => xort.toValidated.map(_.toXor) should === (xort.value) From d2a0912ccfffa14d2f4da4f8fafd6b125e9de99c Mon Sep 17 00:00:00 2001 From: Yilin Wei Date: Thu, 9 Jun 2016 22:34:33 +0100 Subject: [PATCH 07/36] add monoid and semigroup tests --- .../src/test/scala/cats/tests/XorTTests.scala | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/src/test/scala/cats/tests/XorTTests.scala b/tests/src/test/scala/cats/tests/XorTTests.scala index 6851fbd929..72fac0e156 100644 --- a/tests/src/test/scala/cats/tests/XorTTests.scala +++ b/tests/src/test/scala/cats/tests/XorTTests.scala @@ -5,7 +5,7 @@ import cats.functor.Bifunctor import cats.data.{Xor, XorT} import cats.laws.discipline._ import cats.laws.discipline.arbitrary._ -import cats.kernel.laws.OrderLaws +import cats.kernel.laws.{OrderLaws, GroupLaws} class XorTTests extends CatsSuite { implicit val iso = CartesianTests.Isomorphisms.invariant[XorT[ListWrapper, String, ?]](XorT.catsDataFunctorForXorT(ListWrapper.functor)) @@ -95,6 +95,22 @@ class XorTTests extends CatsSuite { checkAll("PartialOrder[XorT[ListWrapper, String, Int]]", SerializableTests.serializable(PartialOrder[XorT[ListWrapper, String, Int]])) } + { + implicit val F = ListWrapper.semigroup[String Xor Int] + + checkAll("XorT[ListWrapper, String, Int]", GroupLaws[XorT[ListWrapper, String, Int]].semigroup) + checkAll("Semigroup[XorT[ListWrapper, String, Int]]", SerializableTests.serializable(Semigroup[XorT[ListWrapper, String, Int]])) + } + + { + implicit val F = ListWrapper.monoid[String Xor Int] + + Semigroup[XorT[ListWrapper, String, Int]] + + checkAll("XorT[ListWrapper, String, Int]", GroupLaws[XorT[ListWrapper, String, Int]].monoid) + checkAll("Monoid[XorT[ListWrapper, String, Int]]", SerializableTests.serializable(Monoid[XorT[ListWrapper, String, Int]])) + } + { implicit val F = ListWrapper.eqv[String Xor Int] From cdefe0062a113b93818d1db853d8a737b2575ccf Mon Sep 17 00:00:00 2001 From: Yilin Wei Date: Fri, 10 Jun 2016 19:16:36 +0100 Subject: [PATCH 08/36] remove applicative instance --- core/src/main/scala/cats/data/Xor.scala | 5 +++-- core/src/main/scala/cats/data/XorT.scala | 18 +++--------------- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/core/src/main/scala/cats/data/Xor.scala b/core/src/main/scala/cats/data/Xor.scala index e6ac7cd517..3b18b35e8b 100644 --- a/core/src/main/scala/cats/data/Xor.scala +++ b/core/src/main/scala/cats/data/Xor.scala @@ -180,8 +180,8 @@ sealed abstract class Xor[+A, +B] extends Product with Serializable { b => s"Xor.Right(${BB.show(b)})" ) - def ap[AA >: A, BB >: B, C](that: AA Xor (BB => C)): AA Xor C = flatMap( - a => that.map(f => f(a)) + def ap[AA >: A, BB >: B, C](that: AA Xor (BB => C)): AA Xor C = that.flatMap( + f => this.map(a => f(a)) ) } @@ -244,6 +244,7 @@ private[data] sealed abstract class XorInstances extends XorInstances1 { def foldLeft[B, C](fa: A Xor B, c: C)(f: (C, B) => C): C = fa.foldLeft(c)(f) def foldRight[B, C](fa: A Xor B, lc: Eval[C])(f: (B, Eval[C]) => Eval[C]): Eval[C] = fa.foldRight(lc)(f) def flatMap[B, C](fa: A Xor B)(f: B => A Xor C): A Xor C = fa.flatMap(f) + override def ap[B, C](x: A Xor (B => C))(y: A Xor B): A Xor C = y.ap(x) def pure[B](b: B): A Xor B = Xor.right(b) @tailrec def tailRecM[B, C](b: B)(f: B => A Xor (B Xor C)): A Xor C = f(b) match { diff --git a/core/src/main/scala/cats/data/XorT.scala b/core/src/main/scala/cats/data/XorT.scala index 91b8109d8d..8241f46c46 100644 --- a/core/src/main/scala/cats/data/XorT.scala +++ b/core/src/main/scala/cats/data/XorT.scala @@ -300,15 +300,9 @@ private[data] abstract class XorTInstances3 extends XorTInstances4 { } } -private[data] abstract class XorTInstances4 extends XorTInstances5 { - implicit def catsDataApplicativeForXorT[F[_], L](implicit F0: Applicative[F]): Applicative[XorT[F, L, ?]] = - new XorTApplicative[F, L] { implicit val F = F0 } -} - -private[data] abstract class XorTInstances5 { +private[data] abstract class XorTInstances4 { implicit def catsDataFunctorForXorT[F[_], L](implicit F0: Functor[F]): Functor[XorT[F, L, ?]] = new XorTFunctor[F, L] { implicit val F = F0 } - } private[data] trait XorTSemigroup[F[_], L, A] extends Semigroup[XorT[F, L, A]] { @@ -322,13 +316,6 @@ private[data] trait XorTMonoid[F[_], L, A] extends Monoid[XorT[F, L, A]] with Xo def empty: XorT[F, L, A] = XorT(F0.empty) } -private[data] trait XorTApplicative[F[_], L] extends Applicative[XorT[F, L, ?]] with XorTFunctor[F, L] { - implicit val F: Applicative[F] - def pure[A](a: A): XorT[F, L, A] = XorT(F.pure(Xor.right(a))) - def ap[A, B](x: XorT[F, L, A => B])(y: XorT[F, L, A]): XorT[F, L, B] = - XorT(F.ap(F.map(y.value)(_.ap[L, A, B] _))(x.value)) -} - private[data] trait XorTSemigroupK[F[_], L] extends SemigroupK[XorT[F, L, ?]] { implicit val F: Monad[F] def combineK[A](x: XorT[F,L,A], y: XorT[F, L, A]): XorT[F, L, A] = @@ -345,8 +332,9 @@ private[data] trait XorTFunctor[F[_], L] extends Functor[XorT[F, L, ?]] { private[data] trait XorTMonad[F[_], L] extends Monad[XorT[F, L, ?]] with XorTFunctor[F, L] { implicit val F: Monad[F] - def pure[A](a: A): XorT[F, L, A] = XorT.pure[F, L, A](a) + def pure[A](a: A): XorT[F, L, A] = XorT(F.pure(Xor.right(a))) def flatMap[A, B](fa: XorT[F, L, A])(f: A => XorT[F, L, B]): XorT[F, L, B] = fa flatMap f + override def ap[A, B](x: XorT[F, L, A => B])(y: XorT[F, L, A]): XorT[F, L, B] = super.ap(x)(y) } private[data] trait XorTMonadError[F[_], L] extends MonadError[XorT[F, L, ?], L] with XorTMonad[F, L] { From 9516f8f1443978702f36195148e464d16aa4502b Mon Sep 17 00:00:00 2001 From: Yilin Wei Date: Fri, 10 Jun 2016 19:27:48 +0100 Subject: [PATCH 09/36] would help if I commited the test --- tests/src/test/scala/cats/tests/XorTTests.scala | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/tests/src/test/scala/cats/tests/XorTTests.scala b/tests/src/test/scala/cats/tests/XorTTests.scala index 72fac0e156..678094946b 100644 --- a/tests/src/test/scala/cats/tests/XorTTests.scala +++ b/tests/src/test/scala/cats/tests/XorTTests.scala @@ -69,17 +69,6 @@ class XorTTests extends CatsSuite { checkAll("MonadRec[XorT[ListWrapper, String, ?]]", SerializableTests.serializable(MonadRec[XorT[ListWrapper, String, ?]])) } - { - //If an applicative is defined - implicit val F = ListWrapper.applicative - - Functor[XorT[ListWrapper, String, ?]] - - checkAll("XorT[ListWrapper, String, ?]", ApplicativeTests[XorT[ListWrapper, String, ?]].applicative[Int, Int, Int]) - checkAll("Applicative[XorT[ListWrapper, String, ?]]", SerializableTests.serializable(Applicative[XorT[ListWrapper, String, ?]])) - - } - { //If a foldable is defined implicit val F = ListWrapper.foldable From 5f51fa11a51de5b7bf37fef9eb564232b9245ae4 Mon Sep 17 00:00:00 2001 From: Kailuo Wang Date: Fri, 10 Jun 2016 15:11:23 -0400 Subject: [PATCH 10/36] uniquify implicit names in syntax part 3 of #1061 --- core/src/main/scala/cats/syntax/applicative.scala | 4 ++-- core/src/main/scala/cats/syntax/applicativeError.scala | 4 ++-- core/src/main/scala/cats/syntax/apply.scala | 4 ++-- core/src/main/scala/cats/syntax/bifoldable.scala | 2 +- core/src/main/scala/cats/syntax/bifunctor.scala | 2 +- core/src/main/scala/cats/syntax/bitraverse.scala | 4 ++-- core/src/main/scala/cats/syntax/cartesian.scala | 4 ++-- core/src/main/scala/cats/syntax/coflatMap.scala | 2 +- core/src/main/scala/cats/syntax/comonad.scala | 2 +- core/src/main/scala/cats/syntax/compose.scala | 2 +- core/src/main/scala/cats/syntax/contravariant.scala | 2 +- core/src/main/scala/cats/syntax/coproduct.scala | 2 +- core/src/main/scala/cats/syntax/either.scala | 2 +- core/src/main/scala/cats/syntax/eq.scala | 2 +- core/src/main/scala/cats/syntax/flatMap.scala | 8 ++++---- core/src/main/scala/cats/syntax/foldable.scala | 4 ++-- core/src/main/scala/cats/syntax/functor.scala | 2 +- core/src/main/scala/cats/syntax/group.scala | 2 +- core/src/main/scala/cats/syntax/invariant.scala | 2 +- core/src/main/scala/cats/syntax/list.scala | 2 +- core/src/main/scala/cats/syntax/monadCombine.scala | 4 ++-- core/src/main/scala/cats/syntax/monadError.scala | 2 +- core/src/main/scala/cats/syntax/monadFilter.scala | 2 +- core/src/main/scala/cats/syntax/option.scala | 4 ++-- core/src/main/scala/cats/syntax/order.scala | 2 +- core/src/main/scala/cats/syntax/partialOrder.scala | 2 +- core/src/main/scala/cats/syntax/profunctor.scala | 2 +- core/src/main/scala/cats/syntax/reducible.scala | 4 ++-- core/src/main/scala/cats/syntax/semigroup.scala | 2 +- core/src/main/scala/cats/syntax/semigroupk.scala | 2 +- core/src/main/scala/cats/syntax/split.scala | 2 +- core/src/main/scala/cats/syntax/strong.scala | 2 +- core/src/main/scala/cats/syntax/transLift.scala | 2 +- core/src/main/scala/cats/syntax/traverse.scala | 6 +++--- core/src/main/scala/cats/syntax/validated.scala | 2 +- core/src/main/scala/cats/syntax/writer.scala | 2 +- core/src/main/scala/cats/syntax/xor.scala | 2 +- tests/src/test/scala/cats/tests/CatsSuite.scala | 4 ++-- 38 files changed, 53 insertions(+), 53 deletions(-) diff --git a/core/src/main/scala/cats/syntax/applicative.scala b/core/src/main/scala/cats/syntax/applicative.scala index abd73a64e0..60df3a33e5 100644 --- a/core/src/main/scala/cats/syntax/applicative.scala +++ b/core/src/main/scala/cats/syntax/applicative.scala @@ -2,8 +2,8 @@ package cats package syntax trait ApplicativeSyntax { - implicit def applicativeIdSyntax[A](a: A): ApplicativeIdOps[A] = new ApplicativeIdOps[A](a) - implicit def applicativeEvalSyntax[A](a: Eval[A]): ApplicativeEvalOps[A] = new ApplicativeEvalOps[A](a) + implicit def catsSyntaxApplicativeId[A](a: A): ApplicativeIdOps[A] = new ApplicativeIdOps[A](a) + implicit def catsSyntaxApplicativeEval[A](a: Eval[A]): ApplicativeEvalOps[A] = new ApplicativeEvalOps[A](a) } final class ApplicativeIdOps[A](val a: A) extends AnyVal { diff --git a/core/src/main/scala/cats/syntax/applicativeError.scala b/core/src/main/scala/cats/syntax/applicativeError.scala index 5cf4f30b21..73c57aef64 100644 --- a/core/src/main/scala/cats/syntax/applicativeError.scala +++ b/core/src/main/scala/cats/syntax/applicativeError.scala @@ -4,10 +4,10 @@ package syntax import cats.data.{Xor, XorT} trait ApplicativeErrorSyntax { - implicit def applicativeErrorIdSyntax[E](e: E): ApplicativeErrorIdOps[E] = + implicit def catsSyntaxApplicativeErrorId[E](e: E): ApplicativeErrorIdOps[E] = new ApplicativeErrorIdOps(e) - implicit def applicativeErrorSyntax[F[_], E, A](fa: F[A])(implicit F: ApplicativeError[F, E]): ApplicativeErrorOps[F, E, A] = + implicit def catsSyntaxApplicativeError[F[_], E, A](fa: F[A])(implicit F: ApplicativeError[F, E]): ApplicativeErrorOps[F, E, A] = new ApplicativeErrorOps[F, E, A](fa) } diff --git a/core/src/main/scala/cats/syntax/apply.scala b/core/src/main/scala/cats/syntax/apply.scala index 650c44c613..babd68cafb 100644 --- a/core/src/main/scala/cats/syntax/apply.scala +++ b/core/src/main/scala/cats/syntax/apply.scala @@ -2,7 +2,7 @@ package cats package syntax trait ApplySyntax1 { - implicit def applySyntaxU[FA](fa: FA)(implicit U: Unapply[Apply, FA]): Apply.Ops[U.M, U.A] = + implicit def catsSyntaxUApply[FA](fa: FA)(implicit U: Unapply[Apply, FA]): Apply.Ops[U.M, U.A] = new Apply.Ops[U.M, U.A] { val self = U.subst(fa) val typeClassInstance = U.TC @@ -10,7 +10,7 @@ trait ApplySyntax1 { } trait ApplySyntax extends ApplySyntax1 { - implicit def applySyntax[F[_], A](fa: F[A])(implicit F: Apply[F]): Apply.Ops[F, A] = + implicit def catsSyntaxApply[F[_], A](fa: F[A])(implicit F: Apply[F]): Apply.Ops[F, A] = new Apply.Ops[F,A] { val self = fa val typeClassInstance = F diff --git a/core/src/main/scala/cats/syntax/bifoldable.scala b/core/src/main/scala/cats/syntax/bifoldable.scala index 698695c275..9a93b1230c 100644 --- a/core/src/main/scala/cats/syntax/bifoldable.scala +++ b/core/src/main/scala/cats/syntax/bifoldable.scala @@ -2,7 +2,7 @@ package cats package syntax trait BifoldableSyntax { - implicit def bifoldableSyntax[F[_, _]: Bifoldable, A, B](fab: F[A, B]): BifoldableOps[F, A, B] = + implicit def catsSyntaxBifoldable[F[_, _]: Bifoldable, A, B](fab: F[A, B]): BifoldableOps[F, A, B] = new BifoldableOps[F, A, B](fab) } diff --git a/core/src/main/scala/cats/syntax/bifunctor.scala b/core/src/main/scala/cats/syntax/bifunctor.scala index b22c50768e..404e53e001 100644 --- a/core/src/main/scala/cats/syntax/bifunctor.scala +++ b/core/src/main/scala/cats/syntax/bifunctor.scala @@ -5,7 +5,7 @@ import cats.functor.Bifunctor trait BifunctorSyntax { // TODO: use simulacrum instances eventually - implicit def bifunctorSyntax[F[_, _]: Bifunctor, A, B](fab: F[A, B]): BifunctorOps[F, A, B] = + implicit def catsSyntaxBifunctor[F[_, _]: Bifunctor, A, B](fab: F[A, B]): BifunctorOps[F, A, B] = new BifunctorOps[F, A, B](fab) } diff --git a/core/src/main/scala/cats/syntax/bitraverse.scala b/core/src/main/scala/cats/syntax/bitraverse.scala index cbf7d72ad9..e34372ade3 100644 --- a/core/src/main/scala/cats/syntax/bitraverse.scala +++ b/core/src/main/scala/cats/syntax/bitraverse.scala @@ -2,12 +2,12 @@ package cats package syntax trait BitraverseSyntax extends BitraverseSyntax1 { - implicit def bitraverseSyntax[F[_, _]: Bitraverse, A, B](fab: F[A, B]): BitraverseOps[F, A, B] = + implicit def catsSyntaxBitraverse[F[_, _]: Bitraverse, A, B](fab: F[A, B]): BitraverseOps[F, A, B] = new BitraverseOps[F, A, B](fab) } private[syntax] trait BitraverseSyntax1 { - implicit def nestedBitraverseSyntax[F[_, _]: Bitraverse, G[_], A, B](fgagb: F[G[A], G[B]]): NestedBitraverseOps[F, G, A, B] = + implicit def catsSyntaxNestedBitraverse[F[_, _]: Bitraverse, G[_], A, B](fgagb: F[G[A], G[B]]): NestedBitraverseOps[F, G, A, B] = new NestedBitraverseOps[F, G, A, B](fgagb) } diff --git a/core/src/main/scala/cats/syntax/cartesian.scala b/core/src/main/scala/cats/syntax/cartesian.scala index 6506668548..dfa3ed9a12 100644 --- a/core/src/main/scala/cats/syntax/cartesian.scala +++ b/core/src/main/scala/cats/syntax/cartesian.scala @@ -2,7 +2,7 @@ package cats package syntax trait CartesianSyntax1 { - implicit def cartesianSyntaxU[FA](fa: FA)(implicit U: Unapply[Cartesian, FA]): CartesianOps[U.M, U.A] = + implicit def catsSyntaxUCartesian[FA](fa: FA)(implicit U: Unapply[Cartesian, FA]): CartesianOps[U.M, U.A] = new CartesianOps[U.M, U.A] { val self = U.subst(fa) val typeClassInstance = U.TC @@ -10,7 +10,7 @@ trait CartesianSyntax1 { } trait CartesianSyntax extends CartesianSyntax1 { - implicit def cartesianSyntax[F[_], A](fa: F[A])(implicit F: Cartesian[F]): CartesianOps[F, A] = + implicit def catsSyntaxCartesian[F[_], A](fa: F[A])(implicit F: Cartesian[F]): CartesianOps[F, A] = new CartesianOps[F, A] { val self = fa val typeClassInstance = F diff --git a/core/src/main/scala/cats/syntax/coflatMap.scala b/core/src/main/scala/cats/syntax/coflatMap.scala index 7b73d93e20..a3e31fbc15 100644 --- a/core/src/main/scala/cats/syntax/coflatMap.scala +++ b/core/src/main/scala/cats/syntax/coflatMap.scala @@ -2,7 +2,7 @@ package cats package syntax trait CoflatMapSyntax1 { - implicit def coflatMapSyntaxU[FA](fa: FA)(implicit U: Unapply[CoflatMap, FA]): CoflatMap.Ops[U.M, U.A] = new CoflatMap.Ops[U.M, U.A] { + implicit def catsSyntaxUCoflatMap[FA](fa: FA)(implicit U: Unapply[CoflatMap, FA]): CoflatMap.Ops[U.M, U.A] = new CoflatMap.Ops[U.M, U.A] { val self = U.subst(fa) val typeClassInstance = U.TC } diff --git a/core/src/main/scala/cats/syntax/comonad.scala b/core/src/main/scala/cats/syntax/comonad.scala index 8fb15dc384..36f3bb97f2 100644 --- a/core/src/main/scala/cats/syntax/comonad.scala +++ b/core/src/main/scala/cats/syntax/comonad.scala @@ -2,7 +2,7 @@ package cats package syntax trait ComonadSyntax1 { - implicit def comonadSyntaxU[FA](fa: FA)(implicit U: Unapply[Comonad, FA]): Comonad.Ops[U.M, U.A] = + implicit def catsSyntaxUComonad[FA](fa: FA)(implicit U: Unapply[Comonad, FA]): Comonad.Ops[U.M, U.A] = new Comonad.Ops[U.M, U.A] { val self = U.subst(fa) val typeClassInstance = U.TC diff --git a/core/src/main/scala/cats/syntax/compose.scala b/core/src/main/scala/cats/syntax/compose.scala index 6c102ea4d7..87ddb82d8c 100644 --- a/core/src/main/scala/cats/syntax/compose.scala +++ b/core/src/main/scala/cats/syntax/compose.scala @@ -5,7 +5,7 @@ import cats.arrow.Compose trait ComposeSyntax { // TODO: use simulacrum instances eventually - implicit def composeSyntax[F[_, _]: Compose, A, B](fab: F[A, B]): ComposeOps[F, A, B] = + implicit def catsSyntaxCompose[F[_, _]: Compose, A, B](fab: F[A, B]): ComposeOps[F, A, B] = new ComposeOps[F, A, B](fab) } diff --git a/core/src/main/scala/cats/syntax/contravariant.scala b/core/src/main/scala/cats/syntax/contravariant.scala index 592ea6f36e..472aa84174 100644 --- a/core/src/main/scala/cats/syntax/contravariant.scala +++ b/core/src/main/scala/cats/syntax/contravariant.scala @@ -5,7 +5,7 @@ import cats.functor.Contravariant trait ContravariantSyntax1 { - implicit def contravariantSyntaxU[FA](fa: FA)(implicit U: Unapply[Contravariant, FA]): Contravariant.Ops[U.M, U.A] = + implicit def catsSyntaxUContravariant[FA](fa: FA)(implicit U: Unapply[Contravariant, FA]): Contravariant.Ops[U.M, U.A] = new Contravariant.Ops[U.M, U.A] { val self = U.subst(fa) val typeClassInstance = U.TC diff --git a/core/src/main/scala/cats/syntax/coproduct.scala b/core/src/main/scala/cats/syntax/coproduct.scala index 95e8843873..af6b45760a 100644 --- a/core/src/main/scala/cats/syntax/coproduct.scala +++ b/core/src/main/scala/cats/syntax/coproduct.scala @@ -4,7 +4,7 @@ package syntax import cats.data.Coproduct trait CoproductSyntax { - implicit def coproductSyntax[F[_], A](a: F[A]): CoproductOps[F, A] = new CoproductOps(a) + implicit def catsSyntaxCoproduct[F[_], A](a: F[A]): CoproductOps[F, A] = new CoproductOps(a) } final class CoproductOps[F[_], A](val fa: F[A]) extends AnyVal { diff --git a/core/src/main/scala/cats/syntax/either.scala b/core/src/main/scala/cats/syntax/either.scala index 4d886ba933..b91efb2635 100644 --- a/core/src/main/scala/cats/syntax/either.scala +++ b/core/src/main/scala/cats/syntax/either.scala @@ -4,7 +4,7 @@ package syntax import cats.data.Xor trait EitherSyntax { - implicit def eitherSyntax[A, B](eab: Either[A, B]): EitherOps[A, B] = new EitherOps(eab) + implicit def catsSyntaxEither[A, B](eab: Either[A, B]): EitherOps[A, B] = new EitherOps(eab) } final class EitherOps[A, B](val eab: Either[A, B]) extends AnyVal { diff --git a/core/src/main/scala/cats/syntax/eq.scala b/core/src/main/scala/cats/syntax/eq.scala index e3e9faf190..87250f8643 100644 --- a/core/src/main/scala/cats/syntax/eq.scala +++ b/core/src/main/scala/cats/syntax/eq.scala @@ -4,7 +4,7 @@ package syntax import cats.macros.Ops trait EqSyntax { - implicit def eqSyntax[A: Eq](a: A): EqOps[A] = + implicit def catsSyntaxEq[A: Eq](a: A): EqOps[A] = new EqOps[A](a) } diff --git a/core/src/main/scala/cats/syntax/flatMap.scala b/core/src/main/scala/cats/syntax/flatMap.scala index 68f697c34f..80d89180a7 100644 --- a/core/src/main/scala/cats/syntax/flatMap.scala +++ b/core/src/main/scala/cats/syntax/flatMap.scala @@ -2,18 +2,18 @@ package cats package syntax trait FlatMapSyntax1 { - implicit def flatMapSyntaxU[FA](fa: FA)(implicit U: Unapply[FlatMap, FA]): FlatMapOps[U.M, U.A] = + implicit def catsSyntaxUFlatMap[FA](fa: FA)(implicit U: Unapply[FlatMap, FA]): FlatMapOps[U.M, U.A] = new FlatMapOps[U.M, U.A](U.subst(fa))(U.TC) } trait FlatMapSyntax extends FlatMapSyntax1 { - implicit def flatMapSyntax[F[_]: FlatMap, A](fa: F[A]): FlatMapOps[F, A] = + implicit def catsSyntaxFlatMap[F[_]: FlatMap, A](fa: F[A]): FlatMapOps[F, A] = new FlatMapOps(fa) - implicit def flattenSyntax[F[_]: FlatMap, A](ffa: F[F[A]]): FlattenOps[F, A] = + implicit def catsSyntaxFlatten[F[_]: FlatMap, A](ffa: F[F[A]]): FlattenOps[F, A] = new FlattenOps[F, A](ffa) - implicit def ifMSyntax[F[_]: FlatMap](fa: F[Boolean]): IfMOps[F] = + implicit def catsSyntaxIfM[F[_]: FlatMap](fa: F[Boolean]): IfMOps[F] = new IfMOps[F](fa) } diff --git a/core/src/main/scala/cats/syntax/foldable.scala b/core/src/main/scala/cats/syntax/foldable.scala index b4df275aa5..a88aee0625 100644 --- a/core/src/main/scala/cats/syntax/foldable.scala +++ b/core/src/main/scala/cats/syntax/foldable.scala @@ -2,7 +2,7 @@ package cats package syntax trait FoldableSyntax1 { - implicit def foldableSyntaxU[FA](fa: FA)(implicit U: Unapply[Foldable,FA]): Foldable.Ops[U.M, U.A] = + implicit def catsSyntaxUFoldable[FA](fa: FA)(implicit U: Unapply[Foldable,FA]): Foldable.Ops[U.M, U.A] = new Foldable.Ops[U.M, U.A] { val self = U.subst(fa) val typeClassInstance = U.TC @@ -10,7 +10,7 @@ trait FoldableSyntax1 { } trait FoldableSyntax extends Foldable.ToFoldableOps with FoldableSyntax1 { - implicit def nestedFoldableSyntax[F[_]: Foldable, G[_], A](fga: F[G[A]]): NestedFoldableOps[F, G, A] = + implicit def catsSyntaxNestedFoldable[F[_]: Foldable, G[_], A](fga: F[G[A]]): NestedFoldableOps[F, G, A] = new NestedFoldableOps[F, G, A](fga) } diff --git a/core/src/main/scala/cats/syntax/functor.scala b/core/src/main/scala/cats/syntax/functor.scala index a90af84a53..9ea1027825 100644 --- a/core/src/main/scala/cats/syntax/functor.scala +++ b/core/src/main/scala/cats/syntax/functor.scala @@ -2,7 +2,7 @@ package cats package syntax trait FunctorSyntax1 { - implicit def functorSyntaxU[FA](fa: FA)(implicit U: Unapply[Functor,FA]): Functor.Ops[U.M, U.A] = + implicit def catsSyntaxUFunctor[FA](fa: FA)(implicit U: Unapply[Functor,FA]): Functor.Ops[U.M, U.A] = new Functor.Ops[U.M, U.A]{ val self = U.subst(fa) val typeClassInstance = U.TC diff --git a/core/src/main/scala/cats/syntax/group.scala b/core/src/main/scala/cats/syntax/group.scala index b2e2ccc9e4..dca6c12780 100644 --- a/core/src/main/scala/cats/syntax/group.scala +++ b/core/src/main/scala/cats/syntax/group.scala @@ -5,7 +5,7 @@ import cats.macros.Ops trait GroupSyntax extends SemigroupSyntax { // TODO: use simulacrum instances eventually - implicit def groupSyntax[A: Group](a: A): GroupOps[A] = + implicit def catsSyntaxGroup[A: Group](a: A): GroupOps[A] = new GroupOps[A](a) } diff --git a/core/src/main/scala/cats/syntax/invariant.scala b/core/src/main/scala/cats/syntax/invariant.scala index 5bde8d1353..f40b5e04b7 100644 --- a/core/src/main/scala/cats/syntax/invariant.scala +++ b/core/src/main/scala/cats/syntax/invariant.scala @@ -4,7 +4,7 @@ package syntax import cats.functor.Invariant trait InvariantSyntax1 { - implicit def invariantSyntaxU[FA](fa: FA)(implicit U: Unapply[Invariant, FA]): Invariant.Ops[U.M, U.A] = + implicit def catsSyntaxUInvariant[FA](fa: FA)(implicit U: Unapply[Invariant, FA]): Invariant.Ops[U.M, U.A] = new Invariant.Ops[U.M, U.A] { val self = U.subst(fa) val typeClassInstance = U.TC diff --git a/core/src/main/scala/cats/syntax/list.scala b/core/src/main/scala/cats/syntax/list.scala index a7380318ec..88defb39da 100644 --- a/core/src/main/scala/cats/syntax/list.scala +++ b/core/src/main/scala/cats/syntax/list.scala @@ -4,7 +4,7 @@ package syntax import cats.data.NonEmptyList trait ListSyntax { - implicit def listSyntax[A](la: List[A]): ListOps[A] = new ListOps(la) + implicit def catsSyntaxList[A](la: List[A]): ListOps[A] = new ListOps(la) } final class ListOps[A](val la: List[A]) extends AnyVal { diff --git a/core/src/main/scala/cats/syntax/monadCombine.scala b/core/src/main/scala/cats/syntax/monadCombine.scala index 5808cc7007..53cbbd4fdb 100644 --- a/core/src/main/scala/cats/syntax/monadCombine.scala +++ b/core/src/main/scala/cats/syntax/monadCombine.scala @@ -3,10 +3,10 @@ package syntax trait MonadCombineSyntax { // TODO: use simulacrum instances eventually - implicit def monadCombineSyntax[F[_]: MonadCombine, G[_], A](fga: F[G[A]]): MonadCombineOps[F, G, A] = + implicit def catsSyntaxMonadCombine[F[_]: MonadCombine, G[_], A](fga: F[G[A]]): MonadCombineOps[F, G, A] = new MonadCombineOps[F, G, A](fga) - implicit def separateSyntax[F[_]: MonadCombine, G[_, _], A, B](fgab: F[G[A, B]]): SeparateOps[F, G, A, B] = + implicit def catsSyntaxMonadCombineSeparate[F[_]: MonadCombine, G[_, _], A, B](fgab: F[G[A, B]]): SeparateOps[F, G, A, B] = new SeparateOps[F, G, A, B](fgab) } diff --git a/core/src/main/scala/cats/syntax/monadError.scala b/core/src/main/scala/cats/syntax/monadError.scala index 93023431d5..1f32df0b13 100644 --- a/core/src/main/scala/cats/syntax/monadError.scala +++ b/core/src/main/scala/cats/syntax/monadError.scala @@ -3,7 +3,7 @@ package syntax trait MonadErrorSyntax { - implicit def monadErrorSyntax[F[_], E, A](fa: F[A])(implicit F: MonadError[F, E]): MonadErrorOps[F, E, A] = + implicit def catsSyntaxMonadError[F[_], E, A](fa: F[A])(implicit F: MonadError[F, E]): MonadErrorOps[F, E, A] = new MonadErrorOps(fa) } diff --git a/core/src/main/scala/cats/syntax/monadFilter.scala b/core/src/main/scala/cats/syntax/monadFilter.scala index 3c1dcf3169..18db067ff7 100644 --- a/core/src/main/scala/cats/syntax/monadFilter.scala +++ b/core/src/main/scala/cats/syntax/monadFilter.scala @@ -2,7 +2,7 @@ package cats package syntax trait MonadFilterSyntax1 { - implicit def monadFilterSyntaxU[FA](fa: FA)(implicit U: Unapply[MonadFilter,FA]): MonadFilter.Ops[U.M, U.A] = + implicit def catsSyntaxUMonadFilter[FA](fa: FA)(implicit U: Unapply[MonadFilter,FA]): MonadFilter.Ops[U.M, U.A] = new MonadFilter.Ops[U.M, U.A] { val self = U.subst(fa) val typeClassInstance = U.TC diff --git a/core/src/main/scala/cats/syntax/option.scala b/core/src/main/scala/cats/syntax/option.scala index 536f6faf24..5d567c7365 100644 --- a/core/src/main/scala/cats/syntax/option.scala +++ b/core/src/main/scala/cats/syntax/option.scala @@ -5,8 +5,8 @@ import cats.data.{ Xor, Validated, ValidatedNel } trait OptionSyntax { final def none[A]: Option[A] = Option.empty[A] - implicit final def optionIdSyntax[A](a: A): OptionIdOps[A] = new OptionIdOps(a) - implicit final def optionSyntax[A](oa: Option[A]): OptionOps[A] = new OptionOps(oa) + implicit final def catsSyntaxOptionId[A](a: A): OptionIdOps[A] = new OptionIdOps(a) + implicit final def catsSyntaxOption[A](oa: Option[A]): OptionOps[A] = new OptionOps(oa) } final class OptionIdOps[A](val a: A) extends AnyVal { diff --git a/core/src/main/scala/cats/syntax/order.scala b/core/src/main/scala/cats/syntax/order.scala index 34d5a9055d..cf562252ed 100644 --- a/core/src/main/scala/cats/syntax/order.scala +++ b/core/src/main/scala/cats/syntax/order.scala @@ -4,7 +4,7 @@ package syntax import cats.macros.Ops trait OrderSyntax extends PartialOrderSyntax { - implicit def orderSyntax[A: Order](a: A): OrderOps[A] = + implicit def catsSyntaxOrder[A: Order](a: A): OrderOps[A] = new OrderOps[A](a) } diff --git a/core/src/main/scala/cats/syntax/partialOrder.scala b/core/src/main/scala/cats/syntax/partialOrder.scala index 3b3dd677a6..21b350f732 100644 --- a/core/src/main/scala/cats/syntax/partialOrder.scala +++ b/core/src/main/scala/cats/syntax/partialOrder.scala @@ -4,7 +4,7 @@ package syntax import cats.macros.Ops trait PartialOrderSyntax extends EqSyntax { - implicit def partialOrderSyntax[A: PartialOrder](a: A): PartialOrderOps[A] = + implicit def catsSyntaxPartialOrder[A: PartialOrder](a: A): PartialOrderOps[A] = new PartialOrderOps[A](a) } diff --git a/core/src/main/scala/cats/syntax/profunctor.scala b/core/src/main/scala/cats/syntax/profunctor.scala index 10ec9eaa39..fb926cb01f 100644 --- a/core/src/main/scala/cats/syntax/profunctor.scala +++ b/core/src/main/scala/cats/syntax/profunctor.scala @@ -5,7 +5,7 @@ import cats.functor.Profunctor trait ProfunctorSyntax { // TODO: use simulacrum instances eventually - implicit def profunctorSyntax[F[_, _]: Profunctor, A, B](fab: F[A, B]): ProfunctorOps[F, A, B] = + implicit def catsSyntaxProfunctor[F[_, _]: Profunctor, A, B](fab: F[A, B]): ProfunctorOps[F, A, B] = new ProfunctorOps[F, A, B](fab) } diff --git a/core/src/main/scala/cats/syntax/reducible.scala b/core/src/main/scala/cats/syntax/reducible.scala index ed687ce800..241f3542e8 100644 --- a/core/src/main/scala/cats/syntax/reducible.scala +++ b/core/src/main/scala/cats/syntax/reducible.scala @@ -2,7 +2,7 @@ package cats package syntax trait ReducibleSyntax1 { - implicit def reducibleSyntaxU[FA](fa: FA)(implicit U: Unapply[Reducible,FA]): Reducible.Ops[U.M, U.A] = + implicit def catsSyntaxUReducible[FA](fa: FA)(implicit U: Unapply[Reducible,FA]): Reducible.Ops[U.M, U.A] = new Reducible.Ops[U.M, U.A] { val self = U.subst(fa) val typeClassInstance = U.TC @@ -10,7 +10,7 @@ trait ReducibleSyntax1 { } trait ReducibleSyntax extends Reducible.ToReducibleOps with ReducibleSyntax1 { - implicit def nestedReducibleSyntax[F[_]: Reducible, G[_], A](fga: F[G[A]]): NestedReducibleOps[F, G, A] = + implicit def catsSyntaxNestedReducible[F[_]: Reducible, G[_], A](fga: F[G[A]]): NestedReducibleOps[F, G, A] = new NestedReducibleOps[F, G, A](fga) } diff --git a/core/src/main/scala/cats/syntax/semigroup.scala b/core/src/main/scala/cats/syntax/semigroup.scala index fbfd783f5a..b87cfce3ba 100644 --- a/core/src/main/scala/cats/syntax/semigroup.scala +++ b/core/src/main/scala/cats/syntax/semigroup.scala @@ -5,7 +5,7 @@ import cats.macros.Ops trait SemigroupSyntax { // TODO: use simulacrum instances eventually - implicit def semigroupSyntax[A: Semigroup](a: A): SemigroupOps[A] = + implicit def catsSyntaxSemigroup[A: Semigroup](a: A): SemigroupOps[A] = new SemigroupOps[A](a) } diff --git a/core/src/main/scala/cats/syntax/semigroupk.scala b/core/src/main/scala/cats/syntax/semigroupk.scala index 8dfbcae15c..ceeddfae52 100644 --- a/core/src/main/scala/cats/syntax/semigroupk.scala +++ b/core/src/main/scala/cats/syntax/semigroupk.scala @@ -3,7 +3,7 @@ package syntax trait SemigroupKSyntax1 { // TODO: use simulacrum instances eventually - implicit def semigroupSyntaxU[FA](fa: FA)(implicit U: Unapply[SemigroupK,FA]): SemigroupK.Ops[U.M, U.A] = + implicit def catsSyntaxUSemigroup[FA](fa: FA)(implicit U: Unapply[SemigroupK,FA]): SemigroupK.Ops[U.M, U.A] = new SemigroupK.Ops[U.M, U.A] { val self = U.subst(fa) val typeClassInstance = U.TC diff --git a/core/src/main/scala/cats/syntax/split.scala b/core/src/main/scala/cats/syntax/split.scala index a5eaca249e..5884fd795d 100644 --- a/core/src/main/scala/cats/syntax/split.scala +++ b/core/src/main/scala/cats/syntax/split.scala @@ -5,7 +5,7 @@ import cats.arrow.Split trait SplitSyntax { // TODO: use simulacrum instances eventually - implicit def splitSyntax[F[_, _]: Split, A, B](fab: F[A, B]): SplitOps[F, A, B] = + implicit def catsSyntaxSplit[F[_, _]: Split, A, B](fab: F[A, B]): SplitOps[F, A, B] = new SplitOps[F, A, B](fab) } diff --git a/core/src/main/scala/cats/syntax/strong.scala b/core/src/main/scala/cats/syntax/strong.scala index b836f6b623..df0c1005d9 100644 --- a/core/src/main/scala/cats/syntax/strong.scala +++ b/core/src/main/scala/cats/syntax/strong.scala @@ -5,7 +5,7 @@ import cats.functor.Strong trait StrongSyntax { // TODO: use simulacrum instances eventually - implicit def strongSyntax[F[_, _]: Strong, A, B](fab: F[A, B]): StrongOps[F, A, B] = + implicit def catsSyntaxStrong[F[_, _]: Strong, A, B](fab: F[A, B]): StrongOps[F, A, B] = new StrongOps[F, A, B](fab) } diff --git a/core/src/main/scala/cats/syntax/transLift.scala b/core/src/main/scala/cats/syntax/transLift.scala index 1dac0d79d5..97bdc5ed84 100644 --- a/core/src/main/scala/cats/syntax/transLift.scala +++ b/core/src/main/scala/cats/syntax/transLift.scala @@ -2,7 +2,7 @@ package cats package syntax trait TransLiftSyntax { - implicit def transLiftSyntax[E](ma: E)(implicit U: Unapply[Trivial.PH1, E]): TransLiftOps[U.M, U.A] = new TransLiftOps(U.subst(ma)) + implicit def catsSyntaxTransLift[E](ma: E)(implicit U: Unapply[Trivial.PH1, E]): TransLiftOps[U.M, U.A] = new TransLiftOps(U.subst(ma)) } final class TransLiftOps[M0[_], A](val ma: M0[A]) extends AnyVal { diff --git a/core/src/main/scala/cats/syntax/traverse.scala b/core/src/main/scala/cats/syntax/traverse.scala index ea5917b8dd..e2c22469f0 100644 --- a/core/src/main/scala/cats/syntax/traverse.scala +++ b/core/src/main/scala/cats/syntax/traverse.scala @@ -2,16 +2,16 @@ package cats package syntax trait TraverseSyntax1 { - implicit def traverseSyntaxU[FA](fa: FA)(implicit U: Unapply[Traverse,FA]): TraverseOps[U.M, U.A] = + implicit def catsSyntaxUTraverse[FA](fa: FA)(implicit U: Unapply[Traverse,FA]): TraverseOps[U.M, U.A] = new TraverseOps(U.subst(fa))(U.TC) } trait TraverseSyntax extends TraverseSyntax1 { // TODO: use simulacrum instances eventually - implicit def traverseSyntax[F[_]: Traverse, A](fa: F[A]): TraverseOps[F, A] = + implicit def catsSyntaxTraverse[F[_]: Traverse, A](fa: F[A]): TraverseOps[F, A] = new TraverseOps(fa) - implicit def nestedTraverseSyntax[F[_]: Traverse, G[_], A](fga: F[G[A]]): NestedTraverseOps[F, G, A] = + implicit def catsSyntaxNestedTraverse[F[_]: Traverse, G[_], A](fga: F[G[A]]): NestedTraverseOps[F, G, A] = new NestedTraverseOps[F, G, A](fga) } diff --git a/core/src/main/scala/cats/syntax/validated.scala b/core/src/main/scala/cats/syntax/validated.scala index 7d5cbc8fe5..11e6972a42 100644 --- a/core/src/main/scala/cats/syntax/validated.scala +++ b/core/src/main/scala/cats/syntax/validated.scala @@ -4,7 +4,7 @@ package syntax import cats.data.{ Validated, ValidatedNel } trait ValidatedSyntax { - implicit def validatedIdSyntax[A](a: A): ValidatedIdSyntax[A] = new ValidatedIdSyntax(a) + implicit def catsSyntaxValidatedId[A](a: A): ValidatedIdSyntax[A] = new ValidatedIdSyntax(a) } final class ValidatedIdSyntax[A](val a: A) extends AnyVal { diff --git a/core/src/main/scala/cats/syntax/writer.scala b/core/src/main/scala/cats/syntax/writer.scala index 41dab81a63..828592e6d2 100644 --- a/core/src/main/scala/cats/syntax/writer.scala +++ b/core/src/main/scala/cats/syntax/writer.scala @@ -4,7 +4,7 @@ package syntax import cats.data.Writer trait WriterSyntax { - implicit def writerIdSyntax[A](a: A): WriterIdSyntax[A] = new WriterIdSyntax(a) + implicit def catsSyntaxWriterId[A](a: A): WriterIdSyntax[A] = new WriterIdSyntax(a) } final class WriterIdSyntax[A](val a: A) extends AnyVal { diff --git a/core/src/main/scala/cats/syntax/xor.scala b/core/src/main/scala/cats/syntax/xor.scala index ca0b4160cf..0172eef904 100644 --- a/core/src/main/scala/cats/syntax/xor.scala +++ b/core/src/main/scala/cats/syntax/xor.scala @@ -4,7 +4,7 @@ package syntax import cats.data.Xor trait XorSyntax { - implicit def xorIdSyntax[A](a: A): XorIdOps[A] = new XorIdOps(a) + implicit def catsSyntaxXorId[A](a: A): XorIdOps[A] = new XorIdOps(a) } final class XorIdOps[A](val a: A) extends AnyVal { diff --git a/tests/src/test/scala/cats/tests/CatsSuite.scala b/tests/src/test/scala/cats/tests/CatsSuite.scala index 7a1d0314a8..9f189e8754 100644 --- a/tests/src/test/scala/cats/tests/CatsSuite.scala +++ b/tests/src/test/scala/cats/tests/CatsSuite.scala @@ -39,9 +39,9 @@ trait CatsSuite extends FunSuite with Matchers with GeneratorDrivenPropertyCheck implicit override val generatorDrivenConfig: PropertyCheckConfiguration = checkConfiguration - // disable Eq syntax (by making `eqSyntax` not implicit), since it collides + // disable Eq syntax (by making `catsSyntaxEq` not implicit), since it collides // with scalactic's equality - override def eqSyntax[A: Eq](a: A): EqOps[A] = new EqOps[A](a) + override def catsSyntaxEq[A: Eq](a: A): EqOps[A] = new EqOps[A](a) } trait SlowCatsSuite extends CatsSuite { From bbd3e128a14faa5dad22c6de66b541eb5f05ef35 Mon Sep 17 00:00:00 2001 From: peterneyens Date: Thu, 9 Jun 2016 12:41:52 +0200 Subject: [PATCH 11/36] Add some more OptionT instances. Added `Eq`, `PartialOrder`, `Order`. Added `Semigroup`, `Monoid` Added `SemigroupK`, `MonoidK` Added `Foldable`, `Traverse` Added `MonadError`, `MonadCombine` and `MonadFilter` (the last two instances are dissabled, because they violate the same laws as the equivalent XorT instances). Rewrote the tests to use `ListWrapper`. I used the ListWrapper methods added by @yilinwei in # 1106. --- core/src/main/scala/cats/data/OptionT.scala | 196 ++++++++++++++---- .../test/scala/cats/tests/ListWrapper.scala | 30 ++- .../test/scala/cats/tests/OptionTTests.scala | 170 +++++++++++++-- 3 files changed, 339 insertions(+), 57 deletions(-) diff --git a/core/src/main/scala/cats/data/OptionT.scala b/core/src/main/scala/cats/data/OptionT.scala index 2754604656..8ba27d6690 100644 --- a/core/src/main/scala/cats/data/OptionT.scala +++ b/core/src/main/scala/cats/data/OptionT.scala @@ -1,6 +1,8 @@ package cats package data +import std.option.{catsStdInstancesForOption => optionInstance} + /** * `OptionT[F[_], A]` is a light wrapper on an `F[Option[A]]` with some * convenient methods for working with this nested structure. @@ -29,11 +31,7 @@ final case class OptionT[F[_], A](value: F[Option[A]]) { flatMapF(a => f(a).value) def flatMapF[B](f: A => F[Option[B]])(implicit F: Monad[F]): OptionT[F, B] = - OptionT( - F.flatMap(value){ - case Some(a) => f(a) - case None => F.pure(None) - }) + OptionT(F.flatMap(value)(_.fold(F.pure[Option[B]](None))(f))) def transform[B](f: Option[A] => Option[B])(implicit F: Functor[F]): OptionT[F, B] = OptionT(F.map(value)(f)) @@ -45,10 +43,7 @@ final case class OptionT[F[_], A](value: F[Option[A]]) { F.map(value)(_.getOrElse(default)) def getOrElseF(default: => F[A])(implicit F: Monad[F]): F[A] = - F.flatMap(value){ - case Some(a) => F.pure(a) - case None => default - } + F.flatMap(value)(_.fold(default)(F.pure)) def collect[B](f: PartialFunction[A, B])(implicit F: Functor[F]): OptionT[F, B] = OptionT(F.map(value)(_.collect(f))) @@ -91,6 +86,24 @@ final case class OptionT[F[_], A](value: F[Option[A]]) { XorT(cata(Xor.Right(right), Xor.Left.apply)) def show(implicit F: Show[F[Option[A]]]): String = F.show(value) + + def compare(that: OptionT[F, A])(implicit o: Order[F[Option[A]]]): Int = + o.compare(value, that.value) + + def partialCompare(that: OptionT[F, A])(implicit p: PartialOrder[F[Option[A]]]): Double = + p.partialCompare(value, that.value) + + def ===(that: OptionT[F, A])(implicit eq: Eq[F[Option[A]]]): Boolean = + eq.eqv(value, that.value) + + def traverse[G[_], B](f: A => G[B])(implicit F: Traverse[F], G: Applicative[G]): G[OptionT[F, B]] = + G.map(F.compose(optionInstance).traverse(value)(f))(OptionT.apply) + + def foldLeft[B](b: B)(f: (B, A) => B)(implicit F: Foldable[F]): B = + F.compose(optionInstance).foldLeft(value, b)(f) + + def foldRight[B](lb: Eval[B])(f: (A, Eval[B]) => Eval[B])(implicit F: Foldable[F]): Eval[B] = + F.compose(optionInstance).foldRight(value, lb)(f) } object OptionT extends OptionTInstances { @@ -132,12 +145,44 @@ object OptionT extends OptionTInstances { def liftF[F[_], A](fa: F[A])(implicit F: Functor[F]): OptionT[F, A] = OptionT(F.map(fa)(Some(_))) } -private[data] sealed trait OptionTInstances2 { - implicit def catsDataFunctorForOptionT[F[_]:Functor]: Functor[OptionT[F, ?]] = - new Functor[OptionT[F, ?]] { - override def map[A, B](fa: OptionT[F, A])(f: A => B): OptionT[F, B] = - fa.map(f) - } +private[data] sealed trait OptionTInstances extends OptionTInstances0 { + implicit def catsDataMonadRecForOptionT[F[_]](implicit F0: MonadRec[F]): MonadRec[OptionT[F, ?]] = + new OptionTMonadRec[F] { implicit val F = F0 } + + implicit def catsDataFoldableForOptionT[F[_]](implicit F0: Foldable[F]): Foldable[OptionT[F, ?]] = + new OptionTFoldable[F] { implicit val F = F0 } + + implicit def catsDataSemigroupForOptionT[F[_], A](implicit F0: Semigroup[F[Option[A]]]): Semigroup[OptionT[F, A]] = + new OptionTSemigroup[F, A] { implicit val F = F0 } + + implicit def catsDataOrderForOptionT[F[_], A](implicit F0: Order[F[Option[A]]]): Order[OptionT[F, A]] = + new OptionTOrder[F, A] { implicit val F = F0 } + + implicit def catsDataShowForOptionT[F[_], A](implicit F: Show[F[Option[A]]]): Show[OptionT[F, A]] = + functor.Contravariant[Show].contramap(F)(_.value) +} + +private[data] sealed trait OptionTInstances0 extends OptionTInstances1 { + /* TODO violates right absorbtion, right distributivity, and left distributivity -- re-enable when MonadCombine laws are split in to weak/strong + implicit def catsDataMonadCombineForOptionT[F[_]](implicit F0: Monad[F]): MonadCombine[OptionT[F, ?]] = + new OptionTMonadCombine[F] { implicit val F = F0 } + */ + + implicit def catsDataTraverseForOptionT[F[_]](implicit F0: Traverse[F]): Traverse[OptionT[F, ?]] = + new OptionTTraverse[F] { implicit val F = F0 } + + implicit def catsDataMonoidForOptionT[F[_], A](implicit F0: Monoid[F[Option[A]]]): Monoid[OptionT[F, A]] = + new OptionTMonoid[F, A] { implicit val F = F0 } + + implicit def catsDataPartialOrderForOptionT[F[_], A](implicit F0: PartialOrder[F[Option[A]]]): PartialOrder[OptionT[F, A]] = + new OptionTPartialOrder[F, A] { implicit val F = F0 } +} + +private[data] sealed trait OptionTInstances1 extends OptionTInstances2 { + /* TODO violates monadFilter right empty law -- re-enable when MonadFilter laws are split in to weak/strong + implicit def catsDataMonadFilterForOptionT[F[_]](implicit F0: Monad[F]): MonadFilter[OptionT[F, ?]] = + new OptionTMonadFilter[F] { implicit val F = F0 } + */ // do NOT change this to val! I know it looks like it should work, and really I agree, but it doesn't (for... reasons) implicit def catsDataTransLiftForOptionT: TransLift.Aux[OptionT, Functor] = @@ -146,44 +191,125 @@ private[data] sealed trait OptionTInstances2 { def liftT[M[_]: Functor, A](ma: M[A]): OptionT[M, A] = OptionT.liftF(ma) } -} -private[data] sealed trait OptionTInstances1 extends OptionTInstances2 { + implicit def catsDataSemigroupK[F[_]](implicit F0: Monad[F]): SemigroupK[OptionT[F, ?]] = + new OptionTSemigroupK[F] { implicit val F = F0 } + implicit def catsDataEqForOptionT[F[_], A](implicit F0: Eq[F[Option[A]]]): Eq[OptionT[F, A]] = + new OptionTEq[F, A] { implicit val F = F0 } +} + +private[data] sealed trait OptionTInstances2 extends OptionTInstances3 { implicit def catsDataMonadForOptionT[F[_]](implicit F0: Monad[F]): Monad[OptionT[F, ?]] = new OptionTMonad[F] { implicit val F = F0 } + + implicit def catsDataMonadErrorForOptionT[F[_], E](implicit F0: MonadError[F, E]): MonadError[OptionT[F, ?], E] = + new OptionTMonadError[F, E] { implicit val F = F0 } + + implicit def catsDataMonoidKForOptionT[F[_]](implicit F0: Monad[F]): MonoidK[OptionT[F, ?]] = + new OptionTMonoidK[F] { implicit val F = F0 } } -private[data] sealed trait OptionTInstances extends OptionTInstances1 { - implicit def catsDataMonadRecForOptionT[F[_]](implicit F0: MonadRec[F]): MonadRec[OptionT[F, ?]] = - new OptionTMonadRec[F] { implicit val F = F0 } +private[data] sealed trait OptionTInstances3 { + implicit def catsDataFunctorForOptionT[F[_]](implicit F0: Functor[F]): Functor[OptionT[F, ?]] = + new OptionTFunctor[F] { implicit val F = F0 } +} - implicit def catsDataEqForOptionT[F[_], A](implicit FA: Eq[F[Option[A]]]): Eq[OptionT[F, A]] = - FA.on(_.value) +private[data] trait OptionTFunctor[F[_]] extends Functor[OptionT[F, ?]] { + implicit def F: Functor[F] - implicit def catsDataShowForOptionT[F[_], A](implicit F: Show[F[Option[A]]]): Show[OptionT[F, A]] = - functor.Contravariant[Show].contramap(F)(_.value) + override def map[A, B](fa: OptionT[F, A])(f: A => B): OptionT[F, B] = fa.map(f) } private[data] trait OptionTMonad[F[_]] extends Monad[OptionT[F, ?]] { - implicit val F: Monad[F] + implicit def F: Monad[F] def pure[A](a: A): OptionT[F, A] = OptionT.pure(a) - def flatMap[A, B](fa: OptionT[F, A])(f: A => OptionT[F, B]): OptionT[F, B] = - fa.flatMap(f) + def flatMap[A, B](fa: OptionT[F, A])(f: A => OptionT[F, B]): OptionT[F, B] = fa.flatMap(f) - override def map[A, B](fa: OptionT[F, A])(f: A => B): OptionT[F, B] = - fa.map(f) + override def map[A, B](fa: OptionT[F, A])(f: A => B): OptionT[F, B] = fa.map(f) } +private[data] trait OptionTMonadFilter[F[_]] extends MonadFilter[OptionT[F, ?]] with OptionTMonad[F] { + def empty[A]: OptionT[F, A] = OptionT.none[F, A] +} + +private[data] trait OptionTMonadCombine[F[_]] extends MonadCombine[OptionT[F, ?]] with OptionTMonad[F] with OptionTMonoidK[F] + private[data] trait OptionTMonadRec[F[_]] extends MonadRec[OptionT[F, ?]] with OptionTMonad[F] { - implicit val F: MonadRec[F] + implicit def F: MonadRec[F] def tailRecM[A, B](a: A)(f: A => OptionT[F, A Xor B]): OptionT[F, B] = - OptionT(F.tailRecM(a)(a0 => F.map(f(a0).value){ - case None => Xor.Right(None) - case Some(Xor.Left(a1)) => Xor.Left(a1) - case Some(Xor.Right(b)) => Xor.Right(Some(b)) - })) + OptionT(F.tailRecM(a)(a0 => F.map(f(a0).value)( + _.fold(Xor.right[A, Option[B]](None))(_.map(Some(_))) + ))) +} + +private trait OptionTMonadError[F[_], E] extends MonadError[OptionT[F, ?], E] with OptionTMonad[F] { + override def F: MonadError[F, E] + + override def raiseError[A](e: E): OptionT[F, A] = + OptionT(F.map(F.raiseError[A](e))(Some(_))) + + override def handleErrorWith[A](fa: OptionT[F, A])(f: E => OptionT[F, A]): OptionT[F, A] = + OptionT(F.handleErrorWith(fa.value)(f(_).value)) +} + +private[data] trait OptionTFoldable[F[_]] extends Foldable[OptionT[F, ?]] { + implicit def F: Foldable[F] + + def foldLeft[A, B](fa: OptionT[F, A], b: B)(f: (B, A) => B): B = + fa.foldLeft(b)(f) + + def foldRight[A, B](fa: OptionT[F, A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = + fa.foldRight(lb)(f) +} + +private[data] sealed trait OptionTTraverse[F[_]] extends Traverse[OptionT[F, ?]] with OptionTFoldable[F] { + implicit def F: Traverse[F] + + override def traverse[G[_]: Applicative, A, B](fa: OptionT[F, A])(f: A => G[B]): G[OptionT[F, B]] = + fa traverse f +} + +private[data] trait OptionTSemigroup[F[_], A] extends Semigroup[OptionT[F, A]] { + implicit val F: Semigroup[F[Option[A]]] + + def combine(x: OptionT[F, A], y: OptionT[F, A]): OptionT[F, A] = + OptionT(F.combine(x.value, y.value)) +} + +private[data] trait OptionTMonoid[F[_], A] extends Monoid[OptionT[F, A]] with OptionTSemigroup[F, A] { + implicit val F: Monoid[F[Option[A]]] + + def empty: OptionT[F, A] = OptionT(F.empty) +} + +private[data] trait OptionTSemigroupK[F[_]] extends SemigroupK[OptionT[F, ?]] { + implicit def F: Monad[F] + + def combineK[A](x: OptionT[F, A], y: OptionT[F, A]): OptionT[F, A] = x orElse y +} + +private[data] trait OptionTMonoidK[F[_]] extends MonoidK[OptionT[F, ?]] with OptionTSemigroupK[F] { + def empty[A]: OptionT[F, A] = OptionT.none[F, A] +} + +private[data] sealed trait OptionTEq[F[_], A] extends Eq[OptionT[F, A]] { + implicit def F: Eq[F[Option[A]]] + + override def eqv(x: OptionT[F, A], y: OptionT[F, A]): Boolean = x === y +} + +private[data] sealed trait OptionTPartialOrder[F[_], A] extends PartialOrder[OptionT[F, A]] with OptionTEq[F, A]{ + override implicit def F: PartialOrder[F[Option[A]]] + + override def partialCompare(x: OptionT[F, A], y: OptionT[F, A]): Double = x partialCompare y +} + +private[data] sealed trait OptionTOrder[F[_], A] extends Order[OptionT[F, A]] with OptionTPartialOrder[F, A]{ + override implicit def F: Order[F[Option[A]]] + + override def compare(x: OptionT[F, A], y: OptionT[F, A]): Int = x compare y } diff --git a/tests/src/test/scala/cats/tests/ListWrapper.scala b/tests/src/test/scala/cats/tests/ListWrapper.scala index 1536f25603..469e55d28e 100644 --- a/tests/src/test/scala/cats/tests/ListWrapper.scala +++ b/tests/src/test/scala/cats/tests/ListWrapper.scala @@ -44,14 +44,21 @@ object ListWrapper { def eqv[A : Eq]: Eq[ListWrapper[A]] = Eq[List[A]].on[ListWrapper[A]](_.list) - val foldable: Foldable[ListWrapper] = - new Foldable[ListWrapper] { - def foldLeft[A, B](fa: ListWrapper[A], b: B)(f: (B, A) => B): B = - Foldable[List].foldLeft(fa.list, b)(f) + val traverse: Traverse[ListWrapper] = { + val F = Traverse[List] + new Traverse[ListWrapper] { + def foldLeft[A, B](fa: ListWrapper[A], b: B)(f: (B, A) => B): B = + F.foldLeft(fa.list, b)(f) def foldRight[A, B](fa: ListWrapper[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = - Foldable[List].foldRight(fa.list, lb)(f) + F.foldRight(fa.list, lb)(f) + def traverse[G[_], A, B](fa: ListWrapper[A])(f: A => G[B])(implicit G0: Applicative[G]): G[ListWrapper[B]] = { + G0.map(F.traverse(fa.list)(f))(ListWrapper.apply) + } } + } + + val foldable: Foldable[ListWrapper] = traverse val functor: Functor[ListWrapper] = new Functor[ListWrapper] { @@ -85,6 +92,19 @@ object ListWrapper { } } + val monadRec: MonadRec[ListWrapper] = { + val M = MonadRec[List] + + new MonadRec[ListWrapper] { + def pure[A](x: A): ListWrapper[A] = ListWrapper(M.pure(x)) + def flatMap[A, B](fa: ListWrapper[A])(f: A => ListWrapper[B]): ListWrapper[B] = ListWrapper(M.flatMap(fa.list)(a => f(a).list)) + def tailRecM[A, B](a: A)(f: A => ListWrapper[cats.data.Xor[A,B]]): ListWrapper[B] = + ListWrapper(M.tailRecM(a)(a => f(a).list)) + } + } + + val flatMapRec: FlatMapRec[ListWrapper] = monadRec + val monad: Monad[ListWrapper] = monadCombine val applicative: Applicative[ListWrapper] = monadCombine diff --git a/tests/src/test/scala/cats/tests/OptionTTests.scala b/tests/src/test/scala/cats/tests/OptionTTests.scala index 9d12864e88..e409b6a025 100644 --- a/tests/src/test/scala/cats/tests/OptionTTests.scala +++ b/tests/src/test/scala/cats/tests/OptionTTests.scala @@ -1,11 +1,159 @@ -package cats.tests +package cats +package tests -import cats.{Id, MonadRec, Cartesian, Show} -import cats.data.{OptionT, Xor} -import cats.laws.discipline.{FunctorTests, SerializableTests, CartesianTests, MonadRecTests} +import cats.data.{OptionT, Xor, XorT} +import cats.kernel.laws.OrderLaws +import cats.laws.discipline._ import cats.laws.discipline.arbitrary._ class OptionTTests extends CatsSuite { + implicit val iso = CartesianTests.Isomorphisms.invariant[OptionT[ListWrapper, ?]](OptionT.catsDataFunctorForOptionT(ListWrapper.functor)) + + { + implicit val F = ListWrapper.eqv[Option[Int]] + + checkAll("OptionT[ListWrapper, Int]", OrderLaws[OptionT[ListWrapper, Int]].eqv) + checkAll("Eq[OptionT[ListWrapper, Int]]", SerializableTests.serializable(Eq[OptionT[ListWrapper, Int]])) + } + + { + implicit val F = ListWrapper.partialOrder[Option[Int]] + + checkAll("OptionT[ListWrapper, Int]", OrderLaws[OptionT[ListWrapper, Int]].partialOrder) + checkAll("PartialOrder[OptionT[ListWrapper, Int]]", SerializableTests.serializable(PartialOrder[OptionT[ListWrapper, Int]])) + + Eq[OptionT[ListWrapper, Int]] + } + + { + implicit val F = ListWrapper.order[Option[Int]] + + checkAll("OptionT[ListWrapper, Int]", OrderLaws[OptionT[ListWrapper, Int]].order) + checkAll("Order[OptionT[ListWrapper, Int]]", SerializableTests.serializable(Order[OptionT[ListWrapper, Int]])) + + PartialOrder[OptionT[ListWrapper, Int]] + Eq[OptionT[ListWrapper, Int]] + } + + { + // F has a Functor + implicit val F = ListWrapper.functor + + checkAll("OptionT[ListWrapper, Int]", FunctorTests[OptionT[ListWrapper, ?]].functor[Int, Int, Int]) + checkAll("Functor[OptionT[ListWrapper, ?]]", SerializableTests.serializable(Functor[OptionT[ListWrapper, ?]])) + } + + { + // F has a Monad + implicit val F = ListWrapper.monad + implicit val eq0 = OptionT.catsDataEqForOptionT[ListWrapper, Option[Int]] + implicit val eq1 = OptionT.catsDataEqForOptionT[OptionT[ListWrapper, ?], Int](eq0) + + checkAll("OptionT[ListWrapper, Int]", MonadTests[OptionT[ListWrapper, ?]].monad[Int, Int, Int]) + checkAll("Monad[OptionT[ListWrapper, ?]]", SerializableTests.serializable(Monad[OptionT[ListWrapper, ?]])) + + // checkAll("OptionT[ListWrapper, Int]", MonadFilterTests[OptionT[ListWrapper, ?]].monadFilter[Int, Int, Int]) + // checkAll("MonadFilter[WriterT[ListWrapper, ListWrapper[Int], ?]]", SerializableTests.serializable(MonadFilter[OptionT[ListWrapper, ?]])) + + // checkAll("OptionT[ListWrapper, Int]", MonadCombineTests[OptionT[ListWrapper, ?]].monadCombine[Int, Int, Int]) + // checkAll("MonadCombine[OptionT[ListWrapper, ?]]", SerializableTests.serializable(MonadCombine[OptionT[ListWrapper, ?]])) + + checkAll("OptionT[ListWrapper, Int]", SemigroupKTests[OptionT[ListWrapper, ?]].semigroupK[Int]) + checkAll("SemigroupK[OptionT[ListWrapper, ?]]", SerializableTests.serializable(SemigroupK[OptionT[ListWrapper, ?]])) + + checkAll("OptionT[ListWrapper, Int]", MonoidKTests[OptionT[ListWrapper, ?]].monoidK[Int]) + checkAll("MonoidK[OptionT[ListWrapper, ?]]", SerializableTests.serializable(MonoidK[OptionT[ListWrapper, ?]])) + + FlatMap[OptionT[ListWrapper, ?]] + // Alternative[OptionT[ListWrapper, ?]] + Applicative[OptionT[ListWrapper, ?]] + Apply[OptionT[ListWrapper, ?]] + Functor[OptionT[ListWrapper, ?]] + MonoidK[OptionT[ListWrapper, ?]] + SemigroupK[OptionT[ListWrapper, ?]] + } + + { + // F has a MonadRec + implicit val F = ListWrapper.monadRec + + checkAll("OptionT[ListWrapper, Int]", MonadRecTests[OptionT[ListWrapper, ?]].monadRec[Int, Int, Int]) + checkAll("MonadRec[OptionT[ListWrapper, ?]]", SerializableTests.serializable(MonadRec[OptionT[ListWrapper, ?]])) + + Monad[OptionT[ListWrapper, ?]] + FlatMap[OptionT[ListWrapper, ?]] + Applicative[OptionT[ListWrapper, ?]] + Apply[OptionT[ListWrapper, ?]] + Functor[OptionT[ListWrapper, ?]] + } + + { + // F has a MonadError + type SXor[A] = String Xor A + + implicit val monadError = OptionT.catsDataMonadErrorForOptionT[SXor, String] + + import org.scalacheck.Arbitrary + implicit val arb1 = implicitly[Arbitrary[OptionT[SXor, Int]]] + implicit val arb2 = implicitly[Arbitrary[OptionT[SXor, Int => Int]]] + + implicit val eq0 = OptionT.catsDataEqForOptionT[SXor, Option[Int]] + implicit val eq1 = OptionT.catsDataEqForOptionT[SXor, Int] + implicit val eq2 = OptionT.catsDataEqForOptionT[SXor, Unit] + implicit val eq3 = OptionT.catsDataEqForOptionT[SXor, SXor[Unit]] + implicit val eq4 = OptionT.catsDataEqForOptionT[SXor, SXor[Int]] + implicit val eq5 = XorT.catsDataEqForXorT[OptionT[SXor, ?], String, Int] + implicit val eq6 = OptionT.catsDataEqForOptionT[SXor, (Int, Int, Int)] + + implicit val iso = CartesianTests.Isomorphisms.invariant[OptionT[SXor, ?]] + + checkAll("OptionT[String Xor ?, Int]", MonadErrorTests[OptionT[SXor, ?], String].monadError[Int, Int, Int]) + checkAll("MonadError[OptionT[String Xor ?, ?]]", SerializableTests.serializable(monadError)) + + Monad[OptionT[SXor, ?]] + FlatMap[OptionT[SXor, ?]] + Applicative[OptionT[SXor, ?]] + Apply[OptionT[SXor, ?]] + Functor[OptionT[SXor, ?]] + } + + { + // F has a Foldable + implicit val F = ListWrapper.foldable + + checkAll("OptionT[ListWrapper, Int]", FoldableTests[OptionT[ListWrapper, ?]].foldable[Int, Int]) + checkAll("Foldable[OptionT[ListWrapper, ?]]", SerializableTests.serializable(Foldable[OptionT[ListWrapper, ?]])) + } + + { + // F has a Traverse + implicit val F = ListWrapper.traverse + + checkAll("OptionT[ListWrapper, Int] with Option", TraverseTests[OptionT[ListWrapper, ?]].traverse[Int, Int, Int, Int, Option, Option]) + checkAll("Traverse[OptionT[ListWrapper, ?]]", SerializableTests.serializable(Traverse[OptionT[ListWrapper, ?]])) + + Foldable[OptionT[ListWrapper, ?]] + Functor[OptionT[ListWrapper, ?]] + } + + { + // F[Option[A]] has a monoid + implicit val FA: Monoid[ListWrapper[Option[Int]]] = ListWrapper.monoid[Option[Int]] + + checkAll("OptionT[ListWrapper, Int]", kernel.laws.GroupLaws[OptionT[ListWrapper, Int]].monoid) + + Monoid[OptionT[ListWrapper, Int]] + Semigroup[OptionT[ListWrapper, Int]] + } + + { + // F[Option[A]] has a semigroup + implicit val FA: Semigroup[ListWrapper[Option[Int]]] = ListWrapper.semigroup[Option[Int]] + + checkAll("OptionT[ListWrapper, Int]", kernel.laws.GroupLaws[OptionT[ListWrapper, Int]].semigroup) + + Semigroup[OptionT[ListWrapper, Int]] + } test("fold and cata consistent") { forAll { (o: OptionT[List, Int], s: String, f: Int => String) => @@ -122,11 +270,6 @@ class OptionTTests extends CatsSuite { } } - implicit val iso = CartesianTests.Isomorphisms.invariant[OptionT[List, ?]] - - checkAll("OptionT[List, Int]", CartesianTests[OptionT[List, ?]].cartesian[Int, Int, Int]) - checkAll("Cartesian[OptionT[List, ?]]", SerializableTests.serializable(Cartesian[OptionT[List, ?]])) - test("liftF") { forAll { (xs: List[Int]) => xs.map(Option(_)) should ===(OptionT.liftF(xs).value) @@ -139,7 +282,7 @@ class OptionTTests extends CatsSuite { } test("none") { - OptionT.none[List,Int] should === (OptionT[List,Int](List(None))) + OptionT.none[List, Int] should === (OptionT[List, Int](List(None))) } test("implicit Show[OptionT] instance and explicit show method are consistent") { @@ -160,11 +303,4 @@ class OptionTTests extends CatsSuite { } } - checkAll("OptionT[List, Int]", MonadRecTests[OptionT[List, ?]].monadRec[Int, Int, Int]) - checkAll("MonadRec[OptionT[List, ?]]", SerializableTests.serializable(MonadRec[OptionT[List, ?]])) - - { - implicit val F = ListWrapper.functor - checkAll("Functor[OptionT[ListWrapper, ?]]", FunctorTests[OptionT[ListWrapper, ?]].functor[Int, Int, Int]) - } } From 1e1b3236f015fd6c7920cb6851cdb4443838ce33 Mon Sep 17 00:00:00 2001 From: yilinwei Date: Sat, 11 Jun 2016 14:13:23 +0100 Subject: [PATCH 12/36] Address comments. --- core/src/main/scala/cats/data/Xor.scala | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/core/src/main/scala/cats/data/Xor.scala b/core/src/main/scala/cats/data/Xor.scala index 3b18b35e8b..fce66f538e 100644 --- a/core/src/main/scala/cats/data/Xor.scala +++ b/core/src/main/scala/cats/data/Xor.scala @@ -180,9 +180,7 @@ sealed abstract class Xor[+A, +B] extends Product with Serializable { b => s"Xor.Right(${BB.show(b)})" ) - def ap[AA >: A, BB >: B, C](that: AA Xor (BB => C)): AA Xor C = that.flatMap( - f => this.map(a => f(a)) - ) + def ap[AA >: A, BB >: B, C](that: AA Xor (BB => C)): AA Xor C = that.flatMap(this.map) } object Xor extends XorInstances with XorFunctions { From 41ad7afd3b94eef0492939379a7d5fc8ffdcaa82 Mon Sep 17 00:00:00 2001 From: yilinwei Date: Sat, 11 Jun 2016 14:32:20 +0100 Subject: [PATCH 13/36] Remove useless function --- core/src/main/scala/cats/data/XorT.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/main/scala/cats/data/XorT.scala b/core/src/main/scala/cats/data/XorT.scala index 8241f46c46..f0c9b31ecd 100644 --- a/core/src/main/scala/cats/data/XorT.scala +++ b/core/src/main/scala/cats/data/XorT.scala @@ -334,7 +334,6 @@ private[data] trait XorTMonad[F[_], L] extends Monad[XorT[F, L, ?]] with XorTFun implicit val F: Monad[F] def pure[A](a: A): XorT[F, L, A] = XorT(F.pure(Xor.right(a))) def flatMap[A, B](fa: XorT[F, L, A])(f: A => XorT[F, L, B]): XorT[F, L, B] = fa flatMap f - override def ap[A, B](x: XorT[F, L, A => B])(y: XorT[F, L, A]): XorT[F, L, B] = super.ap(x)(y) } private[data] trait XorTMonadError[F[_], L] extends MonadError[XorT[F, L, ?], L] with XorTMonad[F, L] { From dd61f014a1c482cbd8c68a46cc6e8158dc3ab1b6 Mon Sep 17 00:00:00 2001 From: Cody Allen Date: Sat, 11 Jun 2016 10:06:38 -0400 Subject: [PATCH 14/36] Use uber import in OptionT doc This (strangely?) required adding an explicit type parameter. Follow up to https://github.com/typelevel/cats/pull/1104#issuecomment-224989444 --- docs/src/main/tut/optiont.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/docs/src/main/tut/optiont.md b/docs/src/main/tut/optiont.md index 9125b0fcbf..7df4e5d6b3 100644 --- a/docs/src/main/tut/optiont.md +++ b/docs/src/main/tut/optiont.md @@ -38,7 +38,7 @@ As you can see, the implementations of all of these variations are very similar. ```tut:silent import cats.data.OptionT -import cats.std.future._ +import cats.implicits._ val customGreetingT: OptionT[Future, String] = OptionT(customGreeting) @@ -65,7 +65,7 @@ val lastnameO: Option[String] = Some("Doe") val ot: OptionT[Future, String] = for { g <- OptionT(greetingFO) f <- OptionT.liftF(firstnameF) - l <- OptionT.fromOption(lastnameO) + l <- OptionT.fromOption[Future](lastnameO) } yield s"$g $f $l" val result: Future[Option[String]] = ot.value // Future(Some("Hello Jane Doe")) @@ -77,9 +77,6 @@ val result: Future[Option[String]] = ot.value // Future(Some("Hello Jane Doe")) If you have only an `A` and you wish to *lift* it into an `OptionT[F,A]` assuming you have an [`Applicative`]({{ site.baseurl }}/tut/applicative.html) instance for `F` you can use `some` which is an alias for `pure`. There also exists a `none` method which can be used to create an `OptionT[F,A]`, where the `Option` wrapped `A` type is actually a `None`: ```tut:silent - -import cats.std.future._ - val greet: OptionT[Future,String] = OptionT.pure("Hola!") val greetAlt: OptionT[Future,String] = OptionT.some("Hi!") From 4535d939a3ccf2f2e6f13b6c90c5c896ce86b241 Mon Sep 17 00:00:00 2001 From: Cody Allen Date: Sat, 11 Jun 2016 18:13:18 -0400 Subject: [PATCH 15/36] switch markdown rendering to kramdown --- docs/src/site/_config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/site/_config.yml b/docs/src/site/_config.yml index 26c3f77031..eca1a982e3 100644 --- a/docs/src/site/_config.yml +++ b/docs/src/site/_config.yml @@ -1,5 +1,5 @@ name: Cats Documentation -markdown: redcarpet +markdown: kramdown highlighter: rouge baseurl: /cats apidocs: /cats/api/ From e28204d46b719697d11e532fb9c4b982ac9053ec Mon Sep 17 00:00:00 2001 From: Andrea Fiore Date: Sun, 12 Jun 2016 18:25:08 +0100 Subject: [PATCH 16/36] Fix contramap signature in Contravariant doc page --- docs/src/main/tut/contravariant.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/main/tut/contravariant.md b/docs/src/main/tut/contravariant.md index 8762f2d800..7bbb629a83 100644 --- a/docs/src/main/tut/contravariant.md +++ b/docs/src/main/tut/contravariant.md @@ -11,7 +11,7 @@ The `Contravariant` type class is for functors that define a `contramap` function with the following type: ```scala -def contramap[A, B](f: B => A): F[A] => F[B] +def contramap[A, B](fa: F[A])(f: B => A): F[B] ``` It looks like regular (also called `Covariant`) [`Functor`](functor.html)'s `map`, From 15a0c4d8257aa0ca0fc28b05068a8ab79804b57d Mon Sep 17 00:00:00 2001 From: Andrea Fiore Date: Sat, 11 Jun 2016 14:25:47 +0100 Subject: [PATCH 17/36] Add size to Foldable Override with a more performant implementation in Map, Set, Vector and AndOne using the size method provided by the standard library. see #1091 --- core/src/main/scala/cats/Foldable.scala | 11 +++++++++++ core/src/main/scala/cats/data/OneAnd.scala | 2 ++ core/src/main/scala/cats/std/map.scala | 2 ++ core/src/main/scala/cats/std/set.scala | 2 ++ core/src/main/scala/cats/std/vector.scala | 2 ++ tests/src/test/scala/cats/tests/FoldableTests.scala | 10 ++++++++++ tests/src/test/scala/cats/tests/OneAndTests.scala | 6 ++++++ 7 files changed, 35 insertions(+) diff --git a/core/src/main/scala/cats/Foldable.scala b/core/src/main/scala/cats/Foldable.scala index 54303abdd3..e89c2a468e 100644 --- a/core/src/main/scala/cats/Foldable.scala +++ b/core/src/main/scala/cats/Foldable.scala @@ -1,6 +1,7 @@ package cats import scala.collection.mutable +import cats.std.long._ import simulacrum.typeclass /** @@ -56,6 +57,16 @@ import simulacrum.typeclass } } + /** + * The size of this Foldable. + * + * This is overriden in structures that have more efficient size implementations + * (e.g. Vector, Set, Map). + * + * Note: will not terminate for infinite-sized collections. + */ + def size[A](fa: F[A]): Long = foldMap(fa)(_ => 1) + /** * Fold implemented using the given Monoid[A] instance. */ diff --git a/core/src/main/scala/cats/data/OneAnd.scala b/core/src/main/scala/cats/data/OneAnd.scala index 1541ceeaff..7dc75ac9cf 100644 --- a/core/src/main/scala/cats/data/OneAnd.scala +++ b/core/src/main/scala/cats/data/OneAnd.scala @@ -116,6 +116,8 @@ private[data] sealed trait OneAndInstances extends OneAndLowPriority2 { implicit def catsDataReducibleForOneAnd[F[_]](implicit F: Foldable[F]): Reducible[OneAnd[F, ?]] = new NonEmptyReducible[OneAnd[F,?], F] { override def split[A](fa: OneAnd[F,A]): (A, F[A]) = (fa.head, fa.tail) + + override def size[A](fa: OneAnd[F, A]): Long = 1 + F.size(fa.tail) } implicit def catsDataMonadForOneAnd[F[_]](implicit monad: MonadCombine[F]): Monad[OneAnd[F, ?]] = diff --git a/core/src/main/scala/cats/std/map.scala b/core/src/main/scala/cats/std/map.scala index 9ee18cb689..9e9a1fd965 100644 --- a/core/src/main/scala/cats/std/map.scala +++ b/core/src/main/scala/cats/std/map.scala @@ -45,6 +45,8 @@ trait MapInstances extends cats.kernel.std.MapInstances { def foldRight[A, B](fa: Map[K, A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = Foldable.iterateRight(fa.values.iterator, lb)(f) + override def size[A](fa: Map[K, A]): Long = fa.size.toLong + override def isEmpty[A](fa: Map[K, A]): Boolean = fa.isEmpty } } diff --git a/core/src/main/scala/cats/std/set.scala b/core/src/main/scala/cats/std/set.scala index 09da1a88de..0c95763dec 100644 --- a/core/src/main/scala/cats/std/set.scala +++ b/core/src/main/scala/cats/std/set.scala @@ -18,6 +18,8 @@ trait SetInstances extends cats.kernel.std.SetInstances { def foldRight[A, B](fa: Set[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = Foldable.iterateRight(fa.iterator, lb)(f) + override def size[A](fa: Set[A]): Long = fa.size.toLong + override def exists[A](fa: Set[A])(p: A => Boolean): Boolean = fa.exists(p) diff --git a/core/src/main/scala/cats/std/vector.scala b/core/src/main/scala/cats/std/vector.scala index 62ead466a3..07fb55430f 100644 --- a/core/src/main/scala/cats/std/vector.scala +++ b/core/src/main/scala/cats/std/vector.scala @@ -44,6 +44,8 @@ trait VectorInstances extends cats.kernel.std.VectorInstances { Eval.defer(loop(0)) } + override def size[A](fa: Vector[A]): Long = fa.size.toLong + def traverse[G[_], A, B](fa: Vector[A])(f: A => G[B])(implicit G: Applicative[G]): G[Vector[B]] = foldRight[A, G[Vector[B]]](fa, Always(G.pure(Vector.empty))){ (a, lgvb) => G.map2Eval(f(a), lgvb)(_ +: _) diff --git a/tests/src/test/scala/cats/tests/FoldableTests.scala b/tests/src/test/scala/cats/tests/FoldableTests.scala index 512edaf9e3..f0f4b99aca 100644 --- a/tests/src/test/scala/cats/tests/FoldableTests.scala +++ b/tests/src/test/scala/cats/tests/FoldableTests.scala @@ -10,6 +10,12 @@ abstract class FoldableCheck[F[_]: Foldable](name: String)(implicit ArbFInt: Arb def iterator[T](fa: F[T]): Iterator[T] + test("size") { + forAll { (fa: F[Int]) => + fa.size should === (iterator(fa).size.toLong) + } + } + test("summation") { forAll { (fa: F[Int]) => val total = iterator(fa).sum @@ -123,6 +129,10 @@ class FoldableVectorCheck extends FoldableCheck[Vector]("vector") { def iterator[T](vector: Vector[T]): Iterator[T] = vector.iterator } +class FoldableSetCheck extends FoldableCheck[Set]("set") { + def iterator[T](set: Set[T]): Iterator[T] = set.iterator +} + class FoldableStreamCheck extends FoldableCheck[Stream]("stream") { def iterator[T](stream: Stream[T]): Iterator[T] = stream.iterator } diff --git a/tests/src/test/scala/cats/tests/OneAndTests.scala b/tests/src/test/scala/cats/tests/OneAndTests.scala index 569535205f..7ddb55ef19 100644 --- a/tests/src/test/scala/cats/tests/OneAndTests.scala +++ b/tests/src/test/scala/cats/tests/OneAndTests.scala @@ -64,6 +64,12 @@ class OneAndTests extends CatsSuite { checkAll("NonEmptyList[Int]", ComonadTests[NonEmptyList].comonad[Int, Int, Int]) checkAll("Comonad[NonEmptyList[A]]", SerializableTests.serializable(Comonad[NonEmptyList])) + test("size is consistent with toList.size") { + forAll { (oa: OneAnd[Vector, Int]) => + oa.size should === (oa.toList.size.toLong) + } + } + test("Show is not empty and is formatted as expected") { forAll { (nel: NonEmptyList[Int]) => nel.show.nonEmpty should === (true) From c3cae9ee0309e1e9178d0513a858cb384f60d5ac Mon Sep 17 00:00:00 2001 From: peterneyens Date: Mon, 13 Jun 2016 23:52:49 +0200 Subject: [PATCH 18/36] Remove unlawful MonadFilter and MonadCombine instances of OptionT. Clean up the test of Monoid and Semigroup. --- core/src/main/scala/cats/data/OptionT.scala | 46 ++++++------------- .../test/scala/cats/tests/OptionTTests.scala | 18 ++------ 2 files changed, 18 insertions(+), 46 deletions(-) diff --git a/core/src/main/scala/cats/data/OptionT.scala b/core/src/main/scala/cats/data/OptionT.scala index 8ba27d6690..7ca0418980 100644 --- a/core/src/main/scala/cats/data/OptionT.scala +++ b/core/src/main/scala/cats/data/OptionT.scala @@ -163,14 +163,18 @@ private[data] sealed trait OptionTInstances extends OptionTInstances0 { } private[data] sealed trait OptionTInstances0 extends OptionTInstances1 { - /* TODO violates right absorbtion, right distributivity, and left distributivity -- re-enable when MonadCombine laws are split in to weak/strong - implicit def catsDataMonadCombineForOptionT[F[_]](implicit F0: Monad[F]): MonadCombine[OptionT[F, ?]] = - new OptionTMonadCombine[F] { implicit val F = F0 } - */ + implicit def catsDataMonadForOptionT[F[_]](implicit F0: Monad[F]): Monad[OptionT[F, ?]] = + new OptionTMonad[F] { implicit val F = F0 } + + implicit def catsDataMonadErrorForOptionT[F[_], E](implicit F0: MonadError[F, E]): MonadError[OptionT[F, ?], E] = + new OptionTMonadError[F, E] { implicit val F = F0 } implicit def catsDataTraverseForOptionT[F[_]](implicit F0: Traverse[F]): Traverse[OptionT[F, ?]] = new OptionTTraverse[F] { implicit val F = F0 } + implicit def catsDataSemigroupK[F[_]](implicit F0: Monad[F]): SemigroupK[OptionT[F, ?]] = + new OptionTSemigroupK[F] { implicit val F = F0 } + implicit def catsDataMonoidForOptionT[F[_], A](implicit F0: Monoid[F[Option[A]]]): Monoid[OptionT[F, A]] = new OptionTMonoid[F, A] { implicit val F = F0 } @@ -178,11 +182,9 @@ private[data] sealed trait OptionTInstances0 extends OptionTInstances1 { new OptionTPartialOrder[F, A] { implicit val F = F0 } } -private[data] sealed trait OptionTInstances1 extends OptionTInstances2 { - /* TODO violates monadFilter right empty law -- re-enable when MonadFilter laws are split in to weak/strong - implicit def catsDataMonadFilterForOptionT[F[_]](implicit F0: Monad[F]): MonadFilter[OptionT[F, ?]] = - new OptionTMonadFilter[F] { implicit val F = F0 } - */ +private[data] sealed trait OptionTInstances1 { + implicit def catsDataFunctorForOptionT[F[_]](implicit F0: Functor[F]): Functor[OptionT[F, ?]] = + new OptionTFunctor[F] { implicit val F = F0 } // do NOT change this to val! I know it looks like it should work, and really I agree, but it doesn't (for... reasons) implicit def catsDataTransLiftForOptionT: TransLift.Aux[OptionT, Functor] = @@ -192,27 +194,11 @@ private[data] sealed trait OptionTInstances1 extends OptionTInstances2 { def liftT[M[_]: Functor, A](ma: M[A]): OptionT[M, A] = OptionT.liftF(ma) } - implicit def catsDataSemigroupK[F[_]](implicit F0: Monad[F]): SemigroupK[OptionT[F, ?]] = - new OptionTSemigroupK[F] { implicit val F = F0 } - - implicit def catsDataEqForOptionT[F[_], A](implicit F0: Eq[F[Option[A]]]): Eq[OptionT[F, A]] = - new OptionTEq[F, A] { implicit val F = F0 } -} - -private[data] sealed trait OptionTInstances2 extends OptionTInstances3 { - implicit def catsDataMonadForOptionT[F[_]](implicit F0: Monad[F]): Monad[OptionT[F, ?]] = - new OptionTMonad[F] { implicit val F = F0 } - - implicit def catsDataMonadErrorForOptionT[F[_], E](implicit F0: MonadError[F, E]): MonadError[OptionT[F, ?], E] = - new OptionTMonadError[F, E] { implicit val F = F0 } - implicit def catsDataMonoidKForOptionT[F[_]](implicit F0: Monad[F]): MonoidK[OptionT[F, ?]] = new OptionTMonoidK[F] { implicit val F = F0 } -} -private[data] sealed trait OptionTInstances3 { - implicit def catsDataFunctorForOptionT[F[_]](implicit F0: Functor[F]): Functor[OptionT[F, ?]] = - new OptionTFunctor[F] { implicit val F = F0 } + implicit def catsDataEqForOptionT[F[_], A](implicit F0: Eq[F[Option[A]]]): Eq[OptionT[F, A]] = + new OptionTEq[F, A] { implicit val F = F0 } } private[data] trait OptionTFunctor[F[_]] extends Functor[OptionT[F, ?]] { @@ -231,12 +217,6 @@ private[data] trait OptionTMonad[F[_]] extends Monad[OptionT[F, ?]] { override def map[A, B](fa: OptionT[F, A])(f: A => B): OptionT[F, B] = fa.map(f) } -private[data] trait OptionTMonadFilter[F[_]] extends MonadFilter[OptionT[F, ?]] with OptionTMonad[F] { - def empty[A]: OptionT[F, A] = OptionT.none[F, A] -} - -private[data] trait OptionTMonadCombine[F[_]] extends MonadCombine[OptionT[F, ?]] with OptionTMonad[F] with OptionTMonoidK[F] - private[data] trait OptionTMonadRec[F[_]] extends MonadRec[OptionT[F, ?]] with OptionTMonad[F] { implicit def F: MonadRec[F] diff --git a/tests/src/test/scala/cats/tests/OptionTTests.scala b/tests/src/test/scala/cats/tests/OptionTTests.scala index e409b6a025..c59c7aef0f 100644 --- a/tests/src/test/scala/cats/tests/OptionTTests.scala +++ b/tests/src/test/scala/cats/tests/OptionTTests.scala @@ -2,7 +2,7 @@ package cats package tests import cats.data.{OptionT, Xor, XorT} -import cats.kernel.laws.OrderLaws +import cats.kernel.laws.{GroupLaws, OrderLaws} import cats.laws.discipline._ import cats.laws.discipline.arbitrary._ @@ -52,12 +52,6 @@ class OptionTTests extends CatsSuite { checkAll("OptionT[ListWrapper, Int]", MonadTests[OptionT[ListWrapper, ?]].monad[Int, Int, Int]) checkAll("Monad[OptionT[ListWrapper, ?]]", SerializableTests.serializable(Monad[OptionT[ListWrapper, ?]])) - // checkAll("OptionT[ListWrapper, Int]", MonadFilterTests[OptionT[ListWrapper, ?]].monadFilter[Int, Int, Int]) - // checkAll("MonadFilter[WriterT[ListWrapper, ListWrapper[Int], ?]]", SerializableTests.serializable(MonadFilter[OptionT[ListWrapper, ?]])) - - // checkAll("OptionT[ListWrapper, Int]", MonadCombineTests[OptionT[ListWrapper, ?]].monadCombine[Int, Int, Int]) - // checkAll("MonadCombine[OptionT[ListWrapper, ?]]", SerializableTests.serializable(MonadCombine[OptionT[ListWrapper, ?]])) - checkAll("OptionT[ListWrapper, Int]", SemigroupKTests[OptionT[ListWrapper, ?]].semigroupK[Int]) checkAll("SemigroupK[OptionT[ListWrapper, ?]]", SerializableTests.serializable(SemigroupK[OptionT[ListWrapper, ?]])) @@ -65,7 +59,6 @@ class OptionTTests extends CatsSuite { checkAll("MonoidK[OptionT[ListWrapper, ?]]", SerializableTests.serializable(MonoidK[OptionT[ListWrapper, ?]])) FlatMap[OptionT[ListWrapper, ?]] - // Alternative[OptionT[ListWrapper, ?]] Applicative[OptionT[ListWrapper, ?]] Apply[OptionT[ListWrapper, ?]] Functor[OptionT[ListWrapper, ?]] @@ -140,9 +133,9 @@ class OptionTTests extends CatsSuite { // F[Option[A]] has a monoid implicit val FA: Monoid[ListWrapper[Option[Int]]] = ListWrapper.monoid[Option[Int]] - checkAll("OptionT[ListWrapper, Int]", kernel.laws.GroupLaws[OptionT[ListWrapper, Int]].monoid) + checkAll("OptionT[ListWrapper, Int]", GroupLaws[OptionT[ListWrapper, Int]].monoid) + checkAll("Monoid[OptionT[ListWrapper, Int]]", SerializableTests.serializable(Monoid[OptionT[ListWrapper, Int]])) - Monoid[OptionT[ListWrapper, Int]] Semigroup[OptionT[ListWrapper, Int]] } @@ -150,9 +143,8 @@ class OptionTTests extends CatsSuite { // F[Option[A]] has a semigroup implicit val FA: Semigroup[ListWrapper[Option[Int]]] = ListWrapper.semigroup[Option[Int]] - checkAll("OptionT[ListWrapper, Int]", kernel.laws.GroupLaws[OptionT[ListWrapper, Int]].semigroup) - - Semigroup[OptionT[ListWrapper, Int]] + checkAll("OptionT[ListWrapper, Int]", GroupLaws[OptionT[ListWrapper, Int]].semigroup) + checkAll("Semigroup[OptionT[ListWrapper, Int]]", SerializableTests.serializable(Semigroup[OptionT[ListWrapper, Int]])) } test("fold and cata consistent") { From 2183b75c376c4f349e3dc3736d00f57e554c51d5 Mon Sep 17 00:00:00 2001 From: peterneyens Date: Tue, 14 Jun 2016 10:45:07 +0200 Subject: [PATCH 19/36] Fix some implicit resolution issues in OptionT. Add a "test" to check the implicit resolution of OptionT instances. --- core/src/main/scala/cats/data/OptionT.scala | 24 ++++++++------ .../test/scala/cats/tests/OptionTTests.scala | 32 +++++++++++++++++++ 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/core/src/main/scala/cats/data/OptionT.scala b/core/src/main/scala/cats/data/OptionT.scala index 7ca0418980..565b525764 100644 --- a/core/src/main/scala/cats/data/OptionT.scala +++ b/core/src/main/scala/cats/data/OptionT.scala @@ -163,16 +163,10 @@ private[data] sealed trait OptionTInstances extends OptionTInstances0 { } private[data] sealed trait OptionTInstances0 extends OptionTInstances1 { - implicit def catsDataMonadForOptionT[F[_]](implicit F0: Monad[F]): Monad[OptionT[F, ?]] = - new OptionTMonad[F] { implicit val F = F0 } - implicit def catsDataMonadErrorForOptionT[F[_], E](implicit F0: MonadError[F, E]): MonadError[OptionT[F, ?], E] = new OptionTMonadError[F, E] { implicit val F = F0 } - implicit def catsDataTraverseForOptionT[F[_]](implicit F0: Traverse[F]): Traverse[OptionT[F, ?]] = - new OptionTTraverse[F] { implicit val F = F0 } - - implicit def catsDataSemigroupK[F[_]](implicit F0: Monad[F]): SemigroupK[OptionT[F, ?]] = + implicit def catsDataSemigroupKForOptionT[F[_]](implicit F0: Monad[F]): SemigroupK[OptionT[F, ?]] = new OptionTSemigroupK[F] { implicit val F = F0 } implicit def catsDataMonoidForOptionT[F[_], A](implicit F0: Monoid[F[Option[A]]]): Monoid[OptionT[F, A]] = @@ -182,9 +176,9 @@ private[data] sealed trait OptionTInstances0 extends OptionTInstances1 { new OptionTPartialOrder[F, A] { implicit val F = F0 } } -private[data] sealed trait OptionTInstances1 { - implicit def catsDataFunctorForOptionT[F[_]](implicit F0: Functor[F]): Functor[OptionT[F, ?]] = - new OptionTFunctor[F] { implicit val F = F0 } +private[data] sealed trait OptionTInstances1 extends OptionTInstances2 { + implicit def catsDataMonadForOptionT[F[_]](implicit F0: Monad[F]): Monad[OptionT[F, ?]] = + new OptionTMonad[F] { implicit val F = F0 } // do NOT change this to val! I know it looks like it should work, and really I agree, but it doesn't (for... reasons) implicit def catsDataTransLiftForOptionT: TransLift.Aux[OptionT, Functor] = @@ -201,6 +195,16 @@ private[data] sealed trait OptionTInstances1 { new OptionTEq[F, A] { implicit val F = F0 } } +private[data] sealed trait OptionTInstances2 extends OptionTInstances3 { + implicit def catsDataTraverseForOptionT[F[_]](implicit F0: Traverse[F]): Traverse[OptionT[F, ?]] = + new OptionTTraverse[F] { implicit val F = F0 } +} + +private[data] sealed trait OptionTInstances3 { + implicit def catsDataFunctorForOptionT[F[_]](implicit F0: Functor[F]): Functor[OptionT[F, ?]] = + new OptionTFunctor[F] { implicit val F = F0 } +} + private[data] trait OptionTFunctor[F[_]] extends Functor[OptionT[F, ?]] { implicit def F: Functor[F] diff --git a/tests/src/test/scala/cats/tests/OptionTTests.scala b/tests/src/test/scala/cats/tests/OptionTTests.scala index c59c7aef0f..aa42778bad 100644 --- a/tests/src/test/scala/cats/tests/OptionTTests.scala +++ b/tests/src/test/scala/cats/tests/OptionTTests.scala @@ -295,4 +295,36 @@ class OptionTTests extends CatsSuite { } } + + /** + * Testing that implicit resolution works. If it compiles, the "test" passes. + */ + object ImplicitResolution{ + Eq[OptionT[List, Int]] + PartialOrder[OptionT[List, Int]] + Order[OptionT[List, Int]] + + Semigroup[OptionT[List, Int]] + Monoid[OptionT[List, Int]] + + SemigroupK[OptionT[List, ?]] + MonoidK[OptionT[List, ?]] + + Functor[OptionT[List, ?]] + Monad[OptionT[List, ?]] + MonadRec[OptionT[List, ?]] + + import scala.util.Try + Functor[OptionT[Try, ?]] + Monad[OptionT[Try, ?]] + MonadError[OptionT[Try, ?], Throwable] + + Foldable[OptionT[List, ?]] + Traverse[OptionT[List, ?]] + + implicit val T = ListWrapper.traverse + implicit val M = ListWrapper.monad + Functor[OptionT[ListWrapper, ?]] + } + } From 65433840283da5513a6d3ea5cce082596d9246c9 Mon Sep 17 00:00:00 2001 From: Cody Allen Date: Tue, 14 Jun 2016 08:47:38 -0400 Subject: [PATCH 20/36] Yet some more uniquifying of implicit names I think this is the last of the implicit names for #1061. --- core/src/main/scala/cats/Eval.scala | 14 +++--- core/src/main/scala/cats/NotNull.scala | 4 +- core/src/main/scala/cats/Show.scala | 2 +- core/src/main/scala/cats/Trivial.scala | 2 +- core/src/main/scala/cats/Unapply.scala | 20 ++++---- core/src/main/scala/cats/data/Func.scala | 2 +- core/src/main/scala/cats/data/IdT.scala | 14 +++--- core/src/main/scala/cats/data/Nested.scala | 32 ++++++------- core/src/main/scala/cats/data/OneAnd.scala | 2 +- core/src/main/scala/cats/data/Validated.scala | 6 +-- core/src/main/scala/cats/data/XorT.scala | 2 +- .../main/scala/cats/functor/Invariant.scala | 4 +- core/src/main/scala/cats/package.scala | 2 +- free/src/main/scala/cats/free/Coyoneda.scala | 2 +- free/src/main/scala/cats/free/Free.scala | 4 +- free/src/main/scala/cats/free/Inject.scala | 6 +-- free/src/main/scala/cats/free/Yoneda.scala | 2 +- free/src/test/scala/cats/free/FreeTests.scala | 2 +- .../main/scala/cats/kernel/laws/package.scala | 7 --- kernel/src/main/scala/cats/kernel/Eq.scala | 2 +- kernel/src/main/scala/cats/kernel/Order.scala | 2 +- .../main/scala/cats/kernel/PartialOrder.scala | 2 +- .../cats/laws/discipline/Arbitrary.scala | 46 +++++++++---------- .../main/scala/cats/laws/discipline/Eq.scala | 18 +++----- .../scala/cats/laws/discipline/package.scala | 2 +- .../test/scala/cats/tests/CategoryTests.scala | 2 +- .../scala/cats/tests/CokleisliTests.scala | 8 ++-- .../test/scala/cats/tests/ComposeTest.scala | 2 +- .../test/scala/cats/tests/ConstTests.scala | 2 +- .../scala/cats/tests/MonadCombineTests.scala | 2 +- .../test/scala/cats/tests/NestedTests.scala | 18 ++++---- 31 files changed, 112 insertions(+), 123 deletions(-) diff --git a/core/src/main/scala/cats/Eval.scala b/core/src/main/scala/cats/Eval.scala index a56e6215bf..a3833fa0aa 100644 --- a/core/src/main/scala/cats/Eval.scala +++ b/core/src/main/scala/cats/Eval.scala @@ -295,7 +295,7 @@ object Eval extends EvalInstances { private[cats] trait EvalInstances extends EvalInstances0 { - implicit val evalBimonad: Bimonad[Eval] with MonadRec[Eval] = + implicit val catsBimonadForEval: Bimonad[Eval] with MonadRec[Eval] = new Bimonad[Eval] with MonadRec[Eval] { override def map[A, B](fa: Eval[A])(f: A => B): Eval[B] = fa.map(f) def pure[A](a: A): Eval[A] = Now(a) @@ -310,35 +310,35 @@ private[cats] trait EvalInstances extends EvalInstances0 { }) } - implicit def evalOrder[A: Order]: Order[Eval[A]] = + implicit def catsOrderForEval[A: Order]: Order[Eval[A]] = new Order[Eval[A]] { def compare(lx: Eval[A], ly: Eval[A]): Int = lx.value compare ly.value } - implicit def evalGroup[A: Group]: Group[Eval[A]] = + implicit def catsGroupForEval[A: Group]: Group[Eval[A]] = new EvalGroup[A] { val algebra: Group[A] = Group[A] } } private[cats] trait EvalInstances0 extends EvalInstances1 { - implicit def evalPartialOrder[A: PartialOrder]: PartialOrder[Eval[A]] = + implicit def catsPartialOrderForEval[A: PartialOrder]: PartialOrder[Eval[A]] = new PartialOrder[Eval[A]] { def partialCompare(lx: Eval[A], ly: Eval[A]): Double = lx.value partialCompare ly.value } - implicit def evalMonoid[A: Monoid]: Monoid[Eval[A]] = + implicit def catsMonoidForEval[A: Monoid]: Monoid[Eval[A]] = new EvalMonoid[A] { val algebra = Monoid[A] } } private[cats] trait EvalInstances1 { - implicit def evalEq[A: Eq]: Eq[Eval[A]] = + implicit def catsEqForEval[A: Eq]: Eq[Eval[A]] = new Eq[Eval[A]] { def eqv(lx: Eval[A], ly: Eval[A]): Boolean = lx.value === ly.value } - implicit def evalSemigroup[A: Semigroup]: Semigroup[Eval[A]] = + implicit def catsSemigroupForEval[A: Semigroup]: Semigroup[Eval[A]] = new EvalSemigroup[A] { val algebra = Semigroup[A] } } diff --git a/core/src/main/scala/cats/NotNull.scala b/core/src/main/scala/cats/NotNull.scala index fba9975b59..5cf16b5e02 100644 --- a/core/src/main/scala/cats/NotNull.scala +++ b/core/src/main/scala/cats/NotNull.scala @@ -20,7 +20,7 @@ object NotNull { implicit def `If you are seeing this, you probably need to add an explicit type parameter somewhere, because Null is being inferred.`: NotNull[Null] = throw ambiguousException - implicit def ambiguousNull2: NotNull[Null] = throw ambiguousException + implicit def catsAmbiguousNotNullNull2: NotNull[Null] = throw ambiguousException - implicit def notNull[A]: NotNull[A] = singleton.asInstanceOf[NotNull[A]] + implicit def catsNotNullForA[A]: NotNull[A] = singleton.asInstanceOf[NotNull[A]] } diff --git a/core/src/main/scala/cats/Show.scala b/core/src/main/scala/cats/Show.scala index 214ad82ceb..e09b9c85fb 100644 --- a/core/src/main/scala/cats/Show.scala +++ b/core/src/main/scala/cats/Show.scala @@ -25,7 +25,7 @@ object Show { def show(a: A): String = a.toString } - implicit val showContravariant: Contravariant[Show] = new Contravariant[Show] { + implicit val catsContravariantForShow: Contravariant[Show] = new Contravariant[Show] { def contramap[A, B](fa: Show[A])(f: B => A): Show[B] = show[B](fa.show _ compose f) } diff --git a/core/src/main/scala/cats/Trivial.scala b/core/src/main/scala/cats/Trivial.scala index 1ad335d8a5..1f8ed629c9 100644 --- a/core/src/main/scala/cats/Trivial.scala +++ b/core/src/main/scala/cats/Trivial.scala @@ -19,5 +19,5 @@ object Trivial { type P3[A, B, C] = Trivial type P3H1[F[_], A, B, C] = Trivial - implicit val manifest: Trivial = new Trivial {} + implicit val catsTrivialInstance: Trivial = new Trivial {} } diff --git a/core/src/main/scala/cats/Unapply.scala b/core/src/main/scala/cats/Unapply.scala index 9949c73cdd..c47b34213e 100644 --- a/core/src/main/scala/cats/Unapply.scala +++ b/core/src/main/scala/cats/Unapply.scala @@ -39,7 +39,7 @@ object Unapply extends Unapply2Instances { type A = AA } - implicit def unapply1[TC[_[_]], F[_], AA](implicit tc: TC[F]) + implicit def catsUnapply1[TC[_[_]], F[_], AA](implicit tc: TC[F]) : Aux1[TC,F[AA],F,AA] = new Unapply[TC,F[AA]] { type M[X] = F[X] @@ -80,14 +80,14 @@ private[cats] sealed abstract class Unapply2Instances extends Unapply3Instances } - implicit def unapply2left[TC[_[_]], F[_,_], AA, B](implicit tc: TC[F[?,B]]): Aux2Left[TC,F[AA,B], F, AA, B] = new Unapply[TC, F[AA,B]] { + implicit def catsUnapply2left[TC[_[_]], F[_,_], AA, B](implicit tc: TC[F[?,B]]): Aux2Left[TC,F[AA,B], F, AA, B] = new Unapply[TC, F[AA,B]] { type M[X] = F[X, B] type A = AA def TC: TC[F[?, B]] = tc def subst: F[AA, B] => M[A] = identity } - implicit def unapply2right[TC[_[_]], F[_,_], AA, B](implicit tc: TC[F[AA,?]]): Aux2Right[TC,F[AA,B], F, AA, B] = new Unapply[TC, F[AA,B]] { + implicit def catsUnapply2right[TC[_[_]], F[_,_], AA, B](implicit tc: TC[F[AA,?]]): Aux2Right[TC,F[AA,B], F, AA, B] = new Unapply[TC, F[AA,B]] { type M[X] = F[AA, X] type A = B def TC: TC[F[AA, ?]] = tc @@ -95,14 +95,14 @@ private[cats] sealed abstract class Unapply2Instances extends Unapply3Instances } - implicit def unapply2leftK[TC[_[_]], F[_,_[_]], AA, B[_]](implicit tc: TC[F[?,B]]): Aux2LeftK[TC,F[AA,B], F, AA, B] = new Unapply[TC, F[AA,B]] { + implicit def catsUnapply2leftK[TC[_[_]], F[_,_[_]], AA, B[_]](implicit tc: TC[F[?,B]]): Aux2LeftK[TC,F[AA,B], F, AA, B] = new Unapply[TC, F[AA,B]] { type M[X] = F[X, B] type A = AA def TC: TC[F[?, B]] = tc def subst: F[AA, B] => M[A] = identity } - implicit def unapply2rightK[TC[_[_]], F[_[_],_], AA[_], B](implicit tc: TC[F[AA,?]]): Aux2RightK[TC,F[AA,B], F, AA, B] = new Unapply[TC, F[AA,B]] { + implicit def catsUnapply2rightK[TC[_[_]], F[_[_],_], AA[_], B](implicit tc: TC[F[AA,?]]): Aux2RightK[TC,F[AA,B], F, AA, B] = new Unapply[TC, F[AA,B]] { type M[X] = F[AA, X] type A = B def TC: TC[F[AA, ?]] = tc @@ -114,14 +114,14 @@ private[cats] sealed abstract class Unapply2Instances extends Unapply3Instances // STEW: I'm not sure why these Nothing cases are needed and aren't // just caught by the generic cases, I'd love for someone to figure // that out and report back. - implicit def unapply2leftN[TC[_[_]], F[_,+_], AA](implicit tc: TC[F[?,Nothing]]): Aux2Left[TC,F[AA,Nothing], F, AA, Nothing] = new Unapply[TC, F[AA,Nothing]] { + implicit def catsUnapply2leftN[TC[_[_]], F[_,+_], AA](implicit tc: TC[F[?,Nothing]]): Aux2Left[TC,F[AA,Nothing], F, AA, Nothing] = new Unapply[TC, F[AA,Nothing]] { type M[X] = F[X, Nothing] type A = AA def TC: TC[F[?, Nothing]] = tc def subst: F[AA, Nothing] => M[A] = identity } - implicit def unapply2rightN[TC[_[_]], F[+_,_], B](implicit tc: TC[F[Nothing,?]]): Aux2Right[TC,F[Nothing,B], F, Nothing, B] = new Unapply[TC, F[Nothing,B]] { + implicit def catsUnapply2rightN[TC[_[_]], F[+_,_], B](implicit tc: TC[F[Nothing,?]]): Aux2Right[TC,F[Nothing,B], F, Nothing, B] = new Unapply[TC, F[Nothing,B]] { type M[X] = F[Nothing, X] type A = B def TC: TC[F[Nothing, ?]] = tc @@ -155,14 +155,14 @@ private[cats] sealed abstract class Unapply3Instances { } - implicit def unapply3MTLeft[TC[_[_]], F[_[_],_,_], AA[_], B, C](implicit tc: TC[F[AA,?,C]]): Aux3MTLeft[TC,F[AA, B, C], F, AA, B, C] = new Unapply[TC, F[AA,B,C]] { + implicit def catsUnapply3MTLeft[TC[_[_]], F[_[_],_,_], AA[_], B, C](implicit tc: TC[F[AA,?,C]]): Aux3MTLeft[TC,F[AA, B, C], F, AA, B, C] = new Unapply[TC, F[AA,B,C]] { type M[X] = F[AA, X, C] type A = B def TC: TC[F[AA, ?, C]] = tc def subst: F[AA, B, C] => M[A] = identity } - implicit def unapply3MTright[TC[_[_]], F[_[_],_,_], AA[_], B, C](implicit tc: TC[F[AA,B,?]]): Aux3MTRight[TC,F[AA,B,C], F, AA, B, C] = new Unapply[TC, F[AA,B,C]] { + implicit def catsUnapply3MTright[TC[_[_]], F[_[_],_,_], AA[_], B, C](implicit tc: TC[F[AA,B,?]]): Aux3MTRight[TC,F[AA,B,C], F, AA, B, C] = new Unapply[TC, F[AA,B,C]] { type M[X] = F[AA, B, X] type A = C def TC: TC[F[AA, B, ?]] = tc @@ -174,7 +174,7 @@ private[cats] sealed abstract class Unapply3Instances { type A = C } - implicit def unapply3Nested[TC[_[_]], MA, F[_[_], _[_], _], AA[_], BB[_], C](implicit tc: TC[F[AA, BB, ?]]): Aux3Nested[TC, F[AA, BB, C], F, AA, BB, C] = new Unapply[TC, F[AA, BB, C]] { + implicit def catsUnapply3Nested[TC[_[_]], MA, F[_[_], _[_], _], AA[_], BB[_], C](implicit tc: TC[F[AA, BB, ?]]): Aux3Nested[TC, F[AA, BB, C], F, AA, BB, C] = new Unapply[TC, F[AA, BB, C]] { type M[X] = F[AA, BB, X] type A = C def TC: TC[F[AA, BB, ?]] = tc diff --git a/core/src/main/scala/cats/data/Func.scala b/core/src/main/scala/cats/data/Func.scala index de64c0f941..45b18eeac9 100644 --- a/core/src/main/scala/cats/data/Func.scala +++ b/core/src/main/scala/cats/data/Func.scala @@ -88,7 +88,7 @@ sealed abstract class AppFunc[F[_], A, B] extends Func[F, A, B] { self => } def compose[G[_], C](g: AppFunc[G, C, A]): AppFunc[Nested[G, F, ?], C, B] = { - implicit val gfApplicative: Applicative[Nested[G, F, ?]] = Nested.nestedApplicative[G, F](g.F, F) + implicit val gfApplicative: Applicative[Nested[G, F, ?]] = Nested.catsDataApplicativeForNested[G, F](g.F, F) Func.appFunc[Nested[G, F, ?], C, B]({ c: C => Nested(g.F.map(g.run(c))(self.run)) }) diff --git a/core/src/main/scala/cats/data/IdT.scala b/core/src/main/scala/cats/data/IdT.scala index 97cb261960..47b2da4bc6 100644 --- a/core/src/main/scala/cats/data/IdT.scala +++ b/core/src/main/scala/cats/data/IdT.scala @@ -70,7 +70,7 @@ private[data] sealed trait IdTTraverse[F[_]] extends Traverse[IdT[F, ?]] with Id } private[data] sealed abstract class IdTInstances1 { - implicit def idTFunctor[F[_]](implicit F: Functor[F]): Functor[IdT[F, ?]] = + implicit def catsDataFunctorForIdT[F[_]](implicit F: Functor[F]): Functor[IdT[F, ?]] = new IdTFunctor[F] { implicit val F0: Functor[F] = F } @@ -78,30 +78,30 @@ private[data] sealed abstract class IdTInstances1 { private[data] sealed abstract class IdTInstances0 extends IdTInstances1 { - implicit def idTMonad[F[_]](implicit F: Monad[F]): Monad[IdT[F, ?]] = + implicit def catsDataMonadForIdT[F[_]](implicit F: Monad[F]): Monad[IdT[F, ?]] = new IdTMonad[F] { implicit val F0: Monad[F] = F } - implicit def idTFoldable[F[_]](implicit F: Foldable[F]): Foldable[IdT[F, ?]] = + implicit def catsDataFoldableForIdT[F[_]](implicit F: Foldable[F]): Foldable[IdT[F, ?]] = new IdTFoldable[F] { implicit val F0: Foldable[F] = F } - implicit def idTOrder[F[_], A](implicit F: Order[F[A]]): Order[IdT[F, A]] = + implicit def catsDataOrderForIdT[F[_], A](implicit F: Order[F[A]]): Order[IdT[F, A]] = F.on(_.value) } private[data] sealed abstract class IdTInstances extends IdTInstances0 { - implicit def idTTraverse[F[_]](implicit F: Traverse[F]): Traverse[IdT[F, ?]] = + implicit def catsDataTraverseForIdT[F[_]](implicit F: Traverse[F]): Traverse[IdT[F, ?]] = new IdTTraverse[F] { implicit val F0: Traverse[F] = F } - implicit def idTEq[F[_], A](implicit F: Eq[F[A]]): Eq[IdT[F, A]] = + implicit def catsDataEqForIdT[F[_], A](implicit F: Eq[F[A]]): Eq[IdT[F, A]] = F.on(_.value) - implicit def idTShow[F[_], A](implicit F: Show[F[A]]): Show[IdT[F, A]] = + implicit def catsDataShowForIdT[F[_], A](implicit F: Show[F[A]]): Show[IdT[F, A]] = functor.Contravariant[Show].contramap(F)(_.value) } diff --git a/core/src/main/scala/cats/data/Nested.scala b/core/src/main/scala/cats/data/Nested.scala index 7dbdf00ee8..49be416b04 100644 --- a/core/src/main/scala/cats/data/Nested.scala +++ b/core/src/main/scala/cats/data/Nested.scala @@ -28,10 +28,10 @@ final case class Nested[F[_], G[_], A](value: F[G[A]]) object Nested extends NestedInstances private[data] sealed abstract class NestedInstances extends NestedInstances1 { - implicit def nestedEq[F[_], G[_], A](implicit FGA: Eq[F[G[A]]]): Eq[Nested[F, G, A]] = + implicit def catsDataEqForNested[F[_], G[_], A](implicit FGA: Eq[F[G[A]]]): Eq[Nested[F, G, A]] = FGA.on(_.value) - implicit def nestedTraverse[F[_]: Traverse, G[_]: Traverse]: Traverse[Nested[F, G, ?]] = + implicit def catsDataTraverseForNested[F[_]: Traverse, G[_]: Traverse]: Traverse[Nested[F, G, ?]] = new Traverse[Nested[F, G, ?]] { val instance = Traverse[F].compose[G] @@ -53,7 +53,7 @@ private[data] sealed abstract class NestedInstances extends NestedInstances1 { } private[data] sealed abstract class NestedInstances1 extends NestedInstances2 { - implicit def nestedReducible[F[_]: Reducible, G[_]: Reducible]: Reducible[Nested[F, G, ?]] = + implicit def catsDataReducibleForNested[F[_]: Reducible, G[_]: Reducible]: Reducible[Nested[F, G, ?]] = new Reducible[Nested[F, G, ?]] { val instance = Reducible[F].compose[G] @@ -70,7 +70,7 @@ private[data] sealed abstract class NestedInstances1 extends NestedInstances2 { instance.foldRight(fga.value, lb)(f) } - implicit def nestedContravariant[F[_]: Contravariant, G[_]: Contravariant]: Functor[Nested[F, G, ?]] = + implicit def catsDataContravariantForNested[F[_]: Contravariant, G[_]: Contravariant]: Functor[Nested[F, G, ?]] = new Functor[Nested[F, G, ?]] { val instance = Contravariant[F].compose[G] @@ -81,7 +81,7 @@ private[data] sealed abstract class NestedInstances1 extends NestedInstances2 { } private[data] sealed abstract class NestedInstances2 extends NestedInstances3 { - implicit def nestedFoldable[F[_]: Foldable, G[_]: Foldable]: Foldable[Nested[F, G, ?]] = + implicit def catsDataFoldableForNested[F[_]: Foldable, G[_]: Foldable]: Foldable[Nested[F, G, ?]] = new Foldable[Nested[F, G, ?]] { val instance = Foldable[F].compose[G] @@ -93,7 +93,7 @@ private[data] sealed abstract class NestedInstances2 extends NestedInstances3 { } - implicit def nestedContravariantCovariant[F[_]: Contravariant, G[_]: Functor]: Contravariant[Nested[F, G, ?]] = + implicit def catsDataContravariantForCovariantNested[F[_]: Contravariant, G[_]: Functor]: Contravariant[Nested[F, G, ?]] = new Contravariant[Nested[F, G, ?]] { val instance = Contravariant[F].composeFunctor[G] @@ -103,7 +103,7 @@ private[data] sealed abstract class NestedInstances2 extends NestedInstances3 { } private[data] sealed abstract class NestedInstances3 extends NestedInstances4 { - implicit def nestedAlternative[F[_]: Alternative, G[_]: Applicative]: Alternative[Nested[F, G, ?]] = + implicit def catsDataAlternativeForNested[F[_]: Alternative, G[_]: Applicative]: Alternative[Nested[F, G, ?]] = new Alternative[Nested[F, G, ?]] { val instance = Alternative[F].compose[G] @@ -126,7 +126,7 @@ private[data] sealed abstract class NestedInstances3 extends NestedInstances4 { def empty[A]: Nested[F, G, A] = Nested(instance.empty[A]) } - implicit def nestedCovariantContravariant[F[_]: Functor, G[_]: Contravariant]: Contravariant[Nested[F, G, ?]] = + implicit def catsDataContravariantForContravariantNested[F[_]: Functor, G[_]: Contravariant]: Contravariant[Nested[F, G, ?]] = new Contravariant[Nested[F, G, ?]] { val instance = Functor[F].composeContravariant[G] @@ -136,7 +136,7 @@ private[data] sealed abstract class NestedInstances3 extends NestedInstances4 { } private[data] sealed abstract class NestedInstances4 extends NestedInstances5 { - implicit def nestedApplicative[F[_]: Applicative, G[_]: Applicative]: Applicative[Nested[F, G, ?]] = + implicit def catsDataApplicativeForNested[F[_]: Applicative, G[_]: Applicative]: Applicative[Nested[F, G, ?]] = new Applicative[Nested[F, G, ?]] { val instance = Applicative[F].compose[G] @@ -155,7 +155,7 @@ private[data] sealed abstract class NestedInstances4 extends NestedInstances5 { def pure[A](x: A): Nested[F, G, A] = Nested(instance.pure(x)) } - implicit def nestedMonoidK[F[_]: MonoidK, G[_]]: MonoidK[Nested[F, G, ?]] = + implicit def catsDataMonoidKForNested[F[_]: MonoidK, G[_]]: MonoidK[Nested[F, G, ?]] = new MonoidK[Nested[F, G, ?]] { val instance = MonoidK[F].compose[G] @@ -166,7 +166,7 @@ private[data] sealed abstract class NestedInstances4 extends NestedInstances5 { } private[data] sealed abstract class NestedInstances5 extends NestedInstances6 { - implicit def nestedApply[F[_]: Apply, G[_]: Apply]: Apply[Nested[F, G, ?]] = + implicit def catsDataApplyForNested[F[_]: Apply, G[_]: Apply]: Apply[Nested[F, G, ?]] = new Apply[Nested[F, G, ?]] { val instance = Apply[F].compose[G] @@ -180,7 +180,7 @@ private[data] sealed abstract class NestedInstances5 extends NestedInstances6 { Nested(instance.map(fga.value)(f)) } - implicit def nestedSemigroupK[F[_]: SemigroupK, G[_]]: SemigroupK[Nested[F, G, ?]] = + implicit def catsDataSemigroupKForNested[F[_]: SemigroupK, G[_]]: SemigroupK[Nested[F, G, ?]] = new SemigroupK[Nested[F, G, ?]] { val instance = SemigroupK[F].compose[G] @@ -189,7 +189,7 @@ private[data] sealed abstract class NestedInstances5 extends NestedInstances6 { } private[data] sealed abstract class NestedInstances6 extends NestedInstances7 { - implicit def nestedFunctor[F[_]: Functor, G[_]: Functor]: Functor[Nested[F, G, ?]] = + implicit def catsDataFunctorForNested[F[_]: Functor, G[_]: Functor]: Functor[Nested[F, G, ?]] = new Functor[Nested[F, G, ?]] { val instance = Functor[F].compose[G] @@ -202,7 +202,7 @@ private[data] sealed abstract class NestedInstances6 extends NestedInstances7 { } private[data] sealed abstract class NestedInstances7 extends NestedInstances8 { - implicit def nestedInvariant[F[_]: Invariant, G[_]: Invariant]: Invariant[Nested[F, G, ?]] = + implicit def catsDataInvariantForNested[F[_]: Invariant, G[_]: Invariant]: Invariant[Nested[F, G, ?]] = new Invariant[Nested[F, G, ?]] { val instance = Invariant[F].compose[G] @@ -212,7 +212,7 @@ private[data] sealed abstract class NestedInstances7 extends NestedInstances8 { } private[data] sealed abstract class NestedInstances8 extends NestedInstances9 { - implicit def nestedInvariantCovariant[F[_]: Invariant, G[_]: Functor]: Invariant[Nested[F, G, ?]] = + implicit def catsDataInvariantForCovariantNested[F[_]: Invariant, G[_]: Functor]: Invariant[Nested[F, G, ?]] = new Invariant[Nested[F, G, ?]] { val instance = Invariant[F].composeFunctor[G] @@ -222,7 +222,7 @@ private[data] sealed abstract class NestedInstances8 extends NestedInstances9 { } private[data] sealed abstract class NestedInstances9 { - implicit def nestedInvariantContravariant[F[_]: Invariant, G[_]: Contravariant]: Invariant[Nested[F, G, ?]] = + implicit def catsDataInvariantForNestedContravariant[F[_]: Invariant, G[_]: Contravariant]: Invariant[Nested[F, G, ?]] = new Invariant[Nested[F, G, ?]] { val instance = Invariant[F].composeContravariant[G] diff --git a/core/src/main/scala/cats/data/OneAnd.scala b/core/src/main/scala/cats/data/OneAnd.scala index 1541ceeaff..4c236ae572 100644 --- a/core/src/main/scala/cats/data/OneAnd.scala +++ b/core/src/main/scala/cats/data/OneAnd.scala @@ -138,7 +138,7 @@ private[data] sealed trait OneAndInstances extends OneAndLowPriority2 { } trait OneAndLowPriority0 { - implicit val nelComonad: Comonad[OneAnd[List, ?]] = + implicit val catsDataComonadForOneAnd: Comonad[OneAnd[List, ?]] = new Comonad[OneAnd[List, ?]] { def coflatMap[A, B](fa: OneAnd[List, A])(f: OneAnd[List, A] => B): OneAnd[List, B] = { @tailrec def consume(as: List[A], buf: ListBuffer[B]): List[B] = diff --git a/core/src/main/scala/cats/data/Validated.scala b/core/src/main/scala/cats/data/Validated.scala index 0d52616c4a..d8a1f2c44a 100644 --- a/core/src/main/scala/cats/data/Validated.scala +++ b/core/src/main/scala/cats/data/Validated.scala @@ -312,12 +312,12 @@ private[data] sealed abstract class ValidatedInstances extends ValidatedInstance private[data] sealed abstract class ValidatedInstances1 extends ValidatedInstances2 { - implicit def validatedSemigroup[A, B](implicit A: Semigroup[A], B: Semigroup[B]): Semigroup[Validated[A, B]] = + implicit def catsDataSemigroupForValidated[A, B](implicit A: Semigroup[A], B: Semigroup[B]): Semigroup[Validated[A, B]] = new Semigroup[Validated[A, B]] { def combine(x: Validated[A, B], y: Validated[A, B]): Validated[A, B] = x combine y } - implicit def validatedPartialOrder[A: PartialOrder, B: PartialOrder]: PartialOrder[Validated[A,B]] = + implicit def catsDataPartialOrderForValidated[A: PartialOrder, B: PartialOrder]: PartialOrder[Validated[A,B]] = new PartialOrder[Validated[A,B]] { def partialCompare(x: Validated[A,B], y: Validated[A,B]): Double = x partialCompare y override def eqv(x: Validated[A,B], y: Validated[A,B]): Boolean = x === y @@ -325,7 +325,7 @@ private[data] sealed abstract class ValidatedInstances1 extends ValidatedInstanc } private[data] sealed abstract class ValidatedInstances2 { - implicit def validatedEq[A: Eq, B: Eq]: Eq[Validated[A,B]] = + implicit def catsDataEqForValidated[A: Eq, B: Eq]: Eq[Validated[A,B]] = new Eq[Validated[A,B]] { def eqv(x: Validated[A,B], y: Validated[A,B]): Boolean = x === y } diff --git a/core/src/main/scala/cats/data/XorT.scala b/core/src/main/scala/cats/data/XorT.scala index be129f4b6b..8d8e819220 100644 --- a/core/src/main/scala/cats/data/XorT.scala +++ b/core/src/main/scala/cats/data/XorT.scala @@ -241,7 +241,7 @@ private[data] abstract class XorTInstances extends XorTInstances1 { val F0: Traverse[F] = F } - implicit def xortTransLift[E]: TransLift.Aux[XorT[?[_], E, ?], Functor] = + implicit def catsDataTransLiftForXorT[E]: TransLift.Aux[XorT[?[_], E, ?], Functor] = new TransLift[XorT[?[_], E, ?]] { type TC[M[_]] = Functor[M] diff --git a/core/src/main/scala/cats/functor/Invariant.scala b/core/src/main/scala/cats/functor/Invariant.scala index 5914d6d6f9..0ea0c719e0 100644 --- a/core/src/main/scala/cats/functor/Invariant.scala +++ b/core/src/main/scala/cats/functor/Invariant.scala @@ -36,14 +36,14 @@ object Invariant extends AlgebraInvariantInstances */ private[functor] sealed trait AlgebraInvariantInstances { - implicit val invariantSemigroup: Invariant[Semigroup] = new Invariant[Semigroup] { + implicit val catsFunctorInvariantForSemigroup: Invariant[Semigroup] = new Invariant[Semigroup] { def imap[A, B](fa: Semigroup[A])(f: A => B)(g: B => A): Semigroup[B] = new Semigroup[B] { def combine(x: B, y: B): B = f(fa.combine(g(x), g(y))) } } - implicit val invariantMonoid: Invariant[Monoid] = new Invariant[Monoid] { + implicit val catsFunctorInvariantForMonoid: Invariant[Monoid] = new Invariant[Monoid] { def imap[A, B](fa: Monoid[A])(f: A => B)(g: B => A): Monoid[B] = new Monoid[B] { val empty = f(fa.empty) diff --git a/core/src/main/scala/cats/package.scala b/core/src/main/scala/cats/package.scala index dc4b89373a..bc16a90951 100644 --- a/core/src/main/scala/cats/package.scala +++ b/core/src/main/scala/cats/package.scala @@ -29,7 +29,7 @@ package object cats { * encodes pure unary function application. */ type Id[A] = A - implicit val idInstances: Bimonad[Id] with MonadRec[Id] with Traverse[Id] = + implicit val catsInstancesForId: Bimonad[Id] with MonadRec[Id] with Traverse[Id] = new Bimonad[Id] with MonadRec[Id] with Traverse[Id] { def pure[A](a: A): A = a def extract[A](a: A): A = a diff --git a/free/src/main/scala/cats/free/Coyoneda.scala b/free/src/main/scala/cats/free/Coyoneda.scala index 2bf8ec5774..36625ca744 100644 --- a/free/src/main/scala/cats/free/Coyoneda.scala +++ b/free/src/main/scala/cats/free/Coyoneda.scala @@ -63,7 +63,7 @@ object Coyoneda { /** * As the free functor, `Coyoneda[F, ?]` provides a functor for any `F`. */ - implicit def coyonedaFunctor[F[_]]: Functor[Coyoneda[F, ?]] = + implicit def catsFreeFunctorForCoyoneda[F[_]]: Functor[Coyoneda[F, ?]] = new Functor[Coyoneda[F, ?]] { def map[A, B](cfa: Coyoneda[F, A])(f: A => B): Coyoneda[F, B] = cfa map f } diff --git a/free/src/main/scala/cats/free/Free.scala b/free/src/main/scala/cats/free/Free.scala index d5734b179d..c7c6c5cf4c 100644 --- a/free/src/main/scala/cats/free/Free.scala +++ b/free/src/main/scala/cats/free/Free.scala @@ -138,7 +138,7 @@ sealed abstract class Free[S[_], A] extends Product with Serializable { new FunctionK[S, Free[T, ?]] { def apply[B](fa: S[B]): Free[T, B] = Suspend(f(fa)) } - }(Free.freeMonad) + }(Free.catsFreeMonadRecForFree) override def toString(): String = "Free(...)" @@ -195,7 +195,7 @@ object Free { /** * `Free[S, ?]` has a monad for any type constructor `S[_]`. */ - implicit def freeMonad[S[_]]: MonadRec[Free[S, ?]] = + implicit def catsFreeMonadRecForFree[S[_]]: MonadRec[Free[S, ?]] = new MonadRec[Free[S, ?]] { def pure[A](a: A): Free[S, A] = Free.pure(a) override def map[A, B](fa: Free[S, A])(f: A => B): Free[S, B] = fa.map(f) diff --git a/free/src/main/scala/cats/free/Inject.scala b/free/src/main/scala/cats/free/Inject.scala index eb56f0f014..c1e54680a6 100644 --- a/free/src/main/scala/cats/free/Inject.scala +++ b/free/src/main/scala/cats/free/Inject.scala @@ -16,21 +16,21 @@ sealed abstract class Inject[F[_], G[_]] { } private[free] sealed abstract class InjectInstances { - implicit def reflexiveInjectInstance[F[_]]: Inject[F, F] = + implicit def catsFreeReflexiveInjectInstance[F[_]]: Inject[F, F] = new Inject[F, F] { def inj[A](fa: F[A]): F[A] = fa def prj[A](ga: F[A]): Option[F[A]] = Some(ga) } - implicit def leftInjectInstance[F[_], G[_]]: Inject[F, Coproduct[F, G, ?]] = + implicit def catsFreeLeftInjectInstance[F[_], G[_]]: Inject[F, Coproduct[F, G, ?]] = new Inject[F, Coproduct[F, G, ?]] { def inj[A](fa: F[A]): Coproduct[F, G, A] = Coproduct.leftc(fa) def prj[A](ga: Coproduct[F, G, A]): Option[F[A]] = ga.run.fold(Some(_), _ => None) } - implicit def rightInjectInstance[F[_], G[_], H[_]](implicit I: Inject[F, G]): Inject[F, Coproduct[H, G, ?]] = + implicit def catsFreeRightInjectInstance[F[_], G[_], H[_]](implicit I: Inject[F, G]): Inject[F, Coproduct[H, G, ?]] = new Inject[F, Coproduct[H, G, ?]] { def inj[A](fa: F[A]): Coproduct[H, G, A] = Coproduct.rightc(I.inj(fa)) diff --git a/free/src/main/scala/cats/free/Yoneda.scala b/free/src/main/scala/cats/free/Yoneda.scala index a7c14c0466..7f2b54438f 100644 --- a/free/src/main/scala/cats/free/Yoneda.scala +++ b/free/src/main/scala/cats/free/Yoneda.scala @@ -35,7 +35,7 @@ object Yoneda { /** * `Yoneda[F, _]` is a functor for any `F`. */ - implicit def yonedaFunctor[F[_]]: Functor[Yoneda[F, ?]] = + implicit def catsFreeFunctorForYoneda[F[_]]: Functor[Yoneda[F, ?]] = new Functor[Yoneda[F, ?]] { def map[A, B](ya: Yoneda[F, A])(f: A => B): Yoneda[F, B] = ya map f } diff --git a/free/src/test/scala/cats/free/FreeTests.scala b/free/src/test/scala/cats/free/FreeTests.scala index d0bdf9a64a..b2db47c362 100644 --- a/free/src/test/scala/cats/free/FreeTests.scala +++ b/free/src/test/scala/cats/free/FreeTests.scala @@ -5,7 +5,7 @@ import cats.tests.CatsSuite import cats.arrow.FunctionK import cats.data.Xor import cats.laws.discipline.{CartesianTests, MonadRecTests, SerializableTests} -import cats.laws.discipline.arbitrary.function0Arbitrary +import cats.laws.discipline.arbitrary.catsLawsArbitraryForFn0 import org.scalacheck.{Arbitrary, Gen} import Arbitrary.arbFunction1 diff --git a/kernel-laws/src/main/scala/cats/kernel/laws/package.scala b/kernel-laws/src/main/scala/cats/kernel/laws/package.scala index f4c7ed5ca0..f97de5ab1f 100644 --- a/kernel-laws/src/main/scala/cats/kernel/laws/package.scala +++ b/kernel-laws/src/main/scala/cats/kernel/laws/package.scala @@ -1,18 +1,11 @@ package cats.kernel -import org.typelevel.discipline.Predicate - import org.scalacheck._ import org.scalacheck.util.Pretty import Prop.{False, Proof, Result} package object laws { - implicit def nonEmptyPredicate[A](implicit ev: Eq[A], A: Monoid[A]): Predicate[A] = - new Predicate[A] { - def apply(a: A) = ev.neqv(a, A.empty) - } - lazy val proved = Prop(Result(status = Proof)) lazy val falsified = Prop(Result(status = False)) diff --git a/kernel/src/main/scala/cats/kernel/Eq.scala b/kernel/src/main/scala/cats/kernel/Eq.scala index 5ae4ec752e..4a25cbbab7 100644 --- a/kernel/src/main/scala/cats/kernel/Eq.scala +++ b/kernel/src/main/scala/cats/kernel/Eq.scala @@ -75,7 +75,7 @@ object Eq extends EqFunctions[Eq] { /** * This gives compatibility with scala's Equiv trait */ - implicit def equiv[A](implicit ev: Eq[A]): Equiv[A] = + implicit def catsKernelEquivForEq[A](implicit ev: Eq[A]): Equiv[A] = new Equiv[A] { def equiv(a: A, b: A) = ev.eqv(a, b) } diff --git a/kernel/src/main/scala/cats/kernel/Order.scala b/kernel/src/main/scala/cats/kernel/Order.scala index 577214057e..32f29f1634 100644 --- a/kernel/src/main/scala/cats/kernel/Order.scala +++ b/kernel/src/main/scala/cats/kernel/Order.scala @@ -164,7 +164,7 @@ object Order extends OrderFunctions[Order] { * Implicitly convert a `Order[A]` to a `scala.math.Ordering[A]` * instance. */ - implicit def ordering[A](implicit ev: Order[A]): Ordering[A] = + implicit def catsKernelOrderingForOrder[A](implicit ev: Order[A]): Ordering[A] = ev.toOrdering /** diff --git a/kernel/src/main/scala/cats/kernel/PartialOrder.scala b/kernel/src/main/scala/cats/kernel/PartialOrder.scala index 9d5f35ecb6..7a56eeabf8 100644 --- a/kernel/src/main/scala/cats/kernel/PartialOrder.scala +++ b/kernel/src/main/scala/cats/kernel/PartialOrder.scala @@ -167,7 +167,7 @@ object PartialOrder extends PartialOrderFunctions[PartialOrder] { * Implicitly convert a `PartialOrder[A]` to a * `scala.math.PartialOrdering[A]` instance. */ - implicit def partialOrdering[A](implicit ev: PartialOrder[A]): PartialOrdering[A] = + implicit def catsKernelPartialOrderingForPartialOrder[A](implicit ev: PartialOrder[A]): PartialOrdering[A] = new PartialOrdering[A] { def tryCompare(x: A, y: A): Option[Int] = ev.tryCompare(x, y) def lteq(x: A, y: A): Boolean = ev.lteqv(x, y) diff --git a/laws/src/main/scala/cats/laws/discipline/Arbitrary.scala b/laws/src/main/scala/cats/laws/discipline/Arbitrary.scala index 7e823c6a06..41efdee091 100644 --- a/laws/src/main/scala/cats/laws/discipline/Arbitrary.scala +++ b/laws/src/main/scala/cats/laws/discipline/Arbitrary.scala @@ -14,77 +14,77 @@ object arbitrary extends ArbitraryInstances0 { // A special function1Arbitrary for testing operations like dropWhile specifically // in the context of Int => Boolean. Once scalacheck supports better Function1 arbitrary // instances this can be removed. - implicit def function1Arbitrary: Arbitrary[(Int) => Boolean] = + implicit def catsLawsArbitraryForIntToBool: Arbitrary[(Int) => Boolean] = Arbitrary(getArbitrary[Int].map(x => (input) => input < x)) - implicit def constArbitrary[A, B](implicit A: Arbitrary[A]): Arbitrary[Const[A, B]] = + implicit def catsLawsArbitraryForConst[A, B](implicit A: Arbitrary[A]): Arbitrary[Const[A, B]] = Arbitrary(A.arbitrary.map(Const[A, B])) - implicit def oneAndArbitrary[F[_], A](implicit A: Arbitrary[A], F: Arbitrary[F[A]]): Arbitrary[OneAnd[F, A]] = + implicit def catsLawsArbitraryForOneAnd[F[_], A](implicit A: Arbitrary[A], F: Arbitrary[F[A]]): Arbitrary[OneAnd[F, A]] = Arbitrary(F.arbitrary.flatMap(fa => A.arbitrary.map(a => OneAnd(a, fa)))) - implicit def xorArbitrary[A, B](implicit A: Arbitrary[A], B: Arbitrary[B]): Arbitrary[A Xor B] = + implicit def catsLawsArbitraryForXor[A, B](implicit A: Arbitrary[A], B: Arbitrary[B]): Arbitrary[A Xor B] = Arbitrary(Gen.oneOf(A.arbitrary.map(Xor.left), B.arbitrary.map(Xor.right))) - implicit def xorTArbitrary[F[_], A, B](implicit F: Arbitrary[F[A Xor B]]): Arbitrary[XorT[F, A, B]] = + implicit def catsLawsArbitraryForXorT[F[_], A, B](implicit F: Arbitrary[F[A Xor B]]): Arbitrary[XorT[F, A, B]] = Arbitrary(F.arbitrary.map(XorT(_))) - implicit def validatedArbitrary[A, B](implicit A: Arbitrary[A], B: Arbitrary[B]): Arbitrary[Validated[A, B]] = + implicit def catsLawsArbitraryForValidated[A, B](implicit A: Arbitrary[A], B: Arbitrary[B]): Arbitrary[Validated[A, B]] = Arbitrary(Gen.oneOf(A.arbitrary.map(Validated.invalid), B.arbitrary.map(Validated.valid))) - implicit def iorArbitrary[A, B](implicit A: Arbitrary[A], B: Arbitrary[B]): Arbitrary[A Ior B] = + implicit def catsLawsArbitraryForIor[A, B](implicit A: Arbitrary[A], B: Arbitrary[B]): Arbitrary[A Ior B] = Arbitrary(Gen.oneOf(A.arbitrary.map(Ior.left), B.arbitrary.map(Ior.right), for { a <- A.arbitrary; b <- B.arbitrary } yield Ior.both(a, b))) - implicit def kleisliArbitrary[F[_], A, B](implicit F: Arbitrary[F[B]]): Arbitrary[Kleisli[F, A, B]] = + implicit def catsLawsArbitraryForKleisli[F[_], A, B](implicit F: Arbitrary[F[B]]): Arbitrary[Kleisli[F, A, B]] = Arbitrary(F.arbitrary.map(fb => Kleisli[F, A, B](_ => fb))) - implicit def cokleisliArbitrary[F[_], A, B](implicit B: Arbitrary[B]): Arbitrary[Cokleisli[F, A, B]] = + implicit def catsLawsArbitraryForCokleisli[F[_], A, B](implicit B: Arbitrary[B]): Arbitrary[Cokleisli[F, A, B]] = Arbitrary(B.arbitrary.map(b => Cokleisli[F, A, B](_ => b))) - implicit def optionTArbitrary[F[_], A](implicit F: Arbitrary[F[Option[A]]]): Arbitrary[OptionT[F, A]] = + implicit def catsLawsArbitraryForOptionT[F[_], A](implicit F: Arbitrary[F[Option[A]]]): Arbitrary[OptionT[F, A]] = Arbitrary(F.arbitrary.map(OptionT.apply)) - implicit def idTArbitrary[F[_], A](implicit F: Arbitrary[F[A]]): Arbitrary[IdT[F, A]] = + implicit def catsLawsArbitraryForIdT[F[_], A](implicit F: Arbitrary[F[A]]): Arbitrary[IdT[F, A]] = Arbitrary(F.arbitrary.map(IdT.apply)) - implicit def evalArbitrary[A: Arbitrary]: Arbitrary[Eval[A]] = + implicit def catsLawsArbitraryForEval[A: Arbitrary]: Arbitrary[Eval[A]] = Arbitrary(Gen.oneOf( getArbitrary[A].map(Eval.now(_)), getArbitrary[A].map(Eval.later(_)), getArbitrary[A].map(Eval.always(_)))) - implicit def prodArbitrary[F[_], G[_], A](implicit F: Arbitrary[F[A]], G: Arbitrary[G[A]]): Arbitrary[Prod[F, G, A]] = + implicit def catsLawsArbitraryForProd[F[_], G[_], A](implicit F: Arbitrary[F[A]], G: Arbitrary[G[A]]): Arbitrary[Prod[F, G, A]] = Arbitrary(F.arbitrary.flatMap(fa => G.arbitrary.map(ga => Prod[F, G, A](fa, ga)))) - implicit def funcArbitrary[F[_], A, B](implicit F: Arbitrary[F[B]]): Arbitrary[Func[F, A, B]] = + implicit def catsLawsArbitraryForFunc[F[_], A, B](implicit F: Arbitrary[F[B]]): Arbitrary[Func[F, A, B]] = Arbitrary(F.arbitrary.map(fb => Func.func[F, A, B](_ => fb))) - implicit def appFuncArbitrary[F[_], A, B](implicit F: Arbitrary[F[B]], FF: Applicative[F]): Arbitrary[AppFunc[F, A, B]] = + implicit def catsLawsArbitraryForAppFunc[F[_], A, B](implicit F: Arbitrary[F[B]], FF: Applicative[F]): Arbitrary[AppFunc[F, A, B]] = Arbitrary(F.arbitrary.map(fb => Func.appFunc[F, A, B](_ => fb))) - implicit def writerArbitrary[L:Arbitrary, V:Arbitrary]: Arbitrary[Writer[L, V]] = - writerTArbitrary[Id, L, V] + implicit def catsLawsArbitraryForWriter[L:Arbitrary, V:Arbitrary]: Arbitrary[Writer[L, V]] = + catsLawsArbitraryForWriterT[Id, L, V] // until this is provided by scalacheck - implicit def partialFunctionArbitrary[A, B](implicit F: Arbitrary[A => Option[B]]): Arbitrary[PartialFunction[A, B]] = + implicit def catsLawsArbitraryForPartialFunction[A, B](implicit F: Arbitrary[A => Option[B]]): Arbitrary[PartialFunction[A, B]] = Arbitrary(F.arbitrary.map(Function.unlift)) - implicit def coproductArbitrary[F[_], G[_], A](implicit F: Arbitrary[F[A]], G: Arbitrary[G[A]]): Arbitrary[Coproduct[F, G, A]] = + implicit def catsLawsArbitraryForCoproduct[F[_], G[_], A](implicit F: Arbitrary[F[A]], G: Arbitrary[G[A]]): Arbitrary[Coproduct[F, G, A]] = Arbitrary(Gen.oneOf( F.arbitrary.map(Coproduct.leftc[F, G, A]), G.arbitrary.map(Coproduct.rightc[F, G, A]))) - implicit def showArbitrary[A: Arbitrary]: Arbitrary[Show[A]] = + implicit def catsLawsArbitraryForShow[A: Arbitrary]: Arbitrary[Show[A]] = Arbitrary(Show.fromToString[A]) - implicit def function0Arbitrary[A: Arbitrary]: Arbitrary[() => A] = + implicit def catsLawsArbitraryForFn0[A: Arbitrary]: Arbitrary[() => A] = Arbitrary(getArbitrary[A].map(() => _)) - implicit def nestedArbitrary[F[_], G[_], A](implicit FG: Arbitrary[F[G[A]]]): Arbitrary[Nested[F, G, A]] = + implicit def catsLawsArbitraryForNested[F[_], G[_], A](implicit FG: Arbitrary[F[G[A]]]): Arbitrary[Nested[F, G, A]] = Arbitrary(FG.arbitrary.map(Nested(_))) } private[discipline] sealed trait ArbitraryInstances0 { - implicit def writerTArbitrary[F[_], L, V](implicit F: Arbitrary[F[(L, V)]]): Arbitrary[WriterT[F, L, V]] = + implicit def catsLawsArbitraryForWriterT[F[_], L, V](implicit F: Arbitrary[F[(L, V)]]): Arbitrary[WriterT[F, L, V]] = Arbitrary(F.arbitrary.map(WriterT(_))) } diff --git a/laws/src/main/scala/cats/laws/discipline/Eq.scala b/laws/src/main/scala/cats/laws/discipline/Eq.scala index 432b1d7a80..406b95f56f 100644 --- a/laws/src/main/scala/cats/laws/discipline/Eq.scala +++ b/laws/src/main/scala/cats/laws/discipline/Eq.scala @@ -12,7 +12,7 @@ object eq { * Create an approximation of Eq[A => B] by generating 100 values for A * and comparing the application of the two functions. */ - implicit def function1Eq[A, B](implicit A: Arbitrary[A], B: Eq[B]): Eq[A => B] = new Eq[A => B] { + implicit def catsLawsEqForFn1[A, B](implicit A: Arbitrary[A], B: Eq[B]): Eq[A => B] = new Eq[A => B] { val sampleCnt: Int = if (Platform.isJvm) 50 else 5 def eqv(f: A => B, g: A => B): Boolean = { @@ -24,9 +24,9 @@ object eq { } } - /** Create an approximation of Eq[Show[A]] by using function1Eq[A, String] */ - implicit def showEq[A: Arbitrary]: Eq[Show[A]] = { - val xyz = function1Eq[A, String] + /** Create an approximation of Eq[Show[A]] by using catsLawsEqForFn1[A, String] */ + implicit def catsLawsEqForShow[A: Arbitrary]: Eq[Show[A]] = { + val xyz = catsLawsEqForFn1[A, String] Eq.by[Show[A], A => String] { showInstance => (a: A) => showInstance.show(a) } @@ -36,18 +36,14 @@ object eq { * Create an approximation of Eq[Semigroup[A]] by generating values for A * and comparing the application of the two combine functions. */ - implicit def semigroupEq[A](implicit arbAA: Arbitrary[(A, A)], eqA: Eq[A]): Eq[Semigroup[A]] = - function1Eq[(A, A), A].on(f => + implicit def catsLawsEqForSemigroup[A](implicit arbAA: Arbitrary[(A, A)], eqA: Eq[A]): Eq[Semigroup[A]] = + catsLawsEqForFn1[(A, A), A].on(f => Function.tupled((x, y) => f.combine(x, y)) ) - implicit def monoidEq[A](implicit eqSA: Eq[Semigroup[A]], eqA: Eq[A]): Eq[Monoid[A]] = new Eq[Monoid[A]] { + implicit def catsLawsEqForMonoid[A](implicit eqSA: Eq[Semigroup[A]], eqA: Eq[A]): Eq[Monoid[A]] = new Eq[Monoid[A]] { def eqv(f: Monoid[A], g: Monoid[A]): Boolean = { eqSA.eqv(f, g) && eqA.eqv(f.empty, g.empty) } } - - implicit val unitEq: Eq[Unit] = new Eq[Unit] { - def eqv(a: Unit, b: Unit): Boolean = true - } } diff --git a/laws/src/main/scala/cats/laws/discipline/package.scala b/laws/src/main/scala/cats/laws/discipline/package.scala index 6862b3036c..b4fb5ca831 100644 --- a/laws/src/main/scala/cats/laws/discipline/package.scala +++ b/laws/src/main/scala/cats/laws/discipline/package.scala @@ -6,6 +6,6 @@ import cats.kernel.laws._ import org.scalacheck.Prop package object discipline { - implicit def isEqToProp[A: Eq](isEq: IsEq[A]): Prop = + implicit def catsLawsIsEqToProp[A: Eq](isEq: IsEq[A]): Prop = isEq.lhs ?== isEq.rhs } diff --git a/tests/src/test/scala/cats/tests/CategoryTests.scala b/tests/src/test/scala/cats/tests/CategoryTests.scala index dc0de32190..a052e7c9fe 100644 --- a/tests/src/test/scala/cats/tests/CategoryTests.scala +++ b/tests/src/test/scala/cats/tests/CategoryTests.scala @@ -5,7 +5,7 @@ import cats.kernel.laws.GroupLaws import cats.arrow.Category import cats.laws.discipline.{MonoidKTests, SerializableTests} -import cats.laws.discipline.eq.function1Eq +import cats.laws.discipline.eq.catsLawsEqForFn1 class CategoryTest extends CatsSuite { val functionCategory = Category[Function1] diff --git a/tests/src/test/scala/cats/tests/CokleisliTests.scala b/tests/src/test/scala/cats/tests/CokleisliTests.scala index 212de1f56b..342f33a108 100644 --- a/tests/src/test/scala/cats/tests/CokleisliTests.scala +++ b/tests/src/test/scala/cats/tests/CokleisliTests.scala @@ -37,10 +37,10 @@ class CokleisliTests extends SlowCatsSuite { type CokleisliNEL[A, B] = Cokleisli[NonEmptyList, A, B] implicit def ev0[A: Arbitrary, B: Arbitrary]: Arbitrary[CokleisliNEL[A, B]] = - cokleisliArbitrary + catsLawsArbitraryForCokleisli implicit def ev1[A: Arbitrary, B: Eq]: Eq[CokleisliNEL[A, B]] = - cokleisliEq[NonEmptyList, A, B](oneAndArbitrary, Eq[B]) + cokleisliEq[NonEmptyList, A, B](catsLawsArbitraryForOneAnd, Eq[B]) checkAll("Cokleisli[NonEmptyList, Int, Int]", ArrowTests[CokleisliNEL].arrow[Int, Int, Int, Int, Int, Int]) checkAll("Arrow[Cokleisli[NonEmptyList, ?, ?]]", SerializableTests.serializable(Arrow[CokleisliNEL])) @@ -51,10 +51,10 @@ class CokleisliTests extends SlowCatsSuite { type CokleisliNELE[A] = Cokleisli[NonEmptyList, A, A] implicit def ev0[A: Arbitrary]: Arbitrary[CokleisliNELE[A]] = - cokleisliArbitrary[NonEmptyList, A, A] + catsLawsArbitraryForCokleisli[NonEmptyList, A, A] implicit def ev1[A: Eq](implicit arb: Arbitrary[A]): Eq[CokleisliNELE[A]] = - cokleisliEqE[NonEmptyList, A](oneAndArbitrary, Eq[A]) + cokleisliEqE[NonEmptyList, A](catsLawsArbitraryForOneAnd, Eq[A]) { implicit val cokleisliMonoidK = Cokleisli.catsDataMonoidKForCokleisli[NonEmptyList] diff --git a/tests/src/test/scala/cats/tests/ComposeTest.scala b/tests/src/test/scala/cats/tests/ComposeTest.scala index d6694e7caf..55c3df6bc4 100644 --- a/tests/src/test/scala/cats/tests/ComposeTest.scala +++ b/tests/src/test/scala/cats/tests/ComposeTest.scala @@ -5,7 +5,7 @@ import cats.kernel.laws.GroupLaws import cats.arrow.Compose import cats.laws.discipline.{SemigroupKTests, SerializableTests} -import cats.laws.discipline.eq.function1Eq +import cats.laws.discipline.eq.catsLawsEqForFn1 class ComposeTest extends CatsSuite { val functionCompose = Compose[Function1] diff --git a/tests/src/test/scala/cats/tests/ConstTests.scala b/tests/src/test/scala/cats/tests/ConstTests.scala index fafce196bc..ae0f0c0017 100644 --- a/tests/src/test/scala/cats/tests/ConstTests.scala +++ b/tests/src/test/scala/cats/tests/ConstTests.scala @@ -6,7 +6,7 @@ import cats.kernel.laws.{GroupLaws, OrderLaws} import cats.data.{Const, NonEmptyList} import cats.functor.Contravariant import cats.laws.discipline._ -import cats.laws.discipline.arbitrary.{constArbitrary, oneAndArbitrary} +import cats.laws.discipline.arbitrary.{catsLawsArbitraryForConst, catsLawsArbitraryForOneAnd} class ConstTests extends CatsSuite { diff --git a/tests/src/test/scala/cats/tests/MonadCombineTests.scala b/tests/src/test/scala/cats/tests/MonadCombineTests.scala index 32b3577d77..6a4901b10a 100644 --- a/tests/src/test/scala/cats/tests/MonadCombineTests.scala +++ b/tests/src/test/scala/cats/tests/MonadCombineTests.scala @@ -2,7 +2,7 @@ package cats package tests import cats.data.Xor -import cats.laws.discipline.arbitrary.xorArbitrary +import cats.laws.discipline.arbitrary.catsLawsArbitraryForXor class MonadCombineTest extends CatsSuite { test("separate") { diff --git a/tests/src/test/scala/cats/tests/NestedTests.scala b/tests/src/test/scala/cats/tests/NestedTests.scala index 7625b70d86..d2318b0860 100644 --- a/tests/src/test/scala/cats/tests/NestedTests.scala +++ b/tests/src/test/scala/cats/tests/NestedTests.scala @@ -6,7 +6,7 @@ import cats.functor._ import cats.laws.discipline._ import cats.laws.discipline.CartesianTests.Isomorphisms._ import cats.laws.discipline.arbitrary._ -import cats.laws.discipline.eq.showEq +import cats.laws.discipline.eq.catsLawsEqForShow class NestedTests extends CatsSuite { // we have a lot of generated lists of lists in these tests. We have to tell @@ -29,14 +29,14 @@ class NestedTests extends CatsSuite { { // Invariant + Covariant = Invariant - val instance = Nested.nestedInvariantCovariant(ListWrapper.invariant, ListWrapper.functor) + val instance = Nested.catsDataInvariantForCovariantNested(ListWrapper.invariant, ListWrapper.functor) checkAll("Nested[ListWrapper, ListWrapper] - Invariant + Covariant", InvariantTests[Nested[ListWrapper, ListWrapper, ?]](instance).invariant[Int, Int, Int]) checkAll("Invariant[Nested[ListWrapper, ListWrapper, ?]] - Invariant + Covariant", SerializableTests.serializable(instance)) } { // Invariant + Contravariant = Invariant - val instance = Nested.nestedInvariantContravariant(ListWrapper.invariant, Contravariant[Show]) + val instance = Nested.catsDataInvariantForNestedContravariant(ListWrapper.invariant, Contravariant[Show]) checkAll("Nested[ListWrapper, Show]", InvariantTests[Nested[ListWrapper, Show, ?]](instance).invariant[Int, Int, Int]) checkAll("Invariant[Nested[ListWrapper, Show, ?]]", SerializableTests.serializable(instance)) } @@ -58,9 +58,9 @@ class NestedTests extends CatsSuite { // Contravariant + Contravariant = Functor type ConstInt[A] = Const[Int, A] // SI-2712 - implicit val instance = Nested.nestedContravariant[ConstInt, Show] - implicit val arbitrary = nestedArbitrary[ConstInt, Show, Int] - implicit val eqv = Nested.nestedEq[ConstInt, Show, Int] + implicit val instance = Nested.catsDataContravariantForNested[ConstInt, Show] + implicit val arbitrary = catsLawsArbitraryForNested[ConstInt, Show, Int] + implicit val eqv = Nested.catsDataEqForNested[ConstInt, Show, Int] checkAll("Nested[Const[Int, ?], Show, ?]", FunctorTests[Nested[ConstInt, Show, ?]].functor[Int, Int, Int]) checkAll("Functor[Nested[Const[Int, ?], Show, ?]]", SerializableTests.serializable(instance)) } @@ -96,9 +96,9 @@ class NestedTests extends CatsSuite { // SI-2712? It can resolve Reducible[NonEmptyList] and Reducible[NonEmptyVector] but not // Reducible[Nested[NonEmptyList, NonEmptyVector, ?]] // Similarly for Arbitrary. - implicit val reducible = Nested.nestedReducible[NonEmptyList, NonEmptyVector] - implicit val arbitrary0 = nestedArbitrary[NonEmptyList, NonEmptyVector, Int] - implicit val arbitrary1 = nestedArbitrary[NonEmptyList, NonEmptyVector, Option[Int]] + implicit val reducible = Nested.catsDataReducibleForNested[NonEmptyList, NonEmptyVector] + implicit val arbitrary0 = catsLawsArbitraryForNested[NonEmptyList, NonEmptyVector, Int] + implicit val arbitrary1 = catsLawsArbitraryForNested[NonEmptyList, NonEmptyVector, Option[Int]] checkAll("Nested[NonEmptyList, NonEmptyVector, ?]", ReducibleTests[Nested[NonEmptyList, NonEmptyVector, ?]].reducible[Option, Int, Int]) checkAll("Reducible[Nested[NonEmptyList, NonEmptyVector, ?]]", SerializableTests.serializable(reducible)) From ef69db1bb2bffc79e7d03f3cf7dc45d6186c99a5 Mon Sep 17 00:00:00 2001 From: "Marius B. Kotsbak" Date: Tue, 14 Jun 2016 14:20:32 +0200 Subject: [PATCH 21/36] Add valueOr and merge to Validated, analog to Xor's --- core/src/main/scala/cats/data/Validated.scala | 7 +++++++ tests/src/test/scala/cats/tests/ValidatedTests.scala | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/core/src/main/scala/cats/data/Validated.scala b/core/src/main/scala/cats/data/Validated.scala index 0d52616c4a..0791bb13bd 100644 --- a/core/src/main/scala/cats/data/Validated.scala +++ b/core/src/main/scala/cats/data/Validated.scala @@ -27,6 +27,11 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable { */ def getOrElse[B >: A](default: => B): B = fold(_ => default, identity) + /** + * Return the Valid value, or the result of f if Invalid + */ + def valueOr[B >: A](f: E => B): B = fold(f, identity) + /** * Is this Valid and matching the given predicate */ @@ -203,6 +208,8 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable { case Invalid(e) => Valid(e) } + def merge[EE >: E](implicit ev: A <:< EE): EE = fold(identity, ev.apply) + /** * Ensure that a successful result passes the given predicate, * falling back to an Invalid of `onFailure` if the predicate diff --git a/tests/src/test/scala/cats/tests/ValidatedTests.scala b/tests/src/test/scala/cats/tests/ValidatedTests.scala index 22cc72fb6f..1c1f2365c9 100644 --- a/tests/src/test/scala/cats/tests/ValidatedTests.scala +++ b/tests/src/test/scala/cats/tests/ValidatedTests.scala @@ -114,6 +114,12 @@ class ValidatedTests extends CatsSuite { } } + test("valueOr consistent with swap then map then merge") { + forAll { (v: Validated[String, Int], f: String => Int) => + v.valueOr(f) should === (v.swap.map(f).merge) + } + } + test("toEither then fromEither is identity") { forAll { (v: Validated[String, Int]) => Validated.fromEither(v.toEither) should === (v) From 8c91537c632805b04ad02af3440c238335f8f804 Mon Sep 17 00:00:00 2001 From: Cody Allen Date: Tue, 14 Jun 2016 09:04:09 -0400 Subject: [PATCH 22/36] Include kernel in ScalaDoc Currently the [ScalaDoc](http://typelevel.org/cats/api/#package) doesn't include the kernel module, so types like Semigroup aren't present. --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 4443e59913..eeb1c8941d 100644 --- a/build.sbt +++ b/build.sbt @@ -107,7 +107,7 @@ lazy val testingDependencies = Seq( def docsSourcesAndProjects(sv: String): (Boolean, Seq[ProjectReference]) = CrossVersion.partialVersion(sv) match { case Some((2, 10)) => (false, Nil) - case _ => (true, Seq(coreJVM, freeJVM)) + case _ => (true, Seq(kernelJVM, coreJVM, freeJVM)) } lazy val javadocSettings = Seq( From 4b0eb010efd63d2822145d9904102bd9c58243d5 Mon Sep 17 00:00:00 2001 From: Oscar Boykin Date: Tue, 14 Jun 2016 09:37:35 -1000 Subject: [PATCH 23/36] Add Xor.toTry --- core/src/main/scala/cats/data/Xor.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/src/main/scala/cats/data/Xor.scala b/core/src/main/scala/cats/data/Xor.scala index bda34ec4a4..857ef3c155 100644 --- a/core/src/main/scala/cats/data/Xor.scala +++ b/core/src/main/scala/cats/data/Xor.scala @@ -69,6 +69,8 @@ sealed abstract class Xor[+A, +B] extends Product with Serializable { def toList: List[B] = fold(_ => Nil, _ :: Nil) + def toTry(implicit ev: A <:< Throwable): Try[B] = fold(a => Failure(ev(a)), Success(_)) + def toValidated: Validated[A,B] = fold(Validated.Invalid.apply, Validated.Valid.apply) /** Returns a [[ValidatedNel]] representation of this disjunction with the `Left` value From feba40a401bd01aeda83b706a7f4b3a79fc7143f Mon Sep 17 00:00:00 2001 From: Oscar Boykin Date: Tue, 14 Jun 2016 10:03:21 -1000 Subject: [PATCH 24/36] Add ApplySemigroup and ApplicativeMonoid --- core/src/main/scala/cats/Applicative.scala | 4 ++++ core/src/main/scala/cats/Apply.scala | 5 +++++ core/src/main/scala/cats/std/future.scala | 13 ++++--------- core/src/main/scala/cats/std/try.scala | 13 ++----------- 4 files changed, 15 insertions(+), 20 deletions(-) diff --git a/core/src/main/scala/cats/Applicative.scala b/core/src/main/scala/cats/Applicative.scala index 28b6cfba45..afc5fcee86 100644 --- a/core/src/main/scala/cats/Applicative.scala +++ b/core/src/main/scala/cats/Applicative.scala @@ -50,3 +50,7 @@ import simulacrum.typeclass val G = Applicative[G] } } + +abstract class ApplicativeMonoid[F[_], A](f: Applicative[F], monoid: Monoid[A]) extends ApplySemigroup(f, monoid) with Monoid[F[A]] { + def empty: F[A] = f.pure(monoid.empty) +} diff --git a/core/src/main/scala/cats/Apply.scala b/core/src/main/scala/cats/Apply.scala index 20bc75c179..03f4fb06c7 100644 --- a/core/src/main/scala/cats/Apply.scala +++ b/core/src/main/scala/cats/Apply.scala @@ -64,3 +64,8 @@ trait Apply[F[_]] extends Functor[F] with Cartesian[F] with ApplyArityFunctions[ val G = Apply[G] } } + +abstract class ApplySemigroup[F[_], A](f: Apply[F], sg: Semigroup[A]) extends Semigroup[F[A]] { + def combine(a: F[A], b: F[A]): F[A] = + f.map2(a, b)(sg.combine) +} diff --git a/core/src/main/scala/cats/std/future.scala b/core/src/main/scala/cats/std/future.scala index 1fef79e1f0..8cb9b23483 100644 --- a/core/src/main/scala/cats/std/future.scala +++ b/core/src/main/scala/cats/std/future.scala @@ -1,7 +1,6 @@ package cats package std -import cats.syntax.all._ import cats.data.Xor import scala.util.control.NonFatal @@ -51,12 +50,8 @@ private[cats] abstract class FutureCoflatMap(implicit ec: ExecutionContext) exte def coflatMap[A, B](fa: Future[A])(f: Future[A] => B): Future[B] = Future(f(fa)) } -private[cats] class FutureSemigroup[A: Semigroup](implicit ec: ExecutionContext) extends Semigroup[Future[A]] { - def combine(fx: Future[A], fy: Future[A]): Future[A] = - (fx zip fy).map { case (x, y) => x |+| y } -} +private[cats] class FutureSemigroup[A: Semigroup](implicit ec: ExecutionContext) + extends ApplySemigroup[Future, A](future.catsStdInstancesForFuture, implicitly) -private[cats] class FutureMonoid[A](implicit A: Monoid[A], ec: ExecutionContext) extends FutureSemigroup[A] with Monoid[Future[A]] { - def empty: Future[A] = - Future.successful(A.empty) -} +private[cats] class FutureMonoid[A](implicit A: Monoid[A], ec: ExecutionContext) + extends ApplicativeMonoid[Future, A](future.catsStdInstancesForFuture, implicitly) diff --git a/core/src/main/scala/cats/std/try.scala b/core/src/main/scala/cats/std/try.scala index 770fd6b704..d10d919fd8 100644 --- a/core/src/main/scala/cats/std/try.scala +++ b/core/src/main/scala/cats/std/try.scala @@ -1,7 +1,6 @@ package cats package std -import cats.syntax.all._ import cats.data.Xor import TryInstances.castFailure @@ -122,14 +121,6 @@ private[cats] abstract class TryCoflatMap extends CoflatMap[Try] { def coflatMap[A, B](ta: Try[A])(f: Try[A] => B): Try[B] = Try(f(ta)) } -private[cats] class TrySemigroup[A: Semigroup] extends Semigroup[Try[A]] { - def combine(fx: Try[A], fy: Try[A]): Try[A] = - for { - x <- fx - y <- fy - } yield x |+| y -} +private[cats] class TrySemigroup[A: Semigroup] extends ApplySemigroup[Try, A](try_.catsStdInstancesForTry, implicitly) -private[cats] class TryMonoid[A](implicit A: Monoid[A]) extends TrySemigroup[A] with Monoid[Try[A]] { - def empty: Try[A] = Success(A.empty) -} +private[cats] class TryMonoid[A](implicit A: Monoid[A]) extends ApplicativeMonoid[Try, A](try_.catsStdInstancesForTry, implicitly) From 2eebf31488617d9c984114647ec835072821ef15 Mon Sep 17 00:00:00 2001 From: Oscar Boykin Date: Tue, 14 Jun 2016 11:06:10 -1000 Subject: [PATCH 25/36] Add tests for toTry --- tests/src/test/scala/cats/tests/XorTests.scala | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/src/test/scala/cats/tests/XorTests.scala b/tests/src/test/scala/cats/tests/XorTests.scala index ac984230f6..8a8bea7237 100644 --- a/tests/src/test/scala/cats/tests/XorTests.scala +++ b/tests/src/test/scala/cats/tests/XorTests.scala @@ -204,6 +204,14 @@ class XorTests extends CatsSuite { } } + test("toTry then fromTry is identity") { + implicit def eqTh: Eq[Throwable] = Eq.allEqual + + forAll { (x: Throwable Xor String) => + Xor.fromTry(x.toTry) should === (x) + } + } + test("isLeft consistency") { forAll { (x: Int Xor String) => x.isLeft should === (x.toEither.isLeft) From e651f5b1e3be164f4d5f6aa95fc9e6591efa6238 Mon Sep 17 00:00:00 2001 From: Oscar Boykin Date: Tue, 14 Jun 2016 12:09:50 -1000 Subject: [PATCH 26/36] make types private --- core/src/main/scala/cats/Applicative.scala | 7 ++++++- core/src/main/scala/cats/Apply.scala | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/core/src/main/scala/cats/Applicative.scala b/core/src/main/scala/cats/Applicative.scala index afc5fcee86..49355724c8 100644 --- a/core/src/main/scala/cats/Applicative.scala +++ b/core/src/main/scala/cats/Applicative.scala @@ -51,6 +51,11 @@ import simulacrum.typeclass } } -abstract class ApplicativeMonoid[F[_], A](f: Applicative[F], monoid: Monoid[A]) extends ApplySemigroup(f, monoid) with Monoid[F[A]] { +object Applicative { + def monoid[F[_], A](implicit f: Applicative[F], monoid: Monoid[A]): Monoid[F[A]] = + new ApplicativeMonoid[F, A](f, monoid) +} + +private[cats] class ApplicativeMonoid[F[_], A](f: Applicative[F], monoid: Monoid[A]) extends ApplySemigroup(f, monoid) with Monoid[F[A]] { def empty: F[A] = f.pure(monoid.empty) } diff --git a/core/src/main/scala/cats/Apply.scala b/core/src/main/scala/cats/Apply.scala index 03f4fb06c7..8b235dd2d8 100644 --- a/core/src/main/scala/cats/Apply.scala +++ b/core/src/main/scala/cats/Apply.scala @@ -65,7 +65,12 @@ trait Apply[F[_]] extends Functor[F] with Cartesian[F] with ApplyArityFunctions[ } } -abstract class ApplySemigroup[F[_], A](f: Apply[F], sg: Semigroup[A]) extends Semigroup[F[A]] { +object Apply { + def semigroup[F[_], A](implicit f: Apply[F], sg: Semigroup[A]): Semigroup[F[A]] = + new ApplySemigroup[F, A](f, sg) +} + +private[cats] class ApplySemigroup[F[_], A](f: Apply[F], sg: Semigroup[A]) extends Semigroup[F[A]] { def combine(a: F[A], b: F[A]): F[A] = f.map2(a, b)(sg.combine) } From e784f98bf0d45cc72db765d24c545a2010cfc734 Mon Sep 17 00:00:00 2001 From: Erik Osheim Date: Wed, 15 Jun 2016 01:29:45 -0400 Subject: [PATCH 27/36] Add Kailuo Wang as a Cats maintainer. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f3e3cff3e9..e92055840c 100644 --- a/README.md +++ b/README.md @@ -183,6 +183,7 @@ The current maintainers (people who can merge pull requests) are: * [milessabin](https://github.com/milessabin) Miles Sabin * [fthomas](https://github.com/fthomas) Frank Thomas * [julien-truffaut](https://github.com/julien-truffaut) Julien Truffaut + * [kailuowang](https://github.com/kailuowang) Kailuo Wang We are currently following a practice of requiring at least two sign-offs to merge PRs (and for large or contentious issues we may From 0830a7caf2c43cc1e9969529733ee09afb37fcff Mon Sep 17 00:00:00 2001 From: hamishdickson Date: Wed, 15 Jun 2016 08:31:23 +0100 Subject: [PATCH 28/36] Add monoid syntax --- core/src/main/scala/cats/syntax/monoid.scala | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 core/src/main/scala/cats/syntax/monoid.scala diff --git a/core/src/main/scala/cats/syntax/monoid.scala b/core/src/main/scala/cats/syntax/monoid.scala new file mode 100644 index 0000000000..0858424a04 --- /dev/null +++ b/core/src/main/scala/cats/syntax/monoid.scala @@ -0,0 +1,12 @@ +package cats +package syntax + +trait MonoidSyntax extends SemigroupSyntax { + // TODO: use simulacrum instances eventually + implicit def catsSyntaxMonoid[A: Monoid](a: A): MonoidOps[A] = + new MonoidOps[A](a) +} + +final class MonoidOps[A: Monoid](lhs: A) { + def isEmpty(implicit eq: Eq[A]): Boolean = Monoid[A].isEmpty(lhs)(eq) +} From 6ad6b72bc72c6c904d9e860b899179aafd728c2f Mon Sep 17 00:00:00 2001 From: hamishdickson Date: Wed, 15 Jun 2016 08:33:37 +0100 Subject: [PATCH 29/36] Add monoid syntax --- core/src/main/scala/cats/syntax/all.scala | 1 + tests/src/test/scala/cats/tests/SyntaxTests.scala | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/core/src/main/scala/cats/syntax/all.scala b/core/src/main/scala/cats/syntax/all.scala index bbb196d91b..7634719b2f 100644 --- a/core/src/main/scala/cats/syntax/all.scala +++ b/core/src/main/scala/cats/syntax/all.scala @@ -23,6 +23,7 @@ trait AllSyntax with ListSyntax with MonadCombineSyntax with MonadFilterSyntax + with MonoidSyntax with OptionSyntax with OrderSyntax with PartialOrderSyntax diff --git a/tests/src/test/scala/cats/tests/SyntaxTests.scala b/tests/src/test/scala/cats/tests/SyntaxTests.scala index 9208c26b06..36f21b5355 100644 --- a/tests/src/test/scala/cats/tests/SyntaxTests.scala +++ b/tests/src/test/scala/cats/tests/SyntaxTests.scala @@ -40,6 +40,12 @@ class SyntaxTests extends AllInstances with AllSyntax { val z: A = x |-| y } + def testMonoid[A: Monoid]: Unit = { + val x = mock[A] + implicit val y = mock[Eq[A]] + val z: Boolean = x.isEmpty + } + def testEq[A: Eq]: Unit = { val x = mock[A] val y = mock[A] From 226ca618e55bab3e1ed8a557dc2464474c1703d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Merlin=20G=C3=B6ttlinger?= Date: Wed, 15 Jun 2016 09:59:12 +0200 Subject: [PATCH 30/36] Removed nesting in project structure listing --- docs/src/site/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/site/index.md b/docs/src/site/index.md index cb08a2b44f..fa2c0c4e5b 100644 --- a/docs/src/site/index.md +++ b/docs/src/site/index.md @@ -88,7 +88,7 @@ In an attempt to be more modular, Cats is broken up into a number of sub-project * *core* - contains type class definitions (e.g. Functor, Applicative, Monad), essential datatypes, and type class instances for those datatypes and standard library types * *laws* - laws for the type classes, used to validate type class instances - * *cats-free* - free structures such as the free monad, and supporting type classes. +* *cats-free* - free structures such as the free monad, and supporting type classes. * *tests* - tests that check type class instances with laws from *laws* * *docs* - The source for this website From 80d8da2a670fe5c248fa5ad6af9d32f21ab3c692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Merlin=20G=C3=B6ttlinger?= Date: Wed, 15 Jun 2016 11:21:23 +0200 Subject: [PATCH 31/36] Fixed nesting on free monad documentation --- docs/src/main/tut/freemonad.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/src/main/tut/freemonad.md b/docs/src/main/tut/freemonad.md index 02d4e83f46..3fc33fdd27 100644 --- a/docs/src/main/tut/freemonad.md +++ b/docs/src/main/tut/freemonad.md @@ -461,10 +461,10 @@ From a computational point of view, `Free` recursive structure can be seen as a sequence of operations. - `Pure` returns an `A` value and ends the entire computation. -- `Suspend` is a continuation; it suspends the current computation - with the suspension functor `F` (which can represent a command for - example) and hands control to the caller. `A` represents a value - bound to this computation. + - `Suspend` is a continuation; it suspends the current computation + with the suspension functor `F` (which can represent a command for + example) and hands control to the caller. `A` represents a value + bound to this computation. Please note this `Free` construction has the interesting quality of _encoding_ the recursion on the heap instead of the stack as classic From 851855abe03672801fb45d562481c93fa0ca6a87 Mon Sep 17 00:00:00 2001 From: Adelbert Chang Date: Wed, 15 Jun 2016 09:57:42 -0700 Subject: [PATCH 32/36] Make composed instanes for binary type classes consisted with the unary ones --- core/src/main/scala/cats/Bifoldable.scala | 8 ++++---- core/src/main/scala/cats/Bitraverse.scala | 11 ++++++----- core/src/main/scala/cats/functor/Bifunctor.scala | 6 +++--- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/core/src/main/scala/cats/Bifoldable.scala b/core/src/main/scala/cats/Bifoldable.scala index 7350c5fe3c..5d7721c06c 100644 --- a/core/src/main/scala/cats/Bifoldable.scala +++ b/core/src/main/scala/cats/Bifoldable.scala @@ -18,7 +18,7 @@ trait Bifoldable[F[_, _]] extends Any with Serializable { self => ) def compose[G[_, _]](implicit ev: Bifoldable[G]): Bifoldable[λ[(α, β) => F[G[α, β], G[α, β]]]] = - new CompositeBifoldable[F, G] { + new ComposedBifoldable[F, G] { val F = self val G = ev } @@ -28,17 +28,17 @@ object Bifoldable { def apply[F[_, _]](implicit F: Bifoldable[F]): Bifoldable[F] = F } -trait CompositeBifoldable[F[_, _], G[_, _]] extends Bifoldable[λ[(α, β) => F[G[α, β], G[α, β]]]] { +private[cats] trait ComposedBifoldable[F[_, _], G[_, _]] extends Bifoldable[λ[(α, β) => F[G[α, β], G[α, β]]]] { implicit def F: Bifoldable[F] implicit def G: Bifoldable[G] - def bifoldLeft[A, B, C](fab: F[G[A, B], G[A, B]], c: C)(f: (C, A) => C, g: (C, B) => C): C = + override def bifoldLeft[A, B, C](fab: F[G[A, B], G[A, B]], c: C)(f: (C, A) => C, g: (C, B) => C): C = F.bifoldLeft(fab, c)( (c: C, gab: G[A, B]) => G.bifoldLeft(gab, c)(f, g), (c: C, gab: G[A, B]) => G.bifoldLeft(gab, c)(f, g) ) - def bifoldRight[A, B, C](fab: F[G[A, B], G[A, B]], c: Eval[C])(f: (A, Eval[C]) => Eval[C], g: (B, Eval[C]) => Eval[C]): Eval[C] = + override def bifoldRight[A, B, C](fab: F[G[A, B], G[A, B]], c: Eval[C])(f: (A, Eval[C]) => Eval[C], g: (B, Eval[C]) => Eval[C]): Eval[C] = F.bifoldRight(fab, c)( (gab: G[A, B], c: Eval[C]) => G.bifoldRight(gab, c)(f, g), (gab: G[A, B], c: Eval[C]) => G.bifoldRight(gab, c)(f, g) diff --git a/core/src/main/scala/cats/Bitraverse.scala b/core/src/main/scala/cats/Bitraverse.scala index 58ceaa7574..61057a6f21 100644 --- a/core/src/main/scala/cats/Bitraverse.scala +++ b/core/src/main/scala/cats/Bitraverse.scala @@ -1,6 +1,6 @@ package cats -import cats.functor.Bifunctor +import cats.functor.{Bifunctor, ComposedBifunctor} /** * A type class abstracting over types that give rise to two independent [[cats.Traverse]]s. @@ -15,7 +15,7 @@ trait Bitraverse[F[_, _]] extends Bifoldable[F] with Bifunctor[F] { self => /** If F and G are both [[cats.Bitraverse]] then so is their composition F[G[_, _], G[_, _]] */ def compose[G[_, _]](implicit ev: Bitraverse[G]): Bitraverse[λ[(α, β) => F[G[α, β], G[α, β]]]] = - new CompositeBitraverse[F, G] { + new ComposedBitraverse[F, G] { val F = self val G = ev } @@ -28,13 +28,14 @@ object Bitraverse { def apply[F[_, _]](implicit F: Bitraverse[F]): Bitraverse[F] = F } -trait CompositeBitraverse[F[_, _], G[_, _]] +private[cats] trait ComposedBitraverse[F[_, _], G[_, _]] extends Bitraverse[λ[(α, β) => F[G[α, β], G[α, β]]]] - with CompositeBifoldable[F, G] { + with ComposedBifoldable[F, G] + with ComposedBifunctor[F,G] { def F: Bitraverse[F] def G: Bitraverse[G] - def bitraverse[H[_]: Applicative, A, B, C, D]( + override def bitraverse[H[_]: Applicative, A, B, C, D]( fab: F[G[A, B], G[A, B]])( f: A => H[C], g: B => H[D] ): H[F[G[C, D], G[C, D]]] = diff --git a/core/src/main/scala/cats/functor/Bifunctor.scala b/core/src/main/scala/cats/functor/Bifunctor.scala index f6072573d5..2b11824677 100644 --- a/core/src/main/scala/cats/functor/Bifunctor.scala +++ b/core/src/main/scala/cats/functor/Bifunctor.scala @@ -26,7 +26,7 @@ trait Bifunctor[F[_, _]] extends Any with Serializable { self => /** The composition of two Bifunctors is itself a Bifunctor */ def compose[G[_, _]](implicit G0: Bifunctor[G]): Bifunctor[λ[(α, β) => F[G[α, β], G[α, β]]]] = - new CompositeBifunctor[F, G] { + new ComposedBifunctor[F, G] { val F = self val G = G0 } @@ -36,12 +36,12 @@ object Bifunctor { def apply[F[_, _]](implicit ev: Bifunctor[F]): Bifunctor[F] = ev } -trait CompositeBifunctor[F[_, _], G[_, _]] +private[cats] trait ComposedBifunctor[F[_, _], G[_, _]] extends Bifunctor[λ[(A, B) => F[G[A, B], G[A, B]]]] { def F: Bifunctor[F] def G: Bifunctor[G] - def bimap[A, B, C, D](fab: F[G[A, B], G[A, B]])(f: A => C, g: B => D): F[G[C, D], G[C, D]] = { + override def bimap[A, B, C, D](fab: F[G[A, B], G[A, B]])(f: A => C, g: B => D): F[G[C, D], G[C, D]] = { val innerBimap: G[A, B] => G[C, D] = gab => G.bimap(gab)(f, g) F.bimap(fab)(innerBimap, innerBimap) } From c3ead79c25caf41bb58b630b4414af8f7d753f98 Mon Sep 17 00:00:00 2001 From: Cody Allen Date: Thu, 16 Jun 2016 08:54:55 -0400 Subject: [PATCH 33/36] Add list syntax object Currently `import cats.syntax._` brings in the list syntax but there is no object to import only the list syntax. --- core/src/main/scala/cats/syntax/package.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/main/scala/cats/syntax/package.scala b/core/src/main/scala/cats/syntax/package.scala index 5b76537b5d..655c51f819 100644 --- a/core/src/main/scala/cats/syntax/package.scala +++ b/core/src/main/scala/cats/syntax/package.scala @@ -22,6 +22,7 @@ package object syntax { object functor extends FunctorSyntax object group extends GroupSyntax object invariant extends InvariantSyntax + object list extends ListSyntax object monadCombine extends MonadCombineSyntax object monadFilter extends MonadFilterSyntax object option extends OptionSyntax From e229bebcc1a8d5705d6ac3190e4836c452246038 Mon Sep 17 00:00:00 2001 From: Zainab Ali Date: Thu, 16 Jun 2016 18:56:11 +0100 Subject: [PATCH 34/36] Adding symbols chart --- docs/src/main/tut/symbols.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 docs/src/main/tut/symbols.md diff --git a/docs/src/main/tut/symbols.md b/docs/src/main/tut/symbols.md new file mode 100644 index 0000000000..000f800d2a --- /dev/null +++ b/docs/src/main/tut/symbols.md @@ -0,0 +1,31 @@ +#Symbols + +Below is a list of symbols used in cats. + +The `~>`, `⊥` and `⊤` symbols can be imported with `import cats._`. + +All other symbols can be imported with `import cats.implicits._` + +A scaladoc generated list is also available on the [Scaladoc symbols page](http://typelevel.org/cats/api/#index.index-_). + +| Symbol | Name | Typeclass | Definition | +| ---------- | ---------------------- | ---------------------------------------------------------------------------------------- |--------------------------------------- | +| `fa |@| fb`| Cartesian builder | [`Cartesian[F[_]]`]({{ site.sources }}/core/src/main/scala/cats/Cartesian.scala) | `|@|(fa: F[A])(fb: F[B]): F[(A, B)]` | +| `fa *> fb` | right apply | [`Cartesian[F[_]]`]({{ site.sources }}/core/src/main/scala/cats/Cartesian.scala) | `*>(fa: F[A])(fb: F[B]): F[A]` | +| `fa <* fb` | left apply | [`Cartesian[F[_]]`]({{ site.sources }}/core/src/main/scala/cats/Cartesian.scala) | `<*(fa: F[A])(fb: F[B]): F[B]` | +| `x === y` | equals | [`Eq[A]`]({{ site.sources }}/kernel/src/main/scala/cats/kernel/Eq.scala) | `eqv(x: A, y: A): Boolean` | +| `x =!= y` | not equals | [`Eq[A]`]({{ site.sources }}/kernel/src/main/scala/cats/kernel/Eq.scala) | `neqv(x: A, y: A): Boolean` | +| `fa >>= f` | flatMap | [`FlatMap[F[_]]`]({{ site.sources }}/core/src/main/scala/cats/FlatMap.scala) | `flatMap(fa: F[A])(f: A => F[B]): F[B]`| +| `fa >> fb` | followed by | [`FlatMap[F[_]]`]({{ site.sources }}/core/src/main/scala/cats/FlatMap.scala) | `followedBy(fa: F[A])(fb: F[B]): F[B]` | +| `x |-| y` | remove | [`Group[A]`]({{ site.sources }}/kernel/src/main/scala/cats/kernel/Group.scala) | `remove(x: A, y: A): A` | +| `x > y` | greater than | [`PartialOrder[A]`]({{ site.sources }}/kernel/src/main/scala/cats/kernel/PartialOrder.scala)| `gt(x: A, y: A): Boolean` | +| `x >= y` | greater than or equal | [`PartialOrder[A]`]({{ site.sources }}/kernel/src/main/scala/cats/kernel/PartialOrder.scala)| `gteq(x: A, y: A): Boolean` | +| `x < y` | less than | [`PartialOrder[A]`]({{ site.sources }}/kernel/src/main/scala/cats/kernel/PartialOrder.scala)| `lt(x: A, y: A): Boolean` | +| `x <= y` | less than or equal | [`PartialOrder[A]`]({{ site.sources }}/kernel/src/main/scala/cats/kernel/PartialOrder.scala)| `lteq(x: A, y: A): Boolean` | +| `x |+| y` | Semigroup combine | [`Semigroup[A]`]({{ site.sources }}/kernel/src/main/scala/cats/kernel/Semigroup.scala) | `combine(x: A, y: A): A` | +| `x <+> y` | SemigroupK combine | [`SemigroupK[F[_]]`]({{ site.sources }}/core/src/main/scala/cats/SemigroupK.scala) | `combineK(x: F[A], y: F[A]): F[A]` | +| `F ~> G` | natural transformation | [`FunctionK[F[_], G[_]]`]({{ site.sources }}/core/src/main/scala/cats/arrow/FunctionK.scala)| `FunctionK` alias | +| `F :<: G` | inject | [`Inject[F[_], G[_]]`]({{ site.sources }}/free/src/main/scala/cats/free/package.scala) | `Inject` alias | +| `F :≺: G` | inject | [`Inject[F[_], G[_]]`]({{ site.sources }}/free/src/main/scala/cats/free/package.scala) | `Inject` alias | +| `⊥` | bottom | [N/A]({{ site.sources }}/core/src/main/scala/cats/package.scala) | `Nothing` | +| `⊤` | top | [N/A]({{ site.sources }}/core/src/main/scala/cats/package.scala) | `Any` | \ No newline at end of file From 96b6f4dfa65b5b785cbea0c9511a7d77f853a6e1 Mon Sep 17 00:00:00 2001 From: peterneyens Date: Fri, 17 Jun 2016 20:47:48 +0200 Subject: [PATCH 35/36] Add SemigroupK and MonadCombine instances for StateT. --- core/src/main/scala/cats/data/StateT.scala | 48 +++++++++++--- .../test/scala/cats/tests/StateTTests.scala | 62 ++++++++++++++++--- 2 files changed, 93 insertions(+), 17 deletions(-) diff --git a/core/src/main/scala/cats/data/StateT.scala b/core/src/main/scala/cats/data/StateT.scala index 4b90add74f..6a87e6dba0 100644 --- a/core/src/main/scala/cats/data/StateT.scala +++ b/core/src/main/scala/cats/data/StateT.scala @@ -135,24 +135,32 @@ object StateT extends StateTInstances { StateT(s => F.pure((s, a))) } -private[data] sealed abstract class StateTInstances extends StateTInstances1 { +private[data] sealed trait StateTInstances extends StateTInstances1 { implicit def catsDataMonadStateForStateT[F[_], S](implicit F0: Monad[F]): MonadState[StateT[F, S, ?], S] = new StateTMonadState[F, S] { implicit def F = F0 } implicit def catsDataLiftForStateT[S]: TransLift.Aux[StateT[?[_], S, ?], Applicative] = - new TransLift[StateT[?[_], S, ?]] { - type TC[M[_]] = Applicative[M] - - def liftT[M[_]: Applicative, A](ma: M[A]): StateT[M, S, A] = StateT(s => Applicative[M].map(ma)(s -> _)) - } - + new StateTTransLift[S] {} } -private[data] sealed abstract class StateTInstances1 { +private[data] sealed trait StateTInstances1 extends StateTInstances2 { implicit def catsDataMonadRecForStateT[F[_], S](implicit F0: MonadRec[F]): MonadRec[StateT[F, S, ?]] = new StateTMonadRec[F, S] { implicit def F = F0 } } +private[data] sealed trait StateTInstances2 extends StateTInstances3 { + implicit def catsDataMonadCombineForStateT[F[_], S](implicit F0: MonadCombine[F]): MonadCombine[StateT[F, S, ?]] = + new StateTMonadCombine[F, S] { implicit def F = F0 } +} + +private[data] sealed trait StateTInstances3 { + implicit def catsDataMonadForStateT[F[_], S](implicit F0: Monad[F]): Monad[StateT[F, S, ?]] = + new StateTMonad[F, S] { implicit def F = F0 } + + implicit def catsDataSemigroupKForStateT[F[_], S](implicit F0: Monad[F], G0: SemigroupK[F]): SemigroupK[StateT[F, S, ?]] = + new StateTSemigroupK[F, S] { implicit def F = F0; implicit def G = G0 } +} + // To workaround SI-7139 `object State` needs to be defined inside the package object // together with the type alias. private[data] abstract class StateFunctions { @@ -195,8 +203,7 @@ private[data] sealed trait StateTMonad[F[_], S] extends Monad[StateT[F, S, ?]] { def flatMap[A, B](fa: StateT[F, S, A])(f: A => StateT[F, S, B]): StateT[F, S, B] = fa.flatMap(f) - override def map[A, B](fa: StateT[F, S, A])(f: A => B): StateT[F, S, B] = - fa.map(f) + override def map[A, B](fa: StateT[F, S, A])(f: A => B): StateT[F, S, B] = fa.map(f) } private[data] sealed trait StateTMonadState[F[_], S] extends MonadState[StateT[F, S, ?], S] with StateTMonad[F, S] { @@ -213,3 +220,24 @@ private[data] sealed trait StateTMonadRec[F[_], S] extends MonadRec[StateT[F, S, case (s, a) => F.map(f(a).run(s)) { case (s, ab) => ab.bimap((s, _), (s, _)) } }) } + +private[data] sealed trait StateTTransLift[S] extends TransLift[StateT[?[_], S, ?]] { + type TC[M[_]] = Applicative[M] + + def liftT[M[_]: Applicative, A](ma: M[A]): StateT[M, S, A] = StateT(s => Applicative[M].map(ma)(s -> _)) +} + +private[data] sealed trait StateTSemigroupK[F[_], S] extends SemigroupK[StateT[F, S, ?]] { + implicit def F: Monad[F] + implicit def G: SemigroupK[F] + + def combineK[A](x: StateT[F, S, A], y: StateT[F, S, A]): StateT[F, S, A] = + StateT(s => G.combineK(x.run(s), y.run(s))) +} + +private[data] sealed trait StateTMonadCombine[F[_], S] extends MonadCombine[StateT[F, S, ?]] with StateTMonad[F, S] with StateTSemigroupK[F, S] with StateTTransLift[S] { + implicit def F: MonadCombine[F] + override def G: MonadCombine[F] = F + + def empty[A]: StateT[F, S, A] = liftT[F, A](F.empty[A]) +} diff --git a/tests/src/test/scala/cats/tests/StateTTests.scala b/tests/src/test/scala/cats/tests/StateTTests.scala index 1f7b3aee75..096cc228f0 100644 --- a/tests/src/test/scala/cats/tests/StateTTests.scala +++ b/tests/src/test/scala/cats/tests/StateTTests.scala @@ -1,9 +1,9 @@ package cats package tests -import cats.kernel.std.tuple._ -import cats.laws.discipline.{CartesianTests, MonadRecTests, MonadStateTests, SerializableTests} import cats.data.{State, StateT} +import cats.kernel.std.tuple._ +import cats.laws.discipline._ import cats.laws.discipline.eq._ import cats.laws.discipline.arbitrary._ import org.scalacheck.Arbitrary @@ -114,14 +114,62 @@ class StateTTests extends CatsSuite { got should === (expected) } + + implicit val iso = CartesianTests.Isomorphisms.invariant[StateT[ListWrapper, Int, ?]](StateT.catsDataMonadForStateT(ListWrapper.monad)) + + { + // F has a Monad + implicit val F = ListWrapper.monad + + checkAll("StateT[ListWrapper, Int, Int]", MonadStateTests[StateT[ListWrapper, Int, ?], Int].monadState[Int, Int, Int]) + // checkAll("MonadState[StateT[ListWrapper, Int, ?], Int]", SerializableTests.serializable(MonadState[StateT[ListWrapper, Int, ?], Int])) + checkAll("MonadState[StateT[List, Int, ?], Int]", SerializableTests.serializable(MonadState[StateT[List, Int, ?], Int])) + + Monad[StateT[ListWrapper, Int, ?]] + FlatMap[StateT[ListWrapper, Int, ?]] + Applicative[StateT[ListWrapper, Int, ?]] + Apply[StateT[ListWrapper, Int, ?]] + Functor[StateT[ListWrapper, Int, ?]] + } + + { + // F has a MonadRec + implicit val F = ListWrapper.monadRec + + checkAll("StateT[ListWrapper, Int, Int]", MonadRecTests[StateT[ListWrapper, Int, ?]].monadRec[Int, Int, Int]) + checkAll("MonadRec[StateT[ListWrapper, Int, ?]]", SerializableTests.serializable(MonadRec[StateT[ListWrapper, Int, ?]])) + + Monad[StateT[ListWrapper, Int, ?]] + FlatMap[StateT[ListWrapper, Int, ?]] + Applicative[StateT[ListWrapper, Int, ?]] + Apply[StateT[ListWrapper, Int, ?]] + Functor[StateT[ListWrapper, Int, ?]] + } + { - implicit val iso = CartesianTests.Isomorphisms.invariant[StateT[Option, Int, ?]] + // F has a Monad and a SemigroupK + implicit def F = ListWrapper.monad + implicit def S = ListWrapper.semigroupK - checkAll("StateT[Option, Int, Int]", MonadStateTests[StateT[Option, Int, ?], Int].monadState[Int, Int, Int]) - checkAll("MonadState[StateT[Option, Int, ?], Int]", SerializableTests.serializable(MonadState[StateT[Option, Int, ?], Int])) + checkAll("StateT[ListWrapper, Int, Int]", SemigroupKTests[StateT[ListWrapper, Int, ?]].semigroupK[Int]) + checkAll("SemigroupK[StateT[ListWrapper, Int, ?]]", SerializableTests.serializable(SemigroupK[StateT[ListWrapper, Int, ?]])) + } - checkAll("StateT[Option, Int, Int]", MonadRecTests[StateT[Option, Int, ?]].monadRec[Int, Int, Int]) - checkAll("MonadRec[StateT[Option, Int, ?]]", SerializableTests.serializable(MonadRec[StateT[Option, Int, ?]])) + { + // F has a MonadCombine + implicit def F = ListWrapper.monadCombine + + checkAll("StateT[ListWrapper, Int, Int]", MonadCombineTests[StateT[ListWrapper, Int, ?]].monadCombine[Int, Int, Int]) + checkAll("MonadCombine[StateT[ListWrapper, Int, ?]]", SerializableTests.serializable(MonadCombine[StateT[ListWrapper, Int, ?]])) + + Monad[StateT[ListWrapper, Int, ?]] + FlatMap[StateT[ListWrapper, Int, ?]] + Alternative[StateT[ListWrapper, Int, ?]] + Applicative[StateT[ListWrapper, Int, ?]] + Apply[StateT[ListWrapper, Int, ?]] + Functor[StateT[ListWrapper, Int, ?]] + MonoidK[StateT[ListWrapper, Int, ?]] + SemigroupK[StateT[ListWrapper, Int, ?]] } { From 0e7c28b100bafef1ca2e82f71318ef8441246f2a Mon Sep 17 00:00:00 2001 From: peterneyens Date: Fri, 17 Jun 2016 22:14:04 +0200 Subject: [PATCH 36/36] Change get to lazy val for MonadState StateT instance. MonadState[StateT[List, Int, ?]] failed the serializable tests. --- core/src/main/scala/cats/data/StateT.scala | 2 +- tests/src/test/scala/cats/tests/StateTTests.scala | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/core/src/main/scala/cats/data/StateT.scala b/core/src/main/scala/cats/data/StateT.scala index 6a87e6dba0..09b6d56d51 100644 --- a/core/src/main/scala/cats/data/StateT.scala +++ b/core/src/main/scala/cats/data/StateT.scala @@ -207,7 +207,7 @@ private[data] sealed trait StateTMonad[F[_], S] extends Monad[StateT[F, S, ?]] { } private[data] sealed trait StateTMonadState[F[_], S] extends MonadState[StateT[F, S, ?], S] with StateTMonad[F, S] { - val get: StateT[F, S, S] = StateT(s => F.pure((s, s))) + lazy val get: StateT[F, S, S] = StateT(s => F.pure((s, s))) def set(s: S): StateT[F, S, Unit] = StateT(_ => F.pure((s, ()))) } diff --git a/tests/src/test/scala/cats/tests/StateTTests.scala b/tests/src/test/scala/cats/tests/StateTTests.scala index 096cc228f0..79f1a37ed1 100644 --- a/tests/src/test/scala/cats/tests/StateTTests.scala +++ b/tests/src/test/scala/cats/tests/StateTTests.scala @@ -122,8 +122,7 @@ class StateTTests extends CatsSuite { implicit val F = ListWrapper.monad checkAll("StateT[ListWrapper, Int, Int]", MonadStateTests[StateT[ListWrapper, Int, ?], Int].monadState[Int, Int, Int]) - // checkAll("MonadState[StateT[ListWrapper, Int, ?], Int]", SerializableTests.serializable(MonadState[StateT[ListWrapper, Int, ?], Int])) - checkAll("MonadState[StateT[List, Int, ?], Int]", SerializableTests.serializable(MonadState[StateT[List, Int, ?], Int])) + checkAll("MonadState[StateT[ListWrapper, Int, ?], Int]", SerializableTests.serializable(MonadState[StateT[ListWrapper, Int, ?], Int])) Monad[StateT[ListWrapper, Int, ?]] FlatMap[StateT[ListWrapper, Int, ?]]