[英]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.