30

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?

2 Answers 2

39

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!

Sign up to request clarification or add additional context in comments.

3 Comments

You can also specify the type params like so: mapFun[Int, Int](List(1,2,3), x => x * x)
Oh yeah, of course. You could always tell explicitly what your types are. Thanks Dominic.
I tried implementing his function on the List type using the Pimp my library pattern, but couldn't get the types to work. Possible?
19

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.

1 Comment

Would be awesome to learn more about this limitation, is there anything written about it in the spec?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.