【发布时间】:2015-04-02 13:35:13
【问题描述】:
我使用 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,我认为它可能很冗长。有什么简洁的方法来处理这个吗?
【问题讨论】:
-
没有真正的好方法来处理这个问题,因为
IO操作仅作为返回IO a而不是MonadIO m => m a来实现。我经常在函数上看到where io = liftIO之类的东西,并且使用函数io而不是liftIO,只是为了减少打字。理想情况下,我们应该有hPutStrLn :: MonadIO m => Handle -> String -> m (),但我们不能指望base中的函数依赖于第三方库中定义的类(即使这些库是haskell 平台的一部分)。 -
如果您有一系列 IO 操作,您可以将
do liftIO action1 ; liftIO action2更改为liftIO $ do action1; action2以节省一些提升。