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
<
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!
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.