From d5466149a55dcd8bdc8ae55eb4fefa0b5d669780 Mon Sep 17 00:00:00 2001 From: Luka Jacobowitz Date: Wed, 27 May 2020 11:59:30 -0400 Subject: [PATCH 1/4] Add auto variance as additional import --- .gitignore | 2 ++ core/src/main/scala/cats/AutoVariance.scala | 10 ++++++ core/src/main/scala/cats/implicits.scala | 4 ++- .../test/scala/cats/tests/VarianceSuite.scala | 32 +++++++++++++++++++ 4 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 core/src/main/scala/cats/AutoVariance.scala create mode 100644 tests/src/test/scala/cats/tests/VarianceSuite.scala diff --git a/.gitignore b/.gitignore index bebf6c3f5a..7c99f0ab71 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,8 @@ TAGS .DS_Store .vscode .sbtrc +.semanticdb +metals.sbt *.sublime-project *.sublime-workspace tests.iml diff --git a/core/src/main/scala/cats/AutoVariance.scala b/core/src/main/scala/cats/AutoVariance.scala new file mode 100644 index 0000000000..a3d21cc8b3 --- /dev/null +++ b/core/src/main/scala/cats/AutoVariance.scala @@ -0,0 +1,10 @@ +package cats + +trait AutoVariance { + implicit def autoWidenFunctor[F[_]: Functor, A, B >: A](fa: F[A]): F[B] = Functor[F].widen(fa) + + implicit def autoNarrowContravariant[F[_]: Contravariant, A, B <: A](fa: F[A]): F[B] = Contravariant[F].narrow(fa) + + implicit def autoLeftWidenBifunctor[F[_, _]: Bifunctor, A, B >: A, C](fac: F[A, C]): F[B, C] = + Bifunctor[F].leftWiden(fac) +} diff --git a/core/src/main/scala/cats/implicits.scala b/core/src/main/scala/cats/implicits.scala index 5c2f3202b9..183b2c5da1 100644 --- a/core/src/main/scala/cats/implicits.scala +++ b/core/src/main/scala/cats/implicits.scala @@ -16,4 +16,6 @@ object implicits with instances.AllInstancesBinCompat3 with instances.AllInstancesBinCompat4 with instances.AllInstancesBinCompat5 - with instances.AllInstancesBinCompat6 + with instances.AllInstancesBinCompat6 { + object variance extends AutoVariance +} diff --git a/tests/src/test/scala/cats/tests/VarianceSuite.scala b/tests/src/test/scala/cats/tests/VarianceSuite.scala new file mode 100644 index 0000000000..35cc4a98d0 --- /dev/null +++ b/tests/src/test/scala/cats/tests/VarianceSuite.scala @@ -0,0 +1,32 @@ +package cats.tests + +import cats.{Bifunctor, Contravariant, Functor} +import cats.implicits._ +import cats.implicits.variance._ + +class VarianceSuite extends CatsSuite { + + sealed trait Foo + case class Bar(x: Int) extends Foo + case object Baz extends Foo + + test("Auto-variance should infer subtypes correctly") { + def shouldInfer[F[_]: Functor](fi: F[Int]) = + fi.map(i => if (true) Left(Bar(i)) else Right(Baz)) + + def inferred[F[_]: Functor](fi: F[Int]): F[Either[Foo, Foo]] = shouldInfer[F](fi) + } + + test("Auto-variance should infer supertypes correctly") { + def shouldCompile[F[_]: Contravariant](fi: F[Foo])(f: F[Bar] => Int) = + f(fi) + } + + test("Auto-variance should left widen a bifunctor automatically") { + def shouldInfer[F[_, _]: Bifunctor](fi: F[Int, Int]) = + fi.leftMap(i => if (true) Left(Bar(i)) else Right(Baz)) + + def inferred[F[_, _]: Bifunctor](fi: F[Int, Int]): F[Either[Foo, Foo], Int] = shouldInfer[F](fi) + } + +} From 9d140bd6dd3da20d51db0dc4c78140731499fb19 Mon Sep 17 00:00:00 2001 From: Luka Jacobowitz Date: Wed, 27 May 2020 14:27:36 -0400 Subject: [PATCH 2/4] Full Bifunctor widening --- core/src/main/scala/cats/AutoVariance.scala | 9 ++++++--- tests/src/test/scala/cats/tests/VarianceSuite.scala | 6 +++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/core/src/main/scala/cats/AutoVariance.scala b/core/src/main/scala/cats/AutoVariance.scala index a3d21cc8b3..8a8cbddced 100644 --- a/core/src/main/scala/cats/AutoVariance.scala +++ b/core/src/main/scala/cats/AutoVariance.scala @@ -1,10 +1,13 @@ package cats -trait AutoVariance { +trait AutoVariance extends AutoVarianceLowPriority { implicit def autoWidenFunctor[F[_]: Functor, A, B >: A](fa: F[A]): F[B] = Functor[F].widen(fa) implicit def autoNarrowContravariant[F[_]: Contravariant, A, B <: A](fa: F[A]): F[B] = Contravariant[F].narrow(fa) - implicit def autoLeftWidenBifunctor[F[_, _]: Bifunctor, A, B >: A, C](fac: F[A, C]): F[B, C] = - Bifunctor[F].leftWiden(fac) +} + +trait AutoVarianceLowPriority { + implicit def autoWidenBifunctor[F[_, _]: Bifunctor, A, B >: A, C, D >: C](fac: F[A, C]): F[B, D] = + Bifunctor[F].leftWiden(Bifunctor[F].rightFunctor.widen(fac)) } diff --git a/tests/src/test/scala/cats/tests/VarianceSuite.scala b/tests/src/test/scala/cats/tests/VarianceSuite.scala index 35cc4a98d0..dc627b768d 100644 --- a/tests/src/test/scala/cats/tests/VarianceSuite.scala +++ b/tests/src/test/scala/cats/tests/VarianceSuite.scala @@ -22,11 +22,11 @@ class VarianceSuite extends CatsSuite { f(fi) } - test("Auto-variance should left widen a bifunctor automatically") { + test("Auto-variance should widen a bifunctor automatically") { def shouldInfer[F[_, _]: Bifunctor](fi: F[Int, Int]) = - fi.leftMap(i => if (true) Left(Bar(i)) else Right(Baz)) + fi.bimap(i => if (true) Left(Bar(i)) else Right(Baz), i => if (true) Left(Bar(i)) else Right(Baz)) - def inferred[F[_, _]: Bifunctor](fi: F[Int, Int]): F[Either[Foo, Foo], Int] = shouldInfer[F](fi) + def inferred[F[_, _]: Bifunctor](fi: F[Int, Int]): F[Either[Foo, Foo], Either[Foo, Foo]] = shouldInfer[F](fi) } } From e63c4d5fcc05459748ef8110801606e2555826c1 Mon Sep 17 00:00:00 2001 From: Luka Jacobowitz Date: Thu, 28 May 2020 11:15:48 -0400 Subject: [PATCH 3/4] Switch precedence --- core/src/main/scala/cats/AutoVariance.scala | 6 +++--- .../src/test/scala/cats/tests/VarianceSuite.scala | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/core/src/main/scala/cats/AutoVariance.scala b/core/src/main/scala/cats/AutoVariance.scala index 8a8cbddced..0df16d1467 100644 --- a/core/src/main/scala/cats/AutoVariance.scala +++ b/core/src/main/scala/cats/AutoVariance.scala @@ -1,13 +1,13 @@ package cats trait AutoVariance extends AutoVarianceLowPriority { - implicit def autoWidenFunctor[F[_]: Functor, A, B >: A](fa: F[A]): F[B] = Functor[F].widen(fa) + implicit def autoWidenBifunctor[F[_, _]: Bifunctor, A, B >: A, C, D >: C](fac: F[A, C]): F[B, D] = + Bifunctor[F].leftWiden(Bifunctor[F].rightFunctor.widen(fac)) implicit def autoNarrowContravariant[F[_]: Contravariant, A, B <: A](fa: F[A]): F[B] = Contravariant[F].narrow(fa) } trait AutoVarianceLowPriority { - implicit def autoWidenBifunctor[F[_, _]: Bifunctor, A, B >: A, C, D >: C](fac: F[A, C]): F[B, D] = - Bifunctor[F].leftWiden(Bifunctor[F].rightFunctor.widen(fac)) + implicit def autoWidenFunctor[F[_]: Functor, A, B >: A](fa: F[A]): F[B] = Functor[F].widen(fa) } diff --git a/tests/src/test/scala/cats/tests/VarianceSuite.scala b/tests/src/test/scala/cats/tests/VarianceSuite.scala index dc627b768d..89813bb09d 100644 --- a/tests/src/test/scala/cats/tests/VarianceSuite.scala +++ b/tests/src/test/scala/cats/tests/VarianceSuite.scala @@ -29,4 +29,18 @@ class VarianceSuite extends CatsSuite { def inferred[F[_, _]: Bifunctor](fi: F[Int, Int]): F[Either[Foo, Foo], Either[Foo, Foo]] = shouldInfer[F](fi) } + test("Auto-variance should left widen a bifunctor automatically") { + def shouldInfer[F[_, _]: Bifunctor](fi: F[Int, Int]) = + fi.bimap(identity, i => if (true) Left(Bar(i)) else Right(Baz)) + + def inferred[F[_, _]: Bifunctor](fi: F[Int, Int]): F[Int, Either[Foo, Foo]] = shouldInfer[F](fi) + } + + test("Auto-variance should right widen a bifunctor automatically") { + def shouldInfer[F[_, _]: Bifunctor](fi: F[Int, Int]) = + fi.bimap(i => if (true) Left(Bar(i)) else Right(Baz), identity) + + def inferred[F[_, _]: Bifunctor](fi: F[Int, Int]): F[Either[Foo, Foo], Int] = shouldInfer[F](fi) + } + } From 7bae2723ae5f723f86c682b237b01cc19b282625 Mon Sep 17 00:00:00 2001 From: Luka Jacobowitz Date: Sun, 31 May 2020 15:59:59 -0400 Subject: [PATCH 4/4] move variance conversions to its own package --- .../VarianceConversions.scala} | 5 +++-- core/src/main/scala/cats/conversions/all.scala | 3 +++ core/src/main/scala/cats/conversions/package.scala | 6 ++++++ core/src/main/scala/cats/implicits.scala | 4 +--- tests/src/test/scala/cats/tests/VarianceSuite.scala | 2 +- 5 files changed, 14 insertions(+), 6 deletions(-) rename core/src/main/scala/cats/{AutoVariance.scala => conversions/VarianceConversions.scala} (74%) create mode 100644 core/src/main/scala/cats/conversions/all.scala create mode 100644 core/src/main/scala/cats/conversions/package.scala diff --git a/core/src/main/scala/cats/AutoVariance.scala b/core/src/main/scala/cats/conversions/VarianceConversions.scala similarity index 74% rename from core/src/main/scala/cats/AutoVariance.scala rename to core/src/main/scala/cats/conversions/VarianceConversions.scala index 0df16d1467..7e8b7f7697 100644 --- a/core/src/main/scala/cats/AutoVariance.scala +++ b/core/src/main/scala/cats/conversions/VarianceConversions.scala @@ -1,6 +1,7 @@ package cats +package conversions -trait AutoVariance extends AutoVarianceLowPriority { +trait VarianceConversions extends VarianceConversionsLowPriority { implicit def autoWidenBifunctor[F[_, _]: Bifunctor, A, B >: A, C, D >: C](fac: F[A, C]): F[B, D] = Bifunctor[F].leftWiden(Bifunctor[F].rightFunctor.widen(fac)) @@ -8,6 +9,6 @@ trait AutoVariance extends AutoVarianceLowPriority { } -trait AutoVarianceLowPriority { +private[cats] trait VarianceConversionsLowPriority { implicit def autoWidenFunctor[F[_]: Functor, A, B >: A](fa: F[A]): F[B] = Functor[F].widen(fa) } diff --git a/core/src/main/scala/cats/conversions/all.scala b/core/src/main/scala/cats/conversions/all.scala new file mode 100644 index 0000000000..676b563542 --- /dev/null +++ b/core/src/main/scala/cats/conversions/all.scala @@ -0,0 +1,3 @@ +package cats.conversions + +trait AllConversions extends VarianceConversions diff --git a/core/src/main/scala/cats/conversions/package.scala b/core/src/main/scala/cats/conversions/package.scala new file mode 100644 index 0000000000..ac47bccbf5 --- /dev/null +++ b/core/src/main/scala/cats/conversions/package.scala @@ -0,0 +1,6 @@ +package cats + +package object conversions { + object all extends AllConversions + object variance extends VarianceConversions +} diff --git a/core/src/main/scala/cats/implicits.scala b/core/src/main/scala/cats/implicits.scala index 183b2c5da1..5c2f3202b9 100644 --- a/core/src/main/scala/cats/implicits.scala +++ b/core/src/main/scala/cats/implicits.scala @@ -16,6 +16,4 @@ object implicits with instances.AllInstancesBinCompat3 with instances.AllInstancesBinCompat4 with instances.AllInstancesBinCompat5 - with instances.AllInstancesBinCompat6 { - object variance extends AutoVariance -} + with instances.AllInstancesBinCompat6 diff --git a/tests/src/test/scala/cats/tests/VarianceSuite.scala b/tests/src/test/scala/cats/tests/VarianceSuite.scala index 89813bb09d..33d029b8f6 100644 --- a/tests/src/test/scala/cats/tests/VarianceSuite.scala +++ b/tests/src/test/scala/cats/tests/VarianceSuite.scala @@ -2,7 +2,7 @@ package cats.tests import cats.{Bifunctor, Contravariant, Functor} import cats.implicits._ -import cats.implicits.variance._ +import cats.conversions.all._ class VarianceSuite extends CatsSuite {