27

我写了以下

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?

4

2 回答 2

35

在我看来,因为“f”与“xs”在同一个参数列表中,所以您需要提供一些关于 x 类型的信息,以便编译器可以解决它。

在您的情况下,这将起作用:

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

你看到我如何通知编译器 x 是一个 Int 吗?

你可以做的一个“技巧”是currying 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)

干杯!

于 2012-10-29T02:12:24.317 回答
17

您在这里遇到的 scala 类型系统的限制是类型信息在参数组中从左到右流动,而不是在参数组内从左到右流动。

这意味着T通过提供 a来指定类型参数List[Int]不会将该信息提供给组内的其他参数,例如f. 这会导致缺少参数类型错误。f但如果 f 是下一个参数组的一部分,它将提供它。这就是柯里化函数方法有效的原因。

即,如果你这样定义它:

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

T您在第一个参数组中定义的类型参数: (xs: List[T])asInt将可用于下一个参数组:(f: T => U)。因此,现在您不必T在调用站点明确指定。

于 2012-10-29T02:30:12.807 回答