2016-03-06 22 views
2

我使用在其中一個模塊中定義的功能if'而不是內置的if-then-else構造。它是平凡的定義,工作得很好。在我的程序中解除「if」功能的意外行爲

但是,在代碼中有一個地方需要將它應用於monad值(我的情況爲IO),即類型簽名應該看起來有點像IO Bool -> IO a -> IO a -> IO a。當然,我試圖解除它。

if' <$> mb <*> action1 <*> action2 

但是,當我試圖評估表達式,我沒有得到我所期望的。

*Main> if' <$> return True <*> putStrLn "yes" <*> putStrLn "no" 
yes 
no 

我知道<*>說明寫着「序貫應用」,所以也許它是。但是這裏發生了什麼?我可以在不寫一個全新的專用功能的情況下修復它嗎?

+0

在上一個表達式中,if語句只控制返回的值 - 爲了甚至計算這些值,兩個分支都必須執行,因爲它使用IO的應用接口。如果'b(putStrLn「是」)(putStrLn「no」),你可能希望'返回True >> = \ b - >' - 注意'if'直接應用於不同分支。 – user2407038

回答

3

(<*>)評估它的兩個參數,所以它實際上是一個應用程序的管道解除了一些應用。檢查數值和改變計算未來的能力是Monad類超過Applicative的額外能力,因此您需要使用它,例如

mif' :: Monad m => m Bool -> m a -> m a -> m a 
mif' bm xm ym = bm >>= (\b -> if b then xm else ym) 
+1

@Carl在[https://stackoverflow.com/questions/17409260/what-advantage-does-monad-give-us-over-an-applicative](https://stackoverflow.com)有一個很好的答案。 /問題/ 17409260 /什麼-優勢,確實-單子放棄的我們,過度的,應用性) – badcook