2009-07-14 11 views
18

Özellikle CGI monadını IO monad ile birleştirebilmem gerekir, ancak IO monadını Belki monad ile birleştirmenin bir örneği belki de daha iyi olabilir ...Haskell'deki monadları nasıl birleştiririm?

+0

ilginizi çekebilir: [Monad_transformers] (http://www.haskell.org/haskellwiki/Typeclassopedia#Monad_transformers) – mb21

cevap

0

Ne anlamda istersin? monadları birleştirmek için? Size tam olarak IO ve Maybe birleştirmek istiyorum nasıl söyleme

[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

Belki üzerinde bir hesap oluşturmuyorsunuz, bu yüzden Belki bir monad olduğu gerçeği alakasız. – jrockway

17

, ama kolayca birleştirmek istediğiniz IO (Maybe a) dönmek birçok fonksiyona sahiptir varsayalım:

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

için değerlendirilebilir Can .

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() 

: Eğer do -Notation IO (Maybe a), IO a veya Maybe a dönmek işlevlerini birleştirmek için kullanabileceğiniz Bununla

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) 

: Bu Monad örneği kendi var olan Temelde ayrı türü olarak IO (Maybe a) tedavi etmek istiyorum Genellikle bu gibi monadları bir araya getiren ve değiştiren bir şey, monad transformer olarak adlandırılır ve GHC, yaygın durumlar için monad transformatörlerini içeren package ile birlikte gelir. Bu monad trafo kütüphanesinde senaryonunuza uyan bir şey varsa, belki de Belki ve IO'yu birleştirmek istediğinize bağlıdır.

+0

Farkında olmasaydınız, otomatik olarak "runIOMaybe" öğesini "newtype IOMaybe a = IOM {runIOMaybe :: IO (Belki a)}" – rovaughn

21

Belki de erken fesih için (örneğin, break veya return C), belki de Monad'ı kullanmak istediğinizi varsayalım.

Bu durumda, MaybeT'u, BelkiT paketinden (cabal install MaybeT) kullanmanız gerekir.

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() 

BelkiT belki de monadın bir monad transformatör sürümüdür.

Monad transformatörler diğer monadlara "işlevsellik ekle".

+3

olarak bildirerek oluşturabilirsiniz. Ayrıca mtT'de ErrorT varlığına da değmezsiniz. MonadPlus uygular, yani yukarıdaki kod Hata monadında neredeyse hiç değişmezdi. (Değişiklik, ErrorT'nin "Sol" bölümünün bir tür imzası gerektirmesidir, çünkü "mzero" yeterince özgül değildir.) – jrockway

+0

@jrockway: Ve soldaki tür bir "Hata" örneğine gereksinim duyar ve bu da biraz rahatsızlık verir. çünkü 'BelkiT' aslında' ErrorT() 'gibi bir şeye isomorfiktir, ancak 'Error()' örneği olmadığı için buna izin verilmez. EitherT kullanmak daha iyidir, ancak bu aynı zamanda ek bir paket gerektirir. –

İlgili konular