2013-08-21 7 views
6

私は質問を拡大するためにあまりできません。しかし、ここで使用する場合は、次のとおりです。あなたが同じモナドm上で変換、2つのモナド変圧器、tsを持っているとしましょう:彼らは互いに通信することができますslaveよう2つのモナド変圧器が異なるタイプのものであっても、それらの基礎となるモナドが同じタイプのものであれば、原理的な方法がありますか?

master :: (MonadTrans t, Monad m) => t m a b 
slave :: (MonadTrans t, Monad m) => s m a b 

そして、私はmasterを構成したいとするときmプリミティブはtsに持ち上げられます。署名は、かもしれない:

bound :: (MonadTrans t, MonadTrans s, Monad m, Monoid a) => t m a b -> s m a b -> (...) 
But what is the type of (...) ? 

ユースケース、シュガー入りの表記:

master :: Monoid a => a -> t m a b 
master a = do 
    a <- lift . send $ (a,False)  -- * here master is passing function param to slave 
    ...        -- * do some logic with a 
    b <- lift . send $ (mempty,True) -- * master terminates slave, and get back result 

slave :: Monoid a => (a -> b) -> s m a b 
slave g = do 
    (a,end) <- lift receive 
    case end of 
     True -> get >>= \b -> exit b 
     _ -> (modify (++[g a])) >> slave g 

更新:sendreceiveタイプmのプリミティブです。

この例題が工夫されていたり、コルーチンに似ていたりすると、質問の精神と実際には関係がないので、すべての類似点を無視してください。しかし、主なポイントは、モナドtsは以前はお互いに分かりやすく構成することができませんでしたが、どちらも基礎モナドをラップした後、それらを合成して単一の関数として実行できるようになりました。合成された関数の型については、私は実際にはいくつかの方向が評価されているか分からない。今、この抽象化がすでに存在していて、それについてはわかりません。

+0

's'と' t'は任意であるか、何らかの形で具体的です - このような 's'と' t'を作成しようとしていますか?そして同じ質問が 'm'にも当てはまります - それについて、' send'と 'receive'についてどうですか? –

+0

はい 's'と' t'は任意です。 'm'はここで作成しようとしている特定のタイプです。 'send'と' receive'は '(a、Bool) - > m a b'と' m a b'型の単なる基本関数です。しかし、彼らは私が与えた考案されたユースケースに付随しているので、その実装の詳細は重要ではありません。 – chibro2

答えて

8

はい。 hoistの種類を研究、これは働く理由を理解するには

bound 
    :: (MonadTrans t, MonadTrans s, MFunctor t, Monad m) 
    => t m() -> s m() -> t (s m)() 
bound master slave = do 
    hoist lift master 
    lift slave 

:これを行うにはliftmmorphパッケージからhoistを組み合わせ

hoist :: (MFunctor t) => (forall x . m x -> n x) -> t m r -> t n r 

hoistは、あなたがそのすべてのモナド変換子のベースモナドを変更できますMFunctor(ほとんどの場合)が実装されています。

boundのコードでは、最終的なターゲットモナド(この場合はt (s m))に一致する2つのモナドトランスがあります。 tsをネストする順序はあなた次第ですので、私はちょうどあなたが外側にtを望んでいると仮定しました。

次に、hoistとのさまざまな組み合わせを使用して、2つのサブ計算が最終的なモナドスタックに一致するようにします。最初のものは、このように動作します:

master :: t m r 
hoist lift master :: t (s m) r 

秒1は次のように動作します。今、彼らの両方が、私たちは同じdoブロック内でそれらの配列を決定することができ、それが「ただ働き」だろう同意

slave :: s m r 
lift slave :: t (s m) r 

hoistの動作の詳細については、の下部にmmorphパッケージのthe documentationを確認することをおすすめします。

関連する問題