簡體   English   中英

Scala泛型語法中“ forSome”子句的位置有何重要意義?

[英]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.headb.test ,我們仍然無法對其應用b.test.contains 我們已經告訴編譯器,它對b.test的項目類型唯一了解的是它的存在,因此它不會跟蹤b.test.head是我們應該做的那種事情。能夠適用b.test.contains

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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