Scala 2.8 CanBuildFrom

2024-01-06

继我问的另一个问题之后,Scala 2.8 突破 https://stackoverflow.com/questions/1715681/scala-2-8-breakout,我想更多地了解一下 Scala 方法TraversableLike[A].map其签名如下:

def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That

请注意有关此方法的一些事项:

  • 它需要一个函数来转动每个A在可遍历成B.
  • 它返回That并采用类型的隐式参数CanBuildFrom[Repr, B, That].

我可以这样称呼它:

> val s: Set[Int] = List("Paris", "London").map(_.length)
s: Set[Int] Set(5,6)

What 我不太明白事实是怎样的That is bound to B(也就是说,它是 B 的某个集合)由编译器强制执行。类型参数看起来独立于上面的签名和特征的签名CanBuildFrom itself:

trait CanBuildFrom[-From, -Elem, +To]

Scala 编译器如何确保That不可能是forced陷入一些没有意义的事情?

> val s: Set[String] = List("Paris", "London").map(_.length) //will not compile

编译器如何决定隐含的内容CanBuildFrom对象是否在调用范围内?


请注意,第二个参数map是一个隐含的论点。那里must是具有适当类型的隐式范围,否则,您must通过这样的论证。

在你的例子中,That必须是Set[String], B 必须是Int and Repr必须是List[String]。因此,为了进行编译,您需要在范围内包含以下隐式对象:

implicit object X: CanBuildFrom[List[String], Int, Set[String]]

范围内不存在这样的事情。还,breakOut无法提供它,因为它本身需要一个隐式的CanBuildFrom,其第一个类型可以是任何类(Nothing),但受到其他类型的限制。

例如,看一下CanBuildFrom来自伴随对象的工厂List:

implicit def  canBuildFrom [A] : CanBuildFrom[List, A, List[A]]  

因为它通过绑定第二个和第三个参数A,所讨论的隐含内容将不起作用。

那么,对于这些隐含的内容,人们如何知道去哪里寻找呢?首先,Scala 确实将一些东西导入到所有范围中。现在,我可以回忆起以下进口:

import scala.package._ // Package object
import scala.Predef._  // Object
// import scala.LowPriorityImplicits, class inherited by Predef
import scala.runtime._ // Package

由于我们关心隐式,请注意,当您从包中导入内容时,唯一可能的隐式是单例。另一方面,当您从对象(单例)导入内容时,您可以拥有隐式定义、值和单例。

目前,有CanBuildFrom隐式的内部Predef and LowPriorityImplicits,与字符串有关。它们使我们能够写作"this is a string" map (_.toInt).

那么,除了这些自动导入以及您进行的显式导入之外,还能在哪里找到隐式导入呢?一处:应用该方法的实例的伴生对象。

我说伴生对象s,以复数形式,因为相关实例的类继承的所有特征和类的伴生对象可能包含相关的隐式。我不确定实例本身是否可能包含隐式。老实说,我现在无法重现这一点,所以我肯定在这里犯了某种错误。

无论如何,看看伴生物体的内部。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Scala 2.8 CanBuildFrom 的相关文章

随机推荐