/-
Copyright (c) 2026 Terence Rokop. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Terence Rokop
-/modulepublicimportGeb.Mathlib.Data.Vector.OfFnpublicimportMathlib.CategoryTheory.Category.BasicpublicimportMathlib.Tactic.Attr.Core
FinSetSkel: a skeletal category of finite sets with vector morphisms
Objects are natural numbers; a morphism X ⟶ Y is a vector of X.len
indices into Fin Y.len. mathlib's FintypeCat.Skeleton has the same
objects up to the evident bijection with ℕ but takes morphisms to be
functions, whose equality is decidable only through
Classical.choice. Morphisms here are data: they can be
pattern-matched through toVec, serialised through Repr, and
compared through DecidableEq, all choice-free.
The objects are a one-field structure rather than ULift ℕ with mk
and len as definitions. A definition is opaque at reducible
transparency, so Fin (mk n).len would not match a lemma stated at
Fin X.len and no simp lemma would fire; the repair, marking mk
and len@[reducible], cannot be confined to this module, and every
downstream construction is stated over Fin X.len. A structure
projection reduces by iota, which is available at reducible
transparency, so no reducibility attribute is needed anywhere.
The morphism representation is root-namespace Vector, not
List.Vector. The evidence runs both ways and is recorded so the
decision is not revisited on one side of it.
Mathlib/Data/Vector/Defs.lean says both "Any combination of reducing
the use of List.Vector in Mathlib, or modernising its API, would be
welcome" and "Typically, if you are doing programming or verification,
you will primarily use Vector α n, and if you are doing mathematics,
you may want to use List.Vector α n instead." On axioms
List.Vector is the cleaner: its DecidableEq is axiom-free where
root Vector's costs propext and Quot.sound, and its get_ofFn
and ofFn_get are choice-free where root Vector's are not, which
costs the five declarations of Mathlib/Data/Vector/OfFn.lean.
Root Vector is chosen because composition is the operation this
category exists to run: composing f : X ⟶ Y with g : Y ⟶ Z is
O(X.len) here and O(X.len² + X.len · Y.len) on the list-backed
representation, whose indexing is linear.
The API shape — a named Hom, an ofVec/toVec pair, @[ext], the
@[simp] application lemmas, then attribute [irreducible] — is
mathlib's own, from SimplexCategory. Only the shape is borrowed:
SimplexCategory.Hom is a bundled monotone function and its
hom-DecidableEq depends on Classical.choice.
Main definitions
FinSetSkel — the objects.
FinSetSkel.Hom, FinSetSkel.Hom.ofVec, FinSetSkel.Hom.toVec —
the morphisms and their representation.
FinSetSkel.smallCategory — the category instance.
FinSetSkel.ofIdxFun, FinSetSkel.toIdxFun — the correspondence
with lifted index functions, which the skeleton comparison uses.
Main statements
FinSetSkel.hom_ext — morphisms agreeing indexwise are equal.
FinSetSkel.id_get, FinSetSkel.comp_get — the
application-normal form for identity and composition.
Implementation notes
The name records the skeletal model: Skel marks this as the skeletal
model of the category of finite sets, parallel to FintypeCat.Skeleton.
References
[nLabSkeletalCategory] — skeletal categories and the skeleton of a
category. In the absence of the axiom of choice the entry notes that
a weak skeleton is the more appropriate notion; the skeletality of
this category is established in the wrapper module, which is where
Classical.choice is permitted.
Decidable equality of morphisms, pinned to the choice-free route.
Instance search does not unfold the Hom definition, so this does not
follow from the category instance; and instDecidableEqOfLawfulBEq
inhabits the same class through the choice-dependent
Vector.instLawfulBEq, so leaving the instance to search would let a
bump silently change its axioms.