我正在读这篇文章 “Scala中的存在类型”,发现了一些我无法理解的东西:
Array[T] forSome { type T; }
Array[T forSome { type T; }]
它们看起来几乎相同,但实际上它们非常不同。第一个是所有数组的类型,无论它们的类型参数如何。第二个是Array [Any]。
为什么他们如此不同,尤其是,为什么第二个意味着什么 Array[Any]
?
我正在读这篇文章 “Scala中的存在类型”,发现了一些我无法理解的东西:
Array[T] forSome { type T; }
Array[T forSome { type T; }]
它们看起来几乎相同,但实际上它们非常不同。第一个是所有数组的类型,无论它们的类型参数如何。第二个是Array [Any]。
为什么他们如此不同,尤其是,为什么第二个意味着什么 Array[Any]
?
不同之处在于类型系统何时决定T是什么。
也许最好的答案是,尝试在某些代码中使用这两种类型,看看会发生什么,并试图找出原因。但我会首先尝试解释一些类型理论。在这种情况下:
Array[T forSome { type T; }]
在哪里 forSome
在里面 []
括号,每个元素本身只需要以某种方式解释为 T forSome { type T; }
。好的,所以 Int
是一个 T
对于某种类型 T
,所以你可以放一个 Int
在数组中。一个 String
也是一个 T
对于某种类型 T
,因为选择 forSome
你可以说,一次只适用于一个元素 T
是 String
这一次而不是 Int
,所以你可以把 String
在数组中,即使它已经包含一个 Int
。
另一方面,虽然我们可以选择 T
独立于数组的任何元素,已经选择了数组本身的类型:它是可以容纳任何东西的数组类型。它不可能是一个 Array[Int]
或者 Array[String]
。
但在这种情况下:
Array[T] forSome { type T; }
方式 T
在阵列之外只决定一次。该阵列实际上可能是一个 Array[Int]
,和 Array[String]
或者 Array[Any]
。但一旦类型 T
如果选择,则阵列的所有元素必须与该类型一致。
好, 现在 让我们尝试一些代码。这是一个例子:
scala> var a = Array(1,2);
a: Array[Int] = Array(1, 2)
scala> def first(z : Array[T] forSome { type T }) = z(0);
first: (z: Array[_])Any
scala> def firstany(z : Array[T forSome { type T }]) = z(0);
firstany: (z: Array[T forSome { type T }])Any
scala> first(a);
res0: Any = 1
scala> firstany(a);
error: type mismatch;
found : Array[Int]
required: Array[T forSome { type T }]
firstany(a);
^
为什么错误?因为阵列 a
有类型 Array[Int]
,只能包含类型的东西 Int
。那肯定是一个 Array[T] forSome {type T}
,因为所有类型系统需要做的是选择Int作为类型T.因此 first(a)
没关系但正如上面所解释的那样 Array[T forSome { type T }]
不可能是一个 Array[Int]
所以 firstany(a)
是一个错误。
但是以下是可以的,因为一个 Array[Any]
是一个 Array[T forSome { type T }]
:
scala> var b = Array(1, "x");
b: Array[Any] = Array(1, x)
scala> firstany(b);
res1: Any = 1
改变括号的位置可能会改变很多意义,这不足为奇。有点像你切换∃和∀
第一个意思是:有一些类型 T
这是一个 Array[T]
。所以这很满意 Array[String]
, Array[Int]
等数组是同质的,但我们不知道哪种类型。
第二个意思是:对于数组的每个元素,都有一些类型 T
,使元素属于类型 T
。这根本没有约束,所以它只是 Array[Any]
。有了 forSome
在方括号内,如果你这样做,可能会很有用
Array[Set[T] forSome {type T}]
这意味着数组的元素都是集合,但在同一个数组中可能同时存在一组Int和一组字符串。
关于Rich Oliver关于类型擦除的评论:这主要是编译时间的事情,它们确实是不同的。在第一种情况下,它是一个我们不知道的元素类型的数组。所以我们不能这样做 a(0) = 1
,因为它可能是一个很好的 Array[String]
。相反,对于第二种类型,它是一种 Array[Any]
,和(0)= 1是好的。
不同之处在于类型系统何时决定T是什么。
也许最好的答案是,尝试在某些代码中使用这两种类型,看看会发生什么,并试图找出原因。但我会首先尝试解释一些类型理论。在这种情况下:
Array[T forSome { type T; }]
在哪里 forSome
在里面 []
括号,每个元素本身只需要以某种方式解释为 T forSome { type T; }
。好的,所以 Int
是一个 T
对于某种类型 T
,所以你可以放一个 Int
在数组中。一个 String
也是一个 T
对于某种类型 T
,因为选择 forSome
你可以说,一次只适用于一个元素 T
是 String
这一次而不是 Int
,所以你可以把 String
在数组中,即使它已经包含一个 Int
。
另一方面,虽然我们可以选择 T
独立于数组的任何元素,已经选择了数组本身的类型:它是可以容纳任何东西的数组类型。它不可能是一个 Array[Int]
或者 Array[String]
。
但在这种情况下:
Array[T] forSome { type T; }
方式 T
在阵列之外只决定一次。该阵列实际上可能是一个 Array[Int]
,和 Array[String]
或者 Array[Any]
。但一旦类型 T
如果选择,则阵列的所有元素必须与该类型一致。
好, 现在 让我们尝试一些代码。这是一个例子:
scala> var a = Array(1,2);
a: Array[Int] = Array(1, 2)
scala> def first(z : Array[T] forSome { type T }) = z(0);
first: (z: Array[_])Any
scala> def firstany(z : Array[T forSome { type T }]) = z(0);
firstany: (z: Array[T forSome { type T }])Any
scala> first(a);
res0: Any = 1
scala> firstany(a);
error: type mismatch;
found : Array[Int]
required: Array[T forSome { type T }]
firstany(a);
^
为什么错误?因为阵列 a
有类型 Array[Int]
,只能包含类型的东西 Int
。那肯定是一个 Array[T] forSome {type T}
,因为所有类型系统需要做的是选择Int作为类型T.因此 first(a)
没关系但正如上面所解释的那样 Array[T forSome { type T }]
不可能是一个 Array[Int]
所以 firstany(a)
是一个错误。
但是以下是可以的,因为一个 Array[Any]
是一个 Array[T forSome { type T }]
:
scala> var b = Array(1, "x");
b: Array[Any] = Array(1, x)
scala> firstany(b);
res1: Any = 1
改变括号的位置可能会改变很多意义,这不足为奇。有点像你切换∃和∀
第一个意思是:有一些类型 T
这是一个 Array[T]
。所以这很满意 Array[String]
, Array[Int]
等数组是同质的,但我们不知道哪种类型。
第二个意思是:对于数组的每个元素,都有一些类型 T
,使元素属于类型 T
。这根本没有约束,所以它只是 Array[Any]
。有了 forSome
在方括号内,如果你这样做,可能会很有用
Array[Set[T] forSome {type T}]
这意味着数组的元素都是集合,但在同一个数组中可能同时存在一组Int和一组字符串。
关于Rich Oliver关于类型擦除的评论:这主要是编译时间的事情,它们确实是不同的。在第一种情况下,它是一个我们不知道的元素类型的数组。所以我们不能这样做 a(0) = 1
,因为它可能是一个很好的 Array[String]
。相反,对于第二种类型,它是一种 Array[Any]
,和(0)= 1是好的。