Как определить параметр функции по умолчанию, связанный с общим параметром?

Я пытаюсь реорганизовать функцию ( найденную в конце этого ответа Stackru), чтобы сделать ее несколько более общей. Вот оригинальное определение функции:

def tryProcessSource(
  file: File,
  parseLine: (Int, String) => Option[List[String]] =
    (index, unparsedLine) => Some(List(unparsedLine)),
  filterLine: (Int, List[String]) => Option[Boolean] =
    (index, parsedValues) => Some(true),
  retainValues: (Int, List[String]) => Option[List[String]] =
    (index, parsedValues) => Some(parsedValues)
): Try[List[List[String]]] = {
  ???
}

И вот к чему я пытаюсь это изменить:

def tryProcessSource[A <: Any](
  file: File,
  parseLine: (Int, String) => Option[List[String]] =
    (index, unparsedLine) => Some(List(unparsedLine)),
  filterLine: (Int, List[String]) => Option[Boolean] =
    (index, parsedValues) => Some(true),
  transformLine: (Int, List[String]) => Option[A] =
    (index, parsedValues) => Some(parsedValues)
): Try[List[A]] = {
  ???
}

Я получаю ошибку выделения в редакторе IntelliJ на Some(parsedValues) который говорит: "Выражение типа Some[List[String]] не соответствует ожидаемому типу Option[A]". Я не смог понять, как правильно изменить определение функции, чтобы удовлетворить требуемое условие; т.е. ошибка исчезнет.

Если я изменю transformLine к этому (замените универсальный параметр A с Any)...

transformLine: (Int, List[String]) => Option[Any] =
  (index, parsedValues) => Some(parsedValues)

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

Любая помощь с этим очень ценится.

2 ответа

В transformLine: (Int, List[String]) => Option[A] = (index, parsedValues) => whatever, parsedValues очевидно, имеет тип List[String], так что Some(parsedValues) является Some[List[String]], Там просто нет разумного значения по умолчанию для transformLine,

Вы можете изменить его тип на (Int, A) => Option[A] или же (Int, List[A]) => Option[List[A]] в зависимости от того, что вам нужно, и измените предыдущие аргументы, но вы застрянете на том факте, что строки Strings, так что вам придется конвертировать их в A где-то

Прочитав и перечитав ответ Алексея Ромонова и комментарий Ли, он дал мне ключ к пониманию того, как это сделать, чтобы заставить его работать. Кроме того, я думаю, что это может также подразумевать руководство по предоставлению значений по умолчанию для функции.

Если я правильно понимаю, я пытаюсь объединить конкретный, в данном примере List[String] в параметре преобразования по умолчанию, с универсальным типом, в данном случае Option[A], По сути, это перекрывает границу, на которой обобщенная копия функции создается компилятором для конкретного предоставленного пользователем типа и явно предоставленного List[String], Это приводит меня к следующему руководству относительно определения общих функций:

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


Итак, помня об этом, давайте переделаем оригинальный код...

Конкретная функция выглядит следующим образом (очень похоже на исходную версию с предварительным обобщением, которая также включает требуемые конкретные параметры по умолчанию):

def tryProcessSource(
  file: File,
  parseLine: (Int, String) => Option[List[String]] =
    (index, unparsedLine) => Some(List(unparsedLine)),
  filter: (Int, List[String]) => Option[Boolean] =
    (index, parsedValues) => Some(true),
  transform: (Int, List[String]) => Option[List[String]] =
    (index, parsedValues) => Some(parsedValues)
): Try[List[List[String]]] =
  tryProcessSourceGeneric(file, parseLine, filter, transform)

И функция generic-ified выглядит следующим образом (обратите внимание на отсутствие значений параметров по умолчанию):

def tryProcessSourceGeneric[A, B](
  file: File,
  parseLine: (Int, String) => Option[A],
  filter: (Int, A) => Option[Boolean]
  transform: (Int, A) => Option[B]
): Try[List[B]] = {
  ???
}

Еще раз огромное спасибо Алексею и Ли за помощь в борьбе с этим.

Другие вопросы по тегам