2010-04-02 153 views
5

我明白Haskell的過濾器是一個高階函數(意思是一個函數,它接受另一個函數作爲參數),通過列表檢查哪個元素滿足某個布爾條件。瞭解Haskell的過濾器

我不太明白它的定義:

filter:: (a->Bool)->[a]->[a] 
filter p [] = [] 
filter p (x:y) | p x = x:filter p y 
       | otherwise = filter p y 

我明白,如果我傳遞一個空列表的功能,它只是返回一個空列表,但我怎麼看最後兩行?

+0

@Justice:我不知道重新格式化是否有效。也許OP真的被奇怪的佈局弄糊塗了? – kennytm 2010-04-02 18:10:00

回答

11

它使用guards,如果您使用的是C風格語法的語言,則與switch結構有點類似。

最後一種模式顯示:如果函數p的計算結果爲真,參數爲x,則返回列表的頭部和列表的過濾尾部。否則,只需返回列表的過濾尾部。

你也可以把它改寫像這樣:

filter p (x:y) = if ( p x) then 
        x:filter p y 
       else 
        filter p y 
+3

另外'otherwise'在前奏中被定義爲'True'。 – 2010-04-02 18:14:11

7

考慮description of filter in the docs

filter,應用於謂詞和一個列表,返回那些滿足謂詞的元素列表;

filter p xs = [x | x <- xs, p x] 

解釋給別人誰不理解列表理解,你可能會說filter有三種情況:

  1. (易情形)時列表是過濾爲空,結果也爲空
  2. 當要過濾的列表頭部滿足謂詞時,它是結果的一部分
  3. 否則,跳過頭部並過濾列表的其餘部分

這些情況與您問題中定義的最後三行一一對應。

小細節可以使定義更地道,因此更容易閱讀:

filter _ []  = [] 
filter p (x:xs) 
    | p x   = x : filter p xs 
    | otherwise =  filter p xs 

對於空單,謂詞可以是任何東西,和下劃線明確地表明,它是在這種情況下不重要。

而不是反對(x:y)匹配,使用(x:xs) -think:「前和前男友」 -emphasizes,你分離列表到它的(的a型)和尾([a]型的頭部,,名單a)。

最後,將遞歸調用排列爲filter很容易讓讀者看到後一種情況省略了x