object Partial {def ok1 (f: Int => Int): Int = f(0)def not1 (f: Int => Int): Int = f(0)def not1 (i: Int): Int = i}import Partial._ok1 { case i => i + 1 } // 1. works because the method is not overloaded, and the partial fun is promoted to Int=>Intnot1 { case i => i + 1 } // 2. fails with (SLS 8.5), apparently because it's overloaded, even though it should be resolved by the argument typenot1 { i => i match { case i2 => i2 + 1 } } // 3. this works, because it's a Int=>Int
Hi,Take the following example (scala 2.11.6)object Partial {def ok1 (f: Int => Int): Int = f(0)def not1 (f: Int => Int): Int = f(0)def not1 (i: Int): Int = i}import Partial._ok1 { case i => i + 1 } // 1. works because the method is not overloaded, and the partial fun is promoted to Int=>Intnot1 { case i => i + 1 } // 2. fails with (SLS 8.5), apparently because it's overloaded, even though it should be resolved by the argument typenot1 { i => i match { case i2 => i2 + 1 } } // 3. this works, because it's a Int=>IntSeems that situation 2 should compile also, even though the partial function itself is not typed, the method argument should provide sufficient clue to complete it. Is this a bug or expected behavior?I can't seem to find anything on the issue tracker that's related. Sorry if this is a known issue and I missed it -- and also let me know because I'd love to learn how to fix it.
Minor nitpick: this is a pattern matching anonymous function, it is somewhat misleading to describe it as “partial” in this context. A patten matching anon function will be either a FunctionN or a PartialFunctionN, depending on the expected type under which it is typechecked.
If multiple overloads are still vying for resolution when it comes time to typecheck the arguments, overload resolution proceeds as described in 6.2.3. The “shape type” of the arguments are computed, which lets us approximate the type of function literals in order to discard alternatives to which they would not conform.
Then, if multiple alternatives remain, the argumetnts are typechecked without an expected type. The computed types of the arguments are then checked for compatibility with the formal parameter types of each alternative (compatibility = type conformance or implicit convertability). If multiple alternatives still exists, the most specific one is chosen. It is an error if no most specific alternative exists.
In your example, no special rule exists for the "shape type" of pattern matching anonymous functions. It is not possible to approximate the type of these. For example: the same syntax can be used to create functions of different arities because of the transparent handling of tuples/param lists:
scala> val f: Function2[Int, Int, String] = { case (x, y) => "" }
f: (Int, Int) => String = <function2>
scala> val g: Function1[(Int, Int), String] = { case (x, y) => "" }
g: ((Int, Int)) => String = <function1>
As a further example:
scala> val g: Function3[Int, Int, Int, String] = { case _ => "" }
g: (Int, Int, Int) => String = <function3>
scala> val g: PartialFunction[Int, String] = { case _ => "" }
g: PartialFunction[Int,String] = <function1>
scala> val g: Function1[Any, String] = { case _ => "" }
g: Any => String = <function1>
The best we could say is that the “shape type” of a pattern matching anonymous function is Function0[_] | Function1[_, _].... | PartialFunction[_, _]. That would be sufficient to exclude the wrong overload and make your example compile. But one would also need to specify the meaning of | (a union type). We tend to take the stand that overloading is a second class feature in Scala, so we'll resist further spec or implementation complexity here, even if they offer incremental improvements.
Interestingly enough, Java 8’s overload resolution does typecheck all the alternatives and could handle this. I was playing around with this the other day (and can’t figure out why the last line doesn’t compile in that gist.
Java can probably afford to pay the cost of this brute force overload resolution because it doesn’t require implicit searches for checking compatibility. They aren’t without the odd pathological performance case around overloading, though, and, AFAICT, are planning to rework the typechecker under the banner of JEP 215 to speed them up.
What a great explanation. Thank you Jason.
Got it! Not a minor nitpick at all -- it's really the root-cause. Good to know that a 'pattern matching anon fun' can be so amorphous.Thanks for the quick reply!
--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.