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.