por - ¿Cómo combino las mónadas en Haskell?
listas intensionales haskell (3)
¿En qué sentido quieres combinar las mónadas?
f :: Int -> IO (Maybe Int)
f x = do
putStrLn "Hello world!"
return $ if x == 0 then Nothing else Just x
Puede ser evaluado para:
[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
Particularmente, necesito poder combinar la mónada CGI con la mónada IO, pero un ejemplo de cómo combinar la mónada IO con la mónada Maybe podría ser aún mejor ...
No dice exactamente cómo desea combinar IO
y Maybe
, pero supongo que tiene muchas funciones que devuelven IO (Maybe a)
que desea combinar fácilmente. Básicamente, usted quiere tratar IO (Maybe a)
como un tipo separado con su propia instancia de 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)
Con esto, puede usar la opción -Notation para combinar funciones que devuelven IO (Maybe a)
, IO a
o 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 ()
En general, algo que combina y modifica las mónadas como esta se denomina transformador de mónada , y GHC viene con un package que incluye transformadores de mónada para casos comunes. Si hay algo en esta biblioteca de transformadores de mónada que se adapte a su escenario, depende de cómo exactamente desea combinar Maybe y IO.
Supongo que desea utilizar la mónada Maybe para la terminación anticipada (como break
o return
en C).
En ese caso, debe usar MaybeT
del paquete MaybeT ( cabal 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 es una versión de la mónada transformadora de la mónada.
Los transformadores de mónada "agregan funcionalidad" a otras mónadas.