Scala Currying: переопределение функции с пустым аргументом частичной функцией

Я пытаюсь реализовать/переопределить функцию с пустым входным аргументом, используя частичную функцию. Лучше всего это объясняется этим неработающим минимальным примером:

trait T
trait TFactory {
  def build(): T
}

class A(someParameter: Int) extends T

object A extends TFactory {
  def build(someParameter: Int)(): T = new A(someParameter)
}

Компилятор жалуется: object creation impossible, since method build in trait TFactory of type ()T is not defined, что логично, так как тип сборки (Int)()T. Моей следующей идеей было сделать тип build явным образом для функции, принимающей пустой аргумент и возвращающей T, то есть:

trait T 
trait TFactory {
  def build: () => T    // what about empty parenthesis after build?
}

class A(someParameter: Int) extends T 

object A extends TFactory {
  def build(someParameter: Int): (() => T) = (() => new A(someParameter))
}

Теперь очевидно, что тип build — это () => T. К моему удивлению, компилятор теперь жалуется на object creation impossible, since method build in trait TFactory of type => () => T is not defined (обратите внимание, что тип неожиданно начинается с =>). Отчаянное добавление пустых скобок в конце определения(й) функции также не помогает.

Как я могу убедить свой компилятор, что эти типы на самом деле одинаковы?

Пояснение:

Моя основная цель — добиться инициализации T без параметров без необходимости фабрики для фабрик. Пример:

val t = A(33).build()      // if this is possible, I though it might be possible to have:
val t = A.build(33)()

Вывод:

Я думаю, что это просто невозможно, потому что абстрактная функция просто определяет, сколько блоков аргументов должна принимать функция build. Другими словами: вы не можете реализовать абстрактную функцию с помощью функции, чье частичное приложение имеет ту же сигнатуру, что и функция, которую вы пытаетесь реализовать.


person bluenote10    schedule 11.12.2013    source источник
comment
Я не уверен, что следую. TFactory обещает предоставить сборку метода, которая не принимает параметров и возвращает либо T (в первом примере), либо функцию, возвращающую T (во втором). Но такой метод не определен в объекте A.   -  person Matt Malone    schedule 11.12.2013
comment
Предполагаемое поведение build состоит в том, чтобы ничего не принимать в качестве входных данных и возвращать новый экземпляр T. Намерение реализации в object A состоит в том, чтобы просто обернуть все необходимые параметры A, позволяя инициализацию без параметров.   -  person bluenote10    schedule 11.12.2013


Ответы (1)


Я не совсем уверен, чего вы хотите достичь. Допустим, ваш TFactory был задан, как в вашем первом примере:

trait T

trait TFactory {
  def build(): T
}

Тогда метод build, очевидно, не может принимать никаких параметров. Если вы хотите настроить свою фабрику, у вас может быть фабрика-фабрика:

class A(x: Int) extends T

object A {
  def apply(x: Int): TFactory = new TFactory {
    def build() = new A(x)
  }
}

val factory = A(33)
val t = factory.build()

Если вы определяете TFactory просто как функцию от () до T, вы можете использовать каррирование

type TFactory = () => T

object A {
  def apply(x: Int)(): T = new A(x)
}

val factory: TFactory = A(33) _
val t = factory()
person 0__    schedule 11.12.2013
comment
И разве нельзя добиться того же, каррируя функцию build? В конце концов, моей главной целью действительно было избежать FactoryFactory. Я надеялся добиться такой инициализации без параметров, просто возвращая функцию типа () => T, что кажется возможным, поскольку типы в примерах почти правильные. - person bluenote10; 11.12.2013
comment
Спасибо за предложение! Я думаю, что моя главная проблема с этим решением заключается в том, что я не могу заставить всех, кто реализует T, также предоставить способ без параметров для создания экземпляра T. Моя первоначальная цель состояла в том, чтобы иметь val factory: TFactory внутри T, что обеспечило бы эту связь (извините, что я не смог сделать это достаточно ясно). - person bluenote10; 11.12.2013
comment
Для полноты: я задал новый вопрос здесь, который касается общей картины, стоящей за этим вопросом; Или, другими словами: этот вопрос здесь был просто совершенно ошибочной попыткой найти альтернативное решение этого другого вопроса. Я добавил соответствующий вывод выше и принимаю этот ответ, если только кто-нибудь не докажет, что мой вывод неверен. - person bluenote10; 12.12.2013