[英]Intersect Scala set with set of subtype
為什么這個函數不能編譯?
case class MyType(n: Int)
def intersection(s1: Set[MyType], s2: Set[_ <: MyType]) =
(s1 & s2)
我收到以下錯誤:
錯誤:類型不匹配; 找到:設置[_ $ 1]其中類型_ $ 1 <:MyType required:scala.collection.GenSet [MyType]注意:_ $ 1 <:MyType,但是特性GenSet在類型A中是不變的。您可能希望研究一個通配符類型as
_ <: MyType
。 (SLS 3.2.10)(w&r)
是否有一種簡單的方法可以“提升”第二個參數來鍵入Set [MyType]而不使用asInstanceOf?
這是因為Set
定義為Set[A]
。 它是變體而不是共變體。
&
被定義為
def &(that: GenSet[A]): Set[A]
它期望和類型Set[A]
。 但是你提供Set[_ <: MyType]
。
Set[_ <: Mytype]
是Set[MyType]
共變體。 但正如聲明所說,該論證應該是變體的,即Set[MyType]
,因此錯誤。
PS:您可以將協方差視為從窄到寬的類型轉換。 例如:如果Dog
延伸Animal
,如果你做Animal a = new Dog()
,你有一只狗(狹窄)轉換為動物(更廣泛)。 期望它不變的類型。 即如果它需要Animal
,你只能提供Animal
。 另一個例子是java.util.ArrayList
,它是in-variant。
Set
在其類型參數上不協變。
所以一個簡單的解決方案是轉換為List
(這是協變的):
def intersection(s1: Set[MyType], s2: Set[_ <: MyType]) =
s1.toList.intersect(s2.toList).toSet
Set
是不變的,但是有一個非常簡單的解決方法:
def intersection(s1: Set[MyType], s2: Set[_ <: MyType]) =
s2 filter s1
或者,如果想要為結果類型獲得更好的類型推斷:
def intersection[X <: MyType](s1: Set[MyType], s2: Set[X]): Set[X] =
s2 filter s1
這里s1
用作函數。 函數在參數中是反變量的,因此s1.apply
of type (MyType) => Boolean
是可接受的(_ <: MyType) => Boolean
。
性能是一樣的intersect
,因為this filter that
是如何intersect
的實現Set
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.