【发布时间】:2014-06-12 07:12:38
【问题描述】:
给定类型
sieve :: [a -> Bool] -> [a] -> [[a]]
我必须编写一个函数,它使用函数列表[a->Bool] 过滤列表。
每个过滤器必须只筛选过滤器之前剩余的部分。
它返回一个列表列表,每个列表代表筛子捕获的内容。
最后一个列表是没有被任何过滤器捕获的内容。
例如
sieve [(<3),(>7),odd] [1..10] gives back [[1,2],[8,9,10],[3,5,7],[4,6]]
我知道筛子必须这样开始...
sieve fs xs = concat $ filter () ...
我的问题是:
在我进入工作的复杂部分,逐步过滤之前,我不知道如何访问函数列表中的每个函数并在 [a] 列表中使用它。
如果它是一个功能,那么(filter f xs) 会很容易
我试了很多次都没有。
有人可以帮忙并可能提供一点提示如何管理一个又一个的过滤系统吗? 欢迎任何提示。
编辑:
我现在有这个: 这是我认为它应该工作的方式,但我在否定布尔函数时遇到了问题...... 你能帮忙吗?
sieve :: [a -> Bool] -> [a] -> [[a]]
sieve [] xs = [xs]
sieve (f:fs) xs = (filter f xs) : (sieve fs (filter nf xs))
where nf = not f
这不起作用,因为我可能不会像这样使用(不是 f)。 有什么想法吗?
编辑:最终解决方案
partition p xs = (filter p xs, filter (not . p) xs)
sieve :: [a -> Bool] -> [a] -> [[a]]
sieve [] xs = [xs];
sieve (f:fs) xs = p1 : (sieve fs p2)
where p1 = fst (partition f xs)
p2 = snd (partition f xs)
【问题讨论】:
-
为什么不使用递归函数:运行第一个过滤器,然后使用结果列表和其余函数递归调用该函数。您还必须累积结果...
-
filter单独无法完成工作。您既需要从列表中删除的内容,也需要剩余的内容。实际上,结果列表是输入列表的一个分区。 咳咳 -
是的,过滤器还不够;我认为递归是正确的想法,而 concat 也是错误的想法
-
我设法结合了
Data.List的一些函数来实现这一点,而无需任何手动递归。我不知道使用Data.List的全部功能是否在你的任务范围内,但你肯定有可能从中获得灵感。