在Haskell中使用concat和map实现过滤器

时间:2018-04-23 19:44:57

标签: haskell functional-programming

filter1 :: (a -> Bool) -> [a] -> [a]
filter1 p = concat.map box
              where box x
                    | p x       = [x]
                    | otherwise = []

我不明白这个解决方案。 map将box应用于列表的所有元素,如果p x == True它将元素放在单个元素的列表中,然后连接取消所有内容? concat最终将所有内容统一起来或逐一统一?

谢谢!我希望有人理解这个

2 个答案:

答案 0 :(得分:6)

很难从你的问题中辨别出你的实际要求。请尝试清楚地表达您的问题。我将解释这个函数是如何工作的,并希望这个解释可以解决你实际要求的任何问题。

首先,map box应用于输入列表。对box的每次调用都会返回[x],对于那些满足谓词x的{​​{1}};或者一个空列表,用于那些不满足谓词的p。因此,x的结果将是空列表和单例列表的列表。

让我们考虑一个例子。我们这样说:

map box

然后:

input_list = [1,2,3,4,5]
p = odd

第一个元素map box input_list = [ [1], [], [3], [], [5] ] 已映射到1,因为[1]。第二个元素p 1 == True已映射到2,因为[]。等等。

之后,p 2 == False将应用于此列表列表。它将所有这些小清单连接成一个大清单。所以在我们的例子中:

concat

答案 1 :(得分:2)

想象一下,我们有五个要素:

[x1, x2, x3, x4, x5]

并且p适用于x2x3x5。然后我们按如下方式执行映射:

              map box [x1, x2, x3, x4, x5]
------------------------------------------
= [box x1, box x2, box x3, box x4, box x5]

由于p适用于x2x3x5,这意味着box会返回x1和{{}的空列表1}},以及包含x4x2x3原始列表的单例列表,所以:

x5

然后,如果我们应用 [box x1, box x2, box x3, box x4, box x5] ------------------------------------------ = [[], [x2], [x3], [], [x5]] ,则空列表(concat)将不会向结果中添加任何元素,因此原始元素被"过滤掉",而单身人士名单的内容 - []所持有的元素 - 被添加到列表中,因此:

p

因此,通过将我们想要过滤的元素映射到空列表,以及我们想要保留到具有该元素的单例列表的元素,并连接这些元素,我们设法过滤掉我们不想要的元素。然而,对于过滤来说,如果没有优化,则效率不高,因为我们将所有想要的元素装箱和拆箱。

请注意,Haskell是一种惰性语言,所以如果你以某种方式 concat [[], [x2], [x3], [], [x5]] ----------------------------------- = [x2, x3, x5] 某些元素,那么这是执行,除非你需要结果。此外,filter1map都是懒惰的(就像所有函数一样)。这意味着如果我们对结果的 i -th元素感兴趣,我们将不会计算整个列表。