Search code examples
scalatype-variables

Scala: Why does function need type variable in front?


From working on the first problem of the 99 Scala Puzzles I defined my own version of last like so:

def last[A](xs: List[A]): A = xs match {
  case x :: Nil => x
  case x :: xs => last(xs)
}

My question is: Why is it necessary for last to be directly followed by the type variable, as in last[A]? Why couldn't the compiler just do the right thing if I wrote the function like so:

def last(xs: List[A]): A
    .....

(leaving the [A] off the end of last[A]?)

And if the compiler is capable of figuring it out, then what is the rationale for designing the language this way?


Solution

  • I got an insight from @Lee's comment:

    How would the compiler know that the A in List[A] doesn't refer to an actual type called A?

    To demonstrate to myself that this made sense, I tried substituting the type variable A, with the name of an actual type String, and then passed the function a List[Int], seeing that when last is declared like def last[String](xs: List[String]): String, I was able to pass last a List[Int]:

    scala> def last[String](xs: List[String]): String = xs match {
         | case x :: Nil => x
         | case x :: xs => last(xs)
         | }
    last: [String](xs: List[String])String
    
    scala> last(List(1,2,3,4))
    res7: Int = 4
    

    Therefore proving the identifier String does behave like a type variable, and does not reference the concrete type String.

    It would also make debugging more difficult if the compiler just assumed that any identifier not in scope was a type variable. It therefore, makes sense to have to declare it at the beginning of the function definition.