2

This code applies a function to List of Ints and sets each value in the List of Option with value 4 :

  val l = List(1,2,3,4,5)                         //> l  : List[Int] = 
  val v = 4                                       //> v  : Int = 4
  def g(v:Int) = List(v-1, v, v+1)                //> g: (v: Int)List[Int]
 l map (x => {f(x);})                            //> res0: List[Option[Int]] = List(Some(4), Some(4), Some(4), Some(4), Some(4)) 

Signature of map :

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

Since B is the first type parameter (in map[B, That]) does this mean its typed to the prefix operand 'l' (List) ?

How is 'A' typed ? Does the scala compiler somehow check the type within the the List 'l' and infer that its of type Int ?

How is 'That' typed ?

blue-sky
  • 51,962
  • 152
  • 427
  • 752
  • possible duplicate of [Scala 2.8 breakout](http://stackoverflow.com/questions/1715681/scala-2-8-breakout) – senia Aug 30 '13 at 11:39
  • In your code, what is the function f? what is the use of the function g? if you look at the API doc for List, you can see that map has the following signature : def map[B](f: (A) ⇒ B): List[B] : it just transforms a List of A in a List of B – bhericher Aug 30 '13 at 11:42
  • 2
    See **About 'CanBuildFrom`** section in [this answer](http://stackoverflow.com/a/1716558/406435) by [Daniel C. Sobral](http://stackoverflow.com/users/53013/daniel-c-sobral). – senia Aug 30 '13 at 11:44

1 Answers1

11

The simple signature for map in a List[A] is

def map[B](f: (A) ⇒ B): List[B]

which means that

  • A is determined by the type parameter of the actual list
    • Int for the example list l
  • B is determined by the target type of the function f passed as argument
    • Option[Int] for the example function f: Int -> Option[Int]

The expanded signature is

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

which exist so that you can generically map between containers that can be traversed in some way, even when the target traversable has a different form than the original.

A specific example is traversing a Map as a container of Pairs, with a mapping function that produces single values. The resulting traversable is not a Map anymore, so the CanBuildFrom implicit parameter is used to find "available representations" for the resulting object.

In this signature we have

  • Repr as the type of the original traversed container
  • B as the target type of the contained values, as in the simplified signature
  • That as the type of the target container, determined by the implicit existence of a CanBuildFrom with the correct types at call site
pagoda_5b
  • 7,333
  • 1
  • 27
  • 40
  • Could you explain why there are parenthesis around type A in the first code snippet ? – vkubicki Apr 24 '20 at 20:08
  • 1
    @vkubicki the parenthesis are optional, in this case. They might be needed in other situations to disambiguate, e.g. if you have a function receiving a tuple, `((A, B)) => C` – pagoda_5b Apr 28 '20 at 09:22