Scala匿名函数缺少参数类型错误。

29

我写了以下内容

def mapFun[T, U](xs: List[T], f: T => U): List[U] = (xs foldRight List[U]())( f(_)::_ )

当我这样做时

def f(x: Int):Int=x*x
mapFun(List(1,2,3), f)

它运行良好。然而,我真的想让以下内容也能够工作
mapFun(List(1,2,3), x=>x*x)

它抱怨缺少参数类型。我知道可以使用柯里化,但是否仍有办法为上述非柯里化def使用匿名函数?
2个回答

39

在我看来,由于"f"与"xs"在同一参数列表中,需要提供有关"x"的类型信息,以便编译器可以解决它。

在您的情况下,以下方法可行:

mapFun(List(1,2,3) , (x: Int) => x * x)  

你看到我是如何告诉编译器x是Int类型的吗?

一个“技巧”是使用柯里化函数f。如果你不知道什么是柯里化,请查看这个链接:http://www.codecommit.com/blog/scala/function-currying-in-scala

你最终将得到一个像这样的mapFun:

def mapFun[T, U](xs: List[T])(f: T => U): List[U] = 
    (xs foldRight List[U]())( f(_)::_ )

这将会起作用:

mapFun(List(1,2,3))(x => x * x)

在最后一次调用中,编译器在检查第一个参数列表时解析x的类型。
编辑:正如Dominic指出的那样,您可以告诉编译器您的类型是什么。导致:
mapFun[Int, Int](List(1,2,3), x => x * x)

干杯!


你也可以像这样指定类型参数:mapFun[Int, Int](List(1,2,3), x => x * x) - Dominic Bou-Samra
1
当然,你总是可以明确地告诉别人你的类型。谢谢Dominic。 - wleao
我尝试使用“Pimp my library”模式在List类型上实现他的函数,但无法使类型正常工作。这可能吗? - Dominic Bou-Samra

18
Scala 的类型系统的限制在这里体现为类型信息从左到右跨越参数组流动,而不会在一个参数组内部从左到右流动。这意味着通过提供 List[Int] 来指定类型参数 T 将不会向同一组中的其他参数(比如 f)提供该信息,这将导致缺少参数类型错误。但是,如果 f 是下一个参数组的一部分,则会向 f 提供此信息。这就是柯里化函数方法有效的原因。
也就是说,如果你像以下这样定义它:
def mapFun[T, U](xs: List[T])(f: T => U): List[U] = (xs foldRight List[U]())( f(_)::_ )

在第一个参数组中定义的类型参数T(xs: List[T]),如果定义为Int,将会被传递给下一个参数组:(f: T => U)。因此,在调用时不需要显式指定T。请注意保留HTML标签。

1
能够了解更多关于这个限制的信息会很棒,规范中有没有相关的说明? - nornagon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接