These four versions compile but i'm curious about context in which we should prefer one option rather than another.
// 1
def f[N, S <: Seq[N]](s: S)
// 2
def f[N, S[N] <: Seq[N]](s: S[N])
They are pretty similar when use 1
rather than 2
2
impose that S
have N
as generic parameter as 1
but then what is the difference between these two ?
Then we have more general settings.
// 3
def f[N, S[X] <: Seq[X]](s: S[N])
// 3.a
def f[N, S[X] <: Seq[X]](s: S[N]): S[Int]
From what i humbly understood 3
authorize to extract the generic container type to reuse it later and get something like 3.a
.
But what is the meaning of the undeclared X generic parameter, i suppose it's a way to declare something special but i don't get it.
// 4
def f[N, S[X] <: Seq[_]](s: S[N])
I don't know what to say about 4
except than from what i know Seq[_]
stands for Seq[Any]
Finally i'm simply curious to have more information about these tools and their specificity to get things done more properly.
The idea here is that the first
N
parameter andN
mentioned inS[N] <: Seq[N]
are completely independent parameters. They are just sharing the same name.N
mentioned inS[N]
is visible only in a scope of its bound<: Seq[N]
.N
used in parameter definition(s: S[N])
comes from firstN
as this is the onlyN
parameter visible for parameter type definition. So instead ofN
inS[N] <: Seq[N]
you can use any letter and this will not affect your parameter type at any way.Here you just ignoredX
parameter.Edit: as @alexey-romanov mentioned in a comment. There is difference between
S[X] <: Seq[X]
andS[X] <: Seq[_]
Here is an example showing the difference:
The problem here is as type constrictor is a kind of "function on types", we can define such "function" accepting one type as a parameter but returning type parametrized by another parameter not related to parameter used in type constructor. (See type
Foo
)Passing
foo
val tof2
is fine becauseX
is infered to String andFoo[String]
is a "subtype"(actually they are equal) ofSeq[Int]
, but when we passfoo
tof1
theX
is still aString
butFoo[String]
is not "subtype" ofSeq[String]
(because Foo[String]==Seq[Int] not subtype of Seq[String])And here you said that
N
used inSeq[N]
is the same as first parameterN
. So this is the sameN