2017-01-05 8 views
0

のリストフィルタリング:IO [Either a b]私はタイプのリストをフィルタリングしようとしていますモナド

理想的には、私は次のタイプのSIGとフィルタリング機能を構成したいと思います:

(Monad m, Monad m2) => m [m2 a] -> (a -> Bool) -> m [m2 a] 

私は多くのことを試してみました、filterMfmap、および=<<は、私の述語を適切なコンテキストに持ち上げようと無駄にしようとしましたが、私はm [m a]-> (a -> m Bool)-> m [m a]を達成することができますが、どちらも同じモナドではないので、私は何か良いことをしているようだ。

これは「do notation」のようなものですが、私は<-オペレータで割り当てられたもののタイプシグネチャを調べる方法を捨てることができず、動いているターゲットで撮影しています。

私は、別のモナド(Either)のインスタンスを含むリストと、リスト自体(IO)を含むモナドを含むリストをトラバースしていることを明確にする方法では、どのように関数を構成するのか不明です。

私はここで何が欠けていますか?

+0

あなたは '' m2'に述語をfmap'ことができますが、どのように結果の '平方メートルBool'を検査するつもりですか? @BenjaminHodgsonが指摘しているように、あなたができるのは '(Functor f、Applicative g)=>(a - > Bool) - > f [ga] - > f(g [a])' –

+0

です。 't(fa) - > f(ta)' – jberryman

+1

私は与えられた型のモナドのリストをフィルタリングする関数があると仮定しました。関数をIOモナドに追加します。 内部では、[[Either ab]]のインスタンスを連結することは、インスタンスを連結することとは異なることを理解しています。これは、たとえば、 'filterM(liftM。(\ x-> True) 'IO [Either ab]'の中で、これはうまくいきませんが、それは不可能ではない、単なる頭痛です。 私はこの問題を抱える最初の人ではなく、誰かがそれを解決したと仮定しました。 –

答えて

5

理想的には、私は次の 型SIGとフィルタリング機能を構成したいと思います:

(Monad m, Monad m2) => m [m2 a] -> (a -> Bool) -> m [m2 a] 

Monadインターフェイスを取得する方法を提供していませんので、それは、一般的に行うことができませんm aのうちaです。 fmap (fmap (fmap f))を使用してm [m2 Bool]まで得ることができますが、要素を削除するかどうかを決定するには、m2 BoolからBoolを取得する必要があります。

このように見てください。問題のモナドがProxyだったら?

data Proxy a = Proxy -- one constructor, no fields 

instance Monad Proxy where 
    return _ = Proxy 
    Proxy >>= _ = Proxy 

その内部に何があることはないので、あなたは、Proxy Bool内部Boolで見ることができません! a -> Bool[Proxy a]を指定すると、リストのどの要素が削除されるのか分かりますか?


あなた次の型シグネチャを持つ関数を書くことができます。

myfilter :: (Functor f, Applicative g) => (a -> Bool) -> f [g a] -> f (g [a]) 

注意を戻り値の型がf (g [a])、ないf [g a]であること。

この関数は、外部ファンクタに入るためにfmapを使用し、リスト内のgを分解し、次にfmapをもう一度破棄して結果をフィルタリングします。

myfilter p = fmap (fmap (filter p) . sequenceA) 
+0

これは動作します、ありがとう! 私はかなり理解しているとは確信していません - 「Boolをラッパーから取得できない」場合、タイプ[m a]のフィルタリングはどのように機能しますか? -EDIT-より明確 - 'FMAP(マップ(FMAP(* 3)))(ちょうど([右5、右12]))' ' 戻る場合は、単に[右15、右36]' なぜ同じことをするフィルタはありませんか? –

+1

一般的には、モナドを使ってモナドを操作することはありません。あなたはモナドの中に自分を持ち上げる。あなたは '[ma]'から 'a 'を得ることはできませんが、' sequenceA :: Applicative m => [ma] - > m [a]を使って 'm' '。 'm'が' Proxy'ならば、あなたは 'sequenceA :: [Proxy a] - > Proxy aを持ちます。シーケンスA _ =プロキシ '。 –

1

あなたがMonad mの外にaを取得することができないかもしれないが、あなたが例えば使用Monad mにあなたの機能を得ることができます受け入れ答えに追加するにはliftM。内部構造に応じて、使用可能なアクションを構成し、最後にそれらをある種の方法で順序付けして、計算が「発生する」ようにすることができます。 IO[Either Bool Integer]として与えられたIO[Either a b]の問題を使用した例を与えることを

import Control.Monad 

testCase :: IO [Either Bool Integer] 
testCase = return [(Right 1), (Left True), (Right 2), (Left False), (Right 3), (Right 4)] 

liftFilter :: Monad m => (a -> Bool) -> m [a] -> m [a] 
liftFilter pred = liftM (filter pred) 

testFilter :: (Either Bool Integer) -> Bool 
testFilter (Left True) = True 
testFilter (Right x) = even x 
testFilter _   = False 

showIt :: (Either Bool Integer) -> String 
showIt (Left True) = "Left True" 
showIt (Left False) = "Left False" 
showIt (Right x) = "Right x=" ++ (show x) 

test = do 
    filtered <- liftFilter testFilter testCase 
    return (fmap showIt filtered) 

runTest = do 
    actions <- liftM (fmap putStrLn) test 
    sequence_ actions 
+0

ありがとう、これは非常に有用な補遺でした。 –

関連する問題