[英]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.