user3663882 user3663882 - 3 months ago 16
Scala Question

Understanding flatMap declaration in List

I just looked at the

List.flatMap
declaration and was kind of surprised by this.

final override def flatMap[B, That](f: A => GenTraversableOnce[B])
(implicit bf: CanBuildFrom[List[A], B, That]): That


Where
object List
defines:

implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, List[A]] =
ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]


So, if we invoke
flatMap
on a
List
we will get the
List
and I don't see any point in
That
type if it will always be deduced to
List[B]
(because of the
implicit
).

Answer

So, if we invoke flatMap on a List[A] we will get the List[A] and I don't see any point in That type if it will always be deduced to List[B]

One thing you're missing is that flatMap isn't actually defined on List[+A]. It is inherited from TraversableLike, which is a trait used by most of Scalas collections. Each of them can supply the implicit CanBuildFrom which may be overridden to supply a different resulting collection.

If you want a little taste of what you can do with a custom CanBuildFrom:

scala> :pa
// Entering paste mode (ctrl-D to finish)

import scala.collection.generic.CanBuildFrom
import scala.collection.immutable._
import scala.collection.mutable
import scala.{List, Vector}

implicit val listToVectorCBF = new CanBuildFrom[List[Int], Int, Vector[Int]] {
  override def apply(from: List[Int]): mutable.Builder[Int, Vector[Int]] = this.apply()
  override def apply(): mutable.Builder[Int, Vector[Int]] = Vector.newBuilder
}

// Exiting paste mode, now interpreting.

scala> List(1,2,3).flatMap(List(_))
res6: Vector[Int] = Vector(1, 2, 3)