2015-11-04 32 views
2

我有一個函數的用例,該函數通過任何類型(任何TTraversableOnce[T])進行參數化。我試圖用Scalac無法編譯通過TraversableOnce [_]參數化的函數,而元素類型爲

def test[T, F[_] <: TraversableOnce[_]](ts: F[T]): Unit = { 
    ts.foldLeft("")((acc: String, t: T) => if (acc.isEmpty) t.toString else acc + "," + t.toString) 
} 

但Scalac中,我已經發現了奇怪的方式抱怨:

<console>:8: error: type mismatch; 
found : (String, T) => String 
required: (String, _$1) => String 
      ts.foldLeft("")((acc: String, t: T) => if (acc.isEmpty) t.toString else acc + "," + t.toString) 

現在我知道我可以使用約束F[T] <: TraversableOnce[T],但我想明白爲什麼Scalac能不適用於我剛剛編寫的函數版本。 ts的類型是F[T],因此foldLeft的第二個參數的類型應該是(String, T) => String而不是(String, _$1) => String_$1是未知的。這裏發生了什麼?

+0

SOM-snytt應該獲得榮譽,在這一個正確的答案。我最初誤解了這個問題,然後回去編輯我的答案,以實際回答你的問題。但是在我糾正自己之前,som-snytt正確回答了。 –

回答

1

你有沒有你喜歡的類型參數綁在穿越的類型參數。

你傳遞一個需要T的功能,但可穿越的未知類型參數沒有限制。

scala> def f[T, F[T] <: TraversableOnce[T]](ts: F[T]) = ts.foldLeft("") _ 
f: [T, F[T] <: TraversableOnce[T]](ts: F[T])((String, T) => String) => String 

scala> def f[T, F[_] <: TraversableOnce[_]](ts: F[T]) = ts.foldLeft("") _ 
f: [T, F[_] <: TraversableOnce[_]](ts: F[T])((String, Any) => String) => String 

的符號TO[_]TO[t] forSome { type t },其中_$1t你穿越的簡寫。

+0

假設你有'F [X with Z]','F [X] <:TO [Y]'b/c'X <:

3

像這樣的簽名:

def test[T, F[_] <: TraversableOnce[_]](ts: F[T]): Unit 

是不一樣的這樣的簽名:

def test[T, F[X] <: TraversableOnce[X]](ts: F[T]): Unit 

在後一種情況下,你說的那個F「F是一種具有單個類型參數是TraversableOnce的子類,只要F和TraversableOnce具有相同的類型參數。「帶下劃線的版本意味着更像「F是帶有單個參數的類型,它是TraversableOnce [Any]的子類」。

之所以意義不同的是,在第一個版本的兩個下劃線無關。在該簽名,TraversableOnce[_]相同TraversableOnce[Any],而在F[_],下劃線充當自由變量。這相當於說這個:

def test[T, F[X] <: TraversableOnce[_]](ts: F[T]): Unit 

在這裏,X是不綁定到任何東西的F[X]外的自由變量。

+0

我從來沒有見過在Scala編譯器看到兩種不同用途如'_'並決定你的意思是他們是同樣的事情的情況。 –

相關問題