Haskell:使用规则列表过滤列表

时间:2012-10-09 15:58:18

标签: haskell

所以我有一个项目列表(食谱),我想根据规则集过滤,

ruleset = [rule0, rule1, rule2, rule3, rule4]

其中每个规则都是一个函数:: Recipe - >布尔。我想将这些规则应用于列表中的每个项目,我一直在使用以下函数:

testRules :: Recipe -> Bool
testRules r = rule0 r && rule1 r && rule2 r && rule3 r && rule4 r

必须有一种方法来应用数组而不明确说“rule0&& rule1&& ...”

有谁知道吗?我知道'map'将一个函数应用于列表..而zipWith将数组乘以数组..必须有另一个函数来执行此任务!

我一直在想,也许我可以将规则集作为参数传递给testRules并递归地遍历规则集:

testRules (rule:rules) r = rule r && testRules rules
testRules [] r = True

但是,我不知道如何提供函数的头部(testRules ::)

为任何帮助干杯!

5 个答案:

答案 0 :(得分:11)

还可以使用函数all :: (a -> Bool) -> [a] -> Bool。此函数检查谓词是否适用于列表的所有值。

只有现在,我们才会转变一些事情,让谓词'是这个规则的结果,当它应用于x'时,列表将包含谓词。

您可以将谓词表达为\rule -> rule x == True但与\rule -> rule x相同,这与\rule -> rule $ x相同,与($x)相同。所以这种思路给了我们好的和简短的:

testRules :: [a -> Bool] -> a -> Bool
testRules rules x = all ($x) rules

这可以通过testRules = flip (all . flip ($))使用免费点,但我认为这有点过头了。

答案 1 :(得分:3)

您可以使用and,其中包含Bool列表,如果所有True都为True,则返回testRules :: [a -> Bool] -> a -> Bool testRules :: and $ zipWith ($) ruleset (repeat r)

然后,使用zipWith和application($):

{{1}}

答案 2 :(得分:3)

and与列表推导相结合可以很好地解决这个问题:

testRules :: [Recipe -> Bool] -> Recipe -> Bool
testRules ruleSet r = and [rule r | rule <- ruleSet]

答案 3 :(得分:2)

首先想到的是:

testRules :: Recipe -> [ Recipe -> Bool ] -> Bool
testRules r ruleset = and $ map (\rule -> rule r) ruleset

答案 4 :(得分:2)

我确信有很多方法。我喜欢折叠(有应用):

testRules = foldl1 (\f r -> (&&) <$> f <*> r) rules