- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Ambiguity in the presence of both overloading and conversion
Tue, 2011-06-28, 09:25
Continuing on from my previous type erasure question, I've just run into another issue (which is no longer anything to do with type erasure).
I was under the impression that Scala only ever applied a single implicit conversion in order to avoid ambiguities. But I seem to have found an occasion where that's not the case.
This works just fine:
> object A {
> def m(x: Int) = "x is: "+ x
> def m(x: Double) = "x is: "+ x
> def m(x: String) = "x is: "+ x
> }
>
> A.m(42)
> A.m(1.23)
> A.m("foo")
As does this:
> case class WrappedInt(x: Int)
> case class WrappedDouble(x: Double)
> case class WrappedString(x: String)
>
> object B {
> def m(x: WrappedInt) = "x is: "+ x
> def m(x: WrappedDouble) = "x is: "+ x
> def m(x: WrappedString) = "x is: "+ x
> }
>
> implicit def wrap(x: Int) = new WrappedInt(x)
> implicit def wrap(x: Double) = new WrappedDouble(x)
> implicit def wrap(x: String) = new WrappedString(x)
>
> B.m(1.23)
> B.m("foo")
But given the above, this:
> B.m(42)
gives:
> error: ambiguous reference to overloaded definition,
> both method m in object B of type (x: this.WrappedDouble)java.lang.String
> and method m in object B of type (x: this.WrappedInt)java.lang.String
> match argument types (Int)
> B.m(42)
> ^
> one error found
I'm guessing that the conversion from Int to Double isn't considered to be an implicit conversion for the purposes of the "only one implicit conversion" rule? Any suggestions for ways to get around this?
--
paul.butcher->msgCount++
Snetterton, Castle Combe, Cadwell Park...
Who says I have a one track mind?
http://www.paulbutcher.com/
LinkedIn: http://www.linkedin.com/in/paulbutcher
MSN: paul@paulbutcher.com
AIM: paulrabutcher
Skype: paulrabutcher
Tue, 2011-06-28, 15:37
#2
Re: Ambiguity in the presence of both overloading and conversio
On Tue, Jun 28, 2011 at 05:25, Paul Butcher wrote:
> Continuing on from my previous type erasure question, I've just run into another issue (which is no longer anything to do with type erasure).
>
> I was under the impression that Scala only ever applied a single implicit conversion in order to avoid ambiguities. But I seem to have found an occasion where that's not the case.
I think, perhaps, it would be more precise to say Scala do not chain
implicit views. A lot of implicit stuff can go on on a single
statement, however.
> But given the above, this:
>
>> B.m(42)
>
> gives:
>
>> error: ambiguous reference to overloaded definition,
>> both method m in object B of type (x: this.WrappedDouble)java.lang.String
>> and method m in object B of type (x: this.WrappedInt)java.lang.String
>> match argument types (Int)
>> B.m(42)
>> ^
>> one error found
>
>
> I'm guessing that the conversion from Int to Double isn't considered to be an implicit conversion for the purposes of the "only one implicit conversion" rule? Any suggestions for ways to get around this?
It is not an implicit view, it is type widening. Int can be widened to
Long, Float or Double, according to 6.26.1 and 12.2.1. Not that Int
weekly conforms to Double (3.5.3), so it can be a parameter to both
WrappedInt and WrappedDouble.
I'm guessing the compiler verifies all overloaded versions of the methods for a match and finds that your '42' can be converted to both WrappedInt and WrappedDouble - and then can't choose which one to call. This won't happen in the 'A' case because its a direct call.
Now, I get confused with implicits from time to time, so an expert's voice here would be great =D
[]s,
2011/6/28 Paul Butcher <paul@paulbutcher.com>
--
Paulo "JCranky" Siqueira
Visit my blog: http://www.jcranky.com/