Почему вывод типа работает при применении карри в Scala? - PullRequest
0 голосов
/ 03 марта 2020

У меня есть некоторый обобщенный метод c, который выглядит следующим образом.

При таком определении метода Scala по какой-то причине не может вывести типы A и B.

  def someMethod[A <: UpperBoundA, B <: UpperBoundB](m: Map[A, B], condition: A => Boolean): Option[B] = 
    m.filterKeys(condition).headOption.map(_._2)

Но при преобразовании метода, как показано ниже, применяя каррирование, Scala удается правильно вывести типы.

  def someMethod[A <: UpperBoundA, B <: UpperBoundB](m: Map[A, B])(condition: A => Boolean): Option[B] = 
    m.filterKeys(condition).headOption.map(_._2)

Вот как все методы называются

someMethod(m, _.someField == "aaa") // not working for some reason
someMethod[Key, Value](m, _.id == "aaa") // working
someMethod(m)(_.someField == "aaa") // working(with currying)

Почему это что?

Ответы [ 3 ]

4 голосов
/ 03 марта 2020

Компилятор не может использовать вывод одного параметра, чтобы помочь разрешить другой, если эти параметры не находятся в разных группах параметров.

То же самое со значениями параметров.

def f(x:Int = 4, y:Int = x) :Int = x*y  //Error: not found: value x
def f(x:Int = 4)(y:Int = x) :Int = x*y  //OK, 2 default values

компилятор разрешает первую группу параметров перед переходом ко второй, и информация, полученная из первой, доступна для второй.

3 голосов
/ 03 марта 2020

Тип вывода выводит слева направо из списка параметров в список параметров . Введите логический вывод в пределах список параметров происходит одновременно для всех параметров.

2 голосов
/ 03 марта 2020

В первом случае someMethod(m, _.someField == "aaa") каждый аргумент в функции равен по важности, но если логический вывод сработает, а вы написали someMethod(m, _.someField == "aaa"), то компилятор обрабатывает его как (x$1) => x$1.someField.$eq$eq("aaa"). x$1 может быть A или любой подтип A. В этом случае, если вы измените порядок аргументов, логический вывод может измениться или не работать вообще, и это сделает сложный логический вывод для компилятора, который должен сканировать определение несколько раз.

Во втором случае, someMethod[Key, Value](m, _.id == "aaa"), компилятор уже знает, что A является типом Key, а B является типом Value, и, следовательно, он компилирует

Что касается третьего случая someMethod(m)(_.someField == "aaa"), компилятор должен выводить тип, когда вы уже написали someMethod (m), потому что это частичное приложение. Так что теперь, когда тип выведен, он может продолжить и применить к нему (f).

Дайте мне знать, если это поможет !!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...