Let's use a real world example. A string parser type class whose implicit instances are created by a function that delegates the creation to a factory.
import scala.reflect.runtime.universe.TypeTag
object Test {
trait Parser[+T] { def parse(input: String): T }
implicit def summonParserOf[T](implicit factory: ParserFactory[T]): Parser[T] = factory.build
trait ParserFactory[T] { def build: Parser[T] }
implicit def summonFactoryOfParsersOf[T](implicit t: TypeTag[T]): ParserFactory[T] =
new ParserFactory[T] {
def build: Parser[T] = new Parser[T] {
def parse(input: String) = {
println("T = " + t.tpe) // this outputs "T = Int" if Parser is non variant, and "T = Nothing" if Parser is covariant on T. Why?
null.asInstanceOf[T]
}
}
}
def main(args: Array[String]): Unit = {
val parserOfInt = implicitly[Parser[Int]]
parserOfInt.parse("")
}
}
The type parameter T
received by the factory is Int
when Parser
is non-variant, and Nothing
when it is covariant. Why?
Edit 1: The factory is not necessary. The replacement occurs before. So the test can be reduced to:
package jsfacile.test
import scala.reflect.runtime.universe.TypeTag
object Probando {
trait Parser[+T] { def parse(input: String): T }
implicit def summonParserOf[T](implicit t: TypeTag[T]): Parser[T] = new Parser[T] {
def parse(input: String): T = {
println("summon parser: T = " + t.tpe) // this outputs "T = Int" if Parser is non variant, and "T = Nothing" if Parser is covariant on T. Why?
null.asInstanceOf[T]
null.asInstanceOf[T]
}
}
def main(args: Array[String]): Unit = {
val parserOfInt = implicitly[Parser[Int]]
parserOfInt.parse("")
}
}
Parser[Nothing]
is assignable to Parser[Int]
, but which is the purpose of choosing the lower bound instead of the upper one?
Edit 2: The answer given by @Dmytro Mitin and the useful comments below, translated to my own words and limited scope of thinking, for future reference to myself.
What stopped me to understand was the wrong idea that, when the implicit value provider is a def
with parametrized result type, there is no set of living values from which the compiler has to pick one of. In that case, I thought, it just skips that step (the one that chooses the value with the most specific declared type).
And given the summoner function grants the compiler the power to build a value of any type, why not to fill the implicit parameter with a value that makes him happy. If the implicit parameter demands something assignable to a type T
then give it a value of type T
. Giving it Nothing
, which is assignable to everything, wouldn't be nice nor useful.
The problem with that idea arises when there is more than one summoner providing values assignable to the implicit parameter type. In that case, the only consistent way to decide which summoner to chose is to deduce the set of types of the values they produce, pick a type from said set based on an established criteria (the most specific, for instance), and choose the summoner that produces it.
Scala spec says
If there are several eligible arguments which match the implicit parameter's type, a most specific one will be chosen using the rules of static overloading resolution
https://scala-lang.org/files/archive/spec/2.11/07-implicits.html#implicit-parameters
Since you defined instances like
implicit def summonParserOf[T](implicit t: TypeTag[T]): Parser[T] = ...
for covariant
trait Parser[+T] { ... }
when you look for implicitly[Parser[T]]
, all summonParserOf[S]
(S <: T
) are eligible candidates, so the compiler selects the most specific one.