scala anonymous function missing parameter type er

2020-02-26 05:04发布

问题:

I wrote the following

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

and when I did

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

It worked fine. However, I really wanted to make the following work too

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

It complains about "missing parameter type". I know that I could use currying, but is there any way to still use anonymous function for non-currying def I had above?

回答1:

It seems to me that because "f" is in the same parameter list as "xs", you're required to give some information regarding the type of x so that the compiler can solve it.

In your case, this will work:

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

Do you see how I'm informing the compiler that x is an Int?

A "trick" that you can do is currying f. If you don't know what currying is check this out: http://www.codecommit.com/blog/scala/function-currying-in-scala

You will end up with a mapFun like this:

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

And this will work:

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

In the last call, the type of x is resolved when the compiler checks the first parameter list.

EDIT:

As Dominic pointed out, you could tell the compiler what your types are. Leading to:

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

Cheers!



回答2:

The limitation of scala's type system that you're running into here is that the type information flows from left to right across parameter groups and does not flow from left to right within a parameter group.

What this means is that specifying the type parameter T by providing a List[Int] will not provide that information to other parameters within the group like f. Which results in a missing parameter type error. But it will provide it to f if f were a part of the next parameter group. This is why the curried function approach works.

i.e. if you defined it like this:

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

The type parameter T that you define in the first parameter group: (xs: List[T]) as Int will be made available to the next parameter group: (f: T => U). So now you do not have to explicitly specify T at the call site.



标签: scala