Skip to content

Add EchoAggregation module — Monoid + GroupAggregator carriers for SQL aggregation-as-fold (consumer: affinescript db-theory #3) #175

Closed

Description

@hyperpolymath

Context (consumer)

AffineScript ships db-theory #3 in the next PR — a new stdlib/Aggregate.affine module exposing SQL group-by + aggregation primitives (count / sum / min / max / avg) plus a db_group_by convenience returning the grouped result-set as JSON. The proof-relevant property is the classical aggregation-as-monoid-homomorphism claim (Green / Karvounarakis / Tannen, provenance semirings): each aggregator is a commutative monoid; group-by is the indexed sum.

Sibling to echo-types#174 (Transaction safety / no-section-of-collapsing-map).

Audit summary (2026-06-01)

Echo-types currently carries no reusable monoid/semiring infrastructure. The closest scaffolding:

  1. EchoCost.CostAlgebra — left-identity + monotonicity, no composition law. Reusable as a Monoid instance once Monoid exists.
  2. Ordinal/Brouwer/OmegaPow.agda#additive-principal — exactly the monoid closure property for ω^n exponents.
  3. EchoDecorationStructure.agda — observer-level lattice, not data-level algebra.

docs/adjacency/provenance-semirings.adoc already names the relevant distinctness story (echo adds types; semirings add scalars; this module bridges both).

Proposed module shape

module EchoAggregation where

open import Level using (Level; suc)
open import Relation.Binary.PropositionalEquality using (_≡_)

record Monoid (ℓ : Level) : Set (suc ℓ) where
  field
    Elem       : Set ℓ
    ε          : Elem
    _⊕_        : Elem → Elem → Elem
    assoc      : ∀ a b c → (a ⊕ b) ⊕ c ≡ a ⊕ (b ⊕ c)
    identity-l : ∀ a → ε ⊕ a ≡ a
    identity-r : ∀ a → a ⊕ ε ≡ a

-- A GroupAggregator over keys K, values V, monoid M is the data of:
--   an aggregator agg : V → M.Elem
--   that lifts to a fold over rows, indexed by their K-key.
record GroupAggregator {ℓ} (K V : Set) (M : Monoid ℓ) : Set ℓ where
  open Monoid M
  field
    agg : V → Elem
    -- Headline lemma (proof TBD upstream; consumer references):
    --   aggregation-as-fold :
    --     (rows : List (K × V)) →
    --     aggregate-by-key (partition rows by .fst)
    --       (λ vs → foldr (λ v acc → agg v ⊕ acc) ε vs)
    --   ≡  the actual SQL GROUP-BY semantics.

-- Concrete instances:
--   countMonoid  : Monoid ℓ-zero       (ℕ, 0, +)
--   sumMonoid    : Monoid ℓ-zero       (ℕ, 0, +)
--   minMonoid    : Monoid ℓ-zero       (ℕ ∪ {∞}, ∞, min)
--   maxMonoid    : Monoid ℓ-zero       (ℕ ∪ {-∞}, -∞, max)
--   -- avg is NOT a monoid (no identity); express as sum / count.

Why this matters

Cross-doc

  • Consumer cross-doc lands at affinescript/docs/academic/proofs/db-theory-3-aggregation-as-fold.md and back-links this issue.
  • Sibling: echo-types#174 (Transaction safety / no-section-of-collapsing-map).

Activity

  1. hyperpolymath commented on Jun 27, 2026

    @hyperpolymath
    OwnerAuthor

    The general monoid/group EchoAggregation has landed on main (proofs/agda/EchoAggregation.agda):

    • record Monoid (Elem/ε/_⊕_/assoc/identity-l/identity-r);
    • ⊕-fold + the ⊕-fold-++ fold-is-a-monoid-homomorphism law over _++_;
    • record GroupAggregator + aggregate-values + the proved aggregation-as-fold;
    • the four instances — sumMonoid / countMonoid / maxMonoid over ℕ and minMonoid over Maybe ℕ (nothing = ∞) — plus countAggregator;
    • the generic no-canonical-disaggregation-of (= no-section-of-collapsing-map);
    • module Example-PairSum (the macro ℕ×ℕ→ℕ reading as an instance — pairSum is the sumMonoid fold).

    Builds --safe --without-K, zero postulates; wired into All.agda, pinned in Smoke.agda, kernel-guard.sh PASS. All acceptance criteria are met (concrete instances + a proved aggregation-as-fold; avg correctly omitted as a non-monoid — express as sum / count).

    Honest scope: aggregation-as-fold is the fold's monoid-homomorphism law, not full SQL GROUP-BY operational semantics; no-canonical-disaggregation-of refutes a section (left inverse), not a representative choice.

    The sibling #174 is already closed (EchoTransaction). The executable EchoTypes.jl finite-domain mirror is tracked separately. Closing as completed.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions