関数のフィルタクラスは条件(a - > Bool)をとり、フィルタリング時に適用します。フィルタ条件の結合方法
複数の条件があるときにフィルタを使用する最も良い方法は何ですか?
liftM2の代わりにアプリケーション機能 liftA2を使用しました。何らかの理由でliftM2が純粋なコード内でどのように動作していたか理解できなかったためです。
関数のフィルタクラスは条件(a - > Bool)をとり、フィルタリング時に適用します。フィルタ条件の結合方法
複数の条件があるときにフィルタを使用する最も良い方法は何ですか?
liftM2の代わりにアプリケーション機能 liftA2を使用しました。何らかの理由でliftM2が純粋なコード内でどのように動作していたか理解できなかったためです。
liftM2、あなたの述語関数に名前を付ける必要はありませんラムダを使用することができますコンビネータは、「より機能的」な方法でこれを行うためにリーダーモナドで使用することができます。輸入が重要であることを
import Control.Monad
import Control.Monad.Reader
-- ....
filter (liftM2 (&&) odd (> 100)) [1..200]
は注意。 Control.Monad.Readerは、これをすべて動作させるMonad(e - >)インスタンスを提供します。
なぜなら、読者のモナドは、ある環境eではちょうど(e - >)であるからです。したがって、ブール・プレディケートは、その引数に対応する環境でブールを返す0個のモナド関数です。次に、liftM2を使用して、2つの述語を介して環境を配布することができます。
や型が出て作業する場合、単純な用語で、liftM2は、このようなビットを動作します:
liftM2 f g h a = f (g a) (h a)
また、あなたはこれらの簡単連鎖にできるようにしたい場合は、新しいコンビネータを定義し、することができます/またはliftM2を台無しにしたくない:
(.&&.) :: (a -> Bool) -> (a -> Bool) -> (a -> Bool)
(.&&.) f g a = (f a) && (g a)
-- or, in points-free style:
(.&&.) = liftM2 (&&)
filter (odd .&&. (> 5) .&&. (< 20)) [1..100]
さて、あなたはHaskellでほしい(ただし限りのタイプが正しいとして)機能を組み合わせて、あなたもすなわち、
filter (\x -> odd x && x > 100) [1..200]
のは、あなたの条件がconditions
と呼ばれるリストに格納されているとしましょう。このリストのタイプは[a -> Bool]
です。
x
にすべての条件を適用するには、
map
を使用することができます。
map ($ x) conditions
これはx
に各条件を適用し、ブールのリストを返します。そうでない場合は、すべての要素がTrueの場合はTrue、Falseを、単一のブールにこのリストを軽減するために、あなたはand
機能を使用することができます。
and $ map ($ x) conditions
は今、あなたはすべての条件を組み合わせた機能を持っています。この関数は、タイプ
a -> Bool
を持っているので、私たちは
filter
への呼び出しで使用することができます
combined_condition x = and $ map ($ x) conditions
::それに名前を挙げてみましょうあなたがタイプa -> Bool
のフィルタリング機能のリストを持っている場合は
filter combined_condition [1..10]
($ x)とは対照的に($ x)、Template Haskellを何らかの理由で有効にしたように$ xは突然スプライスのように見えます。 –
'all'関数を発見しました:' filter(all conditions)[1..10] ' –
述語をどのように組み合わせるかによって、any関数もあります: 任意のp =または。マップp; all p =と。マップp; –
と同じ型の1つの簡潔なフィルタリング関数にそれらを結合したいと思うならば、ちょうど行うための関数を書くことができます。以下の2つの機能は、必要なフィルタの動作に依存します。
anyfilt :: [(a -> Bool)] -> (a -> Bool)
anyfilt fns = \el -> any (\fn -> fn el) fns
allfilt :: [(a -> Bool)] -> (a -> Bool)
allfilt fns = \el -> all (\fn -> fn el) fns
anyfilt
フィルタ機能のすべてがfalseを返す場合、フィルタ機能のいずれかが trueとfalseを返す場合はtrueをを返します。 allfilt
は、すべてのフィルタ関数がtrueを返す場合はtrueを返し、の場合はfalseを返します。 RHS上のfns
への参照は匿名関数内にあるため、いずれの関数もη-reduceできないことに注意してください。
filterLines :: [String] -> [String]
filterLines = let
isComment = isPrefixOf "# "
isBlank = (==) ""
badLine = anyfilt([isComment, isBlank])
in filter (not . badLine)
main = mapM_ putStrLn $ filterLines ["# comment", "", "true line"]
--> "true line"
両方の例は、あなたが 'Control.Monad.Reader'をインポートしない場合でも、GHC 7.6.3で動作します:
はこのようにそれを使用してください。 – sjakobi
私は 'liftM2'を(今日では)次のように置き換えることができます:' filter((&&)<$>奇数<*>(> 100))[1.200] '。どちらが同じですが、よりきれいです。 :)また、 'Control.Applicative'のみ必要で、完全なモナドはありません。 ...私はまだオペレータが2つ以上のブール関数のAND演算を可能にするのは不思議です... – Evi1M4chine