小编典典

<:<、<%< 和 =:= 在 Scala 2.8 中是什么意思,它们在哪里记录?

all

我可以在Predef的 API 文档中看到它们是通用函数类型
(From) => To 的子类,但仅此而已。嗯什么?也许某处有文档,但是搜索引擎不能很好地处理像“<:<”这样的“名称”,所以我一直无法找到它。

后续问题:我什么时候应该使用这些时髦的符号/类,为什么?


阅读 64

收藏
2022-06-28

共1个答案

小编典典

这些称为 广义类型约束 。它们允许您从类型参数化的类或特征中 进一步约束 其类型参数之一。这是一个例子:

case class Foo[A](a:A) { // 'A' can be substituted with any type
    // getStringLength can only be used if this is a Foo[String]
    def getStringLength(implicit evidence: A =:= String) = a.length
}

隐式参数evidence由编译器提供,当且仅AString. 你可以把它看作是一个证明 —— 论证本身并不重要,只知道它存在。
[编辑:嗯,从技术上讲,它实际上很重要,因为它表示从 to的隐式转换 ,这使您可以调用 而不会让编译器对您大喊大叫]A``String
A``String``a.length

现在我可以像这样使用它:

scala> Foo("blah").getStringLength
res6: Int = 4

但是,如果我尝试将它与Foo包含 a 以外的其他内容一起使用String

scala> Foo(123).getStringLength
<console>:9: error: could not find implicit value for parameter evidence: =:=[Int,String]

您可以将该错误理解为“无法找到 Int == String 的证据”......应该是这样!对类型的限制超出getStringLength一般 要求
;即,您只能在 a上调​​用。这个约束是在编译时强制执行的,这很酷!A``Foo``getStringLength``Foo[String]

<:<<%<工作类似,但略有不同:

  • A =:= B意味着 A 必须恰好是 B
  • A <:< B表示 A 必须是 B 的子类型(类似于 简单 类型约束<:
  • A <%< B意味着 A 必须像 B 一样 可见 ,可能通过隐式转换(类似于简单类型约束<%

@retronym
的这个片段
很好地解释了这种事情过去是如何完成的,以及通用类型约束现在如何使它变得更容易。

附录

为了回答您的后续问题,诚然,我给出的示例非常做作,显然没有用。但是想象一下,用它来定义一个List.sumInts方法之类的东西,它加起来一个整数列表。您不想允许在任何
old 上调用此方法List,只是在List[Int]. 但是List类型构造函数不能这么受限制;您仍然希望能够拥有字符串、foos、bars
和诸如此类的列表。因此,通过在 上放置通用类型约束sumInts,您可以确保 该方法 具有只能在
上使用的附加约束List[Int]。本质上,您正在为某些类型的列表编写特殊情况代码。

2022-06-28