Как определить параметр функции по умолчанию, связанный с общим параметром?
Я пытаюсь реорганизовать функцию ( найденную в конце этого ответа 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]]
в зависимости от того, что вам нужно, и измените предыдущие аргументы, но вы застрянете на том факте, что строки String
s, так что вам придется конвертировать их в 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]] = {
???
}
Еще раз огромное спасибо Алексею и Ли за помощь в борьбе с этим.