Короче говоря : filter snd
сохраняет 2 кортежа, где второй элемент кортежа равен True
.
filter :: (a -> Bool) -> [a] -> [a]
принимает в качестве параметра функцию, которая отображает элементы типа a
в Bool
.В случае, если Bool
равно True
, в результате будет сохранен элемент исходного списка, в противном случае этот элемент не будет частью результата.
filter
, таким образом, фильтрует поэлементно : не учитывает следующий или предыдущий элемент (ы) в списке.Он просто проверяет, удовлетворен ли предикат для элемента.
Поскольку у вас здесь есть список из двух кортежей, где вторым элементом каждого кортежа является Bool
, то snd :: (a, b) -> b
, таким образом, отобразит каждый элемент на втором элементе и, таким образом, сохранит 2 кортежа, где второй элемент 2 кортежа равен True
.Таким образом, самый общий тип filter snd
- это filter snd :: [(a, Bool)] -> [(a, Bool)]
, поскольку второй элемент из двух кортежей должен быть 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