Qiang Li
Qiang Li

Reputation: 10865

scala anonymous function missing parameter type error

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?

Upvotes: 29

Views: 29871

Answers (2)

wleao
wleao

Reputation: 2346

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!

Upvotes: 39

Ratan Sebastian
Ratan Sebastian

Reputation: 1892

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.

Upvotes: 18

Related Questions