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
на сайте вызова.