2009-07-14 34 views
18

特別是,我需要能夠將CGI monad與IO monad結合起來,但是如何將IO monad與Maybe monad結合使用的示例可能會更好...如何在Haskell中組合monads?

+0

有趣的閱讀:[Monad_transformers](http://www.haskell.org/haskellwiki/Typeclassopedia#Monad_transformers) – mb21 2013-05-15 14:33:01

回答

0

您希望在什麼意義上結合monads?

f :: Int -> IO (Maybe Int) 
f x = do 
    putStrLn "Hello world!" 
    return $ if x == 0 then Nothing else Just x 

可以計算爲:

[1 of 1] Compiling Main    (maybe-io.hs, interpreted) 
Ok, modules loaded: Main. 
*Main> f 0 
Hello world! 
Nothing 
*Main> f 3 
Hello world! 
Just 3 
+3

您不是正在撰寫可能的計算,因此,可能是monad的事實是不相關的。 – jrockway 2009-09-23 07:38:51

17

你並不確切地說,你怎麼想結合IOMaybe,但我相信你有許多功能,包括返回IO (Maybe a)要輕鬆組合。基本上,你要正確對待IO (Maybe a)作爲一個單獨的類型有它自己的Monad例如:

newtype IOMaybe a = IOM (IO (Maybe a)) 

-- "unpack" a value of the new type 
runIOMaybe :: IOMaybe a -> IO (Maybe a) 
runIOMaybe (IOM a) = a 

instance Monad IOMaybe where 
    -- bind operator 
    (IOM ioa) >>= f = IOM $ do 
     a <- ioa 
     case a of 
     Nothing -> return Nothing 
     Just v -> runIOMaybe (f v) 

    -- return 
    return a = IOM (return (Just a)) 

-- maybe also some convenience functions 
returnIO :: IO a -> IOMaybe a 
returnIO ioa = IOM $ do 
    v <- ioa 
    return (Just v) 

returnMaybe :: Maybe a -> IOMaybe a 
returnMaybe ma = IOM (return ma) 

有了這個,你可以使用do -Notation結合返回IO (Maybe a)IO aMaybe a功能:

f1 :: Int -> IO (Maybe Int) 
f1 0 = return Nothing 
f1 a = return (Just a) 

main = runIOMaybe $ do 
    returnIO $ putStrLn "Hello" 
    a <- returnMaybe $ Just 2 
    IOM $ f1 a 
    return() 

一般來說,組合和修改單子這樣的東西稱爲monad transformer,而GHC帶有package,其中包括常見情況下的單子變換器。如果在這個monad轉換器庫中有些東西符合你的方案,取決於你想要如何組合Maybe和IO。

+0

如果您不知道,您可以通過改爲聲明`newtype IOMaybe a = IOM {runIOMaybe :: IO(也許a)}'來自動創建`runIOMaybe`` – rovaughn 2011-05-12 20:38:31

21

我假設你想使用Maybe monad來提前終止(如C中的breakreturn)。

在這種情況下,您應該使用MaybeT包中的MaybeTcabal install MaybeT)。

main = do 
    runMaybeT . forever $ do 
    liftIO $ putStrLn "I won't stop until you type pretty please" 
    line <- liftIO getLine 
    when ("pretty please" == line) mzero 
    return() 

MaybeT是可能monad的monad變壓器版本。

Monad變壓器「添加功能」給其他monad。

+3

也不值得在mtl中有ErrorT,實現了MonadPlus,這意味着上述代碼在Error monad中幾乎不會改變。 (這個變化是ErrorT的「Left」部分需要一個類型簽名,因爲「mzero」不夠具體。) – jrockway 2009-09-23 07:37:46