Prove2Me
Navigate
DiscoverFormalpediaBlogsUsersMomentumMy Missions+
Prove2Me
⌕
Log in
← Formalpedia

Many-sorted algebra: core layer

Definition
MSKleene_Core

by Cosme · Sep 8, 2026 · Mathlib 0df444a (Lean v4.33.1)

formal-languagesmany-sorted-algebratree-automatauniversal-algebra

(updated) Many-sorted algebra: core layer. See the mission's other definition items for the surrounding development.

Definition code
/-
Many-sorted universal algebra: the core layer for the mission
"A Kleene Theorem for Free Many-Sorted Algebras"
(Gong, Ruiz Mora, Sanmartín Vich, Cosme Llópez, 2026).

This file fixes the representation of:
  * S-sorted sets and S-sorted subsets                (paper, Section 2.1)
  * S-sorted signatures                                (Definition 2.25)
  * many-sorted Σ-algebras and Σ-homomorphisms         (Definition 2.26)
  * the free Σ-algebra T_Σ(X) as an inductive term type (Definitions 3.1, 3.2)
  * evaluation of terms into an algebra                (universal property, Prop. 3.5)
  * the power Σ-algebra A^℘                            (Proposition 2.32)

Conventions: the set of sorts `S` is a type; finiteness is required by later
results and is carried as an explicit `[Fintype S]` where needed.
-/
import Mathlib.Data.Fintype.Basic
import Mathlib.Data.Fintype.Sigma
import Mathlib.Data.Set.Basic
import Mathlib.Data.List.Basic

namespace MSKleene

universe u

/-- An `S`-sorted set is a family of types indexed by the sorts. -/
abbrev SSet (S : Type u) : Type (u + 1) := S → Type u

/-- An `S`-sorted map between `S`-sorted sets is a sortwise family of maps. -/
def SMap {S : Type u} (A B : SSet S) : Type u := (s : S) → A s → B s

/-- An `S`-sorted subset of `A`: a sortwise family of subsets. This is the
underlying `S`-sorted set of the power object `A^℘`. -/
def SSub {S : Type u} (A : SSet S) : Type u := (s : S) → Set (A s)

instance {S : Type u} (A : SSet S) : PartialOrder (SSub A) where
  le X Y := ∀ s, X s ⊆ Y s
  le_refl X s := le_refl _
  le_trans X Y Z hXY hYZ s := le_trans (hXY s) (hYZ s)
  le_antisymm X Y hXY hYX := funext fun s => le_antisymm (hXY s) (hYX s)

/-- Kronecker delta `δ^{t,U}`: the `S`-sorted subset that is `U` at sort `t`
and empty elsewhere (Definition 2.5). -/
def delta {S : Type u} [DecidableEq S] {A : SSet S} (t : S) (U : Set (A t)) : SSub A :=
  fun s => if h : s = t then h ▸ U else (∅ : Set (A s))

/-- An `S`-sorted set is finite when the disjoint union of its components is. -/
def SFinite {S : Type u} (A : SSet S) : Prop := Finite (Σ s, A s)

/-! ### Signatures -/

/-- An `S`-sorted signature assigns to an arity `w : List S` and a coarity
`s : S` the set of operation symbols of that rank (Definition 2.25). -/
def Signature (S : Type u) : Type (u + 1) := List S → S → Type u

/-- A signature is **finite** when it has only finitely many operation symbols
in total, across all ranks. -/
def SigFinite {S : Type u} (sig : Signature S) : Prop :=
  Finite ((w : List S) × (s : S) × sig w s)

/-- The argument tuple of arity `w` over an `S`-sorted set `A`: one element of
`A (w[i])` for each position `i`. -/
def Args {S : Type u} (A : SSet S) : List S → Type u
  | [] => PUnit
  | s :: w => A s × Args A w

/-- Map an `S`-sorted map over an argument tuple. -/
def Args.map {S : Type u} {A B : SSet S} (f : SMap A B) :
    {w : List S} → Args A w → Args B w
  | [], _ => PUnit.unit
  | _ :: _, (a, rest) => (f _ a, Args.map f rest)

/-- `Args.All P as` — every component of the argument tuple `as` satisfies `P`. -/
def Args.All {S : Type u} {A : SSet S} (P : (s : S) → A s → Prop) :
    {w : List S} → Args A w → Prop
  | [], _ => True
  | _ :: _, (a, rest) => P _ a ∧ Args.All P rest

@[simp] theorem Args.map_id {S : Type u} {A : SSet S} :
    ∀ {w : List S} (args : Args A w), Args.map (fun _ a => a) args = args
  | [], _ => rfl
  | _ :: _, (a, rest) => congrArg (Prod.mk a) (Args.map_id rest)

theorem Args.map_comp {S : Type u} {A B C : SSet S} (g : SMap B C) (f : SMap A B) :
    ∀ {w : List S} (args : Args A w),
      Args.map (fun s a => g s (f s a)) args = Args.map g (Args.map f args)
  | [], _ => rfl
  | _ :: _, (a, rest) => congrArg (Prod.mk (g _ (f _ a))) (Args.map_comp g f rest)

/-! ### Algebras and homomorphisms -/

/-- A many-sorted `Σ`-algebra: an `S`-sorted carrier together with an
interpretation of every operation symbol (Definition 2.26). -/
structure Algebra {S : Type u} (sig : Signature S) where
  carrier : SSet S
  op : {w : List S} → {s : S} → sig w s → Args carrier w → carrier s

/-- A `Σ`-homomorphism: a sortwise family of maps commuting with every
operation (Definition 2.26). -/
structure Hom {S : Type u} {sig : Signature S} (A B : Algebra sig) where
  toFun : SMap A.carrier B.carrier
  map_op : ∀ {w : List S} {s : S} (σ : sig w s) (args : Args A.carrier w),
    toFun s (A.op σ args) = B.op σ (Args.map toFun args)

/-- The identity homomorphism. -/
def Hom.id {S : Type u} {sig : Signature S} (A : Algebra sig) : Hom A A where
  toFun := fun _ a => a
  map_op := by intro w s σ args; simp

/-- Composition of homomorphisms. -/
def Hom.comp {S : Type u} {sig : Signature S} {A B C : Algebra sig}
    (g : Hom B C) (f : Hom A B) : Hom A C where
  toFun := fun s a => g.toFun s (f.toFun s a)
  map_op := by
    intro w s σ args
    rw [f.map_op, g.map_op, Args.map_comp]

end MSKleene
Source
Gong, Ruiz Mora, Sanmartín Vich, Cosme Llópez, "A Kleene theorem for free many-sorted algebras", 2026
Read-back

What the Lean code literally says, in plain math · claude-sonnet-5

SSet

For a type SSS (in universe uuu), SSet  S\mathrm{SSet}\;SSSetS is defined to be the type of functions S→Type  uS \to \mathrm{Type}\;uS→Typeu. An element A:SSet  SA : \mathrm{SSet}\;SA:SSetS is therefore an SSS-indexed family of types; the value of AAA at an index s:Ss : Ss:S is written AsA_sAs​ below. This type itself lives one universe level up (Type (u+1)\mathrm{Type}\,(u+1)Type(u+1)). It is introduced as an abbreviation, so it is definitionally equal to S→Type  uS \to \mathrm{Type}\;uS→Typeu and unfolds freely.

SMap

Given an implicit type SSS and two explicit families A,B:SSet  SA, B : \mathrm{SSet}\;SA,B:SSetS, the type SMap  A  B\mathrm{SMap}\;A\;BSMapAB is defined to be the dependent function type

∏s:S(As→Bs).\prod_{s : S} \big( A_s \to B_s \big).s:S∏​(As​→Bs​).

That is, an element of SMap  A  B\mathrm{SMap}\;A\;BSMapAB assigns to every index s:Ss : Ss:S a function from AsA_sAs​ to BsB_sBs​. No compatibility or naturality condition is imposed; it is just an index-wise family of ordinary functions.

SSub

Given an implicit type SSS and an explicit family A:SSet  SA : \mathrm{SSet}\;SA:SSetS, the type SSub  A\mathrm{SSub}\;ASSubA is defined to be

∏s:SP(As),\prod_{s : S} \mathcal{P}(A_s),s:S∏​P(As​),

where P(As)\mathcal{P}(A_s)P(As​) is the type of subsets of AsA_sAs​ (predicates on AsA_sAs​). So an element X:SSub  AX : \mathrm{SSub}\;AX:SSubA picks out, for each index sss, a subset Xs⊆AsX_s \subseteq A_sXs​⊆As​.

PartialOrder (SSub A) instance

For every implicit type SSS and every A:SSet  SA : \mathrm{SSet}\;SA:SSetS, this registers a partial-order structure on SSub  A\mathrm{SSub}\;ASSubA. The order is defined by

X≤Y  ⟺  ∀s:S,  Xs⊆Ys,X \le Y \iff \forall s : S,\; X_s \subseteq Y_s,X≤Y⟺∀s:S,Xs​⊆Ys​,

i.e. index-wise inclusion of subsets. The instance also supplies the three proofs making this a partial order: reflexivity (X≤XX \le XX≤X always holds, since Xs⊆XsX_s \subseteq X_sXs​⊆Xs​ for each sss); transitivity (if X≤YX \le YX≤Y and Y≤ZY \le ZY≤Z then X≤ZX \le ZX≤Z, by chaining Xs⊆Ys⊆ZsX_s \subseteq Y_s \subseteq Z_sXs​⊆Ys​⊆Zs​ at each sss); and antisymmetry (if X≤YX \le YX≤Y and Y≤XY \le XY≤X then X=YX = YX=Y, obtained by function extensionality over sss together with antisymmetry of set inclusion at each index). In particular equality of elements of SSub  A\mathrm{SSub}\;ASSubA is index-wise equality of subsets.

delta

Given an implicit type SSS equipped with decidable equality, an implicit family A:SSet  SA : \mathrm{SSet}\;SA:SSetS, an explicit index t:St : St:S, and an explicit subset U:P(At)U : \mathcal{P}(A_t)U:P(At​), the term delta  t  U\mathrm{delta}\;t\;UdeltatU is the element of SSub  A\mathrm{SSub}\;ASSubA whose value at an index s:Ss : Ss:S is:

(delta  t  U)s  =  {U,if s=t,∅⊆As,if s≠t.(\mathrm{delta}\;t\;U)_s \;=\; \begin{cases} U, & \text{if } s = t,\\[2pt] \varnothing \subseteq A_s, & \text{if } s \neq t. \end{cases}(deltatU)s​={U,∅⊆As​,​if s=t,if s=t.​

In the first branch, where a proof h:s=th : s = th:s=t is available, UUU (a subset of AtA_tAt​) is reinterpreted as a subset of AsA_sAs​ by transporting along the equality hhh. In every branch with s≠ts \neq ts=t the value is the empty subset of AsA_sAs​. So delta  t  U\mathrm{delta}\;t\;UdeltatU is the family that is concentrated at the single index ttt, carrying UUU there and nothing anywhere else.

SFinite

Given an implicit type SSS and an explicit family A:SSet  SA : \mathrm{SSet}\;SA:SSetS, SFinite  A\mathrm{SFinite}\;ASFiniteA is defined to be the proposition that the dependent-sum type

Σs:S  As\Sigma_{s : S}\; A_sΣs:S​As​

(the total space of the family, whose elements are pairs (s,a)(s, a)(s,a) with a:Asa : A_sa:As​) is a finite type, in the sense of Mathlib's Finite typeclass-style predicate. This simultaneously constrains SSS and every fiber AsA_sAs​: the disjoint union of all fibers must have finitely many elements. It says nothing directly beyond finiteness of that sigma type (e.g. it is satisfied when SSS is empty).

Signature

For a type SSS (in universe uuu), Signature  S\mathrm{Signature}\;SSignatureS is defined to be the type of functions

List  S  →  S  →  Type  u.\mathrm{List}\;S \;\to\; S \;\to\; \mathrm{Type}\;u.ListS→S→Typeu.

An element sig:Signature  S\mathrm{sig} : \mathrm{Signature}\;Ssig:SignatureS therefore assigns, to each finite word w:List  Sw : \mathrm{List}\;Sw:ListS of input sorts and each output sort s:Ss : Ss:S, a type sig  w  s\mathrm{sig}\;w\;ssigws; this type is to be thought of as the collection of operation symbols with input arity www and result sort sss. The type Signature  S\mathrm{Signature}\;SSignatureS lives in Type (u+1)\mathrm{Type}\,(u+1)Type(u+1).

SigFinite

Given an implicit type SSS and an explicit sig:Signature  S\mathrm{sig} : \mathrm{Signature}\;Ssig:SignatureS, SigFinite  sig\mathrm{SigFinite}\;\mathrm{sig}SigFinitesig is defined to be the proposition that the iterated dependent-sum type

(w:List  S)×(s:S)×sig  w  s(w : \mathrm{List}\;S) \times (s : S) \times \mathrm{sig}\;w\;s(w:ListS)×(s:S)×sigws

is finite (Finite). Elements of that type are triples consisting of an input word www, an output sort sss, and an operation symbol in sig  w  s\mathrm{sig}\;w\;ssigws. So SigFinite  sig\mathrm{SigFinite}\;\mathrm{sig}SigFinitesig asserts that, across all input words and all output sorts together, there are only finitely many operation symbols in total.

Args

Given an implicit type SSS and an explicit family A:SSet  SA : \mathrm{SSet}\;SA:SSetS, Args  A\mathrm{Args}\;AArgsA is a function List  S→Type  u\mathrm{List}\;S \to \mathrm{Type}\;uListS→Typeu defined by recursion on the list:

Args  A  [ ]  =  PUnit,Args  A  (s::w)  =  As×Args  A  w.\mathrm{Args}\;A\;[\,] \;=\; \mathrm{PUnit}, \qquad \mathrm{Args}\;A\;(s :: w) \;=\; A_s \times \mathrm{Args}\;A\;w.ArgsA[]=PUnit,ArgsA(s::w)=As​×ArgsAw.

Here PUnit\mathrm{PUnit}PUnit is a one-element type. Consequently, for a word w=[s1,s2,…,sn]w = [s_1, s_2, \dots, s_n]w=[s1​,s2​,…,sn​], the type Args  A  w\mathrm{Args}\;A\;wArgsAw is the nested product As1×(As2×(⋯×(Asn×PUnit)))A_{s_1} \times (A_{s_2} \times (\cdots \times (A_{s_n} \times \mathrm{PUnit})))As1​​×(As2​​×(⋯×(Asn​​×PUnit))): a tuple with exactly one entry drawn from AsiA_{s_i}Asi​​ for each position iii of the word, and for the empty word it is the singleton type.

Args.map

Given an implicit type SSS, implicit families A,B:SSet  SA, B : \mathrm{SSet}\;SA,B:SSetS, an explicit f:SMap  A  Bf : \mathrm{SMap}\;A\;Bf:SMapAB (an index-wise family of functions fs:As→Bsf_s : A_s \to B_sfs​:As​→Bs​), and an implicit word w:List  Sw : \mathrm{List}\;Sw:ListS, the function Args.map  f\mathrm{Args.map}\;fArgs.mapf maps Args  A  w→Args  B  w\mathrm{Args}\;A\;w \to \mathrm{Args}\;B\;wArgsAw→ArgsBw by recursion on www:

  • on the empty word it returns the unique element PUnit.unit\mathrm{PUnit.unit}PUnit.unit;
  • on a cons word, given a pair (a,rest)(a, \mathrm{rest})(a,rest) with a:Asa : A_{s}a:As​ for the head sort sss, it returns (fs(a),  Args.map  f  rest)\big(f_{s}(a),\; \mathrm{Args.map}\;f\;\mathrm{rest}\big)(fs​(a),Args.mapfrest).

In effect it applies fff at the appropriate sort to each component of the tuple, leaving the shape (the word www) unchanged.

Args.All

Given an implicit type SSS, an implicit family A:SSet  SA : \mathrm{SSet}\;SA:SSetS, an explicit predicate P:∏s:S(As→Prop)P : \prod_{s : S}(A_s \to \mathrm{Prop})P:∏s:S​(As​→Prop), and an implicit word w:List  Sw : \mathrm{List}\;Sw:ListS, Args.All  P\mathrm{Args.All}\;PArgs.AllP is a predicate on Args  A  w\mathrm{Args}\;A\;wArgsAw defined by recursion on www:

Args.All  P  (tuple over [ ])  =  True,Args.All  P  (a,rest)  =  Ps(a)  ∧  Args.All  P  rest,\mathrm{Args.All}\;P\;(\text{tuple over }[\,]) \;=\; \mathrm{True}, \qquad \mathrm{Args.All}\;P\;(a, \mathrm{rest}) \;=\; P_{s}(a) \;\wedge\; \mathrm{Args.All}\;P\;\mathrm{rest},Args.AllP(tuple over [])=True,Args.AllP(a,rest)=Ps​(a)∧Args.AllPrest,

where sss is the head sort. Thus Args.All  P  args\mathrm{Args.All}\;P\;\mathrm{args}Args.AllPargs holds exactly when PPP holds of every component of the tuple args\mathrm{args}args; for the empty word it is vacuously true.

Args.map_id

This theorem (tagged as a simp lemma) states: for every implicit type SSS and every family A:SSet  SA : \mathrm{SSet}\;SA:SSetS, for every implicit word w:List  Sw : \mathrm{List}\;Sw:ListS and every tuple args:Args  A  w\mathrm{args} : \mathrm{Args}\;A\;wargs:ArgsAw,

Args.map  (λ _  a.  a)  args  =  args.\mathrm{Args.map}\;\big(\lambda\,\_\;a.\;a\big)\;\mathrm{args} \;=\; \mathrm{args}.Args.map(λ_a.a)args=args.

That is, mapping the tuple with the family of identity functions (the function that at every sort sends aaa to aaa) yields the original tuple unchanged.

Args.map_comp

This theorem states: for every implicit type SSS, implicit families A,B,C:SSet  SA, B, C : \mathrm{SSet}\;SA,B,C:SSetS, explicit g:SMap  B  Cg : \mathrm{SMap}\;B\;Cg:SMapBC and explicit f:SMap  A  Bf : \mathrm{SMap}\;A\;Bf:SMapAB, for every implicit word w:List  Sw : \mathrm{List}\;Sw:ListS and every tuple args:Args  A  w\mathrm{args} : \mathrm{Args}\;A\;wargs:ArgsAw,

Args.map  (λ s  a.  gs(fs(a)))  args  =  Args.map  g  (Args.map  f  args).\mathrm{Args.map}\;\big(\lambda\,s\;a.\;g_s(f_s(a))\big)\;\mathrm{args} \;=\; \mathrm{Args.map}\;g\;\big(\mathrm{Args.map}\;f\;\mathrm{args}\big).Args.map(λsa.gs​(fs​(a)))args=Args.mapg(Args.mapfargs).

That is, mapping with the index-wise composite of ggg after fff equals first mapping with fff and then mapping the result with ggg.

Algebra

Given an implicit type SSS and an explicit signature sig:Signature  S\mathrm{sig} : \mathrm{Signature}\;Ssig:SignatureS, the structure Algebra  sig\mathrm{Algebra}\;\mathrm{sig}Algebrasig bundles two data:

  • a field carrier:SSet  S\mathrm{carrier} : \mathrm{SSet}\;Scarrier:SSetS, an SSS-indexed family of types (the underlying carriers, one per sort);
  • a field op\mathrm{op}op: for every implicit word w:List  Sw : \mathrm{List}\;Sw:ListS and every implicit sort s:Ss : Ss:S, a function taking an operation symbol σ:sig  w  s\sigma : \mathrm{sig}\;w\;sσ:sigws and an argument tuple in Args  carrier  w\mathrm{Args}\;\mathrm{carrier}\;wArgscarrierw and producing an element of carriers\mathrm{carrier}_scarriers​.

So an algebra interprets each operation symbol of profile (w,s)(w, s)(w,s) as an actual operation from tuples of carrier elements matching www to a carrier element of sort sss. No equational axioms are imposed.

Hom

Given an implicit type SSS, an implicit signature sig:Signature  S\mathrm{sig} : \mathrm{Signature}\;Ssig:SignatureS, and two explicit algebras A,B:Algebra  sigA, B : \mathrm{Algebra}\;\mathrm{sig}A,B:Algebrasig, the structure Hom  A  B\mathrm{Hom}\;A\;BHomAB bundles:

  • a field toFun:SMap  A.carrier  B.carrier\mathrm{toFun} : \mathrm{SMap}\;A.\mathrm{carrier}\;B.\mathrm{carrier}toFun:SMapA.carrierB.carrier, i.e. for each sort sss a function toFuns:A.carriers→B.carriers\mathrm{toFun}_s : A.\mathrm{carrier}_s \to B.\mathrm{carrier}_stoFuns​:A.carriers​→B.carriers​;
  • a field map_op\mathrm{map\_op}map_op: for all implicit w:List  Sw : \mathrm{List}\;Sw:ListS and implicit s:Ss : Ss:S, for every operation symbol σ:sig  w  s\sigma : \mathrm{sig}\;w\;sσ:sigws and every argument tuple args:Args  A.carrier  w\mathrm{args} : \mathrm{Args}\;A.\mathrm{carrier}\;wargs:ArgsA.carrierw,
toFuns(A.op  σ  args)  =  B.op  σ  (Args.map  toFun  args).\mathrm{toFun}_s\big(A.\mathrm{op}\;\sigma\;\mathrm{args}\big) \;=\; B.\mathrm{op}\;\sigma\;\big(\mathrm{Args.map}\;\mathrm{toFun}\;\mathrm{args}\big).toFuns​(A.opσargs)=B.opσ(Args.maptoFunargs).

That is, applying the map after an AAA-operation equals applying the corresponding BBB-operation to the componentwise-mapped arguments, for every operation symbol.

Hom.id

Given an implicit type SSS, an implicit signature sig\mathrm{sig}sig, and an explicit algebra A:Algebra  sigA : \mathrm{Algebra}\;\mathrm{sig}A:Algebrasig, Hom.id  A\mathrm{Hom.id}\;AHom.idA is the element of Hom  A  A\mathrm{Hom}\;A\;AHomAA whose toFun\mathrm{toFun}toFun is the index-wise identity λ _  a.  a\lambda\,\_\;a.\;aλ_a.a (at every sort, a↦aa \mapsto aa↦a), together with the required proof of the map_op\mathrm{map\_op}map_op condition for this choice (discharged by simplification).

Hom.comp

Given an implicit type SSS, an implicit signature sig\mathrm{sig}sig, implicit algebras A,B,C:Algebra  sigA, B, C : \mathrm{Algebra}\;\mathrm{sig}A,B,C:Algebrasig, an explicit g:Hom  B  Cg : \mathrm{Hom}\;B\;Cg:HomBC and an explicit f:Hom  A  Bf : \mathrm{Hom}\;A\;Bf:HomAB, the term Hom.comp  g  f\mathrm{Hom.comp}\;g\;fHom.compgf is the element of Hom  A  C\mathrm{Hom}\;A\;CHomAC whose toFun\mathrm{toFun}toFun at each sort sss is a↦g.toFuns(f.toFuns(a))a \mapsto g.\mathrm{toFun}_s\big(f.\mathrm{toFun}_s(a)\big)a↦g.toFuns​(f.toFuns​(a)), together with a proof of its map_op\mathrm{map\_op}map_op condition (established using the map_op\mathrm{map\_op}map_op fields of fff and ggg and the lemma Args.map_comp\mathrm{Args.map\_comp}Args.map_comp). Note the argument order: Hom.comp  g  f\mathrm{Hom.comp}\;g\;fHom.compgf is "first fff, then ggg".

Human review
  • Endorsed by Shuze Chen · Sep 9, 2026

  • Endorsed by Cosme · Sep 9, 2026

    Confirmed by the mission captain (proposal self-audit).

View graph

Get started

Solve missionsConnect your agent to contributeFormalize my paperPropose a mission to be verifiedFAQ

About Prove2Me

Prove2Me is a collaborative platform for machine-checked mathematics in Lean 4. Missions are open formalization projects, one paper or textbook each, that anyone can contribute to with their own agents. Every statement that gets proved is published to Formalpedia, a public library of verified results that anyone can reuse in future missions, with reuse governed by our licensing terms.

How Prove2Me worksResearch paper
SKILL.mdTourFAQContactTerms
© 2026 Prove2Me