2016-08-02 91 views
4

我正在處理一個庫(ghcjs-dom),其中每個函數都返回一個IO (Maybe T)如何處理IO(Maybe(IO(Maybe t)))type?

我有返回一個IO (Maybe x)和功能b這需要x作爲參數並返回一個IO (Maybe y)函數a

是一個運營商,讓我做a ??? b並得到IO (Maybe y)。我的Hoogle搜索沒有任何結果。

我看起來像join適用於IO (Maybe (IO (Maybe t)))而不是IO (IO t)Maybe (Maybe t)

+1

什麼是'IO Maybe T'?這看起來像一個善良的錯誤。 – augustss

+0

@augustss IO(也許anyRandomType) – 2426021684

+2

那麼,編輯問題後。目前這是很難讀的。 – leftaroundabout

回答

10

據我所知,您有:

a :: IO (Maybe X) 
b :: X -> IO (Maybe Y) 

IO (Maybe a)MaybeT IO a之間的密切關係,即MaybeT轉換一個到另一個:

MaybeT :: IO (Maybe a) -> MaybeT IO a 

和逆操作就是runMaybeT

runMaybeT :: MaybeT IO a -> IO (MaybeT a) 

在MaybeT單子要執行的組成只是 綁定操作:

MaybeT a >>= (\x -> MaybeT (b x)) :: MaybeT IO Y 

這導致MaybeT IO Y類型的值。要將其轉換回IO (Maybe Y)只需使用runMaybeT

更新

下面是操作員 「撰寫」 一個b

andThen :: IO (Maybe a) -> (a -> IO (Maybe b)) -> IO (Maybe b) 
andThen a b = runMaybeT $ MaybeT a >>= (\x -> MaybeT (b x)) 

但是,如果你發現自己使用該運營商很多,也許你 應該重做你的功能,所以你主要在MaybeT IO monad中工作,然後你可以使用>>=和一個runMaybeT 在外面。

+0

如果沒有運行,MaybeT如何知道操作是否成功? – 2426021684

+1

爲操作員更新的答案。 「MaybeT」和「runMaybeT」都不會改變IO行爲,除了它的類型。 'MaybeT'設置了一些東西,以便'>> ='將添加glue邏輯來處理Nothing情況,並用Just包裝返回值。'runMaybeT'把它轉換回IO動作,以便它可以在'main'中運行。只有當它是「main」的一部分時纔會執行IO動作。 – ErikR

+0

謝謝。不幸的是,這些函數來自ghcjs-dom,所以我不能輕易改變它們。 – 2426021684

3

如果你不想使用MaybeT你需要的是sequenceAtraverseData.Traversable

Prelude Data.Traversable Control.Monad> :t fmap join . join . fmap sequenceA 

fmap join . join . fmap sequenceA 
    :: (Traversable m, Control.Applicative.Applicative f, Monad m, 
     Monad f) => 
     f (m (f (m a))) -> f (m a) 

在你的情況f是IO和m也許。

+0

所以你的答案和ErikR一樣,但是適用於所有單子?我應該使用哪個答案? – 2426021684

+1

我的任何monad都不能工作,需要可以穿越的地方就是表格Maybe,List等......使用任何適合你的地方。如果你有這種情況很多,你可能應該與MaybeT一起去。 – mb14