title: Concurrent DB connection pool in Haskell
body: <p>I am a Java programmer who learns Haskell.<br>
  I work on a small web-app that uses Happstack and talks to a database via HDBC.</p>
  
  <p>I've written <strong>select</strong> and <strong>exec</strong> functions and I use them like this:</p>
  
  <pre><code>module Main where
  
  import Control.Exception (throw)
  
  import Database.HDBC
  import Database.HDBC.Sqlite3 -- just for this example, I use MySQL in production
  
  main = do
      exec "CREATE TABLE IF NOT EXISTS users (name VARCHAR(80) NOT NULL)" []
  
      exec "INSERT INTO users VALUES ('John')" []
      exec "INSERT INTO users VALUES ('Rick')" []
  
      rows &lt;- select "SELECT name FROM users" []
  
      let toS x = (fromSql x)::String
      let names = map (toS . head) rows
  
      print names
  </code></pre>
  
  <p>Very simple as you see. There is <strong>query</strong>, <strong>params</strong> and <strong>result</strong>.<br>
  Connection creation and commit/rollback stuff is hidden inside select and exec.<br>
  This is good, I don't want to care about it in my "logic" code.</p>
  
  <pre><code>exec :: String -&gt; [SqlValue] -&gt; IO Integer
  exec query params = withDb $ \c -&gt; run c query params
  
  select :: String -&gt; [SqlValue] -&gt; IO [[SqlValue]]
  select query params = withDb $ \c -&gt; quickQuery' c query params
  
  withDb :: (Connection -&gt; IO a) -&gt; IO a
  withDb f = do
      conn &lt;- handleSqlError $ connectSqlite3 "users.db"
      catchSql
          (do r &lt;- f conn
              commit conn
              disconnect conn
              return r)
          (\e@(SqlError _ _ m) -&gt; do
              rollback conn
              disconnect conn
              throw e)
  </code></pre>
  
  <p>Bad points:<br></p>
  
  <ul>
  <li>a new connection is always created for every call - this kills performance on heavy load</li>
  <li>DB url "users.db" is hardcoded - I can't reuse these functions across other projects w/o editing</li>
  </ul>
  
  <p><strong>QUESTION 1:</strong> how to introduce a pool of connections with some defined (min, max) number of concurrent connections, so the connections will be reused between select/exec calls?</p>
  
  <p><strong>QUESTION 2:</strong> How to make "users.db" string configurable? (How to move it to client code?)</p>
  
  <p>It should be a transparent feature: user code should not require explicit connection handling/release.</p>