在这种情况下如何使用 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
比如说,我想连接到数据库并进行一些查询。我决定使用 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