与scala中的存在类型混淆 [英] confusion with existential types in scala

查看:82
本文介绍了与scala中的存在类型混淆的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在努力理解scala中的存在类型,但无法弄清楚.这是我的测试代码:

I was struggling to understand existential types in scala but can't figure it out. Here is my test code:

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是什么意思?非常感谢有人可以提供详细的解释,谢谢!

I was told that Array[T] forSome {type T} means any type of Array such as Array[Int], Array[String], etc. Array[T forSome {type T}] means Array[Any]. But according to the result of my test code, I can't see this difference, and the compile error message is also confusing. What does required: T means? I do appreciate if someone can give a detail explanation, thanks!

推荐答案

有人告诉我Array[T] forSome {type T}表示任何类型的Array,例如Array [Int],Array [String]等.

I was told that Array[T] forSome {type T} means any type of Array such as Array[Int], Array[String], etc.

是正确的.您可能会惊讶地看到值Array(1,2.2,"3")被接受为类型Array[T] forSome {type T}的值,即使Array(1,2.2,"3")显然不是类型Array[Int]Array[String]的值也是如此.要了解发生了什么,让我们问一下Scala它为Array(1,2.2,"3")推断出什么类型:

That's correct. You might be surprised to see that the value Array(1,2.2,"3") is accepted as a value of type Array[T] forSome {type T}, even though Array(1,2.2,"3") is clearly not a value of type Array[Int] nor Array[String]. To understand what's going on, let's ask Scala what type it infers for 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}类型的值的原因.

Aha! So there is a type T, namely Any, so that x has type Array[T]. That's why Array(1,2.2,"3") is accepted as a value of type Array[T] forSome {type T}.

Array[T forSome {type T}]表示Array [Any]

Array[T forSome {type T}] means Array[Any]

也正确.类型<type expression involving T> forSome {type T}是在T处实例化<type expression involving T>的所有类型的超类型.所以Array[T] forSome {type T}Array[Int]Array[String]等的超类型.由于T forSome {type T}IntString等的超类型,所以T forSome {type T}是所有类型的aka,也就是Any.

Also correct. The type <type expression involving T> forSome {type T} is the supertype of all types in which <type expression involving T> is instantiated at a particular T. So Array[T] forSome {type T} is the supertype of Array[Int], Array[String], etc. And since T forSome {type T} is the supertype of Int, String, etc., T forSome {type T} is the supertype of all types, aka Any.

scala> a(0)
res35: Any = 1

您可能想知道为什么结果的类型是Any,而不是T.与以下内容进行比较:

You might be wondering why the result has type Any, not T. Compare with the following:

scala> (a(0), a(1))
res0: (T, T) forSome { type T } = (1,2.2)

如您所见,Array[T]的元素类型确实是T.只是当我们仅从数组中获取单个元素时,它的类型是T forSome { type T },简化为Any.

As you can see, the type of the elements of Array[T] is indeed T. It's just that when we only fetch a single element from the array, it's type is T forSome { type T }, which simplifies to Any.

scala> b(0)
res36: Any = 1

这次非常期望类型为Any,因为Array[T forSome {type T}]的元素类型为T forSome {type T},也称为Any.

This time the type Any is very much expected, since the type of the elements of Array[T forSome {type T}] is T forSome {type T}, aka Any.

请注意,由于forSome位于方括号内,因此一对元素的类型...

Note that since the forSome is inside the brackets, the type for a pair of elements...

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的子类型.我们知道值aT实例化为Any,但是在进行类型检查时,重要的不是值的实际类型,而是它的声明类型. StringT的子类型吗?不可以,因为a可能是Array[Int],而String不能放入Array[Int].

The type of the value you assign to an Array[T] must be a subtype of T. We know that the value a has its T instantiated to Any, but when type checking, it's not the value's real type which matters, it is its declared type. And is String a subtype of T? No, since a could be an Array[Int] and a String cannot be put into an 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. StringAny的子类型吗?是的,所以分配成功.

The type of the value you assign to an Array[T forSome {type T}] must be a subtype of T forSome {type T} aka Any. Is String a subtype of Any? Yes, so the assignment succeeds.

关于存在性的最后一件事:当T只需要实例化一次时,类型推断最有效.先前我们看到(a(0), a(1))产生了一对具有相同(未知)类型的元素.实际上,我对此功能感到惊讶.在下面的非常相似的示例中,a(0)a(1)也应该具有相同的类型,因此赋值应该成功,但是不会成功.

One last thing about existentials: type inference works best when T only has to be instantiated once. Earlier we saw that (a(0), a(1)) produced a pair of elements which both have the same (unknown) type. I was actually surprised that this worked. In the following very similar example, a(0) and a(1) are also supposed to have the same type, and so the assignment is supposed to succeed, but it doesn't.

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]的函数中:

To show Scala that such an assignment is type safe, we can wrap it in a function which works for any Array[T]:

scala> def modifyArray[T](arr: Array[T]) =
     |   arr(0) = arr(1)
modifyArray: [T](arr: Array[T])Unit

我们现在可以通过将函数应用于a来执行分配,而这次确实成功了.

We can now perform the assignment by applying our function to a, and this time it does succeed.

scala> modifyArray(a)

scala> a
res3: Array[_] = Array(2.2, 2.2, 3)

这篇关于与scala中的存在类型混淆的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆