Skip to content

Commit

Permalink
Add auto variance as additional import (#3436)
Browse files Browse the repository at this point in the history
* Add auto variance as additional import

* Full Bifunctor widening

* Switch precedence

* move variance conversions to its own package
  • Loading branch information
LukaJCB authored Jun 1, 2020
1 parent b106229 commit 4b3d3ff
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ TAGS
.DS_Store
.vscode
.sbtrc
.semanticdb
metals.sbt
*.sublime-project
*.sublime-workspace
tests.iml
Expand Down
14 changes: 14 additions & 0 deletions core/src/main/scala/cats/conversions/VarianceConversions.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package cats
package conversions

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))

implicit def autoNarrowContravariant[F[_]: Contravariant, A, B <: A](fa: F[A]): F[B] = Contravariant[F].narrow(fa)

}

private[cats] trait VarianceConversionsLowPriority {
implicit def autoWidenFunctor[F[_]: Functor, A, B >: A](fa: F[A]): F[B] = Functor[F].widen(fa)
}
3 changes: 3 additions & 0 deletions core/src/main/scala/cats/conversions/all.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package cats.conversions

trait AllConversions extends VarianceConversions
6 changes: 6 additions & 0 deletions core/src/main/scala/cats/conversions/package.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package cats

package object conversions {
object all extends AllConversions
object variance extends VarianceConversions
}
46 changes: 46 additions & 0 deletions tests/src/test/scala/cats/tests/VarianceSuite.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package cats.tests

import cats.{Bifunctor, Contravariant, Functor}
import cats.implicits._
import cats.conversions.all._

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 widen a bifunctor automatically") {
def shouldInfer[F[_, _]: Bifunctor](fi: F[Int, Int]) =
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], 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)
}

}

0 comments on commit 4b3d3ff

Please sign in to comment.