ワンライナー:
import Control.Monad.Reader
-- sample data
rulesetL = [ (== 1), (>= 2), (<= 3) ]
list = [1..10]
result = and $ concatMap (sequence rulesetL) list
(ここで取り組んでいる型は ですがInteger
、それ以外の型でもかまいません。)
何が起こっているのか説明しましょう:rulesetL
タイプは[Integer -> Bool]
です。(->) e
それがモナドであることを認識することで、
sequence :: Monad m => [m a] -> m [a]
この場合は type に特化され[Integer -> Bool] -> (Integer -> [Bool])
ます。そう
sequence rulesetL :: Integer -> [Bool]
リスト内のすべてのルールに値を渡します。次に、concatMap
この関数を に適用してlist
、すべての結果を 1 つのリストにまとめます。最後に、呼び出し
and :: [Bool] -> Bool
すべての組み合わせが返されたことを確認しますTrue
。
編集: dave4420の回答を確認してください。より適切で簡潔です。私の答えは、ルールを組み合わせて後でいくつかのリストに適用する必要がある場合に役立ちます。特に
liftM and . sequence :: [a -> Bool] -> (a -> Bool)
複数のルールを 1 つに結合します。などを使用するなど、他の同様のコンビネータに拡張することもできますor
。ルールが(->) a
モナドの値であることを理解すると、次のような他の便利なコンビネータが得られます。
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
)。