简体   繁体   English

Haskell中的函数snd如何在过滤器中起作用

[英]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 itemTrue的所有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. 如果BoolTrue ,它将在结果中保留原始列表的元素,否则该元素将不是结果的一部分。

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 sndfilter 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM