开发者

Why scala can't infer the type in a partial method?

See this example:

def hello(a:String, b:String) = println(a + ":" + b)
val m1 = hello("aaa", _ )
m1("bbb")

It can't be compiled, that I need to add the type to the partial method:

val m1 = hello("aaa", _: S开发者_如何转开发tring)

Why scala doesn't know the 2nd parameter of method hello is 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.


To put it very simply, Scala uses the parameter types to search for the appropriate method, not method type to deduce the type of the parameters.

To do what you want, it would have to search for all possible calls to hello with two parameters, the first of them String -- which might include implicit conversions -- and then, if a single most specific option is found, use it to infer the type of that second parameter. It would have to do this in addition to all that it does already, slowing down even more what is already a rather slow compilation. Not impossible, but it doesn't do that.


It might be because there is a potential ambiguity with this definition as hello could be overloaded.

// inside some class context
def hello(a:String, b:String) = println(a + ":" + b)
def hello(a:String, b:Int) = println(a + ":" + b.toString)
val m1 = hello("aaa", _ ) // which one to choose?

Consider that it’s not only you who can do val m1 = hello("aaa", _). There could be a user of your class, doing val my_hello = (new C).hello("aaa", _). And then you break source-code compatibility by adding an overload to your original string hello method because suddenly it is not clear anymore what should be done.

I’m not sure this is the only reason but one can certainly see it as a safety measure.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜