什么是`<:<`的隐式解析链

时间:2018-09-28 09:53:35

标签: scala

编译器能够提供有关类型参数的证据,例如:

def foo[A, B](implicit ev: A <:< B): B

<:<中查看Predef的类型定义

sealed abstract class <:<[-From, +To] extends (From => To) with Serializable
private[this] final val singleton_<:< = new <:<[Any,Any] { def apply(x: Any): Any = x }
implicit def $conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A]
  1. 有人可以在这里解释隐式解析链吗? $conforms[A]: A <:< A如何才能说服编译器例如创建<:<[List[String], Seq[String]]的实例?或<:<[Dog, Animal]。如果.asInstanceOf调用引发异常,会发生什么?
  2. 为什么必须=>的子类化?

1 个答案:

答案 0 :(得分:0)

您可以在scala.Predef对象中看到它:interp1

@implicitNotFound(msg = "Cannot prove that ${From} <:< ${To}.")
sealed abstract class <:<[-From, +To] extends (From => To) with Serializable

private[this] lazy val singleton_<:< = new <:<[Any,Any] { def apply(x: Any): Any = x }
@inline implicit def $conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A]

@deprecated("Use `implicitly[T <:< U]` or `identity` instead.", "2.11.0")
def conforms[A]: A <:< A = $conforms[A]

<:<[-From, +To]Form上是协变的,而在To上是协变的,因此<:<[Seq[String], Seq[String]]<:<[List[String], Seq[String]]的子类型(因为List[String]是...的子类型Seq[String]-From是互变的。因此,当您编写implicit ev List[String] <:< Seq[String]时,编译器将使用<:<[Seq[String], Seq[String]]

当您编写implicit ev T <:< D并且没有符合A的{​​{1}}时,编译器不会编译它,因为没有T <: A <: D符合{{1 }}。因此,<:<[A, A]永远不会在运行时在<:<[A, A] <: <:<[T, D]内部引发异常。

另外,一篇非常好的博客文章:https://github.com/scala-native/scala-native/blob/master/scalalib/overrides-2.11/scala/Predef.scala#L372