簡體   English   中英

與scala中的存在類型混淆

[英]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}IntString等的超類型,所以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的子類型。 我們知道值aT實例化為Any ,但是在進行類型檢查時,重要的不是值的實型,而是它的聲明類型。 並且StringT的子類型嗎? 不可以,因為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 StringAny的子類型嗎? 是的,所以分配成功。

關於存在性的最后一件事:當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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM