简体   繁体   English

参数函数的Scala类型推断问题

[英]Scala Type Inference Issues with Parametric Function

I have been learning Scala these days, and today I ran into some issue that I cannot understand. 这些天我一直在学习Scala,今天我遇到了一些我无法理解的问题。

Suppose we have the following parametric function definition: 假设我们有以下参数函数定义:

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)
    }
}

Now, this works just fine if I invoke it as follows: 现在,如果我按如下方式调用它,这可以正常工作:

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

But if remove the type tag, it appears Scala cannot infer that the type of T is Int. 但是如果删除类型标记,则看起来Scala无法推断出T的类型是Int。

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

So, I am forced to provide explicit type information in this call. 所以,我被迫在这次调用中提供显式类型信息。

Does anybody know why Scala is not capable of inferring the type of T in this call. 有没有人知道为什么Scala无法在此调用中推断出T的类型。 The list is evidently a List of Ints, I cannot see why it cannot infer that the type of n is also Int. 该列表显然是Ints列表,我不明白为什么它不能推断出n的类型也是Int。

Scala's type inference works per parameter list , not per parameter, so it hasn't resolved T to Int by the time it gets to the predicate in your second example. Scala的类型推断适用于每个参数列表 ,而不是每个参数,所以它在第二个示例中到达谓词时没有将T解析为Int You can, however, get what you want by using two parameter lists: 但是,您可以使用两个参数列表获得所需内容:

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)
  }

Now the following will work just fine: 现在以下内容将正常工作:

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

See my answer here for some additional discussion. 见我的答案在这里一些额外的讨论。

You need to put the predicate in an other group of parameters to get inference to work: 您需要将谓词放在另一组参数中以推断工作:

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)

Unfortunately it's a limitation of scala. 不幸的是,它是scala的限制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM