---
layout: default
file: "src/Setoid/Signatures/Finite.lagda.md"
title: "Setoid.Signatures.Finite module (The Agda Universal Algebra Library)"
date: "2026-07-12"
author: "the agda-algebras development team"
---
### 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`{.AgdaRecord} `π`, the signature-side member of the library's
family of finiteness interfaces:
+ `FiniteSignature`{.AgdaRecord} (this module) β finiteness of the *signature*;
+ `FiniteAlgebra`{.AgdaRecord} ([Setoid.Algebras.Finite][]) β finiteness of the *carrier*;
+ `FiniteCongruences`{.AgdaRecord} ([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`{.AgdaRecord} 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`{.AgdaRecord}. 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`{.AgdaFunction} `π`
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`{.AgdaField} 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`{.AgdaFunction} `π`, 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`{.AgdaFunction}, an index map
`arIdx`{.AgdaFunction}, and the round-trip law `arEnum-arIdx`{.AgdaFunction} 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`{.AgdaFunction}
and for the unary signature `Sig-Unary`{.AgdaFunction} `A`.
<!--
```agda
{-# OPTIONS --cubical-compatible --exact-split --safe #-}
module Setoid.Signatures.Finite where
open import Agda.Primitive using () renaming ( Set to Type )
open import Data.Fin.Base using ( Fin )
open import Data.Nat.Base using ( β )
open import Data.Product using ( projβ ; projβ ; β-syntax )
open import Function.Bundles using ( Inverse )
open import Level using ( _β_ )
open import Relation.Binary.PropositionalEquality using ( _β‘_ )
open import Overture using ( π ; π₯ ; Signature
; OperationSymbolsOf ; ArityOf )
open import Setoid.Congruences.ChainJoin using ( Finitary )
```
-->
#### 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.
```agda
record FiniteSignature (π : Signature π π₯) : Type (π β π₯) where
field
opCard : β
opEnum : Fin opCard β OperationSymbolsOf π
opEnum-sur : (f : OperationSymbolsOf π) β β[ i ] opEnum i β‘ f
finitary : Finitary π
```
The derived accessors: `arCard f`{.AgdaFunction} is the arity of `f` as a natural
number, `arEnum f`{.AgdaFunction} enumerates the positions of `f`'s argument
tuples, `arIdx f`{.AgdaFunction} is the inverse index map, and
`arEnum-arIdx`{.AgdaFunction} 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.
```agda
arCard : OperationSymbolsOf π β β
arCard f = projβ (finitary f)
arIdx : (f : OperationSymbolsOf π) β ArityOf π f β Fin (arCard f)
arIdx f = Inverse.to (projβ (finitary f))
arEnum : (f : OperationSymbolsOf π) β Fin (arCard f) β ArityOf π f
arEnum f = Inverse.from (projβ (finitary f))
arEnum-arIdx : (f : OperationSymbolsOf π)(a : ArityOf π f) β arEnum f (arIdx f a) β‘ a
arEnum-arIdx f = Inverse.strictlyInverseΚ³ (projβ (finitary f))
```
--------------------------------------