如何在Haskell中组合monad?

Chr*_* W. 18 monads haskell functional-programming monad-transformers

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

yai*_*chu 21

我假设你想使用Maybe monad提前终止(比如breakreturn在C中).

在这种情况下,您应该使用MaybeTMaybeT包(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 ()
Run Code Online (Sandbox Code Playgroud)

MaybeT是monad的monad变换器版本.

Monad变形金刚"为其他monad添加功能".

  • 同样值得一提的是mtl中有ErrorT,并且还实现了MonadPlus,这意味着上面的代码在Error monad中几乎不会发生变化.(更改是ErrorT的"Left"部分需要类型签名,因为"mzero"不够具体.) (3认同)

sth*_*sth 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)
Run Code Online (Sandbox Code Playgroud)

有了这个,你可以使用do-Notation来组合返回的函数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 ()
Run Code Online (Sandbox Code Playgroud)

通常,组合和修改这样的monad的东西称为monad变换器,GHC附带一个包含monad变换器的,用于常见情况.如果此monad变换器库中有适合您的场景的内容取决于您希望如何组合Maybe和IO.


Mar*_*off 0

你想在什么意义上组合这些单子?

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

可以评估为:

[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
Run Code Online (Sandbox Code Playgroud)

  • 您不是在 Maybe 上进行计算,因此 Maybe 是一个 monad 的事实是无关紧要的。 (4认同)