| Copyright | (c) 2026 The Polytropos Authors |
|---|---|
| License | EUPL-1.2 OR Apache-2.0 |
| Maintainer | nadia.yvette.chambers@ik.me |
| Stability | experimental |
| Portability | non-portable (GHC extensions) |
| Safe Haskell | None |
| Language | GHC2021 |
Polytropos.Beam
Description
Enables polytropos open records to act as beam database schema tables
without GHC out-of-memory compilation crashes on 50+ columns.
Architectural Overview & Rationale
Eliminating Generic Tree Explosion in Beam
A standard beam table is a nominal Haskell record whose Beamable instance is
derived through GHC.Generics. The resulting binary metadata tree is what causes
quadratic compile times and memory blow-up on tables with 50+ columns.
In polytropos-beam, a table is backed by a single flat SmallArray:
* zipBeamFieldsM executes as a linear lockstep walk over flat array slots.
* tblSkeleton builds the table spine once per row arity.
* is a zero-cost newtype wrapper around BeamTableRowRep f ProductRowT r ().
When to Use This Module
- When defining large database tables (dozens or hundreds of columns) with the
beamframework while maintaining predictable, instantaneous compilation.
Worked Example
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedRecordDot #-}
import Database.Beam
import Polytropos
import Polytropos.Beam
type UserRow = '["id" ':= Int, "username" ':= String]
type UserTable f = BeamTable UserRow f
-- 1. Construct an open record using idiomatic REC syntax:
userRec :: Record UserRow
userRec = REC { id = 1, username = "Alice" }
-- 2. Convert to a Beam database table (zero-cost unwrap):
userTable :: UserTable Identity
userTable = toBeamTable userRec
-- 3. Functional updates using REC_UPD prior to database serialization:
updatedUser :: Record UserRow
updatedUser = (REC_UPD userRec) { username = "Bob" }
-- 4. Higher-Kinded Data (HKD) partial table with REC_F and REC_UPD_F:
partialUser :: RecordF Maybe UserRow
partialUser = REC_F { id = Just 1, username = Nothing }
populatedUser :: RecordF Maybe UserRow
populatedUser = (REC_UPD_F partialUser) { username = Just "Bob" }Synopsis
- newtype BeamTable (r :: Row) (f :: Type -> Type) = BeamTable (RowRep f 'ProductRowT r ())
- toBeamTable :: forall (r :: Row). Record r -> BeamTable r Identity
- fromBeamTable :: forall (r :: Row). BeamTable r Identity -> Record r
- beamTableOfSlots :: forall f (r :: Row). [f (Any :: Type)] -> BeamTable r f
- class FieldNames (r :: Row) where
- fieldNames :: Proxy r -> [String]
Beam Tables over Polytropos Rows
newtype BeamTable (r :: Row) (f :: Type -> Type) Source #
A polytropos row presented as a beam table with column functor f.
Zero cost: unwraps to exactly the same Rep spine as the
corresponding Record (for f ~ Identity).
Constructors
| BeamTable (RowRep f 'ProductRowT r ()) |
Instances
| FieldNames r => Beamable (BeamTable r) Source # | |
Defined in Polytropos.Beam Methods zipBeamFieldsM :: forall m (f :: Type -> Type) (g :: Type -> Type) (h :: Type -> Type). Applicative m => (forall a. Columnar' f a -> Columnar' g a -> m (Columnar' h a)) -> BeamTable r f -> BeamTable r g -> m (BeamTable r h) # tblSkeleton :: TableSkeleton (BeamTable r) # | |
toBeamTable :: forall (r :: Row). Record r -> BeamTable r Identity Source #
View a record as a beam table (zero-cost newtype wrap).
fromBeamTable :: forall (r :: Row). BeamTable r Identity -> Record r Source #
View a beam table as a record (zero-cost newtype unwrap).
beamTableOfSlots :: forall f (r :: Row). [f (Any :: Type)] -> BeamTable r f Source #
Build a table from payload slots, in row order. The slot list must have
exactly the row's arity; a shorter list yields a partially filled table
that will misbehave if traversed, so prefer toBeamTable.
Row Introspection
class FieldNames (r :: Row) where Source #
The field names of a row, in row order, reified from the type level. These are the default column names beam derives from the row symbols.
Methods
fieldNames :: Proxy r -> [String] Source #
Instances
| FieldNames ('[] :: [Pair Symbol Type]) Source # | |
Defined in Polytropos.Beam Methods fieldNames :: Proxy ('[] :: [Pair Symbol Type]) -> [String] Source # | |
| (KnownSymbol n, FieldNames r) => FieldNames ((n ':= a) ': r) Source # | |
Defined in Polytropos.Beam Methods fieldNames :: Proxy ((n ':= a) ': r) -> [String] Source # | |