scala - < :<, <%< 和 = := mean in Scala 2. 8 有何作用,它们记录在哪里?

标签 scala scala-2.8 type-constraints

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

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

最佳答案

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

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 。您可以将其视为 A证明String ——论证本身并不重要,重要的是知道它存在。 [编辑:嗯,从技术上来说它实际上很重要,因为它代表了 A 的隐式转换。至String ,这可以让您调用 a.length并且不会让编译器对你大喊大叫]

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

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

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

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

您可以将该错误解读为“无法找到 Int == String 的证据”...这就是它应该的样子! getStringLengthA 的类型施加进一步的限制比什么Foo一般要求;也就是说,您只能调用 getStringLengthFoo[String]上。这个约束在编译时强制执行,这很酷!

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

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

This snippet @retronym 很好地解释了此类事情过去是如何完成的,以及通用类型约束现在如何使其变得更容易。

附录

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

关于scala - < :<, <%< 和 = := mean in Scala 2. 8 有何作用,它们记录在哪里?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3427345/

相关文章:

haskell - 默认约束类型被忽略

scala - 如何获取上传文件的路径

scala - 获取 Scala 列表中的项目?

scala:如何链接不同类型的部分函数

scala - 在 scala 中拉皮条我的函数 - 对函数应用隐式转换

generics - 有没有办法表达具有不同生命周期界限的 "same"泛型类型?

scala - IntelliJ 添加(本地)项目作为另一个项目的依赖项

programming-languages - Scala "continuations"只是用于定义和使用回调函数的时髦语法吗?

generics - Scala 2.8 CanBuildFrom

haskell - 类型族实例中的类型级约束