如何在另一个 Monad 中使用 IO Monad
how to use IO Monad in another Monad
我使用 MongoDB 库来处理来自 Mongodb 的数据。有一个名为 Action
的 Monad,代表一个 DB 读或写操作 https://github.com/TonyGen/mongoDB-haskell/blob/master/doc/tutorial.md
。
但是,我发现当我在 monad Action 中时,我还想做一些必须在 IO Monad 中的 IO。一些代码如
-- `Action' is a Monad
--
intoFile :: String -> Cursor -> Action IO ()
intoFile ric c = do
outH <- liftIO $ openFile ric AppendMode
liftIO $ hPutStrLn outH "Some log"
loopIntoFile outH c
liftIO $ hClose outH
在任何 IO
monad 之前都有一个 liftIO
,我认为它可能很冗长。任何简洁的方法来处理这个?
您想携带 2 个额外的上下文 - IO
上下文和 Action
上下文。 monad 转换器就是这种情况,因为它们允许您处理分层 monad 并在 do
块内部选择要为所需操作选择的 monad。 Here is a great explanation 为什么我们需要它们以及如何使用它们。
您无法避免 liftIO
,不幸的是,因为标准 IO
操作不会过载以在任何 MonadIO
中工作。但是您可以在一次调用 liftIO
:
下加入一系列 IO
操作
intoFile :: String -> Cursor -> Action IO ()
intoFile ric c = do
outH <- liftIO $ do
openFile ric AppendMode
hPutStrLn outH "Some log"
loopIntoFile outH c
liftIO $ hClose outH
或者,如果你打算重复使用相同的IO
操作,你可以为它们引入辅助定义:
intoFile :: String -> Cursor -> Action IO ()
intoFile ric c = do
outH <- openLog ric AppendMode
log outH "Some log"
loopIntoFile outH c
closeLog outH
openLog path mode = liftIO (openFile path mode)
log handle message = liftIO (hPutStrLn handle message)
closeLog handle = liftIO (hClose handle)
我使用 MongoDB 库来处理来自 Mongodb 的数据。有一个名为 Action
的 Monad,代表一个 DB 读或写操作 https://github.com/TonyGen/mongoDB-haskell/blob/master/doc/tutorial.md
。
但是,我发现当我在 monad Action 中时,我还想做一些必须在 IO Monad 中的 IO。一些代码如
-- `Action' is a Monad
--
intoFile :: String -> Cursor -> Action IO ()
intoFile ric c = do
outH <- liftIO $ openFile ric AppendMode
liftIO $ hPutStrLn outH "Some log"
loopIntoFile outH c
liftIO $ hClose outH
在任何 IO
monad 之前都有一个 liftIO
,我认为它可能很冗长。任何简洁的方法来处理这个?
您想携带 2 个额外的上下文 - IO
上下文和 Action
上下文。 monad 转换器就是这种情况,因为它们允许您处理分层 monad 并在 do
块内部选择要为所需操作选择的 monad。 Here is a great explanation 为什么我们需要它们以及如何使用它们。
您无法避免 liftIO
,不幸的是,因为标准 IO
操作不会过载以在任何 MonadIO
中工作。但是您可以在一次调用 liftIO
:
IO
操作
intoFile :: String -> Cursor -> Action IO ()
intoFile ric c = do
outH <- liftIO $ do
openFile ric AppendMode
hPutStrLn outH "Some log"
loopIntoFile outH c
liftIO $ hClose outH
或者,如果你打算重复使用相同的IO
操作,你可以为它们引入辅助定义:
intoFile :: String -> Cursor -> Action IO ()
intoFile ric c = do
outH <- openLog ric AppendMode
log outH "Some log"
loopIntoFile outH c
closeLog outH
openLog path mode = liftIO (openFile path mode)
log handle message = liftIO (hPutStrLn handle message)
closeLog handle = liftIO (hClose handle)