单线:
import Control.Monad.Reader
-- sample data
rulesetL = [ (== 1), (>= 2), (<= 3) ]
list = [1..10]
result = and $ concatMap (sequence rulesetL) list
(我们在这里处理的类型是Integer
,但也可以是其他类型。)
让我解释一下发生了什么:rulesetL
是 type [Integer -> Bool]
。通过意识到这(->) e
是一个单子,我们可以使用
sequence :: Monad m => [m a] -> m [a]
在我们的例子中,它将专门用于 type [Integer -> Bool] -> (Integer -> [Bool])
。所以
sequence rulesetL :: Integer -> [Bool]
将值传递给列表中的所有规则。接下来,我们使用concatMap
此函数将所有结果应用于list
并将所有结果收集到一个列表中。最后,调用
and :: [Bool] -> Bool
将检查返回的所有组合True
。
编辑:查看dave4420的答案,它更好更简洁。如果您需要组合规则并稍后在某些列表中应用它们,我的回答可能会有所帮助。尤其
liftM and . sequence :: [a -> Bool] -> (a -> Bool)
将多个规则合二为一。您还可以将其扩展到其他类似的组合器,例如 usingor
等。意识到规则是(->) a
monad 的值可以为您提供其他有用的组合器,例如:
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
)。