Рассмотрим метод f
, который параметризуется конструктором типа F[_]
и надлежащим типом A
def f[F[_], A](v: F[A]) = v
Давайте попробуем применить его к new Bar
scala> class Bar
class Bar
scala> def f[F[_], A](v: F[A]) = v
def f[F[_], A](v: F[A]): F[A]
scala> f(new Bar)
^
error: no type parameters for method f: (v: F[A]): F[A] exist so that it can be applied to arguments (Bar)
--- because ---
argument expression's type is not compatible with formal parameter type;
found : Bar
required: ?F[?A]
^
error: type mismatch;
found : Bar
required: F[A]
Эта ошибка, как и ожидалось, Bar
неправильной формы.
Теперь давайте добавим неявное преобразование из Bar
в List[Int]
scala> implicit def barToList(b: Bar): List[Int] = List(42)
def barToList(b: Bar): List[Int]
scala> f(new Bar)
val res1: Any = Bar@56881196
Это компилируется, однако обратите внимание, что неявное преобразование, похоже, на самом деле не применялось, потому что класс среды выполнения res1
это Bar
, а не List
. Кроме того, типом времени компиляции res1
является Any
, а не List[Int]
. Глядя на вывод -Xprint:typer
, мы видим что-то вроде
val res1: Any = f[Any, Nothing](new Bar())
, где мы видим, что произошел следующий вывод:
F[_] = Any
A = Nothing
в отличие от
F[_] = List
A = Int
, и мы видим, что на самом деле никакого преобразования не произошло, то есть мы не видим чего-то вроде
f(barToList(new Bar()))
Почему простое присутствие неявного преобразования заставило программу компилироваться, в то время как неявное преобразование фактически не применялось? Обратите внимание, что при явном указании параметров типа он работает как ожидалось
scala> f[List, Int](new Bar)
val res2: List[Int] = List(42)