Haskell 将布尔函数列表应用于列表的最干净方法?

Haskell 将布尔函数列表应用于列表的最干净方法?,haskell,Haskell,考虑这一点: ruleset = [rule0, rule1, rule2, rule3, rule4, rule5] 其中,rule0,rule1等是采用一个参数的布尔函数。找到特定列表的所有元素是否满足规则集中的所有规则的最干净方法是什么 显然,循环是可行的,但是Haskell的人似乎总是有聪明的一行程序来解决这类问题 all函数似乎合适(例如all(=检查一个元素)规则集)或嵌套的maps。另外,map($anElement)规则集基本上是我想要的,但适用于所有元素 我是Haskell的

考虑这一点:

ruleset = [rule0, rule1, rule2, rule3, rule4, rule5]
其中,
rule0
rule1
等是采用一个参数的布尔函数。找到特定列表的所有元素是否满足
规则集中的所有规则的最干净方法是什么

显然,循环是可行的,但是Haskell的人似乎总是有聪明的一行程序来解决这类问题

all
函数似乎合适(例如
all(=检查一个元素)规则集)或嵌套的
map
s。另外,
map($anElement)规则集
基本上是我想要的,但适用于所有元素

我是Haskell的新手,解决这个问题的方法很多。

如果要求每个参数的所有函数都为真,那么

and (ruleset <*> list)
和(规则集列表)
(您需要
导入控件。Applicative
才能使用

说明:


当给
一对列表时,它会将左侧列表中的每个函数应用于右侧列表中的每个参数,并返回一个包含所有结果的列表。

一个更容易理解的版本(无需使用
控件。Applicative
):

一行:

import Control.Monad.Reader

-- sample data
rulesetL = [ (== 1), (>= 2), (<= 3) ]
list = [1..10]

result = and $ concatMap (sequence rulesetL) list
在我们的例子中,它将被专门化为键入
[Integer->Bool]->(Integer->[Bool])
。所以

sequence rulesetL :: Integer -> [Bool]
将向列表中的所有规则传递一个值。接下来,我们使用
concatMap
将此函数应用于
list
,并将所有结果收集到单个列表中。最后,打电话

and :: [Bool] -> Bool
将检查所有组合是否返回
True

编辑:查看dave4420的答案,它更漂亮、更简洁。如果您需要合并规则并在以后的一些列表中应用它们,我的答案可能会有所帮助。特别是

liftM and . sequence :: [a -> Bool] -> (a -> Bool)
将多个规则合并为一个规则。您还可以将其扩展到其他类似的组合符,如使用
等。认识到规则是
(>)单子的值可以为您提供其他有用的组合符,例如:

andRules = liftM2 (&&) :: (a -> Bool) -> (a -> Bool) -> (a -> Bool)
orRules  = liftM2 (||) :: (a -> Bool) -> (a -> Bool) -> (a -> Bool)
notRule  = liftM not :: (a -> Bool) -> (a -> Bool)
         -- or just (not .)

等等(别忘了导入
Control.Monad.Reader
)。

就我个人而言,我喜欢这种编写函数的方式,因为它明确使用的唯一组合符是

allOkay ruleset items = and [rule item | rule <- ruleset, item <- items]

allOkay ruleset items=和[rule item | rule thank!我不会想到这一点。谢谢,这很聪明,而且绝对是最干净的,但是需要导入
控件。Applicative
可能是一个破坏者。非常好的答案。为了完整性,还可以使用
控件中的
ap
。Monad
作为
和(ruleset`ap`list)
@David:如果你想在没有控制的情况下生活。Applicative,使用列表理解:
和[rv | r=(`map`xs)
谢谢大家,非常感谢。(我检查了,我认为导入
控制。Applicative实际上对我的应用程序来说可能很好)
andRules = liftM2 (&&) :: (a -> Bool) -> (a -> Bool) -> (a -> Bool)
orRules  = liftM2 (||) :: (a -> Bool) -> (a -> Bool) -> (a -> Bool)
notRule  = liftM not :: (a -> Bool) -> (a -> Bool)
         -- or just (not .)
allOkay ruleset items = and [rule item | rule <- ruleset, item <- items]