2017-06-05 59 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)