bluefin-postgresql: bluefin support for mid-level PostgreSQL operations.

This is a package candidate release! Here you can preview how this package release will appear once published to the main package index (which can be accomplished via the 'maintain' link below). Please note that once a package has been published to the main package index it cannot be undone! Please consult the package uploading documentation for more information.

[maintain] [Publish]

See the README for an overview, or the documentation in Bluefin.PostgreSQL.


[Skip to Readme]

Properties

Versions 0.1.0.0, 0.1.0.0
Change log CHANGELOG.md
Dependencies base (>=4 && <5), bluefin (>=0.0.11 && <0.0.18), postgresql-simple (>=0.7 && <0.8), unliftio-pool (>=0.4.1 && <0.5) [details]
License BSD-3-Clause
Copyright Copyright(c) Frederick Pringle 2025
Author Frederick Pringle
Maintainer frederick.pringle@fpringle.com
Category Database
Home page https://github.com/fpringle/bluefin-postgresql
Uploaded by fpringle at 2026-02-27T10:09:27Z

Modules

Flags

Automatic Flags
NameDescriptionDefault
enable-pool

Enable support for connection pools using unliftio-pool. You can disable this for a lighter dependency footprint if you don't need support for connection pools.

Enabled

Use -f <flag> to enable a flag, or -f -<flag> to disable that flag. More info

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees


Readme for bluefin-postgresql-0.1.0.0

[back to package description]

bluefin-postgresql

This package provides a bluefin effect for postgresql-simple's Connection type.

It defines a dynamic effect to allow effectful functions to use a Connection, without worrying about where that Connection comes from.

For a higher-level effect library using Opaleye, see bluefin-opaleye.

Effectful functions

In the WithConnection effect we can always request a Connection and use it as we normally would:

import Bluefin.PostgreSQL as BP
import qualified Database.PostgreSQL.Simple as PSQL

insertAndList ::
  (e :> es, e1 :> es) =>
  WithConnection e ->
  IOE e1 ->
  Eff es [User]
insertAndList wc ioe = BP.withConnection wc $ \conn -> do
  effIO ioe $ PSQL.execute conn "insert into users (first_name) values (?)" ["Nuala"]
  effIO ioe $ PSQL.query conn "select * from users where first_name in ?" $ PSQL.Only $ PSQL.In ["Anna", "Boris", "Carla"]

In fact, for convenience we also define lifted versions of all of the query/execute functions from postgresql-simple, so we can completely forget about Connection and rewrite the above to:


import Bluefin.PostgreSQL

insertAndList ::
  (e :> es, e1 :> es) =>
  WithConnection e ->
  IOE e1 ->
  Eff es [User]
insertAndList wc ioe = do
  BP.execute wc ioe "insert into users (first_name) values (?)" ["Nuala"]
  BP.query wc ioe "select * from users where first_name in ?" $ PSQL.Only $ PSQL.In ["Anna", "Boris", "Carla"]

The same goes for other functions:

-- use a transaction
insertAndListCarefully ::
  (e :> es, e1 :> es) =>
  WithConnection e ->
  IOE e1 ->
  Eff es [User]
insertAndListCarefully wc ioe = BP.withTransaction wc ioe $ insertAndList wc ioe

-- stream + fold over results (in Eff)
countUsersIneffeciently ::
  (e :> es, e1 :> es) =>
  WithConnection e ->
  IOE e1 ->
  Eff es Int
countUsersIneffeciently wc ioe =
  BP.fold_ wc ioe "select * from users" 0 $ \acc (row :: User) -> do
    effIO ioe . putStrLn $ "User: " <> show row
    pure $ acc + 1

Interpreters

The simplest way of running the WithConnection effect is by just providing a Connection, which we can get in the normal ways:

import Bluefin.PostgreSQL as BP
import qualified Database.PostgreSQL.Simple as PSQL

usingConnection :: IO ()
usingConnection =
  runEff $ \ioe ->
    bracket (effIO ioe $ PSQL.connectPostgreSQL "") (effIO ioe . PSQL.close) $ \conn ->
      BP.runWithConnection conn $ \wc -> insertAndListCarefully wc ioe >>= effIO ioe . print

usingConnectInfo :: IO ()
usingConnectInfo =
  runEff $ \ioe ->
    BP.runWithConnectInfo ioe PSQL.defaultConnectInfo $ \wc ->
      insertAndListCarefully wc ioe >>= effIO ioe . print

Alternatively, we can use a connection pool (from resource-pool and unliftio-pool), which is much better suited to long-running processes like servers.

import Bluefin.PostgreSQL as BP
import qualified Database.PostgreSQL.Simple as PSQL
import qualified UnliftIO.Pool as P

usingConnectionPool :: IO ()
usingConnectionPool = do
  poolCfg <- P.mkDefaultPoolConfig (PSQL.connectPostgreSQL "") PSQL.close 5.0 10
  pool <- P.newPool poolCfg
  runEff $ \ioe ->
    BP.runWithConnectionPool ioe pool $ \wc ->
      insertAndListCarefully wc ioe >>= effIO ioe . print