2

このことを考慮:

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

、などはrule0rule1引数を 1 つ取るブール関数です。特定のリストのすべての要素が のすべての規則を満たしているかどうかを確認する最もクリーンな方法は何rulesetですか?

明らかに、ループは機能しますが、Haskell の人々は常に、この種の問題に対して巧妙なワンライナーを持っているようです。

all関数は適切 (例: all (== check_one_element) ruleset) またはネストされたmaps のようです。また、map ($ anElement) ruleset大まかに私が欲しいものですが、すべての要素についてです。

私は Haskell の初心者であり、この問題に対処できる多くの方法に圧倒されます。

4

4 に答える 4

12

すべての関数が引数に対して true である必要がある場合は、

and (ruleset <*> list)

import Control.Applicative(使用する必要があります<*>。)

説明:

<*>リストのペアが与えられると、左側のリストの各関数を右側のリストの各引数に適用し、すべての結果を含むリストを返します。

于 2013-02-09T20:05:04.337 に答える
3

ワンライナー:

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)。

于 2013-02-09T20:15:04.967 に答える
1

わかりやすいバージョン(を使用せずにControl.Applicative):

satisfyAll elems ruleset = and $ map (\x -> all ($ x) ruleset) elems
于 2013-02-09T20:07:40.587 に答える
1

個人的には、この関数の書き方が好きです。明示的に使用する唯一のコンビネータは次のandとおりです。

allOkay ruleset items = and [rule item | rule <- ruleset, item <- items]
于 2013-02-10T07:45:21.877 に答える