Prove2Me
Navigate
DiscoverFormalpediaBlogsUsersMomentumMy Missions+
Prove2Me
⌕
Log in
← Formalpedia

The free many-sorted algebra TΣ(X)\mathbf{T}_\Sigma(X)TΣ​(X)

Definition
MSKleene_Term

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

formal-languagesmany-sorted-algebratree-automatauniversal-algebra

The free Σ\SigmaΣ-algebra TΣ(X)\mathbf{T}_\Sigma(X)TΣ​(X) on an SSS-sorted set of variables XXX (Definitions 3.1, 3.2), represented by the mutual inductive Term / TermVec: a term is a variable var x or an operation symbol applied to a vector of subterms of the matching arity, app σ ts (a constant is app σ .nil).

The file provides the algebra structure freeAlgebra (carrier Term sig X, operations app), the insertion of generators eta (ηX\eta^XηX), the evaluation Term.eval of a term in an arbitrary Σ\SigmaΣ-algebra A under an assignment ρ : X → A, and the induced homomorphism evalHom with evalHom_eta : evalHom A ρ ∘ η^X = ρ. This is the existence half of the universal property of TΣ(X)\mathbf{T}_\Sigma(X)TΣ​(X) (Proposition 3.5).

Formalization Note TermVec sig X w is a heterogeneous list holding one subterm of sort w[i] per argument position; ofArgs / toArgs convert between it and the nested-product Args.

Definition code
/-
The free many-sorted `Σ`-algebra `T_Σ(X)` (Definitions 3.1, 3.2) as an
inductive family of terms, together with:
  * its `Algebra` structure (`freeAlgebra`);
  * the insertion of generators `η^X`;
  * evaluation of a term into any `Σ`-algebra under an assignment, and the
    induced homomorphism (the existence half of the universal property, Prop. 3.5).

Terms are represented by the mutual inductive `Term` / `TermVec`, the standard
encoding of many-sorted terms: `TermVec sig X w` is a heterogeneous list holding
one subterm of sort `w[i]` per argument position.
-/
import Definitions.Def_MSKleene_Core

namespace MSKleene

universe u

variable {S : Type u}

-- Many-sorted terms over signature `sig` with variables in `X`:
-- `var` injects a variable; `app` applies an operation symbol to a vector of
-- subterms of the matching arity (a constant is `app σ .nil`).
-- `TermVec sig X w` is a heterogeneous list holding one subterm of sort `w[i]`
-- per argument position.
mutual
inductive Term (sig : Signature S) (X : SSet S) : S → Type u where
  | var {s : S} : X s → Term sig X s
  | app {w : List S} {s : S} : sig w s → TermVec sig X w → Term sig X s
inductive TermVec (sig : Signature S) (X : SSet S) : List S → Type u where
  | nil : TermVec sig X []
  | cons {s : S} {w : List S} : Term sig X s → TermVec sig X w → TermVec sig X (s :: w)
end

/-- Convert an `Args` tuple of terms into a `TermVec`. -/
def TermVec.ofArgs {sig : Signature S} {X : SSet S} :
    {w : List S} → Args (Term sig X) w → TermVec sig X w
  | [], _ => .nil
  | _ :: _, (t, rest) => .cons t (TermVec.ofArgs rest)

/-- Convert a `TermVec` back into an `Args` tuple of terms. -/
def TermVec.toArgs {sig : Signature S} {X : SSet S} :
    {w : List S} → TermVec sig X w → Args (Term sig X) w
  | [], _ => PUnit.unit
  | _ :: _, .cons t rest => (t, TermVec.toArgs rest)

/-- The free `Σ`-algebra `T_Σ(X)`: carrier `Term sig X`, operations `app`
(Definition 3.2). -/
def freeAlgebra (sig : Signature S) (X : SSet S) : Algebra sig where
  carrier := Term sig X
  op := fun σ args => Term.app σ (TermVec.ofArgs args)

/-- Insertion of the generators, `η^X : X → T_Σ(X)` (Proposition 3.5). -/
def eta (sig : Signature S) (X : SSet S) : SMap X (freeAlgebra sig X).carrier :=
  fun _ x => Term.var x

-- Evaluate a term in the algebra `A` under the assignment `ρ : X → A`.
-- Together with `evalArgs` this is the unique-extension map of Proposition 3.5.
mutual
def Term.eval {sig : Signature S} {X : SSet S} (A : Algebra sig)
    (ρ : SMap X A.carrier) : {s : S} → Term sig X s → A.carrier s
  | _, .var x => ρ _ x
  | _, .app σ ts => A.op σ (TermVec.evalArgs A ρ ts)
def TermVec.evalArgs {sig : Signature S} {X : SSet S} (A : Algebra sig)
    (ρ : SMap X A.carrier) : {w : List S} → TermVec sig X w → Args A.carrier w
  | [], _ => PUnit.unit
  | _ :: _, .cons t ts => (Term.eval A ρ t, TermVec.evalArgs A ρ ts)
end

theorem TermVec.evalArgs_ofArgs {sig : Signature S} {X : SSet S} (A : Algebra sig)
    (ρ : SMap X A.carrier) :
    ∀ {w : List S} (args : Args (Term sig X) w),
      TermVec.evalArgs A ρ (TermVec.ofArgs args)
        = Args.map (fun s (t : Term sig X s) => Term.eval A ρ t) args
  | [], _ => rfl
  | _ :: _, (t, rest) => congrArg (Prod.mk (Term.eval A ρ t))
      (TermVec.evalArgs_ofArgs A ρ rest)

/-- The homomorphism `ρ^♯ : T_Σ(X) → A` induced by an assignment `ρ`
(the existence half of Proposition 3.5). -/
def evalHom {sig : Signature S} {X : SSet S} (A : Algebra sig)
    (ρ : SMap X A.carrier) : Hom (freeAlgebra sig X) A where
  toFun := fun _ t => Term.eval A ρ t
  map_op := by
    intro w s σ args
    show Term.eval A ρ (Term.app σ (TermVec.ofArgs args)) = _
    show A.op σ (TermVec.evalArgs A ρ (TermVec.ofArgs args)) = _
    exact congrArg (A.op σ) (TermVec.evalArgs_ofArgs A ρ args)

/-- `ρ^♯ ∘ η^X = ρ`: the induced homomorphism restricts to `ρ` on generators. -/
theorem evalHom_eta {sig : Signature S} {X : SSet S} (A : Algebra sig)
    (ρ : SMap X A.carrier) (s : S) (x : X s) :
    (evalHom A ρ).toFun s (eta sig X s x) = ρ s x := rfl

end MSKleene
Source
Gong, Ruiz Mora, Sanmartín Vich, Cosme Llópez, "A Kleene theorem for free many-sorted algebras", 2026, https://arxiv.org/abs/1808.08217 (predecessor CVCL20)
Read-back

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

Term and TermVec (mutually inductive families)

Throughout, SSS is an implicit type of sorts. Fixed as explicit parameters are a signature sigsigsig over SSS — a rule assigning to each pair consisting of a word w∈List Sw \in \mathrm{List}\,Sw∈ListS and a sort s∈Ss \in Ss∈S a type sig w ssig\,w\,ssigws, thought of as the operation symbols of argument profile www and result sort sss — and a sort-indexed family of variable types XXX, assigning to each sort sss a type XsX_sXs​. The declaration introduces, simultaneously, two inductive families valued in Type\mathrm{Type}Type:

  • Term sig X:S→Type\mathrm{Term}\,sig\,X : S \to \mathrm{Type}TermsigX:S→Type, where Term sig X s\mathrm{Term}\,sig\,X\,sTermsigXs is meant to be the terms of sort sss;
  • TermVec sig X:List S→Type\mathrm{TermVec}\,sig\,X : \mathrm{List}\,S \to \mathrm{Type}TermVecsigX:ListS→Type, where TermVec sig X w\mathrm{TermVec}\,sig\,X\,wTermVecsigXw is meant to be the finite sequences of terms whose sorts are exactly the entries of www, in order.

Term\mathrm{Term}Term has two constructors. The constructor var\mathrm{var}var takes an implicit sort sss and an element x:Xsx : X_sx:Xs​ and returns var x:Term sig X s\mathrm{var}\,x : \mathrm{Term}\,sig\,X\,svarx:TermsigXs. The constructor app\mathrm{app}app takes an implicit word www, an implicit sort sss, an operation symbol σ:sig w s\sigma : sig\,w\,sσ:sigws, and a term-vector ts:TermVec sig X wts : \mathrm{TermVec}\,sig\,X\,wts:TermVecsigXw, and returns app σ ts:Term sig X s\mathrm{app}\,\sigma\,ts : \mathrm{Term}\,sig\,X\,sappσts:TermsigXs. TermVec\mathrm{TermVec}TermVec has two constructors: nil:TermVec sig X [ ]\mathrm{nil} : \mathrm{TermVec}\,sig\,X\,[\,]nil:TermVecsigX[], and cons\mathrm{cons}cons, which takes an implicit sort sss, an implicit word www, a term t:Term sig X st : \mathrm{Term}\,sig\,X\,st:TermsigXs and a vector ts:TermVec sig X wts : \mathrm{TermVec}\,sig\,X\,wts:TermVecsigXw, and returns cons t ts:TermVec sig X (s::w)\mathrm{cons}\,t\,ts : \mathrm{TermVec}\,sig\,X\,(s :: w)constts:TermVecsigX(s::w), where s::ws :: ws::w is the list with head sss and tail www. Being inductive, Term sig X\mathrm{Term}\,sig\,XTermsigX and TermVec sig X\mathrm{TermVec}\,sig\,XTermVecsigX are the least families closed under these constructors: every element is built from finitely many applications of var\mathrm{var}var, app\mathrm{app}app, nil\mathrm{nil}nil, cons\mathrm{cons}cons. Nullary operation symbols σ:sig [ ] s\sigma : sig\,[\,]\,sσ:sig[]s give constant terms app σ nil\mathrm{app}\,\sigma\,\mathrm{nil}appσnil. No finiteness or decidability hypothesis is imposed on SSS, sigsigsig, or XXX; if some XsX_sXs​ is empty there are simply no var\mathrm{var}var-terms of that sort.

TermVec.ofArgs

For implicit sigsigsig, implicit XXX, and implicit word www, this defines a function

ofArgs:Args (Term sig X) w⟶TermVec sig X w.\mathrm{ofArgs} : \mathrm{Args}\,(\mathrm{Term}\,sig\,X)\,w \longrightarrow \mathrm{TermVec}\,sig\,X\,w .ofArgs:Args(TermsigX)w⟶TermVecsigXw.

Here Args B w\mathrm{Args}\,B\,wArgsBw is the iterated product type defined by recursion on www: Args B [ ]\mathrm{Args}\,B\,[\,]ArgsB[] is the one-element type PUnit\mathrm{PUnit}PUnit, and Args B (s::w)=Bs×Args B w\mathrm{Args}\,B\,(s :: w) = B_s \times \mathrm{Args}\,B\,wArgsB(s::w)=Bs​×ArgsBw; so Args (Term sig X) w\mathrm{Args}\,(\mathrm{Term}\,sig\,X)\,wArgs(TermsigX)w is a tuple holding one term for each sort listed in www (plus a trailing unit). The function is defined by recursion on www: on the empty word, the unique input is sent to nil\mathrm{nil}nil; on s::ws :: ws::w, an input which is a pair (t,rest)(t, \mathit{rest})(t,rest) with t:Term sig X st : \mathrm{Term}\,sig\,X\,st:TermsigXs and rest:Args (Term sig X) w\mathit{rest} : \mathrm{Args}\,(\mathrm{Term}\,sig\,X)\,wrest:Args(TermsigX)w is sent to cons t (ofArgs rest)\mathrm{cons}\,t\,(\mathrm{ofArgs}\,\mathit{rest})const(ofArgsrest).

TermVec.toArgs

For implicit sigsigsig, XXX, and www, this defines the reverse conversion

toArgs:TermVec sig X w⟶Args (Term sig X) w,\mathrm{toArgs} : \mathrm{TermVec}\,sig\,X\,w \longrightarrow \mathrm{Args}\,(\mathrm{Term}\,sig\,X)\,w ,toArgs:TermVecsigXw⟶Args(TermsigX)w,

by recursion on www: on the empty word it returns the unique element of PUnit\mathrm{PUnit}PUnit; on s::ws :: ws::w it matches an input of the form cons t rest\mathrm{cons}\,t\,\mathit{rest}constrest and returns the pair (t, toArgs rest)(t,\ \mathrm{toArgs}\,\mathit{rest})(t, toArgsrest).

freeAlgebra

Given explicit parameters sigsigsig and XXX, this produces an element of Algebra sig\mathrm{Algebra}\,sigAlgebrasig. An Algebra sig\mathrm{Algebra}\,sigAlgebrasig is a structure consisting of a carrier family ∣A∣:S→Type|A| : S \to \mathrm{Type}∣A∣:S→Type together with an operation map that, for implicit www and sss, takes an operation symbol σ:sig w s\sigma : sig\,w\,sσ:sigws and a tuple Args ∣A∣ w\mathrm{Args}\,|A|\,wArgs∣A∣w and returns an element of ∣A∣s|A|_s∣A∣s​. For freeAlgebra sig X\mathrm{freeAlgebra}\,sig\,XfreeAlgebrasigX the carrier family is Term sig X\mathrm{Term}\,sig\,XTermsigX itself, and the operation map sends σ:sig w s\sigma : sig\,w\,sσ:sigws and args:Args (Term sig X) wargs : \mathrm{Args}\,(\mathrm{Term}\,sig\,X)\,wargs:Args(TermsigX)w to the term app σ (ofArgs args):Term sig X s\mathrm{app}\,\sigma\,(\mathrm{ofArgs}\,args) : \mathrm{Term}\,sig\,X\,sappσ(ofArgsargs):TermsigXs.

eta

Given explicit parameters sigsigsig and XXX, this produces an element of SMap X (∣freeAlgebra sig X∣)\mathrm{SMap}\,X\,\big(|\mathrm{freeAlgebra}\,sig\,X|\big)SMapX(∣freeAlgebrasigX∣), that is, a family of functions ηs:Xs→Term sig X s\eta_s : X_s \to \mathrm{Term}\,sig\,X\,sηs​:Xs​→TermsigXs (one for each sort sss). The function ignores its sort argument in the sense that at every sort it is given by x↦var xx \mapsto \mathrm{var}\,xx↦varx.

Term.eval and TermVec.evalArgs (mutually recursive)

Fix implicit sigsigsig and XXX, an explicit algebra A:Algebra sigA : \mathrm{Algebra}\,sigA:Algebrasig, and an explicit assignment ρ:SMap X ∣A∣\rho : \mathrm{SMap}\,X\,|A|ρ:SMapX∣A∣, i.e. a family of functions ρs:Xs→∣A∣s\rho_s : X_s \to |A|_sρs​:Xs​→∣A∣s​. This mutually defines two total functions.

Term.eval A ρ\mathrm{Term.eval}\,A\,\rhoTerm.evalAρ takes an implicit sort sss and a term of Term sig X s\mathrm{Term}\,sig\,X\,sTermsigXs and returns an element of ∣A∣s|A|_s∣A∣s​, by structural recursion:

eval (var x)=ρs x,eval (app σ ts)=A.op σ (evalArgs A ρ ts).\mathrm{eval}\,(\mathrm{var}\,x) = \rho_s\,x, \qquad \mathrm{eval}\,(\mathrm{app}\,\sigma\,ts) = A.\mathrm{op}\,\sigma\,\big(\mathrm{evalArgs}\,A\,\rho\,ts\big).eval(varx)=ρs​x,eval(appσts)=A.opσ(evalArgsAρts).

TermVec.evalArgs A ρ\mathrm{TermVec.evalArgs}\,A\,\rhoTermVec.evalArgsAρ takes an implicit word www and a vector of TermVec sig X w\mathrm{TermVec}\,sig\,X\,wTermVecsigXw and returns an element of Args ∣A∣ w\mathrm{Args}\,|A|\,wArgs∣A∣w, by recursion on www: the empty vector is sent to the unique element of PUnit\mathrm{PUnit}PUnit; a vector cons t ts\mathrm{cons}\,t\,tsconstts is sent to the pair (Term.eval A ρ t, TermVec.evalArgs A ρ ts)\big(\mathrm{Term.eval}\,A\,\rho\,t,\ \mathrm{TermVec.evalArgs}\,A\,\rho\,ts\big)(Term.evalAρt, TermVec.evalArgsAρts).

TermVec.evalArgs_ofArgs

For all implicit sigsigsig and XXX, every algebra A:Algebra sigA : \mathrm{Algebra}\,sigA:Algebrasig, every assignment ρ:SMap X ∣A∣\rho : \mathrm{SMap}\,X\,|A|ρ:SMapX∣A∣, every implicit word w:List Sw : \mathrm{List}\,Sw:ListS, and every tuple args:Args (Term sig X) wargs : \mathrm{Args}\,(\mathrm{Term}\,sig\,X)\,wargs:Args(TermsigX)w, the following equality of elements of Args ∣A∣ w\mathrm{Args}\,|A|\,wArgs∣A∣w holds:

TermVec.evalArgs A ρ (TermVec.ofArgs args)  =  Args.map (λ s λ t. Term.eval A ρ t) args,\mathrm{TermVec.evalArgs}\,A\,\rho\,\big(\mathrm{TermVec.ofArgs}\,args\big) \;=\; \mathrm{Args.map}\,\big(\lambda\,s\ \lambda\,t.\ \mathrm{Term.eval}\,A\,\rho\,t\big)\,args ,TermVec.evalArgsAρ(TermVec.ofArgsargs)=Args.map(λs λt. Term.evalAρt)args,

where Args.map f\mathrm{Args.map}\,fArgs.mapf applies the sort-indexed function fff componentwise to every entry of a tuple. In words: converting argsargsargs into a term-vector and then evaluating that vector yields the same tuple as evaluating each component term of argsargsargs individually.

evalHom

For implicit sigsigsig and XXX, an explicit algebra A:Algebra sigA : \mathrm{Algebra}\,sigA:Algebrasig and an explicit assignment ρ:SMap X ∣A∣\rho : \mathrm{SMap}\,X\,|A|ρ:SMapX∣A∣, this produces an element of Hom (freeAlgebra sig X) A\mathrm{Hom}\,(\mathrm{freeAlgebra}\,sig\,X)\,AHom(freeAlgebrasigX)A. A Hom B C\mathrm{Hom}\,B\,CHomBC is a structure bundling a sorted map toFun:SMap ∣B∣ ∣C∣\mathrm{toFun} : \mathrm{SMap}\,|B|\,|C|toFun:SMap∣B∣∣C∣ together with a proof that it commutes with every operation. For evalHom A ρ\mathrm{evalHom}\,A\,\rhoevalHomAρ, the map toFun\mathrm{toFun}toFun is, at every sort, t↦Term.eval A ρ tt \mapsto \mathrm{Term.eval}\,A\,\rho\,tt↦Term.evalAρt, and the bundled proof asserts that for all implicit www, sss, every operation symbol σ:sig w s\sigma : sig\,w\,sσ:sigws and every args:Args (Term sig X) wargs : \mathrm{Args}\,(\mathrm{Term}\,sig\,X)\,wargs:Args(TermsigX)w,

Term.eval A ρ (app σ (ofArgs args))  =  A.op σ (Args.map (λ s λ t. Term.eval A ρ t) args),\mathrm{Term.eval}\,A\,\rho\,\big(\mathrm{app}\,\sigma\,(\mathrm{ofArgs}\,args)\big) \;=\; A.\mathrm{op}\,\sigma\,\big(\mathrm{Args.map}\,(\lambda\,s\ \lambda\,t.\ \mathrm{Term.eval}\,A\,\rho\,t)\,args\big),Term.evalAρ(appσ(ofArgsargs))=A.opσ(Args.map(λs λt. Term.evalAρt)args),

i.e. that applying the evaluation map to the free algebra's interpretation of σ\sigmaσ agrees with AAA's interpretation of σ\sigmaσ applied to the pointwise-evaluated arguments.

evalHom_eta

For all implicit sigsigsig and XXX, every algebra A:Algebra sigA : \mathrm{Algebra}\,sigA:Algebrasig, every assignment ρ:SMap X ∣A∣\rho : \mathrm{SMap}\,X\,|A|ρ:SMapX∣A∣, every sort s:Ss : Ss:S, and every variable x:Xsx : X_sx:Xs​, the following holds:

(evalHom A ρ).toFun s (eta sig X s x)  =  ρ s x.(\mathrm{evalHom}\,A\,\rho).\mathrm{toFun}\,s\,\big(\mathrm{eta}\,sig\,X\,s\,x\big) \;=\; \rho\,s\,x .(evalHomAρ).toFuns(etasigXsx)=ρsx.

Unfolding the definitions, eta sig X s x\mathrm{eta}\,sig\,X\,s\,xetasigXsx is var x\mathrm{var}\,xvarx and the underlying map of evalHom A ρ\mathrm{evalHom}\,A\,\rhoevalHomAρ is Term.eval A ρ\mathrm{Term.eval}\,A\,\rhoTerm.evalAρ, so this states Term.eval A ρ (var x)=ρs x\mathrm{Term.eval}\,A\,\rho\,(\mathrm{var}\,x) = \rho_s\,xTerm.evalAρ(varx)=ρs​x. It is asserted to hold by reflexivity, i.e. definitionally.

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