polytropos-cbor
Copyright(c) 2026 The Polytropos Authors
LicenseEUPL-1.2 OR Apache-2.0
Maintainernadia.yvette.chambers@ik.me
Stabilityexperimental
Portabilitynon-portable (GHC extensions)
Safe HaskellNone
LanguageGHC2021

Polytropos.CBOR

Description

High-performance binary CBOR serialization of heterogeneous and homogeneous polytropos open records and variants via cborg / serialise, without intermediate tree boxing.

Architectural Overview & Rationale

Binary Wire Format

  • A record encodes as a standard CBOR array: one length header (the row's arity) followed by the flat payload field encodings in row order.
  • A variant encodes as a CBOR array consisting of the constructor's Word tag followed by that constructor's payload field encodings.

Positional & Allocation-Free

Because field names exist only at the type level in row polymorphism, the binary encoder is purely positional: no string keys are written to the wire. Encoding and decoding are executed as single unrolled passes directly over the flat Rep payload array with no intermediate allocations.

Truly Heterogeneous Row Support

Unlike satellites restricted to homogeneous types, polytropos-cbor provides genuine heterogeneous serialization across open rows via AllSerialise: every field requires Serialise at its own concrete type, so rows mixing String, Int, Word, custom types, or nested rows serialize and deserialize directly.

When to Use This Module

  • When network bandwidth, binary storage size, and serialization speed are critical.
  • For inter-service RPC, binary logs, and compact caching.

Worked Example

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeApplications #-}
{-# OPTIONS_GHC -fplugin=Polytropos.Plugin #-}

import Codec.Serialise (serialise, deserialise)
import Polytropos
import Polytropos.CBOR

-- A genuinely heterogeneous record:
type Packet = Record '["id" ':= Int, "payload" ':= String, "flags" ':= Word]

pkt :: Packet
pkt = REC { id = 101, payload = "sensor-ok", flags = 0 }

-- Serializes to compact positional CBOR binary:
bytes = serialise pkt

-- Deserializes back to Packet:
pkt' :: Packet
pkt' = deserialise bytes
Synopsis

Heterogeneous Row Codecs

class AllSerialise (r :: Row) where Source #

Evidence that every field of the row r has a Serialise instance at that field's own type. Serializes the erased payload slots in row order.

Methods

encRecordCBOR :: Proxy r -> [Identity (Any :: Type)] -> Encoding Source #

decRecordCBOR :: Proxy r -> Decoder s [Identity (Any :: Type)] Source #

Instances

Instances details
AllSerialise ('[] :: [Pair Symbol Type]) Source # 
Instance details

Defined in Polytropos.CBOR

Methods

encRecordCBOR :: Proxy ('[] :: [Pair Symbol Type]) -> [Identity (Any :: Type)] -> Encoding Source #

decRecordCBOR :: Proxy ('[] :: [Pair Symbol Type]) -> Decoder s [Identity (Any :: Type)] Source #

(Serialise a, AllSerialise r) => AllSerialise ((n ':= a) ': r) Source # 
Instance details

Defined in Polytropos.CBOR

Methods

encRecordCBOR :: Proxy ((n ':= a) ': r) -> [Identity (Any :: Type)] -> Encoding Source #

decRecordCBOR :: Proxy ((n ':= a) ': r) -> Decoder s [Identity (Any :: Type)] Source #

class FieldCount (r :: Row) where Source #

Computes the arity (field count) of a row at compile time.

Methods

fieldCount :: Proxy r -> Int Source #

Instances

Instances details
FieldCount ('[] :: [Pair Symbol Type]) Source # 
Instance details

Defined in Polytropos.CBOR

Methods

fieldCount :: Proxy ('[] :: [Pair Symbol Type]) -> Int Source #

FieldCount r => FieldCount ((n ':= a) ': r) Source # 
Instance details

Defined in Polytropos.CBOR

Methods

fieldCount :: Proxy ((n ':= a) ': r) -> Int Source #

class AllCtorsSerialise (s :: SumRow) where Source #

Evidence that every constructor of the sum row s has a heterogeneous field row satisfying AllSerialise, paired with its constructor tag index.

Methods

encVariantCBOR :: Proxy s -> Word -> Word -> [Identity (Any :: Type)] -> Encoding Source #

decVariantCBOR :: Proxy s -> Word -> Int -> Decoder t [Identity (Any :: Type)] Source #

Instances

Instances details
AllCtorsSerialise ('[] :: [Pair Symbol Row]) Source # 
Instance details

Defined in Polytropos.CBOR

Methods

encVariantCBOR :: Proxy ('[] :: [Pair Symbol Row]) -> Word -> Word -> [Identity (Any :: Type)] -> Encoding Source #

decVariantCBOR :: Proxy ('[] :: [Pair Symbol Row]) -> Word -> Int -> Decoder t [Identity (Any :: Type)] Source #

(FieldCount fs, AllSerialise fs, AllCtorsSerialise s) => AllCtorsSerialise ((c ':= fs) ': s) Source # 
Instance details

Defined in Polytropos.CBOR

Methods

encVariantCBOR :: Proxy ((c ':= fs) ': s) -> Word -> Word -> [Identity (Any :: Type)] -> Encoding Source #

decVariantCBOR :: Proxy ((c ':= fs) ': s) -> Word -> Int -> Decoder t [Identity (Any :: Type)] Source #

Homogeneity Evidence and Introspection Helpers

Homogeneity Evidence and Introspection Helpers

In addition to the primary heterogeneous codecs (AllSerialise, AllCtorsSerialise), this module provides closed type families and reflection classes for inspecting row metadata and enforcing uniform payload types.

type family AllFieldsAre a (r :: Row) where ... Source #

Evidence that every field of the row r has type a.

Equations

AllFieldsAre _1 ('[] :: [Pair Symbol Type]) = () 
AllFieldsAre a ((n ':= a) ': rest) = AllFieldsAre a rest 

class AllCtorsHom a (s :: SumRow) where Source #

Every constructor of the sum row s has a homogeneous field row of type a, reified as constructor names paired with their arities.

Methods

ctorArities :: Proxy a -> Proxy s -> [(String, Int)] Source #

Instances

Instances details
AllCtorsHom a ('[] :: [Pair Symbol Row]) Source # 
Instance details

Defined in Polytropos.CBOR

Methods

ctorArities :: Proxy a -> Proxy ('[] :: [Pair Symbol Row]) -> [(String, Int)] Source #

(KnownSymbol c, AllFieldsAre a fs, AllCtorsHom a s) => AllCtorsHom a ((c ':= fs) ': s) Source # 
Instance details

Defined in Polytropos.CBOR

Methods

ctorArities :: Proxy a -> Proxy ((c ':= fs) ': s) -> [(String, Int)] Source #

type family RowField (r :: Row) where ... Source #

The field type of a homogeneous row: the type of every field, Void for the empty row.

Equations

RowField ('[] :: [Pair Symbol Type]) = Void 
RowField ((n ':= a) ': rest) = a 

type family SumField (s :: SumRow) where ... Source #

The field type shared by every constructor of a sum row, Void for the empty sum.

Equations

SumField ('[] :: [Pair Symbol Row]) = Void 
SumField ((c ':= fs) ': s) = RowField fs 

Orphan instances

(FieldCount r, AllSerialise r) => Serialise (Record r) Source # 
Instance details

AllCtorsSerialise s => Serialise (Variant s) Source # 
Instance details