2017-06-05 39 views
0

鑑於以下兩個Scala函數,兩者都按預期進行編譯。Scala多態函數會編譯但不會按預期運行

scala> def toList[A](a: A) = List(a) 
toList: [A](a: A)List[A] 

scala> def foo[A](f: A => List[A], b: A) = f(b) 
foo: [A](f: A => List[A], b: A)List[A] 

然而,當你運行它,它給了以下錯誤信息:

scala> foo(toList, 12) 
<console>:14: error: type mismatch; 
found : Nothing => List[Nothing] 
required: Int => List[Int] 
     foo(toList, 12) 

爲什麼斯卡拉認爲toList功能是Nothing => List[Nothing]而不是Int => List[Int]

+0

在這種情況下,推理引擎需要一些幫助:'foo [Int](toList,34)'或'foo(toList [Int],34)' – jwvh

回答

1

根據如何定義foofoo(12, toList)在傳遞參數時出錯。正確的方法是foo(toList, 12)

爲什麼斯卡拉認爲toList功能是沒什麼=>列表[沒什麼]代替INT =>列表[INT]的?

12Int類型的,並且自foo

def foo[A](f: A => List[A], b: A) = f(b) 

其期望A類型是InttoList功能以及。

如果你打電話foofoo(toList, 12D),我們得到以下錯誤

<console>:22: error: type mismatch; 
found : Nothing => List[Nothing] 
required: Double => List[Double] 
     foo(toList, 12D) 

其因12DDouble typetoList預計的Double了。

所以正確的方法是

foo(toList[Any], 12) 
1

Scala編譯器將嘗試推斷方法的類型參數,它會尋找到所定義的參數詮釋,他的第一個括號,並嘗試從中提取類型,如果不能將挑選下一組參數推斷出類型,等等...

最好的方式來定義函數是這樣

def foo[A](b: A)(f: A => List[A]) = f(b) 

按照此順序給出參數可以避免向編譯器提供一些提示。你可以調用這個函數是這樣的:

foo(2.0d)(toList) 

,你會得到一個列表[雙]

如果你把另外的順序,你需要給出一個提示編譯器,以找出類型參數A

foo(toList[Double], 2.0d)