Consider method f
which is parameterised by a type constructor F[_]
and a proper type A
def f[F[_], A](v: F[A]) = v
Lets try to apply it to 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]
This errors as expected as Bar
is not of the right shape.
Now lets add an implicit conversion from Bar
to 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
This compiles, however notice that implicit conversion did not seem to have actually been applied because the runtime class of res1
is Bar
and not List
. Furthermore, the compile-time type of res1
is Any
and not List[Int]
. Looking at output of -Xprint:typer
we see something like
val res1: Any = f[Any, Nothing](new Bar())
where we see the following inference happened
F[_] = Any
A = Nothing
as opposed to
F[_] = List
A = Int
and we see that no conversion actually happened, that is, we do not see something like
f(barToList(new Bar()))
Why did the mere presence of implicit conversion make the program compile whilst no implicit conversion was actually applied? Note that when being explicit about type parameters it works as expected
scala> f[List, Int](new Bar)
val res2: List[Int] = List(42)
Bar
is not of the right shape." ActuallyBar
can be considered as having the right shape since it'sId[Bar]
(wheretype Id[A] = A
). It's just too tricky to infer higher-kinded types. With hints everything works:f(new Bar: Id[Bar])
orf(new Bar: List[Int])
. – CampoId
isn't defined already, is it? Wouldn't it be "easier" to infer it to be aList[Int]
? – Helgeson