I can't test it now, but try something like:
handleSql print $ do
query_3 <- quickQuery' conn_1 "SELECT MAX(high) FROM historicalData" []
mapM_ (putStrLn . convertSqlValToString) query_3
It uses
handleSql :: (SqlError -> IO a) -> IO a -> IO a
(which is just catchSql :: IO a -> (SqlError -> IO a) -> IO a
with its arguments reversed).
Function handleSql
runs the action given as its second argument, in your case quickQuery'
followed by mapM_
. And if a SqlError
occurs during that part, it passes it to the function given as the first argument. So in the above example, if a SqlError
occurs during the inner block, handleSql
will call print
on it..