See this example:
def hello(a:String, b:String) = println(a + ":" + b)
val m1 = hello("aaa", _ )
val m1 = hello("aaa", _: String)
Scala's type inference is flow based. Methods and functions need explicit parameter types, which are used to infer other types. The parameter types cannot be inferred from method or function body. Sometimes, however, the parameter types are known from external context, and then don't have to be labeled. Two examples,
val f: String => Unit = hello("aaa", _) val s = Seq(1,2).map(_+1) // Seq[Int].map expects a function of Int argument type
Below is a quote from Martin Odersky about the limitations of Scala's type inference compared to, say, ML and Haskell. Challenges include Scala's overloading, record selection, and subtyping, as well as the need to keep things simple,
The reason Scala does not have Hindley/Milner type inference is that it is very difficult to combine with features such as overloading (the ad-hoc variant, not type classes), record selection, and subtyping. I’m not saying impossible — there exist a number of extensions that incorporate these features; in fact I have been guitly of some of them myself. I’m just saying it’s very difficult to make this work well in practice, where one needs to have small type expressions, and good error messages. It’s not a shut case either — many researchers are working on pushing the boundaries here (look for instance at Remy’s MLF). But right now it is a tradeoff of better type inferencing vs better support for these features. You can make the tradeoff both ways. The fact that we wanted to integrate with Java tipped the scales in favor of subtyping and away from Hindley/Milner.
Source: comment under post Universal Type Inference is a Bad Thing.