haskell-beam / haskell-beam/beam

The whole database is a Monoid.

Open
#588 0 comments 1 reaction 0 assignees View on GitHub
Dominant language
Haskell
Stars
635
Forks
193
PR merge metrics
No merged PRs in 30d

Description

I had a bit of fun turning the whole database into a Monoid:

```haskell
data Db f = Db
{ datumRows :: f (TableEntity DatumRowT)
, scriptRows :: f (TableEntity ScriptRowT)
, txRows :: f (TableEntity TxRowT)
, addressRows :: f (TableEntity AddressRowT)
}
deriving (Generic, Database be)

type AllTables (c :: * -> Constraint) f = (c (f (TableEntity DatumRowT)), c (f (TableEntity ScriptRowT)), c (f (TableEntity TxRowT)), c (f (TableEntity AddressRowT)))
deriving via (GenericSemigroupMonoid (Db f)) instance AllTables Semigroup f => Semigroup (Db f)
deriving via (GenericSemigroupMonoid (Db f)) instance AllTables Monoid f => Monoid (Db f)
```

It’s useful for generating batch inserts. You can `mconcat` together inserts into various tables, and using `zipTables` to generate batch inserts per table:

```haskell
data InsertRows te where
InsertRows :: BeamableSqlite t => [t Identity] -> InsertRows (TableEntity t)

instance Semigroup (InsertRows te) where
InsertRows l <> InsertRows r = InsertRows (l <> r)
instance BeamableSqlite t => Monoid (InsertRows (TableEntity t)) where
mempty = InsertRows []

insertRows :: Db InsertRows -> SqliteM ()
insertRows = getAp . getConst . zipTables (Proxy :: Proxy Sqlite) (\tbl (InsertRows rows) -> Const . Ap . runInsert . insert tbl $ insertValues rows) db
```

I posted this on Twitter and someone replied that this should go in the documentation somewhere. I think that's a good idea, but I'm not sure what would be the right place, and if some of the code should be part of a beam package. If we can decide on the right place for this I'm more than willing to create a PR.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.