2013-03-04 62 views
5

我一直在学习Scala这些天,今天我遇到了一些我无法理解的问题。Scala类型推理问题与参数函数

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

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

但如果去掉类型的标签,似乎斯卡拉:

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

现在,这一点,如果我调用它如下工作得很好不能推断T的类型是Int。

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

所以,我被迫在这个调用中提供显式的类型信息。

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

回答

8

Scala的类型推断的作品,而不是每个参数,因此它没有通过它得到你的第二个例子中的谓语时间分辨TInt。你可以,但是,让你通过使用两个参数列表想要什么:

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) 

见我的回答here一些额外的讨论。

+0

此外,当在单独的参数列表中指定'predicate'(并且具有单个参数并且是最右边的,除了任何隐式参数列表之外)时,调用这样的HOF实际上在句法上更自然。这是因为你不需要在包含'source'的参数列表的parens中嵌套函数参数。由于前提条件是“只有一个参数”,所以除了用来包含函数文字的parens(或大括号)之外,您不需要将它放在parens中。 – 2013-03-05 02:56:07

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) 

不幸的是这是斯卡拉的限制。