简体   繁体   English

如何在Haskell中组合monad?

[英]How do I combine monads in Haskell?

特别是,我需要能够将CGI monad与IO monad结合起来,但是如何将IO monad与Maybe monad相结合的示例可能会更好......

I assume you want to use the Maybe monad for early termination (like break or return in C). 我假设你想使用Maybe monad提前终止(比如在C中breakreturn )。

In that case you should use MaybeT from the MaybeT package ( cabal install MaybeT ). 在这种情况下,你应该使用MaybeT从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 is a monad transformer version of the maybe monad. MaybeT是monad的monad变换器版本。

Monad transformers "add functionality" to other monads. Monad变形金刚“为其他monad添加功能”。

You don't exactly say how you want to combine IO and Maybe , but I assume you have many functions that return IO (Maybe a) that you want to combine easily. 你没有确切地说你想要如何组合IOMaybe ,但是我假设你有许多函数可以返回你想要轻松组合的IO (Maybe a) Basically you want to treat IO (Maybe a) as a separate type with it's own Monad instance: 基本上你想把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)

With this you can use the do -Notation to combine functions that return IO (Maybe a) , IO a or Maybe a : 有了这个,您可以使用do -otation来组合返回IO (Maybe a)IO a或者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 ()

Generally something that combines and modifies monads like this is called a monad transformer , and GHC comes with a package that includes monad transformers for common cases. 通常,组合和修改这样的monad的东西称为monad变换器 ,GHC附带一个包含monad变换器的 ,用于常见情况。 If there is something in this monad transformer library that fits your scenario depends on how exactly you want to combine Maybe and IO. 如果此monad变换器库中有适合您的场景的内容取决于您希望如何组合Maybe和IO。

In what sense do you want to combine the monads? 在什么意义上你想组合monad?

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

Can be evaluated to: 可以评估为:

[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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM