Я просто побежал в странное несоответствие между функциями и объектами (2.10) Scala:Неявные преобразования для defs/lambdas в Scala?
implicit def conv(c: Int => String) : (PrintStream => Int => Unit) = p => v => p.println(c(v))
def f(h: PrintStream => Int => Unit) : Unit = h(System.out)(1)
def a(x: Int) = x.toString
val b = (x: Int) => x.toString
// def main(args: Array[String]) = f(a) // fail
// def main(args: Array[String]) = f((x: Int) => x.toString) // fail
def main(args: Array[String]) = f(b) // ok
Почему существует разница между Defs/лямбда-литералов и лямбда вальса?
Update: видимо, проблема не возникает для бинарных функций: Implicit conversion of a function to a second-order-function only works if the function to convert has at least two parameters
Я проверил это, и действительно следующий код работает:
implicit def conv(c: (Int,Unit) => String) : (PrintStream => Int => Unit) = p => v => p.println(c(v,()))
def f(h: PrintStream => Int => Unit) : Unit = h(System.out)(1)
def a(x: Int, y : Unit) = x.toString
val b = (x: Int, y : Unit) => x.toString
def main(args: Array[String]) = f(a) // ok
def main(args: Array[String]) = f((x: Int, y: Unit) => x.toString) // ok
def main(args: Array[String]) = f(b) // ok
Аналогично, нульарные функции не представляет проблему либо:
implicit def conv(c:() => String) : (PrintStream => Int => Unit) = p => v => p.println(c())
def f(h: PrintStream => Int => Unit) : Unit = h(System.out)(1)
def a() = "1"
val b =() => "1"
def main(args: Array[String]) = f(a) // ok
def main(args: Array[String]) = f(() => "1") // ok
def main(args: Array[String]) = f(b) // ok
Так, перефразировав вопрос: почему это не работает для UNARY методов и функций?
Обновление: проблема также связана с типом цели (тип аргумента f h). Далее работает (на этот раз, в пользу «рассчитывает ETA-расширение, как прыжок», потому что нам нужно создать значение методы из использования _)
implicit def conv(c: Int => String) : Unit =()
def f(h: Unit) : Unit = System.out.print("?")
def a(x: Int) = x.toString
val b = (x: Int) => x.toString
def main(args: Array[String]) = f(a _) // ok
def main(args: Array[String]) = f((x: Int) => x.toString) // ok
def main(args: Array[String]) = f(b) // ok
m aybe scalac считает преобразование defs/lambda литералов в FunctionN уже неявным прыжком (из которого разрешено не более одного)? –
Просто проверил спецификации. Eta-расширение должно появиться бесплатно, поэтому три должны быть эквивалентными w.r.t. view: «Мы говорим, что тип T совместим с типом U, если T слабо соответствует U после применения приложений eta-expand * и * view». –
http://stackoverflow.com/questions/28456012/implicit-conversion-of-a-function-to-a-second-order-function-only-works-if-the-f –