我有這樣定義的類:如何在調用函數時指定一個類型參數,同時讓編譯器推斷另一個?
implicit class TraversableLikeView[+A, +Repr, Raw](self: Raw)(implicit cast: Raw => TraversableLike[A,Repr]) {
def filterByType[B, That](implicit bf: CanBuildFrom[Repr, B, That]): That = {
val result = cast(self).flatMap{
case tt: B => Some(tt)
case _ => None
}(bf)
result
}
}
當調用它TraversableLikeView("abc" :: "def" :: Nil)
:
欲類型參數B
中指定,和類型參數That
從預定義的implicits自動推斷。所以我這樣調用該函數:
TraversableLikeView("abc" :: "def" :: Nil).filterByType[String, _].foreach{...}
然而,編譯器給了我這個錯誤:
Error:(38, 56) unbound wildcard type
....filterByType[String, _].foreach{...
^
爲什麼Scala是無法推斷出這種類型的參數?我該怎麼做才能解決它?
更新:我能得到最接近的事是這樣的:
implicit class TraversableLikeView[A, Repr, Raw <% TraversableLike[A, Repr]](self: Raw) {
def filterByType[B] = new FilterByType[B]
class FilterByType[B] {
def apply[That](implicit bf: CanBuildFrom[Repr, B, That]): That = {
val result = self.flatMap{
case tt: B => Some(tt)
case _ => None
}(bf)
result
}
}
}
test("1") {
val res: Seq[String] = Seq("abc", "def").filterByType[String].apply
println(res)
val res2: Array[String] = Array("abc", "def").filterByType[String].apply
println(res2)
val res3: Set[String] = Set("abc", "def").filterByType[String].apply
println(res3)
}
但是編譯器似乎未能在尋找證據(這甚至不應該需要):
Error:(38, 33) value filterByType is not a member of Array[com.tribbloids.spookystuff.pages.PageLike]
val unfetched = pageLikes.filterByType[Unfetched].head
^
如果我放棄視圖邊界,它將完美工作(當然除了數組[String]),但是我很驚訝地發現它需要這樣的規避才能在scala中實現一個簡單的事情。
是的,它使用的視圖的約束,否則該功能將不會如工作是非常重要的陣列( 「一」, 「B」)。此外,這不是一個完美的解決方案,因爲listResult&setResult的編譯類型仍然是Traversable [String] – tribbloid