Setoid.Signatures.Finite¶
Finite finitary signatures¶
This is the Setoid.Signatures.Finite module of the Agda Universal Algebra Library.
A finite finitary signature has a finite type of operation symbols, each of
finite arity. This module packages that notion as the record
FiniteSignature π, the signature-side member of the library's
family of finiteness interfaces:
FiniteSignature(this module) β finiteness of the signature;FiniteAlgebra(Setoid.Algebras.Finite) β finiteness of the carrier;FiniteCongruences(Setoid.Congruences.Finite) β finite enumerability of the congruence lattice.
The three are logically independent and are kept as separate records so that each
consumer can demand exactly the finiteness it uses. The first consumer of
FiniteSignature is the congruence-closure computation of
Setoid.Congruences.Presented.Decidable, which needs to search all operation
symbols and all arity-tuples of carrier indices; by contrast, the reconstruction
theorem of Setoid.Congruences.Presented needs only carrier finiteness, which is
why signature finiteness is not a field of FiniteAlgebra. This
packaging β a standalone record parameterized by the signature, rather than extra
fields on an algebra-level record β resolves audit A3 of the two-layer congruence
discipline (see docs/adr/008-two-layer-congruence-discipline.md and Β§ 3β4 of
docs/notes/flrp-two-layer-congruences.md).
Why this module lives here¶
The notion is signature-level β no algebra and no setoid occurs in it β so the
natural candidates for its home are Overture.Signatures, where bare signatures
live, and this signature-generic corner of the Setoid/ tree. The deciding
constraint is the one-canonical-form rule: the library already has a canonical
statement that every arity of π is finite, namely Finitary π
of Setoid.Congruences.ChainJoin (introduced there for the finitary JΓ³nsson
theorem), and this record must reuse it rather than restate it. An Overture
module cannot import from the Setoid/ tree, so the record lands here, in
Setoid.Signatures's namespace β the Setoid/ tree's home for signature-generic
material β as a module with no {π : Signature π π₯} parameter, for the same
reason as its parent: both the record and its fields take the signature as an
explicit argument and read no ambient signature.
Design of the operation-symbol half¶
Mirroring the carrier interface of Setoid.Algebras.Finite, the enumeration of
operation symbols is surjective, not bijective: a map Fin opCard β
OperationSymbolsOf π hitting every symbol is exactly what a proof needs in order
to search the symbols, and demanding injectivity would burden every instance with
distinctness proofs that no consumer uses, so opCard is an upper
bound on, not the exact size of, the symbol count. Unlike the carrier case there
is no setoid in play: the symbol type is a bare type, so surjectivity is stated up
to propositional equality _β‘_, and no decidable-equality field is included β
consumers iterate over the enumeration and never compare two symbols.
The arity half is the existing Finitary π, i.e. a bijection
ArityOf π f β Fin k for each symbol f. For the finitary signatures of
ordinary universal algebra this witness is a one-liner per symbol shape (see
Examples.Setoid.FinitarySignatures); the derived accessors below repackage the
bijection as an enumeration arEnum, an index map
arIdx, and the round-trip law arEnum-arIdx that
downstream proofs use to pass between arity-tuples and vectors of indices.
Instances live downstream, where concrete signatures do:
Classical.Signatures.Finite provides witnesses for Sig-Lattice
and for the unary signature Sig-Unary A.
The record¶
A finite finitary signature is a signature together with a finite surjective enumeration of its operation symbols and, for each symbol, a bijection between its arity type and a finite index type.
record FiniteSignature (π : Signature π π₯) : Type (π β π₯) where field opCard : β opEnum : Fin opCard β OperationSymbolsOf π -- finite symbol enumeration opEnum-sur : (f : OperationSymbolsOf π) β β[ i ] opEnum i β‘ f finitary : Finitary π -- each arity is finite
The derived accessors: arCard f is the arity of f as a natural
number, arEnum f enumerates the positions of f's argument
tuples, arIdx f is the inverse index map, and
arEnum-arIdx is the round trip on the arity side, which is the
direction needed to reconstruct an arbitrary arity-tuple from its vector of
values on the enumeration.
-- The (upper bound on the) number of argument positions of f. arCard : OperationSymbolsOf π β β arCard f = projβ (finitary f) -- The index of an argument position of f. arIdx : (f : OperationSymbolsOf π) β ArityOf π f β Fin (arCard f) arIdx f = Inverse.to (projβ (finitary f)) -- The argument position of f at a given index. arEnum : (f : OperationSymbolsOf π) β Fin (arCard f) β ArityOf π f arEnum f = Inverse.from (projβ (finitary f)) -- Round trip: recovering a position from its index is the identity. arEnum-arIdx : (f : OperationSymbolsOf π)(a : ArityOf π f) β arEnum f (arIdx f a) β‘ a arEnum-arIdx f = Inverse.strictlyInverseΚ³ (projβ (finitary f))