在编译器中,<:<,<%<,=:=的Scala实现究竟是如何工作的?

Urb*_*ond 7 compiler-construction scala operators type-equivalence

我现在看到有一个相关的问题,询问这些运算符(<:<,<%<,=:=)在这里做什么:

Scala 2.8中<:<,<%<和=:=的含义是什么?它们在哪里记录?

但我仍然对他们的实施感到困惑.特别是,我假设一旦你放置了一个断言特定关系的隐式参数,那么你可以使用变量,好像它们已经自动被正确地转换,例如这将编译:

class Foo[T](a: T) {
  def splitit(implicit ev: T <:< String) = a split " "
}
Run Code Online (Sandbox Code Playgroud)

但是这在编译器中实际上是如何工作的呢?是否有一些神奇的编译器支持这些运算符,如果没有,它的底层机制是什么允许它从定义中推断出这种关系?(这个机制是否专门用于允许这些运算符工作,以及它对这些特定运算符的具体程度如何?)您可以放置​​一个额外的隐式参数,这样会以某种方式更改编译器对类型的解释,这似乎有点神奇.

Kai*_*ito 8

实施有点棘手,但没有什么神奇之处.

有一种隐式方法Predef可以A <:< A为任何类型提供类型的值A

implicit def conforms[A]: A <:< A
Run Code Online (Sandbox Code Playgroud)

当您尝试调用方法时,它会查找类型的隐式值T <:< String.编译器将检查是否conforms[T]是有效值.比方说,TNothing那么就会有一个隐含的值Nothing <:< Nothing范围,这将使你的方法调用编译.由于方式<:<定义

sealed abstract class <:<[-From, +To]
Run Code Online (Sandbox Code Playgroud)

From允许变化,To允许变化.所以a Nothing <:< Nothing仍然是有效的,Nothing <:< String因为它Nothing是一个子类型String.A String <:< String也是有效的,Nothing <:< String因为String是超类型Nothing(但编译器似乎总是选择第一种类型).

你可以调用的方法String就可以了,因为<:<还延伸=>又名Function1并作为从隐式转换TString,基本上结束了做一个安全的演员.

=:= 是相同的,除了它没有任何方差注释定义,因此类型必须完全匹配.

<%<定义类似<:<但隐式方法有点不同,它添加了另一个参数来指定视图绑定

implicit def conformsOrViewsAs[A <% B, B]: A <%< B
Run Code Online (Sandbox Code Playgroud)

它也被弃用了.