在这种情况下如何使用monad?

时间:2016-12-10 09:44:14

标签: haskell monads

说,我想连接到数据库并进行一些查询。我决定使用monad这样实现:

queryDatabase :: IO String
...

doSomeQuery :: IO ()
doSomeQuery = do
    conn   <- connectToDatabase
    result <- queryDatabase conn
    return ()

doQueryForever :: IO ()
doQueryForever = forever doSomeQuery

但是,我不想每次都有一个新的数据库连接,我想重新使用旧连接并在旧连接断开时重新连接。所以,我重新设计了我的程序:

queryDatabase :: IO (Either Connection String)
-- when the connection is broken, return (Left oldConnection)

doSomeQuery :: IO ()
doSomeQuery = do
    conn   <- connectToDatabase
    result <- queryDatabase conn
    return ()

doQueryForever :: IO ()
doQueryForever = do
    conn   <- connectToDatabase  -- Firstly, create a connection

    forever $ do
        result <- queryDatabase conn -- How can I update this conn when broken?
        case result of
          --
          -- Here is the QUESTION. 
          -- If I create a New connection, it seems difficult for me to 
          -- make the new connection use by queryDatabase function.
          --
          Left oldConn -> createNewConnection
          Right s -> putStrLn s

问题是:如何创建刚创建的新连接以供queryDatabase函数使用?当forever函数再次运行时,我认为它使用的conn是旧连接。

1 个答案:

答案 0 :(得分:2)

doQueryForever应该以连接为参数。查询失败时,使用新连接以递归方式调用它;当查询成功时,使用现有连接以递归方式调用它。当然,初始呼叫也需要进行第一次连接。

handleResult result = ...
runQueries = connectToDatabase >>= doQueryForever

doQueryForever conn = do
    result <- queryDatabase conn
    case result of
        Left _ -> runQueries
        Right s -> handleResult s >> doQueryForever conn

runQueries