18

Insbesondere muss ich in der Lage sein, die CGI-Monade mit der IO-Monade zu kombinieren, aber ein Beispiel, wie man die IO-Monade mit der Maybe-Monade kombinieren könnte, könnte noch besser sein ...Wie kombiniere ich Monaden in Haskell?

+0

interessant lesen: [Monad_transformers] (http://www.haskell.org/haskellwiki/Typeclassopedia#Monad_transformers) – mb21

Antwort

0

In welchem ​​Sinne wollen Sie die Monaden kombinieren?

[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

Sie nicht Berechnungen über Maybe, und damit die Tatsache, dass Maybe ist eine Monade ist irrelevant. – jrockway

17

Sie sagen nicht genau, wie Sie IO und Maybe verbinden wollen, aber ich nehme an, Sie viele Funktionen haben, die IO (Maybe a) zurückkehren, die Sie leicht kombinieren möchten:

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

Kann bewertet werden . Im Grunde wollen Sie IO (Maybe a) als separate Art zu behandeln, mit ihm selbst ist Monad Beispiel:

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) 

Mit diesem können Sie die do -Notation verwenden Funktionen zu kombinieren, die IO (Maybe a) zurückzukehren, IO a oder Maybe 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() 

Im Allgemeinen wird etwas, das Monaden wie diese kombiniert und modifiziert, monad transformer genannt, und GHC kommt mit package, die Monad-Transformatoren für häufige Fälle enthält. Wenn es etwas in dieser Monad Transformer-Bibliothek gibt, das zu Ihrem Szenario passt, hängt davon ab, wie genau Sie Maybe und IO kombinieren möchten.

+0

Wenn Sie nicht wussten, können Sie automatisch die 'runIOMaybe' erstellen, indem Sie stattdessen' newtypeIOMaybe a = IOM {runIOMaybe :: IO (Vielleicht ein)}} – rovaughn

21

Ich nehme an, dass Sie die Maybe-Monade für die vorzeitige Beendigung verwenden möchten (wie break oder return in C). In diesem Fall sollten Sie MaybeT aus dem MaybeT-Paket (cabal install MaybeT) verwenden.

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 ist eine Monade-Transformator-Version der vielleicht Monade.

Monad Transformatoren "Funktionalität hinzufügen" zu anderen Monaden.

+3

Auch nichts wert, dass ErrorT in mtl ist, und das auch implementiert MonadPlus, was bedeutet, dass der obige Code in der Error-Monade fast unverändert funktionieren würde. (Die Änderung besteht darin, dass der "linke" Teil von ErrorT eine Typ-Signatur benötigt, da "mzero" nicht spezifisch genug ist.) – jrockway

+0

@jrockway: Und der linke Typ würde eine "Fehler" -Instanz benötigen, was ein wenig unpraktisch ist weil 'MaybeT' isomorph zu etwas wie' ErrorT() 'ist, aber dies ist nicht erlaubt, da es keine' Instance Error() 'gibt. Es ist besser, "EntwederT" zu verwenden, aber dies erfordert auch ein zusätzliches Paket. –

Verwandte Themen