Skip to content

Instantly share code, notes, and snippets.

@djspiewak
Created May 26, 2020 23:59
Show Gist options
  • Save djspiewak/c800940342e06f86ece8e715f7c8634d to your computer and use it in GitHub Desktop.
Save djspiewak/c800940342e06f86ece8e715f7c8634d to your computer and use it in GitHub Desktop.
import cats.{Applicative, Contravariant, Functor}
import cats.implicits._
implicit def covariance[F[_]: Functor, A, B >: A](fa: F[A]): F[B] =
fa.widen
implicit def contravariance[F[_]: Contravariant, A, B <: A](fa: F[A]): F[B] =
fa.narrow
def test[F[_]: Applicative, A](a: A) = {
if (42 > 24)
Some(a).pure[F]
else
None.pure[F]
}
@leigh-perry
Copy link

Very nice! Unfortunately it still compiles without the covariance implicit, but the return type of test is Any rather than F[Option[A]] :-)

@djspiewak
Copy link
Author

That is quite correct that it compiles without the implicit, but obviously Any isn't a useful type here. :-) Normally you would hit this case with a type annotation already on test. Without covariance, the type of the if/else is inferred to Any and then the type annotation F[Option[A]] would be an error. The implicit fixes this.

The only reason I didn't put the annotation on here is I wanted to test that the type inference was able to piece together the correct thing without any help. There are a number of situations where type inference uses expected result type in working out what a type should be, particularly when resolving implicits. I just wanted to avoid that situation entirely.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment