[CC list are probably all on scala-language, but included for interest.]I don't know how to build a more open-and-shut case than this. (And I won't - whatever remains to be done is unlikely to be done by me.) Given this test case, also attached:In trunk it prints:If there are several eligible arguments which match theimplicit parameter’s type, a most specific one will bechosen using the rules of static overloading resolution.-- SLS 7.2, "Implicit Parameters"Static overloading selection: 1 2 3Implicit value selection: 1 1 1In the branch indicated above (paulp, topic/contrarivariance) it prints the same quote from the specification, followed byStatic overloading selection: 1 2 3Implicit value selection: 1 2 3So as I see it, scala is not implementing its own specification and we should have fixed this bug years ago. It goes back to at least October 2009, closed wontfix: https://issues.scala-lang.org/browse/SI-2509
As noted in my commit comment, once selection is done properly it's easy to make Ordering and friends contravariant. Everything works the way you'd imagine. It's so nice seeing te Iterable[T] implicit Ordering used for any subclass of Iterable without involving the sketchy hijinx seen in Ordering#ExtraImplicits. But I didn't bundle any of those changes.
NOTE: the particulars of how I modified "isAsSpecific" are not anything I'm advocating for, I'm sure it's all totally wrong and etc. My offering is:a) evidence that the specification already mandates that specificity is based on inheritance, not on the subtype latticeb) a complete working implementation, however flawed - all tests pass
To make progress here you'd have to invent a completely new notion of specificity alongside the subtyping relation we have.
I never claimed it is unsound. You can use any relation you like for overloading resolution and implicit search without violating soundness. And maybe I am wrong in my assumption what relationship was proposed, because you did not define it. So I can only guess.
That's the core of my own doubts about this issue: do I want
asymmetric behavior on implicit resolution?
Is there an example where using "reversed specificity" for
contravariant implicit resolution (i.e. preferring Ord[Tiger] over
Ord[Cat]) would cause problems? Bonus points if the example works
currently and does something useful! :)
It works for the example but it repeats a lot of rules.
FYI contravariance is not so rare. We see this issue all the time.
Ah right. Yes I can attest to this, in that I prefer to define a contramap method than declare contravariance with a - symbol. Too much nasty lurks there.
implicit val aa: String => Objectimplicit val bb: Object => String
Which one is more specififc? In Scala, it's bb. It provides a better type_and_ works for more arguments. In types-as-sets-of-values terms, there are way fewer functions of type Object => String than there are of type String => Object. So, clearly bb's type is more specific.
However, in the proposed new scheme, you'd get an ambiguity. Neither aa nor bb is more specific than the other.
Not only does this break code, it is also very unintuitive.
Then ask them the same for1. String => Any2. Any => String
Well, yes, and you specified Null as the lower bound, so, presumably,On Tue, May 29, 2012 at 5:45 PM, martin odersky <martin....@epfl.ch> wrote:
>
>
> On Tue, May 29, 2012 at 9:52 PM, Jesper Nordenberg <mega...@yahoo.com>
> wrote:
>>
>> martin odersky skrev 2012-05-29 19:01:
>>
>>> It could be a polymorphic context such as S => T, for type variables S
>>> and T.
>>
>>
>> Please give a complete example because I can't make this implicit search
>> work unambiguously.
>>
> Here's a self-contained example. You have to exclude some predefined
> function values in Predef, which is achieved by the import.
>
> import Predef.println
>
> object Test extends App {
>
> def foo[S >: Null, T](implicit x: S => T) = x(null)
>
> implicit val f: String => Object = x => { println("String => Object"); x }
> implicit val g: Object => String = x => { println("Object => String");
> ""+x }
>
> println(foo)
>
> }
>
> This will print: Object => String, so g is selected over f.
you could have worked with String => Object as well. This is similar
to the Nothing-inference problem,
and would show up when you have
overly generic types _and_ more than one competing implicit.
Personally, I'd live happily with it.
--
Daniel C. Sobral
I travel to the future all the time.
martin odersky skrev 2012-05-29 22:45:I fail to see why this behavior is desirable. S and T are basically unbounded so why should either implicit be more specific than the other?
Here's a self-contained example. You have to exclude some predefined
function values in Predef, which is achieved by the import.
import Predef.println
object Test extends App {
def foo[S >: Null, T](implicit x: S => T) = x(null)
implicit val f: String => Object = x => { println("String =>
Object"); x }
implicit val g: Object => String = x => { println("Object =>
String"); ""+x }
println(foo)
}
This will print: Object => String, so g is selected over f.
I think of specificity as inverse "type distance", i.e. given A <: B <: C the distance between F[A] and F[C] is greater than the distance between F[A] and F[B] regardless of the variance annotation on F's type parameter. The variance annotation only specifies the subtype relation between for example F[A] and F[B].
On Tue, May 29, 2012 at 11:32 PM, Jesper Nordenberg <mega...@yahoo.com> wrote:martin odersky skrev 2012-05-29 22:45:I fail to see why this behavior is desirable. S and T are basically unbounded so why should either implicit be more specific than the other?
Here's a self-contained example. You have to exclude some predefined
function values in Predef, which is achieved by the import.
import Predef.println
object Test extends App {
def foo[S >: Null, T](implicit x: S => T) = x(null)
implicit val f: String => Object = x => { println("String =>
Object"); x }
implicit val g: Object => String = x => { println("Object =>
String"); ""+x }
println(foo)
}
This will print: Object => String, so g is selected over f.
Because there are fewer functions like f than functions like g.