2

I just looked at the List::map method declaration and was kind of perplexed by its complication. Here is how it looks:

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

Well, I understand what implicit is (as far as I got, the type class based on trait CanBuildFrom will be automatically introduced by the compiler, if in scope). But what is That supposed to mean here?

I understand map(f: A => B) as a functorial thing that maps each function f: A => B to a function between corresponding monadic values List(A) and List(B). So I expected to see the return type to be List[B].

BTW, that's what we actually have in the case of Option.

def map[B](f: A => B): Option[B]

Both List and Option are monads. What's is the trick with List?

stella
  • 2,546
  • 2
  • 18
  • 33
  • related: [Is the Scala 2.8 collections library a case of “the longest suicide note in history”?](http://stackoverflow.com/questions/1722726/is-the-scala-2-8-collections-library-a-case-of-the-longest-suicide-note-in-hist) – stholzm Jul 10 '16 at 18:02
  • 2
    `That` is just a type parameter. They could have chosen `C`, or `T`, or whatever. `That` is often chosen for the name of the output type, so that `this` becomes `That`. – jwvh Jul 10 '16 at 23:38
  • @stella Hey, just checking if this is resolved – slouc Feb 12 '17 at 23:03

2 Answers2

3

Mapping a collection can result in the same collection (only parameterized with a different type), but it doesn't have to be so. It can result in a completely different collection. For example,

val myMap = Map("firstName" -> "foo", "lastName" -> "bar") 
val result = myMap map (_._1.length)

We started from Map[String, String] and ended up with Iterable[Int]. This is why Traversables (note that Traversable is an "abstract trait" and TraversableLike is an "implementation trait") have this implicit builder called CanBuildFrom. Option is not a Traversable and doesn't need all this conversion machinery - we know that mapping an Option always results in an Option.

When performing map on Traversables, compiler will find a corresponding value of type CanBuildFrom in a companion object (for example, here's the one for List). If it doesn't find any, it will go one level above, etc. Check out the docs (find "The CanBuildFrom trait" on page and start from there).

slouc
  • 9,508
  • 3
  • 16
  • 41
2

You can read about the architecture of these collections here. I think it is used for knowing the correct return type of the operation. For example, when you call toSet on a List, an implicit CanBuildFrom[List[A], B, Seq[A]] must be in scope...

insan-e
  • 3,883
  • 3
  • 18
  • 43