这个问题是关于_在类型构造函数中使用的,而不是在用于定义存在类型时。
所以问题是当_
用作类型参数而不是像T
这样的变量时有什么区别。例如F[_]
和F[T]
之间的差异。
我能想到的唯一区别是,使用F[_]
参数本身可以有尽可能多的洞...... F[_]
可以变为F[Int]
或{{1}等等......当你F[Future[Option[Int]]]
时,F[T]
只能是一个合适的类型...... T
或F[String]
等。
这是正确的假设吗?这是F[Int]
和F[_]
之间的主要区别吗?还是还有更多?
将两者用作类型参数的情况如何?例如,F[T]
和trait Functor [F[_]]
之间有什么区别?
如果将仿函数特征定义为trait Functor [F[T]]
而不是trait Functor [F[_]]
,是否存在语义差异?
答案 0 :(得分:3)
上述范围限制一般化为嵌套类型参数子句的情况,它声明了高阶类型参数。高阶类型参数(类型参数
t
的类型参数)仅在其紧邻的参数子句中可见(可能包括更深嵌套级别的子句)和t的边界。因此,它们的名称只能与其他可见参数的名称成对地不同。由于高阶类型参数的名称因此通常是不相关的,因此它们可以用_
表示,其中无处可见。实施例
以下是一些格式正确的类型参数子句:
[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]]
因此,如果你没有界限,就像Functor [F[T]]
一样,Functor [F[_]]
没有任何区别。
答案 1 :(得分:1)
我唯一能想到的是使用
F[_]
参数 本身可以有尽可能多的孔...即F[_]
可以变成F[Int]
时F[Future[Option[Int]]]
或F[T]
等...T
只能是正确的类型...即F[String]
或F[Int]
等这是正确的假设吗?
请注意,Future[Option[Int]]
是与Int
或String
相同类型的正确类型。我们可以通过在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.
为说明这一点,请考虑以下复杂外观的类型
Function3[Int, Tuple2[Double, List[Int]], Char, Future[Either[String, Int]]]
它仍然只是一种简单的具体*
类型
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.
因此,我们看到Future[Option[Int]]
的形状只是*
,而F[_]
不需要任何额外的“孔”即可适合它。 F[_]
和F[T]
类型的构造函数都采用形状参数完全相同的类型参数,即*
,不多也不少。例如,让我们尝试适应更多的可能
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
此错误是因为(* -> *) -> *
的实际Bar
形状不符合* -> *
的预期F
形状。