簡體   English   中英

存在類型和類型成員

[英]Existential types and type members

什么有效(A部分​​)

假設我有一個帶有類型參數的特征:

trait A[T]

我可以使用存在類型來編寫一個方法,該方法將采用所有具有相同TA的集合:

def foo(as: Seq[A[X]] forSome { type X }) = true

請注意,這與以下內容不同:

def otherFoo(as: Seq[A[X] forSome { type X }]) = true

或等效的:

def otherFoo(as: Seq[A[_]]) = true

在這些情況下,存在體的范圍在Seq內部,因此A s可以具有不同的T s。 使用我原來的foo (對Seq的存在范圍),以下情況很好:

foo(Seq(new A[Int] {}, new A[Int] {}))

但是使類型參數不同並且不能編譯:

scala> foo(Seq(new A[Int] {}, new A[String] {}))
<console>:10: error: type mismatch;
 found   : Seq[A[_ >: java.lang.String with Int]]
 required: Seq[A[X]] forSome { type X }

              foo(Seq(new A[Int] {}, new A[String] {}))
                     ^

這一切都非常簡單。

什么有效(B部分)

現在假設我有類似成員的類似特征而不是類型參數:

trait B { type T }

我可以編寫一個只帶有一些指定TB的方法:

scala> def bar[X](b: B { type T = X }) = true
bar: [X](b: B{type T = X})Boolean

scala> bar[Int](new B { type T = Int })
res5: Boolean = true

scala> bar[String](new B { type T = Int })
<console>:10: error: type mismatch;
 found   : java.lang.Object with B
 required: B{type T = String}
              bar[String](new B { type T = Int })
                          ^

同樣,這完全符合您的預期。

什么行不通

當我們嘗試編寫上述foo的等價物,但對於類型成員,事情變得奇怪。

scala> def baz(bs: Seq[B { type T = X }] forSome { type X }) = true
baz: (as: Seq[B{type T = X}] forSome { type X })Boolean

scala> baz(Seq(new B { type T = Int }, new B { type T = String }))
res7: Boolean = true

最后一行編譯對我來說毫無意義。 我告訴它我希望所有類型的成員都是一樣的。 我的foo表明我可以為類型參數執行此操作, bar顯示我可以基於其類型成員約束類型。 但我無法將兩者結合起來。

我在2.9.2和2.10.0-M5上試過這個。

動機

這個問題的靈感來自於這個問題,我的第一個想法是,哦,只使用存在類型(暫時擱置一個問題, 似乎不可能將存在類型轉換為重復參數類型的范圍 ,這將是方便的):

def accept(rs: Seq[RList[Int] { type S = X }] forSome { type X }) = true

但這實際上並不起作用 - 你得到了與上面簡化例子中相同的奇怪結果。

我終於解決了(至少我希望如此)。 讓我們以另一種方式做。 我們建立我們的特質:

scala> trait B {type T}
defined trait B

我們嘗試構建一個B序列:

scala> Seq(new B {type T = Int}, new B {type T = String})
res0: Seq[B{type T >: String with Int}] = List($anon$1@592b12d, $anon$2@61ae0436)

該死的,它的作品! 好吧,我們沒有type T的相等,但讓我們玩它:

scala> res0 : (Seq[B {type T = X}] forSome {type X >: String with Int})
res1: Seq[B{type T = X}] forSome { type X >: String with Int } = List($anon$1@592b12d, $anon$2@61ae0436)

它更接近了。 沒有等待,它不是更接近,它比你提出的baz參數更好 ,我們不僅提供原始類型,我們也有一個上限! 因此,我們可以清楚地將它傳遞給baz 這就是它無法按預期工作的原因。

在你的例子中:

scala> def baz(bs: Seq[B { type T = X }] forSome { type X }) = true

告訴編譯器函數baz采用特征B的Seq。 特征B碰巧采用類型成員T,但就編譯器而言,即使B類型成員T的類型不相同,函數baz也可以采用特征B的Seq。 如果你想讓函數baz采用具有相同類型成員的特征B的Seq,你需要告訴編譯器如下:

scala> def baz[X](bs: Seq[B { type T = X }]) = true
baz: [X](bs: Seq[B{type T = X}])Boolean


scala> baz[Int](Seq(new B { type T = Int }, new B { type T = String }))
    <console>:10: error: type mismatch;
    found   : java.lang.Object with B
    required: B{type T = Int}
              baz[Int](Seq(new B { type T = Int }, new B { type T = String }))
                                               ^

scala> baz[Int](Seq(new B { type T = Int }, new B { type T = Int }))
res10: Boolean = true

暫無
暫無

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

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