所以我有一个项目列表(食谱),我想根据规则集过滤,
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 ::)
为任何帮助干杯!
答案 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