Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/haskell.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ jobs:
- uses: haskell-actions/setup@v2.7
with:
ghc-version: ${{ matrix.ghc }}
cabal-version: '3.0'
cabal-version: '3.10.2.0'

- name: Cache
uses: actions/cache@v3
Expand Down
1 change: 1 addition & 0 deletions bluefin-postgresql/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Haskell Package Versioning Policy](https://pvp.hask
### Changed

- Support `bluefin` versions `0.2.7 && < 0.6` in [#4](https://github.com/fpringle/bluefin-postgresql/pull/4).
- Dynamic `PostgreSQL` effect in [#7](https://github.com/fpringle/bluefin-postgresql/pull/7).

## [0.1.0.0] - 27.02.2026

Expand Down
48 changes: 29 additions & 19 deletions bluefin-postgresql/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# bluefin-postgresql

This package provides a `bluefin` effect for [postgresql-simple](https://hackage.haskell.org/package/postgresql-simple)'s `Connection` type.
This package provides `bluefin` effects for [postgresql-simple](https://hackage.haskell.org/package/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.
It defines:
- a dynamic `WithConnection` effect to allow effectful functions to use a `Connection`, without worrying about where that `Connection` comes from.
- a dynamic `PostgreSQL` effect ro run database operations from `postgresql-simple`.

For a higher-level effect library using [Opaleye](https://hackage.haskell.org/package/opaleye), see [bluefin-opaleye](https://github.com/fpringle/bluefin-postgresql/blob/main/bluefin-opaleye#readme).

Expand All @@ -25,48 +27,53 @@ insertAndList wc ioe = BP.withConnection wc $ \conn -> do
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:
The `PostgreSQL` effect lets us completely forget about `Connection` and rewrite the above to:

```haskell

import Bluefin.PostgreSQL

insertAndList ::
(e :> es, e1 :> es) =>
WithConnection e ->
IOE e1 ->
(e :> es) =>
PostgreSQL e ->
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"]
insertAndList psql = do
BP.execute psql "insert into users (first_name) values (?)" ["Nuala"]
BP.query psql "select * from users where first_name in ?" $ PSQL.Only $ PSQL.In ["Anna", "Boris", "Carla"]
```

The same goes for other functions:

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

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

## Interpreters

In order to discharge the `PostgreSQL` effect we use the `WithConnection` effect:

```haskell
dischargePostgreSQL :: (e :> es, e1 :> es) => WithConnection e -> IOE e1 -> Eff es [User]
dischargePostgreSQL withConn ioe =
runPostgreSQL withConn ioe $ \psql -> insertAndListCarefully psql
```

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

```haskell
Expand All @@ -77,13 +84,16 @@ 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
BP.runWithConnection conn $ \wc ->
BP.runPostgreSQL wc ioe $ \psql ->
insertAndListCarefully wc ioe >>= effIO ioe . print

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

Alternatively, we can use a connection pool (from [resource-pool](https://hackage.haskell.org/package/resource-pool)
Expand Down
1 change: 1 addition & 0 deletions bluefin-postgresql/bluefin-postgresql.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ library
, extensions
exposed-modules:
Bluefin.PostgreSQL
Bluefin.PostgreSQL.Effect
Bluefin.PostgreSQL.Connection
if flag(enable-pool)
exposed-modules:
Expand Down
Loading
Loading