给出类型
sieve :: [a -> Bool] -> [a] -> [[a]]
我必须编写一个函数,它使用函数列表[a->Bool]
过滤列表。
每个过滤器必须只筛选剩余的过滤器。
它返回一个列表列表,每个列表代表筛子捕获的内容。
最后一个列表是任何过滤器都没有捕获到的。
e.g。
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)
答案 0 :(得分:1)
您希望为列表的每个元素执行某些操作并在执行此操作时累积结果,这正是折叠函数的用途:
import Data.List (partition, foldl')
sieve fs xs = let (p1, p2) = fold fs xs in p2 ++ [p1]
where fold fs xs = foldl' step (xs, []) fs
step (lst, rs) f = let (r1, r2) = partition f lst in (r2, rs++[r1])
要使用递归来实现它,您需要做的是过滤前面的过滤器留下的列表,并在执行此操作时收集结果:
import Data.List (partition)
sieve [] xs = [xs]
sieve (f:fs) xs = let (p1, p2) = partition f xs
in p1 : sieve fs p2