A primary key identifies a stored entity and gives persistence code a stable handle for loading it. In a type-safe model, the key should belong to the entity it identifies, so a meteor key cannot be used where a comet key is required. section 11.2.3 section 11.2.2
A tempting relational design uses existing domain fields as a composite natural key. For meteors, azimuth, altitude, and timestamp were marked as a key, but floating-point values are poor keys and natural keys should be exceptional. Keeping database and domain models separate limits the effect of later domain changes. section 12.1.1 section 12.1.1
A typed meteor identifier
The relational meteor table adds an integer _id column. Its Beam Table instance wraps that column in DBMeteorId, and primaryKey extracts it from a row. The table therefore accepts its own associated key type rather than an untyped value. section 12.2.2 section 12.2.2
instance Table DBMeteorT where data PrimaryKey DBMeteorT f = DBMeteorId (Columnar f Int) deriving (Generic, Beamable) primaryKey k = DBMeteorId (_id k)
This instance makes the table-specific primary-key representation explicit: DBMeteorId contains the table’s columnar integer identifier, and primaryKey selects _id. section 12.2.2
The same principle applies to a key–value database: KeyEntity MeteorEntity and KeyEntity CometEntity are distinct ADTs, even though generic loading can abstract over the entity. This removes a class of accidental cross-entity key use without requiring per-entity loading wrappers. section 11.2.3 section 11.2.2




















