[英]What is the significant of the placement of the “forSome” clause in Scala generics syntax?
根據對這個問題的答案,似乎將“ forSome”放置在類型定義的組件之后與將其放置在整個內容的末尾不同。 例如,以下內容似乎有所不同:
def one: Foo[U >: T] forSome {type U >: T}
def one: Foo[U forSome {type U >: T}]
Scala語言規范似乎沒有說出任何區別,並且我會想象將量詞移到外面不會有任何區別。 如果確實有所作為,我會以為這將在此答案中進行描述,它基本上說Set [X forSome {type X}]允許X在集合元素之間變化,其中Set [X] forSome {type X}才不是。 但是,這似乎不是全部內容,並且/或者是不正確的,因為它不能編譯:
trait Bar {
def test: Set[X] forSome {type X}
}
def test(b: Bar) {
val set = b.test
val h = set.head
set.contains(h)
}
但這確實是:
trait Bar {
def test: Set[X forSome {type X}]
}
def test(b: Bar) {
val set = b.test
val h = set.head
set.contains(h)
}
似乎Set [X] forSome {type X}為實例化類中的每個使用站點創建了一個單獨的抽象類型,其中Set [X forSome {type X}]僅創建了一個抽象類型,並將其用於整個類。 這與我的預期相反,並且似乎與上述答案不一致。
以下是一些觀察到的X forSome { type X }
: X forSome { type X }
只是編寫Any
一種奇特的方式-這是我們一無所知的類型,因此它必須位於類型層次結構的頂部。 如果您不相信我,請詢問編譯器:
scala> implicitly[Any =:= X forSome { type X }]
res0: =:=[Any, _] = <function1>
是的,它同意。
相關地,以下內容將無法編譯:
scala> val xs: Set[X forSome { type X }] = Set[Int](1, 2, 3)
<console>:7: error: type mismatch;
found : scala.collection.immutable.Set[Int]
required: Set[X forSome { type X }]
Note: Int <: X forSome { type X }, but trait Set is invariant in type A.
鑒於我們剛剛學到的知識,這不足為奇。 Set
的type參數是不變的,因此Set[Int]
不是Set[X forSome { type X }]
(即Set[Any]
)。
考慮到所有這些,第二種test
方法可以編譯也就不足為奇了。 當我們使用b.test
的頭時,我們得到一個X forSome { type X }
(即, Any
),並且我們需要一個X forSome { type X }
(即Any
)用於b.test.contains
。
所以現在換第一個Bar
。 考慮以下:
scala> val xs: Set[X] forSome { type X } = Set[Int](1, 2, 3)
xs: Set[_] = Set(1, 2, 3)
在這里,我們說xs
是一組特定類型X
的集合,但是我們將立即忘記有關X
所有信息。 請注意,與上面的xs
定義不同,它確實可以編譯,因為我們並不是說xs
是任何東西的集合,只是它是我們不知道的某種特定類型的集合(或者編譯器不知道的) )。
這意味着,絕對沒有任何有可能的a
,這將使xs.contains(a)
編譯。 讓我們嘗試一個顯而易見的方法:
scala> xs.contains(1)
<console>:9: error: type mismatch;
found : Int(1)
required: X
xs.contains(1)
^
這里的錯誤消息很有趣- 我們知道X
實際上是Int
,但是編譯器不是,因為我們明確要求它使用forSome { type X }
來忘記那個事實。 通過重寫第一個Bar
test
方法,您可以看到類似的有趣消息,如下所示:
def test(b: Bar) = b.test.contains(b.test.head)
這也不會編譯,並顯示以下消息:
found : (some other)X(in method test) where type (some other)X(in method test)
required: X(in method test) where type X(in method test)
def test(b: Bar) = b.test.contains(b.test.head)
^
也就是說, 即使我們只是將b.test.head
從b.test
,我們仍然無法對其應用b.test.contains
。 我們已經告訴編譯器,它對b.test
的項目類型唯一了解的是它的存在,因此它不會跟蹤b.test.head
是我們應該做的那種事情。能夠適用b.test.contains
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.