我正在尝试重构一个函数(found towards the end of this StackOverflow answer),使其稍微更通用。这是原始的函数定义:
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]] = {
???
}
我在Some(parsedValues)
上的IntelliJ编辑器中不断收到突出显示错误,其中显示“某些[List [String]]类型的表达式不符合预期类型选项[A]”。我一直无法弄清楚如何正确修改函数定义以满足所需条件;即所以错误消失了。
如果我将transformLine
更改为此(将通用参数A
替换为Any
)...
transformLine: (Int, List[String]) => Option[Any] =
(index, parsedValues) => Some(parsedValues)
......错误消失了。但是,我也失去了与泛型参数相关的强类型。
对此非常感谢。
答案 0 :(得分:1)
在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]]
,也可以更改以前的参数,但是您会遇到行{{1} } s,所以你必须将它们转换为某个地方的String
。
答案 1 :(得分:0)
在阅读并重新阅读Alexey Romonov的回答和Lee的评论之后,它给了我一个如何重构这个以使其工作的线索。另外,我认为它也可能暗示了一个关于为函数提供默认值的指南。
如果我理解正确,我试图在变换参数default中的具体例子List[String]
中使用泛型类型,在本例中为Option[A]
。从本质上讲,这与边界重叠,在边界上,编译器为特定用户提供的类型和明确提供的List[String]
实例化函数的泛型副本。这引出了以下有关定义通用函数的指南:
在转换具体函数以使其成为通用函数时, 每个参数都有一个默认值,可以直接与任何可能需要的通用参数进行交互 被删除并放入一个封闭的具体函数中,该函数将调用转发给泛型函数。
因此,在考虑此指南的情况下,让我们重新修改原始代码......
具体函数看起来像这样(非常类似于原始的pre-generic-ified版本,其中还包含了所需的具体默认参数):
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)
泛型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]] = {
???
}
再一次,非常感谢Alexey和Lee帮助我解决这个问题。