5

这些天我一直在学习Scala,今天遇到了一些我无法理解的问题。

假设我们有以下参数函数定义:

def filter[T](source: List[T], predicate: T=>Boolean): List[T] = {
    source match {
        case Nil => Nil
        case x::xs => if(predicate(x)) x::filter(xs, predicate)
                  else filter(xs, predicate)
    }
}

现在,如果我按如下方式调用它,它就可以正常工作:

filter(List(1,2,3,4,5,6), ( (n:Int) => n % 2 == 0))

但是如果去掉类型标签,Scala 似乎无法推断 T 的类型是 Int。

filter(List(1,2,3,4,5,6), ( n => n % 2 == 0))

所以,我不得不在这个调用中提供明确的类型信息。

有谁知道为什么 Scala 无法在此调用中推断 T 的类型。该列表显然是一个 Int 列表,我不明白为什么它不能推断 n 的类型也是 Int。

4

2 回答 2

8

Scala 的类型推断适用于每个参数列表T,而不是每个参数,因此在第二个示例中到达谓词时它还没有解决Int。但是,您可以通过使用两个参数列表来获得所需的内容:

def filter[T](source: List[T])(predicate: T => Boolean): List[T] =
  source match {
    case Nil => Nil
    case x :: xs =>
      if (predicate(x))
        x :: filter(xs)(predicate)
      else
        filter(xs)(predicate)
  }

现在以下将正常工作:

scala> filter(List(1, 2, 3, 4, 5, 6))((n => n % 2 == 0))
res0: List[Int] = List(2, 4, 6)

有关其他讨论,请参见我的答案。

于 2013-03-04T23:20:50.357 回答
1

您需要将谓词放在另一组参数中才能使推理起作用:

def filter[T](source: List[T])(predicate: T=>Boolean): List[T] = {
    source match {
        case Nil => Nil
        case x::xs => if(predicate(x)) x::filter(xs)(predicate)
                   else filter(xs)(predicate)
    }
}

filter(List(1,2,3,4,5,6))(_ % 2 == 0)

不幸的是,这是 scala 的限制。

于 2013-03-04T23:22:15.540 回答