【发布时间】:2010-11-10 17:32:08
【问题描述】:
特别是,我需要能够将 CGI monad 与 IO monad 结合起来,但是一个如何将 IO monad 与 Maybe monad 结合起来的例子可能会更好......
【问题讨论】:
-
有趣的阅读:Monad_transformers
标签: haskell functional-programming monads monad-transformers
特别是,我需要能够将 CGI monad 与 IO monad 结合起来,但是一个如何将 IO monad 与 Maybe monad 结合起来的例子可能会更好......
【问题讨论】:
标签: haskell functional-programming monads monad-transformers
我假设您想使用 Maybe monad 提前终止(例如 C 中的 break 或 return)。
在这种情况下,您应该使用 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 是 Maybe monad 的 monad 转换器版本。
Monad 转换器“添加功能”到其他 monad。
【讨论】:
Error 实例,这有点不方便,因为MaybeT 实际上与ErrorT () 类似,但这是不允许的,因为有不是instance Error ()。最好使用EitherT,但这也需要额外的包。
您没有确切说明您想如何组合IO 和Maybe,但我假设您有许多返回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)
有了这个,您可以使用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 ()
通常像这样组合和修改 monad 的东西称为 monad transformer,而 GHC 附带一个 package,其中包括用于常见情况的 monad 转换器。这个 monad 转换器库中是否有适合您的场景的东西取决于您希望将 Maybe 和 IO 结合起来的方式。
【讨论】:
newtype IOMaybe a = IOM { runIOMaybe :: IO (Maybe a) }来自动创建runIOMaybe
你想在什么意义上结合单子?
f :: Int -> IO (Maybe Int)
f x = do
putStrLn "Hello world!"
return $ if x == 0 then Nothing else Just x
可以评估为:
[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
【讨论】: