Here is a minimalistic example:
def map[U[_] <: Traversable[T], T](col: U[T]): U[T]
= col.map(identity)
This code does not compile.
type mismatch;
found : Traversable[T]
required: U[T]
= col.map(identity)
My understanding of the problem is the col.map(identity)
where the compiler infers an implicit CanBuildFrom[U[T], T, Traversable[T]]
instead of desired CanBuildFrom[U[T], T, U[T]]
.
Is there a way to make this code working?
The mechanics of builder type classes in Scala 2.12 is something like so
def foo[CC[x] <: Traversable[x], A, B](as: CC[A], f: A => B)(
implicit cbf: CanBuildFrom[CC[A], B, CC[B]]
): CC[B] = {
val bf = cbf()
as.foreach { a => bf += f(a) }
bf.result()
}
or using .to
method
def foo[CC[x] <: Traversable[x], A, B](as: CC[A], f: A => B)(
implicit cbf: CanBuildFrom[CC[A], B, CC[B]]
): CC[B] = {
as.map(f).to[CC]
}
Corresponding Scala 2.13 code might be
def foo[CC[x] <: Iterable[x], A, B](as: CC[A], f: A => B)(
implicit cbf: BuildFrom[CC[A], B, CC[B]]
): CC[B] = {
cbf.fromSpecific(as)(as.map(f))
}
or using factory
def foo[CC[x] <: Iterable[x], A, B](as: CC[A], f: A => B)(
implicit factory: Factory[B, CC[B]]
): CC[B] = {
as.map(f).to(factory) // equivalent to factory.fromSpecific(as.map(f))
}
The meanings of three type parameters of collection builder type class are
| source coll | element of target coll | target coll |
---------------------------------------------------------------------
CanBuildFrom | -From | -Elem | +To |
BuildFrom | -From | -A | +C |
Factory | | -A | +C |
Note these builder type classes are just generalised version of the following idea
scala> val bf = List.newBuilder[Int]
val bf: scala.collection.mutable.Builder[Int,List[Int]] = ListBuffer()
scala> bf += 1 += 4
val res0: bf.type = ListBuffer(1, 4)
scala> bf.result()
val res1: List[Int] = List(1, 4)
but in practice we rarely see collections constructed in such way.
Another option instead of BuildFrom
is to use cats type classes such as Functor
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.