2013-08-21 28 views
6

我可以做很多事來擴展這個問題。但這裏是一個用例:假設您有兩個單子變壓器,ts,轉化在相同的單子m如果兩個monad變換器的類型不同,是否有原則性的構成方式,但是它們的基礎monad是相同類型的?

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

我要撰寫masterslave使得它們能夠相互通信時,基元被提升到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 

更新:sendreceivem類型的原語。

我很抱歉,如果這個例子看起來很有意思,或者太類似於協程,問題的精神實在與它無關,所以請忽略所有相似之處。但要點是單體ts以前不可能明智地組成,但是在包裝一些底層monad m之後,它們現在可以被組合並作爲單個功能運行。至於組合函數的類型,我真的不確定是否讚賞某些方向。現在,如果這種抽象已經存在,我只是不知道它,那麼這將是最好的。

+0

是's'和't'是否任意或者它們是某種特定的 - 我們是否試圖創造這樣的's'和't'?同樣的問題也適用於'm' - 它和它的'send'和'receive'怎麼樣? –

+0

是's'和't'是任意的。 'm'是我們試圖在這裏創建的具體類型。 'send'和'receive'分別是'(a,Bool) - > m a b'和'm a b'類型的原始函數。但是他們對我提供的人爲使用案例是偶然的,他們實施的細節並不重要。 – chibro2

回答

8

是的。從mmorph包結合hoistlift做到這一點:

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 

要理解爲什麼這個工程,研究hoist類型:

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

hoist,您可以修改任何單子轉換的基礎單子說實施MFunctor(這是他們中的大多數)。

bound所做的代碼是兩個單子變換器對最終目標monad達成一致,在此例中爲t (s m)。您嵌套ts的順序取決於您,因此我只是假設您想在外面使用t

然後,它只是使用hoistlift的各種組合來獲得兩個子計算以達成最終monad堆棧。第一個是這樣的:

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

第二個是這樣的:

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

現在他們都同意,所以我們可以在同一do塊中測序他們會「只是工作」。

要了解有關hoist如何工作的更多信息,我建議您檢查the documentation中的mmorph包,它的底部有a nice tutorial

相關問題