2013-03-04 60 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) 

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