[英]confusion with existential types in scala
我在努力理解scala中的存在类型,但无法弄清楚。 这是我的测试代码:
scala> val a: Array[T] forSome {type T} = Array(1,2.2,"3")
a: Array[_] = Array(1, 2.2, 3)
scala> val b: Array[T forSome {type T}] = Array(1,2.2,"3")
b: Array[T forSome { type T }] = Array(1, 2.2, 3)
scala> a(0)
res35: Any = 1
scala> b(0)
res36: Any = 1
scala> a(0) = "x"
<console>:10: error: type mismatch;
found : String("x")
required: T
a(0) = "x"
^
scala> b(0) = "x"
有人告诉我Array[T] forSome {type T}
表示任何类型的Array,例如Array [Int],Array [String]等Array[T forSome {type T}]
表示Array [Any]。 但是根据测试代码的结果,我看不到这种差异,并且编译错误消息也令人困惑。 required: T
什么required: T
是什么意思? 如果有人可以提供详细的解释,我非常感谢,谢谢!
有人告诉我
Array[T] forSome {type T}
表示任何类型的Array,例如Array [Int],Array [String]等。
没错 您可能会惊讶地发现,即使Array(1,2.2,"3")
显然是Array(1,2.2,"3")
Array[T] forSome {type T}
, Array[T] forSome {type T}
的值,也接受Array(1,2.2,"3")
作为Array[T] forSome {type T}
类型的值不是Array[Int]
类型或Array[String]
类型的值。 要了解发生了什么,让我们问一下Scala它为Array(1,2.2,"3")
推断出什么类型:
scala> val x = Array(1,2.2,"3")
x: Array[Any] = Array(1, 2.2, 3)
啊哈! 所以有一个类型T
,即Any
,因此x
具有类型Array[T]
。 这就是为什么Array(1,2.2,"3")
被接受为Array[T] forSome {type T}
类型的值的Array[T] forSome {type T}
。
Array[T forSome {type T}]
表示Array [Any]
也正确。 <type expression involving T> forSome {type T}
的类型<type expression involving T>
是所有类型的超类型,其中在特定T
实例化<type expression involving T>
。 因此, Array[T] forSome {type T}
是Array[Int]
, Array[String]
等的超类型。由于T forSome {type T}
是Int
, String
等的超类型,所以T forSome {type T}
是所有类型(也称为Any
)的超类型。
scala> a(0) res35: Any = 1
您可能想知道为什么结果的类型为Any
而不是T
与以下内容进行比较:
scala> (a(0), a(1))
res0: (T, T) forSome { type T } = (1,2.2)
如您所见, Array[T]
的元素的类型确实是T
只是当我们仅从数组中获取单个元素时,其类型为T forSome { type T }
,它简化为Any
。
scala> b(0) res36: Any = 1
这次非常期待类型Any
,因为Array[T forSome {type T}]
的元素Array[T forSome {type T}]
是T forSome {type T}
,也就是Any
。
请注意,因为forSome
在方括号内,所以一对元素的类型...
scala> (b(0), b(1))
res1: (Any, Any) = (1,2.2)
...是(T forSome {type T}, T forSome {type T})
,又名(Any, Any)
。
scala> a(0) = "x" <console>:10: error: type mismatch; found : String("x") required: T a(0) = "x" ^
您分配给Array[T]
的值的类型必须是T
的子类型。 我们知道值a
的T
实例化为Any
,但是在进行类型检查时,重要的不是值的实型,而是它的声明类型。 并且String
是T
的子类型吗? 不可以,因为a
可以是Array[Int]
并且不能将String
放入Array[Int]
。
scala> b(0) = "x" scala> b res2: Array[T forSome { type T }] = Array(x, 2.2, 3)
您分配给Array[T forSome {type T}]
值的类型必须是T forSome {type T}
的子类型,也称为Any
。 String
是Any
的子类型吗? 是的,所以分配成功。
关于存在性的最后一件事:当T
只需要实例化一次时,类型推断最有效。 之前我们看到(a(0), a(1))
产生了一对具有相同(未知)类型的元素。 实际上,我对此功能感到惊讶。 在以下非常相似的示例中, a(0)
和a(1)
也应该具有相同的类型,因此赋值应该成功,但事实并非如此。
scala> a(0) = a(1)
<console>:12: error: type mismatch;
found : (some other)T(in value a)
required: T(in value a)
a(0) = a(1)
^
为了显示Scala这种分配是类型安全的,我们可以将其包装在适用于任何Array[T]
的函数中:
scala> def modifyArray[T](arr: Array[T]) =
| arr(0) = arr(1)
modifyArray: [T](arr: Array[T])Unit
现在,我们可以通过应用我们的函数来执行任务a
,而这一次它确实成功。
scala> modifyArray(a)
scala> a
res3: Array[_] = Array(2.2, 2.2, 3)
它与Array[Any]
。 Array[T forSome { type T; }]
Array[T forSome { type T; }]
表示您不在乎Array
内部的类型。 您可以在Array上编写通用方法,例如: def swap(arr : Array[T forSome { type T; }]) = arr(0) = arr(1);
。 但是数组类型仍然是已知的,并且所有表达式都经过类型检查。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.