scala - `<:<`的隐式解析链是什么
问题描述
编译器能够提供有关类型参数的证据,例如:
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]
- 谁能在这里解释隐式解析链?如何
$conforms[A]: A <:< A
说服编译器创建实例的<:<[List[String], Seq[String]]
实例?或<:<[Dog, Animal]
。如果(何时).asInstanceOf
调用抛出异常会发生什么? - 为什么子类化是
=>
必要的?
解决方案
您可以在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
并且没有A
that 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
推荐阅读
- javascript - 未捕获的 ReferenceError:SayHi 未在 HTMLInputElement.onclick 中定义((索引):1)
- c# - Visual Studio 2017 调试检查不再起作用
- mysql - MariaDB 拒绝执行我的程序得到一个语法错误“CONN=3259”
- kotlin - Kotlin:数据类私有设置器公共获取器
- javascript - 如何在权限弹出时点击允许按钮
- c++ - Clang 和 Gcc 在实例化后的显式特化上存在分歧
- python - 为什么我的预测结果显示为 NaN?
- c# - 使用 RestSharp 库的不受支持的媒体类型
- django - 为什么我在 urls.py 文件中导入视图时遇到问题?
- c++ - C++17 部分演绎指南