Consider the following type parameter clause [F[_] <: Int]
in
def h[F[_] <: Int] = ???
where a type constructor F
is bounded by the proper type Int
. Now both h[List]
and h[Int]
are illegal
scala> def h[F[_] <: Int] = ???
|
def h[F[_] <: Int]: Nothing
scala> h[List]
^
error: type arguments [List] do not conform to method h's type parameter bounds [F[_] <: Int]
scala> h[Int]
^
error: Int takes no type parameters, expected: 1
so why is then [F[_] <: Int]
legal?
The type parameter declaration F[_] <: Int
means that every instantiation of F
must be a subtype of Int
. It's right in the syntax, though cryptic: F
does not have to be a subtype of Int
; F[_]
has to be a subtype of Int
(for all types that may be placed in the _
). An example of such an F
is one which always returns Int
:
type ConstInt[X] = Int
h[ConstInt] // compiles
Note that you can name the type in the _
. E.g. I can declare a type parameter F[X] <: X
. X
is local to the declaration, defined by appearing under F
on the left, used as a bound on the right, and going out of scope afterwards. This example means that F[X]
must be a subtype of X
, e.g. as in
def f[F[X] <: X] = ???
type Identity[X] = X
f[Identity] // works
type ConstNothing[X] = Nothing
f[ConstNothing] // works
// f[ConstInt] (ConstInt[X] = Int is not always a subtype of X; counterexample X = AnyRef)
Perhaps that drives home what the bound is supposed to mean.