3

ルールセットに基づいてフィルタリングしたい項目 (レシピ) のリストがあります。

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

ここで、各ルールは関数 :: Recipe -> Bool です。これらのルールをリスト内の各項目に適用したいので、次の関数を使用してこれを行っています。

testRules :: Recipe -> Bool
testRules r = rule0 r && rule1 r && rule2 r && rule3 r && rule4 r

「rule0 && rule1&& ...」と明示的に言わずに配列を適用する方法が必要です。

誰も方法を知っていますか?'map' は 1 つの関数をリストに適用することを知っています..そして zipWith は配列を配列で乗算します..このタスクを実行するには別の関数が必要です!

また、ルールセットをパラメーターとして testRules に渡し、一連のルールを再帰的に処理できるのではないかと考えています。

testRules (rule:rules) r = rule r && testRules rules
testRules [] r = True

ただし、関数の先頭 (testRules :: ) を提供する方法がわかりません。

どんな助けにも乾杯!

4

5 に答える 5

11

使える機能もありますall :: (a -> Bool) -> [a] -> Bool。この関数は、リストのすべての値に対して述語が成り立つかどうかをチェックします。

ここで、状況を少し変えて、述語を「x に適用されたときにこのルールの結果が True である」とし、リストに述語が含まれるようにします。

述語を次のように表現できますが\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 ($))、それは少しやり過ぎだと思います。

于 2012-10-09T16:53:32.083 に答える
3

リスト内包表記と組み合わせるandと、これをうまく解決できます。

testRules :: [Recipe -> Bool] -> Recipe -> Bool
testRules ruleSet r = and [rule r | rule <- ruleSet]
于 2012-10-09T17:00:13.357 に答える
3

andのリストを取得し、すべてが である場合Boolに返すを使用できます。TrueTrue

次に、アプリケーション ($) で zipWith を使用します。

testRules :: [a -> Bool] -> a -> Bool
testRules :: and $ zipWith ($) ruleset (repeat r)
于 2012-10-09T16:19:00.380 に答える
2

方法はたくさんあると思います。私は折り目が好きです(アプリカティブ付き):

testRules = foldl1 (\f r -> (&&) <$> f <*> r) rules
于 2012-10-09T16:07:39.407 に答える
2

最初に頭に浮かんだのは:

testRules :: Recipe -> [ Recipe -> Bool ] -> Bool
testRules r ruleset = and $ map (\rule -> rule r) ruleset
于 2012-10-09T16:03:40.350 に答える