- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Why does implicit def conforms[T] return the subclass instance for implicit ev: Sub <:< Super?
Thu, 2011-08-11, 02:38
When I compile
import java.util._
object Main extends App {
println(implicitly[GregorianCalendar <:< Calendar])
}
with -Xprint:typer, I can see which evidence object I get. It is
scala.this.Predef.conforms[java.util.GregorianCalendar].
In Predef, we find these immortal lines:
sealed abstract class <:<[-From, +To] extends (From => To) with Serializable
implicit def conforms[A]: A <:< A = new (A <:< A) { def apply(x: A) = x }
The way I understand it, one looks for an implicit GregorianCalendar
<:< Calendar instance. Or an instance of a subtype. Indeed,
conforms[GregorianCalendar] is such a subtype instance. But so is
conforms[Calendar], as the REPL confirms:
val ev1: GregorianCalendar <:< Calendar = conforms[GregorianCalendar]
ev1: <:<[java.util.GregorianCalendar,java.util.Calendar] =
val ev2: GregorianCalendar <:< Calendar = conforms[Calendar]
ev2: <:<[java.util.GregorianCalendar,java.util.Calendar] =
Why isn't this ambiguous?
Thanks,
Cay
On Thu, Aug 11, 2011 at 3:38 AM, Cay Horstmann wrote:
> When I compile
>
> import java.util._
>
> object Main extends App {
> println(implicitly[GregorianCalendar <:< Calendar])
> }
>
> with -Xprint:typer, I can see which evidence object I get. It is
> scala.this.Predef.conforms[java.util.GregorianCalendar].
>
> In Predef, we find these immortal lines:
>
> sealed abstract class <:<[-From, +To] extends (From => To) with Serializable
> implicit def conforms[A]: A <:< A = new (A <:< A) { def apply(x: A) = x }
>
> The way I understand it, one looks for an implicit GregorianCalendar
> <:< Calendar instance. Or an instance of a subtype. Indeed,
> conforms[GregorianCalendar] is such a subtype instance. But so is
> conforms[Calendar], as the REPL confirms:
>
> val ev1: GregorianCalendar <:< Calendar = conforms[GregorianCalendar]
> ev1: <:<[java.util.GregorianCalendar,java.util.Calendar] =
> val ev2: GregorianCalendar <:< Calendar = conforms[Calendar]
> ev2: <:<[java.util.GregorianCalendar,java.util.Calendar] =
>
> Why isn't this ambiguous?
An implicit method can't be ambiguous with itself. Type inference
selects the most specific type argument.
scala> class A; class B extends A
defined class A
defined class B
scala> conforms[A]: (B => A)
res1: B => A =
scala> conforms[B]: (B => A)
res2: B => A =
scala> conforms: (B => A)
res3: B => A =
// (scala.this.Predef.conforms[B]
For more details, see the section Local Type Inference in the SLS.
-jason