如何定义与通用参数关联的函数参数default?

时间:2015-12-15 16:14:05

标签: scala generics generic-programming

我正在尝试重构一个函数(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)

......错误消失了。但是,我也失去了与泛型参数相关的强类型。

对此非常感谢。

2 个答案:

答案 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帮助我解决这个问题。