使用.toSet生成的Set上的類型推斷失?。?/h1>
3 回答

TA貢獻(xiàn)1829條經(jīng)驗 獲得超6個贊
我同意推斷“唯一可能的”類型會很好,即使調(diào)用是鏈接在一起的,但存在技術(shù)限制。
您可以將推理視為對表達(dá)式的廣度優(yōu)先掃描,收集對類型變量的約束(由子類型邊界和必需的隱式參數(shù)引起),然后求解這些約束。這種方法允許例如隱式指導(dǎo)類型推斷。在您的示例中,即使僅查看xs.toSet
子表達(dá)式也有一個解決方案,但是以后的鏈接調(diào)用可能會引入使系統(tǒng)無法滿足的約束。保留類型變量未解決的缺點是,對閉包的類型推斷需要知道目標(biāo)類型,因此將失?。ㄋ枰鲆恍┚唧w的事情-所需的閉包類型及其參數(shù)類型必須并非兩者都是未知的)。
現(xiàn)在,當(dāng)延遲解決約束使推理失敗時,我們可以回溯,解決所有類型變量,然后重試,但是實現(xiàn)起來很棘手(可能效率很低)。

TA貢獻(xiàn)1871條經(jīng)驗 獲得超8個贊
類型推斷無法正常工作,因為List#toSetis 的簽名
def toSet[B >: A] => scala.collection.immutable.Set[B]
并且編譯器需要在調(diào)用中的兩個位置推斷類型。在函數(shù)中注釋參數(shù)的另一種方法是toSet使用顯式類型參數(shù)進(jìn)行調(diào)用:
xs.toSet[Int] map (_*2)
更新:
關(guān)于您的問題,為什么編譯器可以分兩步進(jìn)行推斷,讓我們看一下一一行地輸入行時會發(fā)生什么:
scala> val xs = List(1,2,3)
xs: List[Int] = List(1, 2, 3)
scala> val ys = xs.toSet
ys: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
在這里,編譯器會推斷出最具體類型,ys這是Set[Int]在這種情況下?,F(xiàn)在已經(jīng)知道這種類型,因此map可以推斷傳遞給函數(shù)的類型。
如果在示例中填寫了所有可能的類型參數(shù),則調(diào)用將寫為:
xs.toSet[Int].map[Int,Set[Int]](_*2)
第二個type參數(shù)用于指定返回的集合的類型(有關(guān)詳細(xì)信息,請查看Scala集合的實現(xiàn)方式)。這意味著我什至低估了編譯器必須推斷的類型數(shù)量。
在這種情況下,似乎很容易推斷出來,Int但在某些情況下卻并非如此(鑒于Scala的其他功能,例如隱式轉(zhuǎn)換,單例類型,混合的特性等)。我并不是說這無法完成-只是Scala編譯器沒有做到這一點。
- 3 回答
- 0 關(guān)注
- 472 瀏覽
添加回答
舉報