F [_]和F [T]之间的区别在Scala中用于类型构造函数时

时间:2018-04-10 20:50:01

标签: scala types

这个问题是关于_在类型构造函数中使用的,而不是在用于定义存在类型时。

所以问题是当_用作类型参数而不是像T这样的变量时有什么区别。例如F[_]F[T]之间的差异。

我能想到的唯一区别是,使用F[_]参数本身可以有尽可能多的洞...... F[_]可以变为F[Int]或{{1}等等......当你F[Future[Option[Int]]]时,F[T]只能是一个合适的类型...... TF[String]等。

这是正确的假设吗?这是F[Int]F[_]之间的主要区别吗?还是还有更多?

将两者用作类型参数的情况如何?例如,F[T]trait Functor [F[_]]之间有什么区别?

如果将仿函数特征定义为trait Functor [F[T]]而不是trait Functor [F[_]],是否存在语义差异?

2 个答案:

答案 0 :(得分:3)

引用the specification

  
    

上述范围限制一般化为嵌套类型参数子句的情况,它声明了高阶类型参数。高阶类型参数(类型参数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]]是与IntString相同类型的正确类型。我们可以通过在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形状。