Я работаю над DSL для экспериментальной библиотеки, которую я создаю в Scala, и я столкнулся с некоторыми неприятными особенностями вывода типов в Scala, которые относятся к аргументам лямбда-выражений, которые, кажется, не рассматриваются вкнига Программирование в Scala .
В моей библиотеке есть черта Effect [-T], которая используется для представления временных модификаторов, которые можно применять к объекту типа TУ меня есть объект myEffects, у которого есть метод с именем + =, который принимает аргумент типа Effect [PlayerCharacter].Наконец, у меня есть универсальный метод, когда [T], который используется для создания условных эффектов, принимая условное выражение и другой эффект в качестве аргумента.Сигнатура выглядит следующим образом:
def when[T](condition : T => Boolean) (effect : Effect[T]) : Effect[T]
Когда я вызываю метод «когда» с вышеуказанной сигнатурой, передавая его результат методу + =, он не может вывести тип аргумента лямбда-выраженияВыражение.
myEffects += when(_.hpLow()) (applyModifierEffect) //<-- Compiler error
Если я объединю аргументы «когда» в один список параметров, Scala может точно определить тип лямбда-выражения.
def when[T](condition : T => Boolean, effect : Effect[T]) : Effect[T]
/* Snip */
myEffects += when(_.hpLow(), applyModifierEffect) //This works fine!
Этотакже работает, если я полностью удаляю второй параметр.
def when[T](condition : T => Boolean) : Effect[T]
/* Snip */
myEffects += when(_.hpLow()) //This works too!
Однако по эстетическим соображениям я действительно хочу, чтобы аргументы передавались методу «когда» в виде отдельных списков параметров.
Мое понимание из раздела 16.10 Программирование в Scala заключается в том, что компилятор сначала проверяет, известен ли тип метода, и если да, то использует его, чтобы вывести ожидаемый тип своих аргументов.В этом случае самым внешним вызовом метода является + =, который принимает аргумент типа Effect [PlayerCharacter].Поскольку тип возвращаемого значения, когда [T] равен Effect [T], а метод, которому передается результат, ожидает аргумент типа Effect [PlayerCharacter], он может заключить, что T - это PlayerCharacter, и, следовательно, тип лямбдавыражение, переданное в качестве первого аргумента «когда», является PlayerCharacter => Boolean.Похоже, это работает, когда аргументы предоставляются в одном списке параметров, так почему же разбивание аргументов на два списка параметров разбивает его?