CanBuildFrom 如何知道一个类型是否可以从另一个类型构建? [英] How does CanBuildFrom know whether a type can build from another?

查看:33
本文介绍了CanBuildFrom 如何知道一个类型是否可以从另一个类型构建?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我阅读了官方文档我仍然无法理解它是如何工作的.例如:

I read the official doc but I can't still understand how it works. For example:

class A {
  type Self
}
def seqToSet[T <: A](seq: Seq[T])
                    (implicit cbf: CanBuildFrom[Seq[T], T#Self, Set[T]]) {}

上面的代码可以编译……但是怎么编译呢?Scala 如何知道 Set 可以从 Seq 构建?以及如何确保 T#Self(实际上是任何类型)可以放入 Set[T] 中?

The above code can be compiled... but how? How does Scala know a Set can be built from a Seq? And how could it ensure a T#Self(literally any type) can be put into Set[T]?

推荐答案

一般不知道.你应该提供这样的CanBuildFrom.

It don't know it in general. You should provide such CanBuildFrom.

对于像这样的简单情况,您可以使用 breakOut:

For simple cases like this you could use breakOut:

class A1 extends A { type Self = A1 }
seqToSet(new A1 :: Nil)(collection.breakOut)
// compiles fine

对于更复杂的情况:

case class A2(val i: Int) extends A {
  type Self = Int
}

implicit val A2cbf = new CanBuildFrom[Seq[A2],A2#Self,Set[A2]] {
  import scala.collection.mutable.Builder
  class A2Builder extends Builder[A2#Self,Set[A2]] {
    var es = List[A2]()
    def +=(elem: A2#Self): this.type = { es ::= A2(elem); this }
    def clear(): Unit = es = Nil
    def result(): Set[A2] = es.toSet
  }
  def apply() = new A2Builder
  def apply(from: Seq[A2]) = apply()
}

seqToSet(new A2 :: Nil)(collection.breakOut)
// compiles fine

您应该提供 Builder(使用 CanBuildFrom),以便它在方法 += 中接受 A2#Self并返回 Set[A2] 作为结果.在代码示例中,它使用 elem 创建新的 A2:A2(elem).

You should provide Builder (using CanBuildFrom) such that it accepts A2#Self in method += and returns Set[A2] as result. In code sample it creates new A2 using elem: A2(elem).

让我们用几乎相同的参数创建更有用的方法:

Let's create more useful method with almost the same parameters:

def seqToSet[T <: A](seq: Seq[T])(f: T => T#Self)
                    (implicit cbf: CanBuildFrom[Seq[T], T#Self, Set[T]]) = {
  seq.map{f}: Set[T]
}

seqToSet(A2(1) :: A2(2) :: Nil){ a2 => a2.i + 1 }
// Set[A2] = Set(A2(3), A2(2))

这个方法提供了一些奇怪的A转换和集合类型转换.

This method provides some strange transformation of A with transformation of collection type.

这篇关于CanBuildFrom 如何知道一个类型是否可以从另一个类型构建?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆