Imports
/-
Copyright (c) 2026 Terence Rokop. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Terence Rokop
-/
moduleFinite-category specifications
A client specifies a finite category by a count of objects, a count of
non-identity morphisms at each pair of objects, a composition function
on those morphisms, and a Bool equation asserting associativity. The
identities are not the client's to supply: one is reserved at the index
one past the client's range in each endo-hom, so the identity laws hold
of the reserved index by construction and only associativity is
checked.
Main definitions
CategoryTheory.FinCat — the specification type.
CategoryTheory.FinCat.homCountOf, CategoryTheory.FinCat.homCount
— the hom-count including the reserved identity.
CategoryTheory.FinCat.Mor, CategoryTheory.FinCat.emb,
CategoryTheory.FinCat.id — the full hom type, the embedding of a
client morphism, and the reserved identity.
CategoryTheory.FinCat.compTotalOf,
CategoryTheory.FinCat.compTotal — composition on the full hom
types.
CategoryTheory.FinCat.assocCheckOf,
CategoryTheory.FinCat.assocCheck — the decidable associativity
check on triples of client morphisms.
Main statements
FinCat.id_comp, FinCat.comp_id — the identity laws, at variable
indices.
FinCat.assocCheck_eq_true_iff — the check reflects associativity on
client triples.
FinCat.compTotal_assoc — associativity on all triples.
Implementation notes
Composition takes the hom-count matrix as primitive rather than a total morphism count with domain and codomain projections. Under the matrix the indexing makes well-typedness a typing obligation, and composition is total; under the projections it is partial, and the client and the checker carry the two side conditions relating the endpoints of a composite to those of its factors.
The identity is reserved one past the client's range rather than at
index 0 so that the embedding of a client morphism into the full hom
type is index-preserving both on and off the diagonal. Reserving 0
makes the embedding Fin.succ on the diagonal and the identity map off
it, so a client's composition function would take arguments in one
numbering and return a result in another.
Total composition dispatches on whether either argument is the reserved
identity, which involves the equation i = j between objects. That
equation is used only inside a Prop: each branch returns
⟨x.val, proof⟩, so the value component crosses with no Eq.rec and
only the bound is transported. This is core's own idiom for
Fin.castLE.
The specification type is declared structure _root_.CategoryTheory.FinCat
inside namespace FinCat, so that its field types name the arithmetic
unqualified and the module needs only one namespace block.
This module has no imports. Its Fin and Nat material is in the
prelude, and nothing in its content mentions a category.
References
[JohnsonYau2021] § 1.1 — the notion of category, of which this module's specification type is a presentation.
Tags
category, finite category, decidable, constructive, choice-free
@[expose] public sectionnamespace CategoryTheorynamespace FinCat
The number of morphisms i ⟶ j a specification with these counts
has: the client's count, plus the reserved identity on the diagonal.
def homCountOf (objCount : Nat) (nonIdCount : Fin objCount → Fin objCount → Nat)
(i j : Fin objCount) : Nat := nonIdCount i j + if i = j then 1 else 0The embedding of a client morphism into the full hom type. It is index-preserving, on and off the diagonal.
def embOf {objCount : Nat} {nonIdCount : Fin objCount → Fin objCount → Nat}
{i j : Fin objCount} (f : Fin (nonIdCount i j)) :
Fin (homCountOf objCount nonIdCount i j) := Fin.castLE (Nat.le_add_right _ _) fOff the diagonal the reserved identity contributes nothing.
theorem homCountOf_of_ne {objCount : Nat}
{nonIdCount : Fin objCount → Fin objCount → Nat} {i j : Fin objCount} (hij : ¬ i = j) :
homCountOf objCount nonIdCount i j = nonIdCount i j :=
(congrArg (nonIdCount i j + ·) (ite_eq_right hij)).trans (Nat.add_zero _)On the diagonal it contributes one.
theorem homCountOf_diag {objCount : Nat}
{nonIdCount : Fin objCount → Fin objCount → Nat} (i : Fin objCount) :
homCountOf objCount nonIdCount i i = nonIdCount i i + 1 :=
congrArg (nonIdCount i i + ·) (ite_eq_left rfl)
An index at or beyond the client's count exists only on the
diagonal: off the diagonal the conditional in homCountOf contributes
0.
theorem objEq_of_le {objCount : Nat} {nonIdCount : Fin objCount → Fin objCount → Nat}
{i j : Fin objCount} (x : Fin (homCountOf objCount nonIdCount i j))
(h : nonIdCount i j ≤ x.val) : i = j :=
if hij : i = j then hij
else absurd (homCountOf_of_ne (nonIdCount := nonIdCount) hij ▸ x.isLt) (Nat.not_lt.mpr h)An index at or beyond the client's count is the reserved identity index of its object.
theorem val_eq_of_le {objCount : Nat} {nonIdCount : Fin objCount → Fin objCount → Nat}
{i j : Fin objCount} (x : Fin (homCountOf objCount nonIdCount i j))
(h : nonIdCount i j ≤ x.val) : x.val = nonIdCount j j := objCount:NatnonIdCount:Fin objCount → Fin objCount → Nati:Fin objCountj:Fin objCountx:Fin (homCountOf objCount nonIdCount i j)h:nonIdCount i j ≤ ↑x⊢ ↑x = nonIdCount j j
objCount:NatnonIdCount:Fin objCount → Fin objCount → Nati:Fin objCountj:Fin objCountx:Fin (homCountOf objCount nonIdCount i j)h:nonIdCount i j ≤ ↑xhij:i = j⊢ ↑x = nonIdCount j j
objCount:NatnonIdCount:Fin objCount → Fin objCount → Nati:Fin objCountx:Fin (homCountOf objCount nonIdCount i i)h:nonIdCount i i ≤ ↑x⊢ ↑x = nonIdCount i i
All goals completed! 🐙
Composition on the full hom types, dispatching on whether either
argument is the reserved identity. Both elided bounds are
objEq_of_le: the value component crosses unchanged and only the
bound is transported.
def compTotalOf {objCount : Nat} {nonIdCount : Fin objCount → Fin objCount → Nat}
(comp : (i j k : Fin objCount) → Fin (nonIdCount i j) → Fin (nonIdCount j k) →
Fin (homCountOf objCount nonIdCount i k))
{i j k : Fin objCount} (f : Fin (homCountOf objCount nonIdCount i j))
(g : Fin (homCountOf objCount nonIdCount j k)) :
Fin (homCountOf objCount nonIdCount i k) :=
if hf : f.val < nonIdCount i j then
if hg : g.val < nonIdCount j k then comp i j k ⟨f.val, hf⟩ ⟨g.val, hg⟩
else ⟨f.val, objCount:NatnonIdCount:Fin objCount → Fin objCount → Natcomp:(i j k : Fin objCount) → Fin (nonIdCount i j) → Fin (nonIdCount j k) → Fin (homCountOf objCount nonIdCount i k)i:Fin objCountj:Fin objCountk:Fin objCountf:Fin (homCountOf objCount nonIdCount i j)g:Fin (homCountOf objCount nonIdCount j k)hf:↑f < nonIdCount i jhg:¬↑g < nonIdCount j k⊢ ↑f < homCountOf objCount nonIdCount i k
objCount:NatnonIdCount:Fin objCount → Fin objCount → Natcomp:(i j k : Fin objCount) → Fin (nonIdCount i j) → Fin (nonIdCount j k) → Fin (homCountOf objCount nonIdCount i k)i:Fin objCountj:Fin objCountk:Fin objCountf:Fin (homCountOf objCount nonIdCount i j)g:Fin (homCountOf objCount nonIdCount j k)hf:↑f < nonIdCount i jhg:¬↑g < nonIdCount j khjk:j = k⊢ ↑f < homCountOf objCount nonIdCount i k; objCount:NatnonIdCount:Fin objCount → Fin objCount → Natcomp:(i j k : Fin objCount) → Fin (nonIdCount i j) → Fin (nonIdCount j k) → Fin (homCountOf objCount nonIdCount i k)i:Fin objCountj:Fin objCountf:Fin (homCountOf objCount nonIdCount i j)hf:↑f < nonIdCount i jg:Fin (homCountOf objCount nonIdCount j j)hg:¬↑g < nonIdCount j j⊢ ↑f < homCountOf objCount nonIdCount i j; All goals completed! 🐙⟩
else ⟨g.val, objCount:NatnonIdCount:Fin objCount → Fin objCount → Natcomp:(i j k : Fin objCount) → Fin (nonIdCount i j) → Fin (nonIdCount j k) → Fin (homCountOf objCount nonIdCount i k)i:Fin objCountj:Fin objCountk:Fin objCountf:Fin (homCountOf objCount nonIdCount i j)g:Fin (homCountOf objCount nonIdCount j k)hf:¬↑f < nonIdCount i j⊢ ↑g < homCountOf objCount nonIdCount i k
objCount:NatnonIdCount:Fin objCount → Fin objCount → Natcomp:(i j k : Fin objCount) → Fin (nonIdCount i j) → Fin (nonIdCount j k) → Fin (homCountOf objCount nonIdCount i k)i:Fin objCountj:Fin objCountk:Fin objCountf:Fin (homCountOf objCount nonIdCount i j)g:Fin (homCountOf objCount nonIdCount j k)hf:¬↑f < nonIdCount i jhij:i = j⊢ ↑g < homCountOf objCount nonIdCount i k; objCount:NatnonIdCount:Fin objCount → Fin objCount → Natcomp:(i j k : Fin objCount) → Fin (nonIdCount i j) → Fin (nonIdCount j k) → Fin (homCountOf objCount nonIdCount i k)i:Fin objCountk:Fin objCountf:Fin (homCountOf objCount nonIdCount i i)g:Fin (homCountOf objCount nonIdCount i k)hf:¬↑f < nonIdCount i i⊢ ↑g < homCountOf objCount nonIdCount i k; All goals completed! 🐙⟩
Associativity of the total composition on triples of client
morphisms, as a Bool. The composition in the statement is the total
one, so a composite landing on the reserved identity index is
covered.
def assocCheckOf (objCount : Nat) (nonIdCount : Fin objCount → Fin objCount → Nat)
(comp : (i j k : Fin objCount) → Fin (nonIdCount i j) → Fin (nonIdCount j k) →
Fin (homCountOf objCount nonIdCount i k)) : Bool :=
decide <| ∀ (i j k l : Fin objCount) (f : Fin (nonIdCount i j)) (g : Fin (nonIdCount j k))
(h : Fin (nonIdCount k l)),
compTotalOf comp (compTotalOf comp (embOf f) (embOf g)) (embOf h)
= compTotalOf comp (embOf f) (compTotalOf comp (embOf g) (embOf h))A finite-category specification: a count of objects, a count of non-identity morphisms at each pair, a composition function on those morphisms, and the associativity check. The client designates no identities, states no identity laws, and supplies no domain or codomain data.
The number of objects, indexed by Fin objCount.
The number of non-identity morphisms i ⟶ j.
Composition of client morphisms. It lands in the full hom type, because a composite of two non-identity morphisms may be an identity.
Associativity on triples of client morphisms. A client with a
concrete category discharges this by rfl.
@[ext] structure _root_.CategoryTheory.FinCat where objCount : Nat nonIdCount : Fin objCount → Fin objCount → Nat comp : (i j k : Fin objCount) →
Fin (nonIdCount i j) → Fin (nonIdCount j k) →
Fin (homCountOf objCount nonIdCount i k) assoc : assocCheckOf objCount nonIdCount comp = true
The number of morphisms i ⟶ j of S.
def homCount (S : FinCat) (i j : Fin S.objCount) : Nat :=
homCountOf S.objCount S.nonIdCount i j
The morphisms i ⟶ j of S, client morphisms and the reserved
identity together. An abbrev rather than a def: instance search
does not unfold a plain def, so DecidableEq (S.Mor i j) would not
be found and compCheckOf's and natCheckOf's decide bodies —
equalities at Mor — would not elaborate.
The embedding of a client morphism of S into the full hom type.
def emb {S : FinCat} {i j : Fin S.objCount} (f : Fin (S.nonIdCount i j)) : S.Mor i j := embOf f
The reserved identity at i, at the index one past the client's
range.
protected def id (S : FinCat) (i : Fin S.objCount) : S.Mor i i :=
⟨S.nonIdCount i i, S:FinCati:Fin S.objCount⊢ S.nonIdCount i i < S.homCount i i All goals completed! 🐙⟩
Composition on the full hom types of S.
def compTotal (S : FinCat) {i j k : Fin S.objCount} (f : S.Mor i j) (g : S.Mor j k) : S.Mor i k :=
compTotalOf S.comp f g
Associativity of S on triples of client morphisms, as a Bool.
def assocCheck (S : FinCat) : Bool := assocCheckOf S.objCount S.nonIdCount S.comp
An index at or beyond S's client count exists only on the
diagonal.
theorem eq_of_nonIdCount_le (S : FinCat) {i j : Fin S.objCount} (x : S.Mor i j)
(h : S.nonIdCount i j ≤ x.val) : i = j := objEq_of_le x h
An index at or beyond S's client count is the reserved identity
index.
theorem val_eq_of_nonIdCount_le (S : FinCat) {i j : Fin S.objCount} (x : S.Mor i j)
(h : S.nonIdCount i j ≤ x.val) : x.val = S.nonIdCount j j := val_eq_of_le x hThe reserved identity is a left identity for the total composition.
theorem id_comp (S : FinCat) {i k : Fin S.objCount} (g : S.Mor i k) :
S.compTotal (S.id i) g = g := S:FinCati:Fin S.objCountk:Fin S.objCountg:S.Mor i k⊢ S.compTotal (S.id i) g = g
S:FinCati:Fin S.objCountk:Fin S.objCountg:S.Mor i khlt:¬↑(S.id i) < S.nonIdCount i i⊢ S.compTotal (S.id i) g = g
S:FinCati:Fin S.objCountk:Fin S.objCountg:S.Mor i khlt:¬↑(S.id i) < S.nonIdCount i i⊢ (if hf : ↑(S.id i) < S.nonIdCount i i then
if hg : ↑g < S.nonIdCount i k then S.comp i i k ⟨↑(S.id i), hf⟩ ⟨↑g, hg⟩ else ⟨↑(S.id i), ⋯⟩
else ⟨↑g, ⋯⟩) =
g
S:FinCati:Fin S.objCountk:Fin S.objCountg:S.Mor i khlt:¬↑(S.id i) < S.nonIdCount i i⊢ ⟨↑g, ⋯⟩ = g
rfl All goals completed! 🐙The reserved identity is a right identity for the total composition.
theorem comp_id (S : FinCat) {i j : Fin S.objCount} (f : S.Mor i j) :
S.compTotal f (S.id j) = f := by S:FinCati:Fin S.objCountj:Fin S.objCountf:S.Mor i j⊢ S.compTotal f (S.id j) = f
have hlt : ¬ ((S.id j).val < S.nonIdCount j j) := Nat.lt_irrefl _ S:FinCati:Fin S.objCountj:Fin S.objCountf:S.Mor i jhlt:¬↑(S.id j) < S.nonIdCount j j⊢ S.compTotal f (S.id j) = f
unfold compTotal compTotalOf S:FinCati:Fin S.objCountj:Fin S.objCountf:S.Mor i jhlt:¬↑(S.id j) < S.nonIdCount j j⊢ (if hf : ↑f < S.nonIdCount i j then
if hg : ↑(S.id j) < S.nonIdCount j j then S.comp i j j ⟨↑f, hf⟩ ⟨↑(S.id j), hg⟩ else ⟨↑f, ⋯⟩
else ⟨↑(S.id j), ⋯⟩) =
f
by_cases hf : f.val < S.nonIdCount i j pos S:FinCati:Fin S.objCountj:Fin S.objCountf:S.Mor i jhlt:¬↑(S.id j) < S.nonIdCount j jhf:↑f < S.nonIdCount i j⊢ (if hf : ↑f < S.nonIdCount i j then
if hg : ↑(S.id j) < S.nonIdCount j j then S.comp i j j ⟨↑f, hf⟩ ⟨↑(S.id j), hg⟩ else ⟨↑f, ⋯⟩
else ⟨↑(S.id j), ⋯⟩) =
fneg S:FinCati:Fin S.objCountj:Fin S.objCountf:S.Mor i jhlt:¬↑(S.id j) < S.nonIdCount j jhf:¬↑f < S.nonIdCount i j⊢ (if hf : ↑f < S.nonIdCount i j then
if hg : ↑(S.id j) < S.nonIdCount j j then S.comp i j j ⟨↑f, hf⟩ ⟨↑(S.id j), hg⟩ else ⟨↑f, ⋯⟩
else ⟨↑(S.id j), ⋯⟩) =
f
· pos S:FinCati:Fin S.objCountj:Fin S.objCountf:S.Mor i jhlt:¬↑(S.id j) < S.nonIdCount j jhf:↑f < S.nonIdCount i j⊢ (if hf : ↑f < S.nonIdCount i j then
if hg : ↑(S.id j) < S.nonIdCount j j then S.comp i j j ⟨↑f, hf⟩ ⟨↑(S.id j), hg⟩ else ⟨↑f, ⋯⟩
else ⟨↑(S.id j), ⋯⟩) =
f rw [dite_eq_left hf, pos S:FinCati:Fin S.objCountj:Fin S.objCountf:S.Mor i jhlt:¬↑(S.id j) < S.nonIdCount j jhf:↑f < S.nonIdCount i j⊢ (if hg : ↑(S.id j) < S.nonIdCount j j then S.comp i j j ⟨↑f, hf⟩ ⟨↑(S.id j), hg⟩ else ⟨↑f, ⋯⟩) = f dite_eq_right hlt pos S:FinCati:Fin S.objCountj:Fin S.objCountf:S.Mor i jhlt:¬↑(S.id j) < S.nonIdCount j jhf:↑f < S.nonIdCount i j⊢ ⟨↑f, ⋯⟩ = f] pos S:FinCati:Fin S.objCountj:Fin S.objCountf:S.Mor i jhlt:¬↑(S.id j) < S.nonIdCount j jhf:↑f < S.nonIdCount i j⊢ ⟨↑f, ⋯⟩ = f
rfl All goals completed! 🐙
· neg S:FinCati:Fin S.objCountj:Fin S.objCountf:S.Mor i jhlt:¬↑(S.id j) < S.nonIdCount j jhf:¬↑f < S.nonIdCount i j⊢ (if hf : ↑f < S.nonIdCount i j then
if hg : ↑(S.id j) < S.nonIdCount j j then S.comp i j j ⟨↑f, hf⟩ ⟨↑(S.id j), hg⟩ else ⟨↑f, ⋯⟩
else ⟨↑(S.id j), ⋯⟩) =
f rw [dite_eq_right hf neg S:FinCati:Fin S.objCountj:Fin S.objCountf:S.Mor i jhlt:¬↑(S.id j) < S.nonIdCount j jhf:¬↑f < S.nonIdCount i j⊢ ⟨↑(S.id j), ⋯⟩ = f] neg S:FinCati:Fin S.objCountj:Fin S.objCountf:S.Mor i jhlt:¬↑(S.id j) < S.nonIdCount j jhf:¬↑f < S.nonIdCount i j⊢ ⟨↑(S.id j), ⋯⟩ = f
exact Fin.ext (val_eq_of_le f (Nat.not_lt.mp hf)).symm All goals completed! 🐙
The specification with no objects. deriving Inhabited fails,
there being no Inhabited instance for the Prop-valued assoc
field.
instance inhabited : Inhabited FinCat :=
⟨⟨0, fun i _ ↦ i.elim0, fun i _ _ ↦ i.elim0, rfl⟩⟩The associativity check reflects associativity on triples of client morphisms.
theorem assocCheck_eq_true_iff (objCount : Nat) (nonIdCount : Fin objCount → Fin objCount → Nat)
(comp : (i j k : Fin objCount) → Fin (nonIdCount i j) → Fin (nonIdCount j k) →
Fin (homCountOf objCount nonIdCount i k)) :
assocCheckOf objCount nonIdCount comp = true ↔
∀ (i j k l : Fin objCount) (f : Fin (nonIdCount i j)) (g : Fin (nonIdCount j k))
(h : Fin (nonIdCount k l)),
compTotalOf comp (compTotalOf comp (embOf f) (embOf g)) (embOf h)
= compTotalOf comp (embOf f) (compTotalOf comp (embOf g) (embOf h)) :=
decide_eq_true_iff
Associativity of the total composition, on all triples of morphisms
of S. A triple of client morphisms is the check's; a triple with the
reserved identity among it is the identity laws'.
theorem compTotal_assoc (S : FinCat) {i j k l : Fin S.objCount}
(f : S.Mor i j) (g : S.Mor j k) (h : S.Mor k l) :
S.compTotal (S.compTotal f g) h = S.compTotal f (S.compTotal g h) := by S:FinCati:Fin S.objCountj:Fin S.objCountk:Fin S.objCountl:Fin S.objCountf:S.Mor i jg:S.Mor j kh:S.Mor k l⊢ S.compTotal (S.compTotal f g) h = S.compTotal f (S.compTotal g h)
by_cases hf : f.val < S.nonIdCount i j pos S:FinCati:Fin S.objCountj:Fin S.objCountk:Fin S.objCountl:Fin S.objCountf:S.Mor i jg:S.Mor j kh:S.Mor k lhf:↑f < S.nonIdCount i j⊢ S.compTotal (S.compTotal f g) h = S.compTotal f (S.compTotal g h)neg S:FinCati:Fin S.objCountj:Fin S.objCountk:Fin S.objCountl:Fin S.objCountf:S.Mor i jg:S.Mor j kh:S.Mor k lhf:¬↑f < S.nonIdCount i j⊢ S.compTotal (S.compTotal f g) h = S.compTotal f (S.compTotal g h)
· pos S:FinCati:Fin S.objCountj:Fin S.objCountk:Fin S.objCountl:Fin S.objCountf:S.Mor i jg:S.Mor j kh:S.Mor k lhf:↑f < S.nonIdCount i j⊢ S.compTotal (S.compTotal f g) h = S.compTotal f (S.compTotal g h) by_cases hg : g.val < S.nonIdCount j k pos S:FinCati:Fin S.objCountj:Fin S.objCountk:Fin S.objCountl:Fin S.objCountf:S.Mor i jg:S.Mor j kh:S.Mor k lhf:↑f < S.nonIdCount i jhg:↑g < S.nonIdCount j k⊢ S.compTotal (S.compTotal f g) h = S.compTotal f (S.compTotal g h)neg S:FinCati:Fin S.objCountj:Fin S.objCountk:Fin S.objCountl:Fin S.objCountf:S.Mor i jg:S.Mor j kh:S.Mor k lhf:↑f < S.nonIdCount i jhg:¬↑g < S.nonIdCount j k⊢ S.compTotal (S.compTotal f g) h = S.compTotal f (S.compTotal g h)
· pos S:FinCati:Fin S.objCountj:Fin S.objCountk:Fin S.objCountl:Fin S.objCountf:S.Mor i jg:S.Mor j kh:S.Mor k lhf:↑f < S.nonIdCount i jhg:↑g < S.nonIdCount j k⊢ S.compTotal (S.compTotal f g) h = S.compTotal f (S.compTotal g h) by_cases hh : h.val < S.nonIdCount k l pos S:FinCati:Fin S.objCountj:Fin S.objCountk:Fin S.objCountl:Fin S.objCountf:S.Mor i jg:S.Mor j kh:S.Mor k lhf:↑f < S.nonIdCount i jhg:↑g < S.nonIdCount j khh:↑h < S.nonIdCount k l⊢ S.compTotal (S.compTotal f g) h = S.compTotal f (S.compTotal g h)neg S:FinCati:Fin S.objCountj:Fin S.objCountk:Fin S.objCountl:Fin S.objCountf:S.Mor i jg:S.Mor j kh:S.Mor k lhf:↑f < S.nonIdCount i jhg:↑g < S.nonIdCount j khh:¬↑h < S.nonIdCount k l⊢ S.compTotal (S.compTotal f g) h = S.compTotal f (S.compTotal g h)
· pos S:FinCati:Fin S.objCountj:Fin S.objCountk:Fin S.objCountl:Fin S.objCountf:S.Mor i jg:S.Mor j kh:S.Mor k lhf:↑f < S.nonIdCount i jhg:↑g < S.nonIdCount j khh:↑h < S.nonIdCount k l⊢ S.compTotal (S.compTotal f g) h = S.compTotal f (S.compTotal g h) exact (assocCheck_eq_true_iff S.objCount S.nonIdCount S.comp).mp S.assoc i j k l
⟨f.val, hf⟩ ⟨g.val, hg⟩ ⟨h.val, hh⟩ All goals completed! 🐙
· neg S:FinCati:Fin S.objCountj:Fin S.objCountk:Fin S.objCountl:Fin S.objCountf:S.Mor i jg:S.Mor j kh:S.Mor k lhf:↑f < S.nonIdCount i jhg:↑g < S.nonIdCount j khh:¬↑h < S.nonIdCount k l⊢ S.compTotal (S.compTotal f g) h = S.compTotal f (S.compTotal g h) have hkl := S.eq_of_nonIdCount_le h (Nat.not_lt.mp hh) neg S:FinCati:Fin S.objCountj:Fin S.objCountk:Fin S.objCountl:Fin S.objCountf:S.Mor i jg:S.Mor j kh:S.Mor k lhf:↑f < S.nonIdCount i jhg:↑g < S.nonIdCount j khh:¬↑h < S.nonIdCount k lhkl:k = l⊢ S.compTotal (S.compTotal f g) h = S.compTotal f (S.compTotal g h)
subst hkl neg S:FinCati:Fin S.objCountj:Fin S.objCountk:Fin S.objCountf:S.Mor i jg:S.Mor j khf:↑f < S.nonIdCount i jhg:↑g < S.nonIdCount j kh:S.Mor k khh:¬↑h < S.nonIdCount k k⊢ S.compTotal (S.compTotal f g) h = S.compTotal f (S.compTotal g h)
rw [show h = S.id _ from Fin.ext (S.val_eq_of_nonIdCount_le h (Nat.not_lt.mp hh)), neg S:FinCati:Fin S.objCountj:Fin S.objCountk:Fin S.objCountf:S.Mor i jg:S.Mor j khf:↑f < S.nonIdCount i jhg:↑g < S.nonIdCount j kh:S.Mor k khh:¬↑h < S.nonIdCount k k⊢ S.compTotal (S.compTotal f g) (S.id k) = S.compTotal f (S.compTotal g (S.id k))
S.comp_id, neg S:FinCati:Fin S.objCountj:Fin S.objCountk:Fin S.objCountf:S.Mor i jg:S.Mor j khf:↑f < S.nonIdCount i jhg:↑g < S.nonIdCount j kh:S.Mor k khh:¬↑h < S.nonIdCount k k⊢ S.compTotal f g = S.compTotal f (S.compTotal g (S.id k)) S.comp_id neg S:FinCati:Fin S.objCountj:Fin S.objCountk:Fin S.objCountf:S.Mor i jg:S.Mor j khf:↑f < S.nonIdCount i jhg:↑g < S.nonIdCount j kh:S.Mor k khh:¬↑h < S.nonIdCount k k⊢ S.compTotal f g = S.compTotal f g] All goals completed! 🐙
· neg S:FinCati:Fin S.objCountj:Fin S.objCountk:Fin S.objCountl:Fin S.objCountf:S.Mor i jg:S.Mor j kh:S.Mor k lhf:↑f < S.nonIdCount i jhg:¬↑g < S.nonIdCount j k⊢ S.compTotal (S.compTotal f g) h = S.compTotal f (S.compTotal g h) have hjk := S.eq_of_nonIdCount_le g (Nat.not_lt.mp hg) neg S:FinCati:Fin S.objCountj:Fin S.objCountk:Fin S.objCountl:Fin S.objCountf:S.Mor i jg:S.Mor j kh:S.Mor k lhf:↑f < S.nonIdCount i jhg:¬↑g < S.nonIdCount j khjk:j = k⊢ S.compTotal (S.compTotal f g) h = S.compTotal f (S.compTotal g h)
subst hjk neg S:FinCati:Fin S.objCountj:Fin S.objCountl:Fin S.objCountf:S.Mor i jhf:↑f < S.nonIdCount i jg:S.Mor j jh:S.Mor j lhg:¬↑g < S.nonIdCount j j⊢ S.compTotal (S.compTotal f g) h = S.compTotal f (S.compTotal g h)
rw [show g = S.id _ from Fin.ext (S.val_eq_of_nonIdCount_le g (Nat.not_lt.mp hg)), neg S:FinCati:Fin S.objCountj:Fin S.objCountl:Fin S.objCountf:S.Mor i jhf:↑f < S.nonIdCount i jg:S.Mor j jh:S.Mor j lhg:¬↑g < S.nonIdCount j j⊢ S.compTotal (S.compTotal f (S.id j)) h = S.compTotal f (S.compTotal (S.id j) h)
S.comp_id, neg S:FinCati:Fin S.objCountj:Fin S.objCountl:Fin S.objCountf:S.Mor i jhf:↑f < S.nonIdCount i jg:S.Mor j jh:S.Mor j lhg:¬↑g < S.nonIdCount j j⊢ S.compTotal f h = S.compTotal f (S.compTotal (S.id j) h) S.id_comp neg S:FinCati:Fin S.objCountj:Fin S.objCountl:Fin S.objCountf:S.Mor i jhf:↑f < S.nonIdCount i jg:S.Mor j jh:S.Mor j lhg:¬↑g < S.nonIdCount j j⊢ S.compTotal f h = S.compTotal f h] All goals completed! 🐙
· neg S:FinCati:Fin S.objCountj:Fin S.objCountk:Fin S.objCountl:Fin S.objCountf:S.Mor i jg:S.Mor j kh:S.Mor k lhf:¬↑f < S.nonIdCount i j⊢ S.compTotal (S.compTotal f g) h = S.compTotal f (S.compTotal g h) have hij := S.eq_of_nonIdCount_le f (Nat.not_lt.mp hf) neg S:FinCati:Fin S.objCountj:Fin S.objCountk:Fin S.objCountl:Fin S.objCountf:S.Mor i jg:S.Mor j kh:S.Mor k lhf:¬↑f < S.nonIdCount i jhij:i = j⊢ S.compTotal (S.compTotal f g) h = S.compTotal f (S.compTotal g h)
subst hij neg S:FinCati:Fin S.objCountk:Fin S.objCountl:Fin S.objCounth:S.Mor k lf:S.Mor i ig:S.Mor i khf:¬↑f < S.nonIdCount i i⊢ S.compTotal (S.compTotal f g) h = S.compTotal f (S.compTotal g h)
rw [show f = S.id _ from Fin.ext (S.val_eq_of_nonIdCount_le f (Nat.not_lt.mp hf)), neg S:FinCati:Fin S.objCountk:Fin S.objCountl:Fin S.objCounth:S.Mor k lf:S.Mor i ig:S.Mor i khf:¬↑f < S.nonIdCount i i⊢ S.compTotal (S.compTotal (S.id i) g) h = S.compTotal (S.id i) (S.compTotal g h)
S.id_comp, neg S:FinCati:Fin S.objCountk:Fin S.objCountl:Fin S.objCounth:S.Mor k lf:S.Mor i ig:S.Mor i khf:¬↑f < S.nonIdCount i i⊢ S.compTotal g h = S.compTotal (S.id i) (S.compTotal g h) S.id_comp neg S:FinCati:Fin S.objCountk:Fin S.objCountl:Fin S.objCounth:S.Mor k lf:S.Mor i ig:S.Mor i khf:¬↑f < S.nonIdCount i i⊢ S.compTotal g h = S.compTotal g h] All goals completed! 🐙end FinCatend CategoryTheory