The problem is that implicit def not considered for converting arguments unless you specify a method definition for this.
Therefore, if you have something like Real(5).foo and foo are only defined for complex, an implicit def will work for that.
If you have one such method: def foo(c : Complex) = ... , you can not call it foo(Real(5)) .
If you want to apply an implicit conversion, you must specify your method so that its arguments can be converted. For the above foo method, you can do it like this:
def foo[T](c : T)(implicit ct : T => Complex) = ...`
Then you can call foo(Real(5)) , and the transform will be used.
Adapted to your specific problem, you can write a test method as follows:
def test[G <: GroupUnderAddition[G],T](a : T, b : G)(implicit ag: T => G) = a + b
By indicating that implicit conversions from T to G should be taken into account, you allow the test method to take test(Real(5), Complex(2,1)) .
However, for now this will not work. So you still cannot call it with test(Complex(2,1), Real(5)) , because there is no implicit conversion of the second argument.
An easy way to account for both transformations would be to write this as follows:
def test[G <: GroupUnderAddition[G],T1, T2](a : T1, b : T2)(implicit ag: T1 => G, bg: T2 => G) = a + b
Unfortunately, the compiler somehow outputs Any for G when calling this method, as described above. I donβt know right now how to solve this problem, and I sent this answer in the hope that someone else could fill in this last piece of the puzzle.
Given the final definition above, you can at least call the method anyway when specifying the full types:
println(test[Complex,Real,Complex](Real(5), Complex(2, 1))) println(test[Complex,Complex,Real](Complex(2,1), Real(5)))