I use MongoDB library to handle data from Mongodb. There is a Monad called Action
representing a DB read or write operation https://github.com/TonyGen/mongoDB-haskell/blob/master/doc/tutorial.md
.
But, I find that when I in monad Action, I also want to do some IO which must be in an IO Monad. Some codes like
-- `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
There is a liftIO
before any IO
monad and I think it may be verbose. Any concise way to handle this ?
You can’t avoid the liftIO
, unfortunately, because the standard IO
actions are not overloaded to work in any MonadIO
. But you can join sequences of IO
actions under one call to liftIO
:
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
Or, if you intend to use the same IO
operations repeatedly, you can introduce auxiliary definitions for them:
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)