Skip to content

Instantly share code, notes, and snippets.

@retronym
Created December 21, 2009 12:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save retronym/260934 to your computer and use it in GitHub Desktop.
Save retronym/260934 to your computer and use it in GitHub Desktop.
How the Scala compiler prioritises implicits based on return types in the face of variance.
trait A
trait B extends A
trait C extends B
{
trait Covariant[+X]
type Expected = Covariant[A]
type CandidateB = Covariant[B]
type CandidateC = Covariant[C]
implicitly[CandidateB <:< Expected]
implicitly[CandidateC <:< Expected]
implicitly[CandidateC <:< CandidateB]
implicit val cb: CandidateB = new CandidateB {}
implicit val cc: CandidateC = new CandidateC {}
// compiler chooses CandidateC because CandidateA <:< CandidateC
assert(implicitly[Expected] eq cc)
}
{
trait Contravariant[-X]
type Expected = Contravariant[C]
type CandidateB = Contravariant[B]
type CandidateA = Contravariant[A]
implicitly[CandidateA <:< Expected]
implicitly[CandidateB <:< Expected]
implicitly[CandidateA <:< CandidateB]
implicit val cb: CandidateB = new CandidateB {}
implicit val ca: CandidateA = new CandidateA {}
// compiler chooses CandidateA because CandidateA <:< CandidateB.
assert(implicitly[Expected] eq ca)
}
/*Infer.scala
private def isAsSpecificValueType(tpe1: Type, tpe2: Type, undef1: List[Symbol], undef2: List[Symbol]): Boolean = (tpe1, tpe2) match {
case (PolyType(tparams1, rtpe1), _) =>
isAsSpecificValueType(rtpe1, tpe2, undef1 ::: tparams1, undef2)
case (_, PolyType(tparams2, rtpe2)) =>
isAsSpecificValueType(tpe1, rtpe2, undef1, undef2 ::: tparams2)
case _ =>
existentialAbstraction(undef1, tpe1) <:< existentialAbstraction(undef2, tpe2)
}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment