缺少一個更好的示例,假設我有一個定義了容器類型的單一類型參數。假設這個容器包裝了一個相同類型的List。我想在我的新容器上定義一個方法,以便每當執行操作時它將調用委託給嵌入列表,但它返回我的容器類型(可能是一個不同的類型參數)。爲了實現這一點,我將使用scala集合中的隱式構建器模式。這裏的基本結構:當選擇隱式用於CanBuildFrom函數時,優先級的規則是什麼
class Foo[A](val data: List[A]) {
def foo[C, That](pf: PartialFunction[A, C])(
implicit bf: CanBuildFrom[Foo[_], C, That]
): That = {
bf(new Foo(data.collect(pf))).result
}
}
object Foo {
def newBuilder[A]: Builder[A, Foo[A]] =
new ArrayBuffer[A] mapResult { r => new Foo(r.toList) }
implicit def canBuildFrom[A]: CanBuildFrom[Foo[_], A, Foo[A]] =
new CanBuildFrom[Foo[_], A, Foo[A]] {
def apply(from: Foo[_]) = newBuilder
def apply() = newBuilder
}
}
所以這個工程,我會期望返回一個Foo [字符串]當我的PF從int到字符串轉換:在具有
scala> val f = new Foo(List(1,2,3))
f: Foo[Int] = [email protected]
scala> f.foo { case x => x.toString }
res318: Foo[java.lang.String] = [email protected]
雖然前面的例子是基於CanBuildFrom採用Foo [_]的「from」類型,「A」的元素類型,並將其轉換爲「Foo [A]」的「to」類型。我想要做的是從'[']類型的List [_],一個元素類型'A',並轉換爲'到'類型'Foo [A]'。沿着這些路線的東西:
class Foo[A](val data: List[A]) {
def foo[C, That](pf: PartialFunction[A, C])(
implicit bf: CanBuildFrom[List[_], C, That]
): That = {
data.collect(pf)(bf)
}
}
object Foo {
def newBuilder[A]: Builder[A, Foo[A]] =
new ArrayBuffer[A] mapResult { r => new Foo(r.toList) }
implicit def canBuildFrom[A]: CanBuildFrom[List[_], A, Foo[A]] =
new CanBuildFrom[List[_], A, Foo[A]] {
def apply(from: List[_]) = newBuilder
def apply() = newBuilder
}
}
在這裏,我已經通過我的隱CanBuildFrom參數關閉的List類直接,以便它可以建立我的Foo類以存儲結果。然而,當我運行相同的測試,來代替。得到一個Foo [String],我得到一個List [String]。換句話說,它不使用我的隱式,它使用的是通用版本。
scala> val f = new Foo(List(1,2,3))
f: Foo[Int] = [email protected]
scala> f.foo { case x => x.toString }
res319: List[java.lang.String] = List(1, 2, 3)
所以,我的問題是爲什麼?我會想,如果我現在的類型是Foo,並且我將轉換爲Foo,並且在範圍中與輸入參數類型(本例中爲List)匹配的隱式fn,那麼這將是最佳匹配。我是做錯了什麼,或者出於安全原因,「收集」集合在選擇要轉換的集合方面具有最高優先權。我能做些什麼來提高隱含的優先級?
感謝您的意見。是的,我在發佈之前檢查了實際上在範圍內的隱式。事情是我不想指定一個類型,我想要類型推斷來完成這項工作。我認爲我的隱含應該優先,但我想這不會是這樣,直到它進入方法foo之後。我能想到的唯一解決方案是用'Foo [C]'替換'That',所以'to'類型是明確的。這很有效,但問題是,如果我沒有'Foo'的'C'類型的支持,我希望它使用更通用的類型(按照CanBuildFrom模式)。這是行不通的。 – Mike 2012-04-02 02:33:55