[英]How function snd in Haskell works in filter
I type this code to ghci 我输入此代码为ghci
Prelude> filter snd [('a',True),('b',True),('c',False),('d',True)]
why it returns 为什么它会回来
[('a',True),('b',True),('d',True)]
rather than 而不是
[('a',True),('c',False),('d',True)]
snd
function returns the second item, so why not filter snd
filter the second item? snd
函数返回第二项,那么为什么不filter snd
过滤第二项呢?
You expect filter
to "filter out" elements from a list in the colloquial sense of that expression, and thus filter snd
to remove the second item. 您希望
filter
器在该表达式的通俗意义上从列表中“过滤掉”元素,从而filter snd
以删除第二个项目。
That is not how it works 这不是它的工作原理
If you were right, filter snd [1,2,3]
would evaluate to [1,3]
. 如果你是对的,
filter snd [1,2,3]
将评估为[1,3]
。 Instead, it doesn't typecheck, as snd
works on tuples, not on numbers. 相反,它没有进行类型检查,因为
snd
适用于元组,而不适用于数字。
So, how does it work? 那么它是怎样工作的?
filter f [item1, item2, ...]
returns a list of all item
s for which f item
is True
filter f [item1, item2, ...]
返回f item
为True
的所有item
的列表
For example, filter even [1,2,3,4]
returns [2,4]
例如,
filter even [1,2,3,4]
返回[2,4]
As snd ('b', True)
evaluates to True
, in your example filter
will include (b, True)
in the result. 当
snd ('b', True)
计算结果为True
,在您的示例中, filter
将在结果中包含(b, True)
。 By the same token, (c, False)
will be omitted 出于同样的原因,将省略
(c, False)
In short : filter snd
retains 2-tuples where the second item of the tuple is True
. 简而言之 :
filter snd
保留2元组,其中元组的第二项为True
。
filter :: (a -> Bool) -> [a] -> [a]
takes as parameter a function that maps elements of type a
to a Bool
. filter :: (a -> Bool) -> [a] -> [a]
将a
将a类型a
元素映射到Bool
的函数作为参数。 In case the Bool
is True
it will retain the element of the original list in the result, otherwise that element will not be part of the result. 如果
Bool
为True
,它将在结果中保留原始列表的元素,否则该元素将不是结果的一部分。
filter
thus filters elementwise : it does not take into account the next or previous element(s) in the list. filter
由此滤波器的elementwise:它不考虑在列表中的下一个或前一个元素(一个或多个)。 It simply checks if a predicate on an element is satisfied. 它只是检查是否满足元素的谓词。
Since you here have a list of 2-tuples where the second item of each tuple is a Bool
, the snd :: (a, b) -> b
will thus map each element on the second element, and thus retain 2-tuples where the second item of the 2-tuple is True
. 既然你有一个2元组的列表,其中每个元组的第二项是
Bool
,那么snd :: (a, b) -> b
将映射第二个元素上的每个元素,从而保留2元组的位置2元组的第二项是True
。 The most generic type of filter snd
is thus filter snd :: [(a, Bool)] -> [(a, Bool)]
, since the second item of the 2-tuples should be a Bool
. 因此,最通用类型的
filter snd
是filter snd :: [(a, Bool)] -> [(a, Bool)]
,因为2元组的第二项应该是Bool
。
This thus means that filter snd
indeed will filter like: 这意味着
filter snd
确实将过滤如下:
Prelude> filter snd [('a',True),('b',True),('c',False),('d',True)]
[('a',True),('b',True),('d',True)]
We can filter out every second element with explicit recursion for example: 我们可以使用显式递归过滤掉每个第二个元素,例如:
filterAtEven :: [a] -> [a]
filterAtEven [] = []
filterAtEven (x:xs) = x : filterAtOdd xs
filterAtOdd :: [a] -> [a]
filterAtOdd [] = []
filterAtOdd (_:xs) = filterAtEven xs
for example: 例如:
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)]
Or if you want to remove a specific index, we can make use of deleteAt :: Int -> [a] -> [a]
of the ilist
package: 或者,如果你想删除一个特定的指数,我们可以利用的
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)]
or we can implement this ourselves: 或者我们可以自己实现:
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
Your filter
function filters your list according to the second value of each pair. 您的
filter
功能会根据每对的第二个值过滤您的列表。 This is why ('c',False)
is filtered out ... 这就是为什么
('c',False)
被过滤掉了...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.