首页 > 解决方案 > `<:<`的隐式解析链是什么

问题描述

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

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

看一下<:<inPredef的类型定义

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. 为什么子类化是=>必要的?

标签: scala

解决方案


您可以在scala.Predef对象中看到它:https ://github.com/scala-native/scala-native/blob/master/scalalib/overrides-2.11/scala/Predef.scala#L372

@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并且没有Athat conformsT <: A <: D时,编译器不会编译它,因为没有<:<[A, A]that conforms <:<[A, A] <: <:<[T, D]。因此,永远不要在运行时.asInstanceOf内部引发异常。$conforms

另外,关于它的一篇非常好的博客文章:http: //blog.bruchez.name/2015/11/generalized-type-constraints-in-scala.html


推荐阅读