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

How to use monad in this case?

比如说,我想连接到数据库并进行一些查询。我决定使用 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 是旧连接。

doQueryForever 应将连接作为参数。当一个查询失败时,用一个新的连接递归调用它;当查询成功时,使用现有连接递归调用它。初次调用,当然也需要走第一个连接。

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

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

runQueries