[英]Difference between F[_] and F[T] In Scala when used in type constructors
This question is about _ as used in type constructor and not when used in defining existential types.这个问题是关于在类型构造函数中使用的 _ 而不是在定义存在类型时使用的。
So the question is what is the difference when _
is used as type parameter instead of a variable like T
.所以问题是当_
用作类型参数而不是像T
这样的变量时有什么区别。 For example difference between F[_]
and F[T]
.例如F[_]
和F[T]
之间的差异。
The only difference I can think of is that with F[_]
the parameter itself can have as many holes as possible...that is F[_]
can become F[Int]
or F[Future[Option[Int]]]
etc...while when you have F[T]
the T
can only be a proper type...that is F[String]
or F[Int]
etc.我能想到的唯一区别是,使用F[_]
参数本身可以有尽可能多的孔……也就是说F[_]
可以变成F[Int]
或F[Future[Option[Int]]]
等等......而当你有F[T]
, T
只能是一个正确的类型......即F[String]
或F[Int]
等。
Is this a correct assumption?这是一个正确的假设吗? and is that the main difference between F[_]
and F[T]
?这是F[_]
和F[T]
之间的主要区别吗? or there are more?或者还有更多?
What about the case where the two are used as type parameters?将两者用作类型参数的情况如何? For example, what is the difference between trait Functor [F[_]]
and trait Functor [F[T]]
?例如, trait Functor [F[_]]
和trait Functor [F[T]]
什么区别?
Is there any semantic difference if the functor trait is defined as trait Functor [F[_]]
instead of trait Functor [F[T]]
?如果 functor trait 被定义为trait Functor [F[_]]
而不是trait Functor [F[T]]
有什么语义上的区别吗?
To quote the specification :引用规范:
The above scoping restrictions are generalized to the case of nested type parameter clauses, which declare higher-order type parameters.上述范围限制被推广到嵌套类型参数子句的情况,它声明了高阶类型参数。 Higher-order type parameters (the type parameters of a type parameter
t
) are only visible in their immediately surrounding parameter clause (possibly including clauses at a deeper nesting level) and in the bounds of t.高阶类型参数(类型参数t
的类型参数)仅在其紧邻的参数子句(可能包括更深嵌套级别的子句)和 t 的边界中可见。 Therefore, their names must only be pairwise different from the names of other visible parameters.因此,它们的名称只能与其他可见参数的名称成对不同。 Since the names of higher-order type parameters are thus often irrelevant, they may be denoted with a_
, which is nowhere visible.由于高阶类型参数的名称因此通常不相关,它们可能用_
表示,这在任何地方都不可见。Example示例
Here are some well-formed type parameter clauses:以下是一些格式良好的类型参数子句:
[S, T] [@specialized T, U] [Ex <: Throwable] [A <: Comparable[B], B <: A] [A, B >: A, C >: A <: B] [M[X], N[X]] [M[_], N[_]] // equivalent to previous clause [M[X <: Bound[X]], Bound[_]] [M[+X] <: Iterable[X]]
So if you have no bounds, as in Functor [F[T]]
, there's no difference at all from Functor [F[_]]
.因此,如果您没有边界,就像在Functor [F[T]]
,那么与Functor [F[_]]
没有任何区别。
The only difference I can think of is that with
F[_]
the parameter itself can have as many holes as possible...that isF[_]
can becomeF[Int]
orF[Future[Option[Int]]]
etc...while when you haveF[T]
theT
can only be a proper type...that isF[String]
orF[Int]
etc.我能想到的唯一区别是,使用F[_]
参数本身可以有尽可能多的孔……也就是说F[_]
可以变成F[Int]
或F[Future[Option[Int]]]
等等......而当你有F[T]
,T
只能是一个正确的类型......即F[String]
或F[Int]
等。Is this a correct assumption?这是一个正确的假设吗?
Note that Future[Option[Int]]
is a proper type of the same kind as Int
or String
.请注意, Future[Option[Int]]
是与Int
或String
类型相同的正确类型。 We can convince ourself by using :kind
command in Scala REPL我们可以通过在 Scala REPL 中使用:kind
命令来说服自己
scala> :kind -v Future[Option[Int]]
scala.concurrent.Future[Option[Int]]'s kind is A
*
This is a proper type.
scala> :kind -v Int
Int's kind is A
*
This is a proper type.
To drive the point, consider the following complicated-looking type为了强调这一点,请考虑以下看起来很复杂的类型
Function3[Int, Tuple2[Double, List[Int]], Char, Future[Either[String, Int]]]
It is still just a simple concrete *
type它仍然只是一个简单的具体*
类型
scala> :kind -v Function3[Int, Tuple2[Double, List[Int]], Char, Future[Either[String, Int]]]
(Int, (Double, List[Int]), Char) => scala.concurrent.Future[Either[String,Int]]'s kind is A
*
This is a proper type.
Hence we see the shape of Future[Option[Int]]
is simply *
, and F[_]
does not need any extra "holes" to fit it.因此,我们看到Future[Option[Int]]
的形状只是*
,而F[_]
不需要任何额外的“孔”来适应它。 Both F[_]
and F[T]
type constructors take a type argument of exactly same shape, namely *
, no more, nor less. F[_]
和F[T]
类型构造函数都采用完全相同形状的类型参数,即*
,不多也不少。 For example, let us try to fit in more than it can handle例如,让我们尝试适应超过它可以处理的
trait Bar[F[_]] // Bar is type constructor of higher order kind - shape (* -> *) -> *
def g[F[_]] = println("g takes type constructor type argument of * -> * shape")
scala> g[Bar]
^
error: kinds of the type arguments (Bar) do not conform to the expected kinds of the type parameters (type F).
Bar's type parameters do not match type F's expected parameters:
type F has 1 type parameter, but type _ has 0
This errors because actual (* -> *) -> *
shape of Bar
does not fit expected * -> *
shape of F
.此错误是因为实际(* -> *) -> *
Bar
形状不符合预期* -> *
F
形状。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.