dips
dips

Reputation: 1637

ambiguous implicit conversion errors

Here is a code snippet that tries to reproduce a problem I am facing while implementing an internal DSL:

object testObj {
    implicit def foo1[T <% Function1[Int, Int]](fun: T): String = "foo1"
    implicit def foo2[T <% Function2[Int, Int, Int]](fun: T): String = "foo2"

    def test(arg: String): Unit = {}

    test((x:Int) => 5) //Ambiguous implicit conversion error
    test((x:Int, y:Int) => 5) //Ambiguous implicit conversion error
}

I am getting ambiguous implicit conversions errors at the shown locations:

<console>:21: error: type mismatch;
 found   : Int => Int
 required: String
Note that implicit conversions are not applicable because they are ambiguous:
 both method foo1 in object testObj of type [T](fun: T)(implicit evidence$1: T => (Int => Int))String
 and method foo2 in object testObj of type [T](fun: T)(implicit evidence$2: T => ((Int, Int) => Int))String
 are possible conversion functions from Int => Int to String
           test((x:Int) => 5) //Ambiguous implicit conversion error
                        ^

However commenting one of the implicits does not solve the problem. I am using view bounds since finally I want to chain the implicits. Note that the code snippet given above does not involve implicit chaining.

I was expecting that foo1 implicit conversion would be applicable for the first test application whereas foo2 implicit conversion would be applicable for the second test application. I don't understand how both the implicits are applicable to both the testfunction applications. Why is this happening and how to make this work?

Edit: If I don't use view bounds, it works fine as shown below. But I want to use view bounds since I want to chain the implicits the way it is explained in the post How can I chain implicits in Scala?.

implicit def foo1(fun: Function1[Int, Int]): String = "foo1"
implicit def foo2(fun: Function2[Int, Int, Int]): String = "foo2"

def test(arg: String): Unit = {}
test((x:Int) => 5) //No error
test((x:Int, y:Int) => 5) //No error

Upvotes: 3

Views: 723

Answers (1)

Kim Stebel
Kim Stebel

Reputation: 42047

I'm afraid this won't work. View bounds are just not taken into account when resolving implicits and thus you can't chain implicits. That is be design, because such chaining could create some very unreadable code. The only option I see is to create a new implicit conversion for each possible chain of conversions.

Upvotes: 0

Related Questions