2

This is a much simpler version of my earlier post ambiguous implicit conversion errors

Here is a code snippet from the post How can I chain implicits in Scala?

class A(val n: Int)
class B(val m: Int, val n: Int)
class C(val m: Int, val n: Int, val o: Int) {
  def total = m + n + o
}

object T2 {
  implicit def toA(n: Int): A = new A(n)
  implicit def aToB[A1 <% A](a: A1): B = new B(a.n, a.n)
  implicit def bToC[B1 <% B](b: B1): C = new C(b.m, b.n, b.m + b.n)

  // works
  println(5.total)
  println(new A(5).total)
  println(new B(5, 5).total)
  println(new C(5, 5, 10).total)
}

Now if I add a class D and implicit def dToC as follows, I get errors at locations shown in the snippet.

class A(val n: Int)
class B(val m: Int, val n: Int)
class D(val m: Int, val n: Int) //Added by me
class C(val m: Int, val n: Int, val o: Int) {
    def total = m + n + o
}

object T2 {
  implicit def toA(n: Int): A = new A(n)
  implicit def aToB[A1 <% A](a: A1): B = new B(a.n, a.n)
  implicit def bToC[B1 <% B](b: B1): C = new C(b.m, b.n, b.m + b.n)
  implicit def dToC[D1 <% D](d: D1): C = new C(d.m, d.n, d.m + d.n)  //Added by me

  println(5.total) //Ambiguous implicit conversion error
  println(new A(5).total) //Ambiguous implicit conversion error
  println(new B(5, 5).total) //Ambiguous implicit conversion error
  println(new C(5, 5, 10).total) 
}

I don't understand how both bToC and dToC are possible conversion functions for say println(new B(5, 5).total).

Community
  • 1
  • 1
dips
  • 1,627
  • 14
  • 25
  • You can simplify it even further by removing ``class A``, ``def toA`` and ``def aToB``, the ambiguity remains (but I also don't see, why). – Malte Schwerhoff Jul 30 '12 at 09:21
  • It seems the second parameter list is not resolved while searching for an implicit if it contains a function. With a "normal" implicit parameter in the second parameter list the code works fine. I can't find any hint if this is a bug or a feature. – kiritsuku Jul 30 '12 at 09:34
  • @mhs Yes, removing `class A` makes sense as an independent post. But I kept `class A` so that people can correlate with the nice explanation in the [How can I chain implicits in Scala?](http://stackoverflow.com/questions/5332801/how-can-i-chain-implicits-in-scala) post. – dips Jul 30 '12 at 09:37
  • I guess the problem is caused by your typebounds or better the context bounds. The error message says: ... both method bToC in object $iw of type [B1](b: B1)(implicit evidence$2: B1 => B)C and methode dToC in object $iw of type [D1](d: D1)(implicit evidence$1: D1 => D)C ... The types of the method are not B and D but B1 and D1. These are context bounds and not view bounds anymore. That is what the evidence says us. Unfortunately I don't know how to fix this problem. – tgr Jul 30 '12 at 11:32

2 Answers2

1

View bounds obviously get translated to an extra implicit function parameter. So both bToC and dToC get translated to [T](x: T)(implicit f: T => Something): C

The issue being that the compiler disregards the presence/absence of implicit arguments in the ambiguity check.

case class Foo[A](value: A)
implicit def foo[A](x: A)(implicit ev: Any =:= String) = Foo(x)
implicit def bar[A](x: A)(implicit ev: Any =:= Int) = Foo(x)
1.value //Ambiguous though none are applicable
Kaito
  • 1,775
  • 1
  • 10
  • 7
  • Thanks! But is this a feature or a bug? btw, what is `=:=` – dips Jul 30 '12 at 16:05
  • For some reason I believe this is by design but I couldn't find it in the spec so I'm not sure. A value of type `A =:= B` is proof that `A` is `B`, [more details here](http://stackoverflow.com/questions/3427345/what-do-and-mean-in-scala-2-8-and-where-are-they-documented). For this example, feel free to replace it with any other type, whether a value exists or not the code will not compile. – Kaito Jul 30 '12 at 17:02
-1

(1) Int=>A=>B=>C

(2) Int=>A=>D=>C

2 paths can be chosen, and the compiler don't know which path to go, so that's why ambiguous implicit conversion error was raised.

Community
  • 1
  • 1
DarrenWang
  • 478
  • 2
  • 3