полиморфная лямбда-функция не разрешена

#scala

#scala

Вопрос:

Я не могу понять, почему этот код ломается. Оба метода отличаются входными параметрами.

   object foo {
    def x: String => String = x => x
    def x: Option[String] => String = x => x.getOrElse("None")
  }
 

Компилятор говорит method x is defined twice; ...
Как я могу обойти это?
Я хотел бы сохранить лямбда-нотацию, чтобы упростить конвейерную обработку при использовании функции.

Комментарии:

1. После удаления типа оба в основном справедливы Function[Object, Object] . Лучшее решение IMHO — использовать разные имена.

2. оба метода отличаются входными параметрами. — Нет, они этого не делают. Они имеют один и тот же входной параметр, который равен none . Они оба возвращают функцию, которая отличается сигнатурой, но оба x являются просто методами, которые не принимают параметров

3. Можете ли вы привести пример того, что вы подразумеваете под «конвейерной обработкой проще»? Может быть другое решение этой проблемы.

4. @Tim: Ниже приведен вспомогательный метод конвейерной обработки, который я использую. Поэтому я могу написать, например f |> g , для цепочки двух вызовов функций. мне легче читать, по сравнению с g(f(...)) : implicit class Pipelining[A](val a: A) extends AnyVal { def |>[B](f: A => B): B = f(a) }

5. Полиморфизм применяется только к вызову метода, и ваш код не выполняет никакого вызова метода, он просто вызывает функции. У вас не может быть значения, которое является полиморфной функцией.

Ответ №1:

Ответ на этот конкретный вопрос станет понятнее, если вы добавите скобки к методам:

 object foo {
  def x(): String => String = x => x
  def x(): Option[String] => String = x => x.getOrElse("None")
}
 

Это дает понять, что методы отличаются только типом возвращаемого значения, а полиморфизм (в Scala) зависит от того, что типы аргументов разные.

Более широкая проблема здесь заключается в том, что полиморфизм применяется только к вызову метода. Она разрешается во время компиляции, а не во время выполнения, поэтому у вас не может быть значения, являющегося полиморфной функцией.

Это нормально:

 object foo {
  def poly(i: Int): Int = i
  def poly(s: String): String = s
}

val i = foo.poly(1)
val s = foo.poly("a")

val y: Int => Int = foo.poly
 

Это НЕ НОРМАЛЬНО, потому что для этого потребуется x содержать полиморфный тип функции:

 val x = foo.poly
 

(Также обратите внимание, что в последних двух строках компилятор выполняет расширение eta от метода к функции)