Scala анонимная функция отсутствует ошибка типа параметра

Я написал следующее

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)

Он жалуется на "отсутствующий тип параметра". Я знаю, что я мог бы использовать currying, но есть ли способ использовать анонимную функцию для non-currying def, который у меня был выше?

Ответы

Ответ 1

Мне кажется, что поскольку "f" находится в том же списке параметров, что и "xs", вам необходимо предоставить некоторую информацию о типе x, чтобы компилятор мог его решить.

В вашем случае это будет работать:

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

Вы видите, как я сообщаю компилятору, что x является Int?

"Трюк", который вы можете сделать, - это currying f. Если вы не знаете, что такое currying, проверьте это: 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 разрешается, когда компилятор проверяет первый список параметров.

EDIT:

Как отметил Доминик, вы можете рассказать компилятору, какие у вас типы. Ведущий:

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

Ура!

Ответ 2

Ограничение системы типов scala, в которой вы работаете, состоит в том, что информация типа течет слева направо через группы параметров и не распространяется слева направо внутри группа параметров.

Это означает, что указание параметра типа T путем предоставления 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]) как Int, будет доступен следующей группе параметров: (f: T => U). Поэтому теперь вам не нужно явно указывать T на сайте вызова.