Проблема в том, что implicit def
не рассматривается для преобразования аргументов, если вы не укажете определение метода для этого.
Следовательно, если у вас есть что-то вроде Real(5).foo
и foo
определено только для сложного, implicit def
будет работать для этого.
Если у вас есть такой метод, как: def foo(c : Complex) = ...
, вы не можете вызывать его с помощью foo(Real(5))
.
Если вы хотите применить неявное преобразование, вы должны указать свой метод так, чтобы его аргументы могли быть преобразованы. Для описанного выше метода foo
вы можете сделать это так:
def foo[T](c : T)(implicit ct : T => Complex) = ...`
Тогда допустимо позвонить foo(Real(5))
, и будет использовано преобразование.
Адаптированный к вашей конкретной проблеме, вы можете написать метод тестирования следующим образом:
def test[G <: GroupUnderAddition[G],T](a : T, b : G)(implicit ag: T => G) = a + b
Указывая, что неявные преобразования из T
в G
должны приниматься во внимание, вы разрешаете методу test
принимать теперь test(Real(5), Complex(2,1))
.
Однако, это не будет работать наоборот. Так что вы пока не можете назвать его с test(Complex(2,1), Real(5))
, потому что нет неявного преобразования второго аргумента.
Простой способ учесть оба преобразования - написать так:
def test[G <: GroupUnderAddition[G],T1, T2](a : T1, b : T2)(implicit ag: T1 => G, bg: T2 => G) = a + b
К сожалению, компилятор каким-то образом получает Any
для G
при вызове этого метода, как описано выше. Я не знаю сейчас, как решить эту проблему, и я опубликовал этот ответ в надежде, что кто-то еще может заполнить этот последний кусок головоломки.
Учитывая приведенное выше окончательное определение, вы можете по крайней мере вызывать метод любым способом, указав полные типы:
println(test[Complex,Real,Complex](Real(5), Complex(2, 1)))
println(test[Complex,Complex,Real](Complex(2,1), Real(5)))