鉴于以下两个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)
为什么Scala认为toList
函数属于Nothing => List[Nothing]
而不是Int => List[Int]
?
答案 0 :(得分:1)
根据foo
的定义,foo(12, toList)
传递参数是错误的。正确的方法是foo(toList, 12)
为什么Scala认为toList函数是Nothing =&gt;列出[Nothing]而不是Int =&gt;列表[INT]?
12
属于Int
类型,因为foo
是
def foo[A](f: A => List[A], b: A) = f(b)
它还期望A
类型,Int
函数也是toList
。
如果您将foo
称为foo(toList, 12D)
,我们会收到以下错误
<console>:22: error: type mismatch;
found : Nothing => List[Nothing]
required: Double => List[Double]
foo(toList, 12D)
因为12D
是Double type
而toList
预计也是Double
。
所以正确的方法是
foo(toList[Any], 12)
答案 1 :(得分:1)
Scala编译器会尝试推断方法的类型参数,它将查看第一个括号中定义的参数并尝试从中提取类型,如果不能,则会选择下一个参数组来推断类型,等等...
定义该功能的最佳方法是这样的
def foo[A](b: A)(f: A => List[A]) = f(b)
按此顺序给出参数将允许您避免向compliler提供一些提示。您可以像这样调用此函数:
foo(2.0d)(toList)
你会得到一个List [Double]
如果你保留另一个顺序,你需要给编译器一个提示,以便找出类型参数A
foo(toList[Double], 2.0d)