[英]How function snd in Haskell works in filter
我輸入此代碼為ghci
Prelude> filter snd [('a',True),('b',True),('c',False),('d',True)]
為什么它會回來
[('a',True),('b',True),('d',True)]
而不是
[('a',True),('c',False),('d',True)]
snd
函數返回第二項,那么為什么不filter snd
過濾第二項呢?
您希望filter
器在該表達式的通俗意義上從列表中“過濾掉”元素,從而filter snd
以刪除第二個項目。
這不是它的工作原理
如果你是對的, filter snd [1,2,3]
將評估為[1,3]
。 相反,它沒有進行類型檢查,因為snd
適用於元組,而不適用於數字。
那么它是怎樣工作的?
filter f [item1, item2, ...]
返回f item
為True
的所有item
的列表
例如, filter even [1,2,3,4]
返回[2,4]
當snd ('b', True)
計算結果為True
,在您的示例中, filter
將在結果中包含(b, True)
。 出於同樣的原因,將省略(c, False)
簡而言之 : filter snd
保留2元組,其中元組的第二項為True
。
filter :: (a -> Bool) -> [a] -> [a]
將a
將a類型a
元素映射到Bool
的函數作為參數。 如果Bool
為True
,它將在結果中保留原始列表的元素,否則該元素將不是結果的一部分。
filter
由此濾波器的elementwise:它不考慮在列表中的下一個或前一個元素(一個或多個)。 它只是檢查是否滿足元素的謂詞。
既然你有一個2元組的列表,其中每個元組的第二項是Bool
,那么snd :: (a, b) -> b
將映射第二個元素上的每個元素,從而保留2元組的位置2元組的第二項是True
。 因此,最通用類型的filter snd
是filter snd :: [(a, Bool)] -> [(a, Bool)]
,因為2元組的第二項應該是Bool
。
這意味着filter snd
確實將過濾如下:
Prelude> filter snd [('a',True),('b',True),('c',False),('d',True)]
[('a',True),('b',True),('d',True)]
我們可以使用顯式遞歸過濾掉每個第二個元素,例如:
filterAtEven :: [a] -> [a]
filterAtEven [] = []
filterAtEven (x:xs) = x : filterAtOdd xs
filterAtOdd :: [a] -> [a]
filterAtOdd [] = []
filterAtOdd (_:xs) = filterAtEven xs
例如:
Prelude> filterAtEven [('a',True),('b',True),('c',False),('d',True)]
[('a',True),('c',False)]
Prelude> filterAtOdd [('a',True),('b',True),('c',False),('d',True)]
[('b',True),('d',True)]
或者,如果你想刪除一個特定的指數,我們可以利用的deleteAt :: Int -> [a] -> [a]
中的ilist
包:
Prelude> import Data.List.Index
Prelude Data.List.Index> deleteAt 2 [('a',True),('b',True),('c',False),('d',True)]
[('a',True),('b',True),('d',True)]
或者我們可以自己實現:
deleteAt :: Int -> [a] -> [a]
deleteAt i | i < 0 = id
| otherwise = go i
where go _ [] = []
go 0 (_:xs) = xs
go n (x:xs) = x : go (n-1) xs
您的filter
功能會根據每對的第二個值過濾您的列表。 這就是為什么('c',False)
被過濾掉了...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.