On page 136. page of the book "Scala in Depth" it is written:
But the following experiment suggests that here _
is just the same as any arbitrary type parameter T
, so it is perhaps not an existential type.
scala> def foo[M[_]](f : M[Int]) = f
foo: [M[_]](f: M[Int])M[Int]
scala> def foo[M[T]](f : M[Int]) = f
foo: [M[T]](f: M[Int])M[Int]
Also note the section 4.4 of the Scala Language Specification below , this also suggests that _
is the same as T
here.
Can someone explain what is going on here ?
M[_]
in that context (i.e. as a type parameter declaration) is a higher kinded type (sometimes called a "type constructor"); as you say it's the same as M[X]
, with the _
just meaning we aren't going to reuse the name.
In a different context (e.g. as a type) the same syntax is sometimes used to mean an existential type M[X] forSome { type X }
.
It's unfortunate and confusing that the syntax looks the same, but they're two different, unrelated features. If you're confused about which one a particular use of _
is, maybe check what the compiler/language feature warning is? In my own code I try to always write existential types explicitly (using forSome
) to avoid this confusion, but this is just something I came up with, not a rule that libraries tend to follow.