Imports
/-
Copyright (c) 2026 Terence Rokop. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Terence Rokop
-/
module
public import Geb.Prototypes.LargeIR.Basic
public import Geb.Mathlib.Data.PFunctor.IndRec.Basic
meta import GebMeta -- shake: keep; supplies the cite docstring roleset_option doc.verso truePrototype: the transcription read back as a large inductive-recursive code
Throwaway exploration, not upstream-eligible content. Every declaration here
is Classical.choice-free.
GebProto.LargeIR.objEquiv computes the value of the transcription
GebProto.LargeIR.arrowPsh of a slice polynomial functor
P : Type/X → Type/Y at a walking-arrow presheaf Z as a level
0 of Y × (X → Z 0) and a level 1 over (y, f₀) of
P at the pullback along f₀. This module reads that computation
back as the interpretation of an inductive-recursive code on
Fam(Type), the free coproduct completion of Type, in the
repository's code system IndRec.IR at input and output index type
Type: the code code P is
σ Y (fun y ↦ δ X (fun A ↦ ι (fibreValue P y A))), whose σ
contributes the Y, whose δ contributes the base map
X → Z 0 as the assignment g : X → U of the δ rule, and
whose ι decodes to the slice functor's fibre at y applied to
the decoded family T ∘ g. The interpretation
IndRec.IR.interpObj of code P at the family (U, T) of
Z — U := Z 0 and T u the fibre of Z 1 → Z 0 over
u — is isomorphic, as a walking-arrow presheaf, to the transcription's
value. That is arrowPshCodeEquiv, and it confirms the reading of the
transcription as a large-IR δ code rather than as the slice functor.
The comparison is stated between walking-arrow presheaves, a family being
turned into one by GebProto.LargeIR.ofSlice of the projection of its
total space, and an isomorphism of walking-arrow presheaves is a pair of
equivalences commuting with the restriction map, PshEquiv. Two
choices are forced by what is available choice-free. A functor-category
isomorphism would name the functor category, which depends on
Classical.choice, so the isomorphism is unbundled. And the
repository's CategoryTheory.FreeCoprodCompDisc is the completion of
Type as a discrete category, whose morphisms compare decodings by
equality, so the agreement is stated at the level of objects: the morphism
action of large inductive-recursive definitions, which compares decodings
by functions T u → T' (h u) and is what the positivity of
[GhaniNordvallForsbergMalatesta2015]
Neil Ghani, Fredrik Nordvall Forsberg, Lorenzo Malatesta (2015). “Positive Inductive-Recursive Definitions”. Logical Methods in Computer Science 11(1). https://doi.org/10.2168/LMCS-11(1:13)2015.
Main definitions
-
fibreValue— the slice functor's fibre at an output index, applied to a familyX → Type. -
code— the codeσ Y (fun y ↦ δ X (fun A ↦ ι (fibreValue P y A))). -
famOfPsh— the family(U, T)of a walking-arrow presheaf;pshOfFam— the walking-arrow presheaf of a family. -
PshEquiv— an isomorphism of walking-arrow presheaves, unbundled;PshEquiv.transits composition. -
levelsPsh—GebProto.LargeIR.Levelsas a walking-arrow presheaf. -
levelZeroEquiv,levelOneEquiv— the level-0and level-1elements of the transcription's value as the two summands ofGebProto.LargeIR.Levels.
Main statements
-
objPresheafEquiv— the transcription's output presheaf islevelsPsh. -
levelsCodeEquiv—levelsPshis the presheaf of the code's interpretation at the family of the input. -
arrowPshCodeEquiv— their composite: the transcription's output presheaf is the presheaf of the code's interpretation.
References
-
[DybjerSetzer2003]
Peter Dybjer, Anton Setzer (2003). “Induction--recursion and initial algebras”. Annals of Pure and Applied Logic 124(1--3), pp. 1–47. https://doi.org/10.1016/S0168-0072(02)00096-9. -
[GhaniNordvallForsbergMalatesta2015]
Neil Ghani, Fredrik Nordvall Forsberg, Lorenzo Malatesta (2015). “Positive Inductive-Recursive Definitions”. Logical Methods in Computer Science 11(1). https://doi.org/10.2168/LMCS-11(1:13)2015.
Tags
prototype, presheaf, walking arrow, inductive-recursive, code, free coproduct completion
@[expose] public sectionopen CategoryTheory PresheafIRUniv IndRecnamespace GebProto.LargeIRvariable {X Y : Type} (P : SlicePFunctor.{0, 0, 0, 0} X Y)The code
The slice functor's fibre at the output index y, applied to a
family A : X → Type: a shape over y with an element of the
family at each direction's input index.
The code σ Y (fun y ↦ δ X (fun A ↦ ι (fibreValue P y A))): a
constructor for each output index, whose recursive arguments are indexed by
X and whose decoding is the slice functor's fibre applied to the
decodings of those arguments.
def code : IR.{0, 0, 1, 1} Type Type :=
IR.sigma Type Type Y fun y ↦ IR.delta Type Type X fun A ↦ IR.iota Type Type (fibreValue P y A)Families and walking-arrow presheaves
The family (U, T) of a walking-arrow presheaf: U := Z 0 and
T u the fibre of the restriction Z 1 → Z 0 over u.
def famOfPsh (Z : (Fin 2)ᵒᵖ ⥤ Type) : FreeCoprodCompDisc.{0, 1} Type :=
⟨Z.obj ⟨0⟩, fun u ↦ { z : Z.obj ⟨1⟩ // Z.map waHom.op z = u }⟩
The walking-arrow presheaf of a family: the projection of its total space
as an object of Type/U.
def pshOfFam (F : FreeCoprodCompDisc.{0, 1} Type) : (Fin 2)ᵒᵖ ⥤ Type :=
ofSlice (Sigma.fst : (Σ u : F.1, F.2 u) → F.1)An isomorphism of walking-arrow presheaves, unbundled: equivalences at the two levels commuting with the restriction map.
The equivalence at level 0.
The equivalence at level 1.
The equivalences commute with the restriction along 0 ⟶ 1.
structure PshEquiv (Z Z' : (Fin 2)ᵒᵖ ⥤ Type) where base : Z.obj ⟨0⟩ ≃ Z'.obj ⟨0⟩ total : Z.obj ⟨1⟩ ≃ Z'.obj ⟨1⟩ map_total : ∀ z, Z'.map waHom.op (total z) = base (Z.map waHom.op z)Composition of isomorphisms of walking-arrow presheaves.
def PshEquiv.trans {Z Z' Z'' : (Fin 2)ᵒᵖ ⥤ Type} (e : PshEquiv Z Z') (e' : PshEquiv Z' Z'') :
PshEquiv Z Z'' where
base := e.base.trans e'.base
total := e.total.trans e'.total
map_total z := (e'.map_total (e.total z)).trans (congrArg e'.base (e.map_total z))The transcription's output presheaf as a family
variable (Z : (Fin 2)ᵒᵖ ⥤ Type)
The level of a summand of GebProto.LargeIR.Levels.
def levelOf : Levels P Z → Fin 2 :=
Sum.elim (fun _ ↦ 0) (fun _ ↦ 1)
The level of an element of the transcription's value is the level of its
image in GebProto.LargeIR.Levels.
theorem q_shape_eq_levelOf (x : (arrowPsh P).obj Z) :
(arrowPsh P).q x.shape = levelOf P Z (toLevels P Z x) :=
match x with
| ⟨⟨⟨.inl _, _⟩, _⟩, _⟩ => rfl
| ⟨⟨⟨.inr _, _⟩, _⟩, _⟩ => rfltheorem toLevels_ofLevels (l : Levels P Z) : toLevels P Z (ofLevels P Z l) = l := X:TypeY:TypeP:SlicePFunctor X YZ:(Fin 2)ᵒᵖ ⥤ Typel:Levels P Z⊢ toLevels P Z (ofLevels P Z l) = l
All goals completed! 🐙theorem ofLevels_toLevels (x : (arrowPsh P).obj Z) : ofLevels P Z (toLevels P Z x) = x := X:TypeY:TypeP:SlicePFunctor X YZ:(Fin 2)ᵒᵖ ⥤ Typex:(arrowPsh P).obj Z⊢ ofLevels P Z (toLevels P Z x) = x
All goals completed! 🐙
The elements of the transcription's value over j are the summands
of GebProto.LargeIR.Levels at level j.
def objLevelEquiv (j : Fin 2) :
{ x : (arrowPsh P).obj Z // (arrowPsh P).q x.shape = j } ≃
{ l : Levels P Z // levelOf P Z l = j } where
toFun x := ⟨toLevels P Z x.1, (q_shape_eq_levelOf P Z x.1).symm.trans x.2⟩
invFun l := ⟨ofLevels P Z l.1,
(q_shape_eq_levelOf P Z _).trans
((congrArg (levelOf P Z) (toLevels_ofLevels P Z l.1)).trans l.2)⟩
left_inv x := Subtype.ext (ofLevels_toLevels P Z x.1)
right_inv l := Subtype.ext (toLevels_ofLevels P Z l.1)
The elements of a sum at level 0 are its left summand.
def sumLeftEquiv {α β : Type} :
{ s : α ⊕ β // Sum.elim (fun _ ↦ 0) (fun _ ↦ 1) s = (0 : Fin 2) } ≃ α where
toFun s :=
match s with
| ⟨.inl a, _⟩ => a
| ⟨.inr _, h⟩ => absurd h Fin.zero_ne_one.symm
invFun a := ⟨.inl a, rfl⟩
left_inv s :=
match s with
| ⟨.inl _, _⟩ => rfl
| ⟨.inr _, h⟩ => absurd h Fin.zero_ne_one.symm
right_inv _ := rfl
The elements of a sum at level 1 are its right summand.
def sumRightEquiv {α β : Type} :
{ s : α ⊕ β // Sum.elim (fun _ ↦ 0) (fun _ ↦ 1) s = (1 : Fin 2) } ≃ β where
toFun s :=
match s with
| ⟨.inl _, h⟩ => absurd h Fin.zero_ne_one
| ⟨.inr b, _⟩ => b
invFun b := ⟨.inr b, rfl⟩
left_inv s :=
match s with
| ⟨.inl _, h⟩ => absurd h Fin.zero_ne_one
| ⟨.inr _, _⟩ => rfl
right_inv _ := rfl
The level-0 elements of the transcription's value are
Y × (X → Z 0).
def levelZeroEquiv :
{ x : (arrowPsh P).obj Z // (arrowPsh P).q x.shape = 0 } ≃ (Y × (X → Z.obj ⟨0⟩)) :=
(objLevelEquiv P Z 0).trans sumLeftEquiv
The level-1 elements of the transcription's value are the sum over
the base maps of the slice functor's values at the pullbacks.
def levelOneEquiv :
{ x : (arrowPsh P).obj Z // (arrowPsh P).q x.shape = 1 } ≃
(Σ f₀ : X → Z.obj ⟨0⟩, P.toSliceDomPFunctor.Obj (pullbackProj Z f₀)) :=
(objLevelEquiv P Z 1).trans sumRightEquiv
The level-1 part of GebProto.LargeIR.Levels regrouped over
the level-0 part: over (y, f₀), the slice functor's values at the
pullback along f₀ whose output index is y.
def levelsFibre (yf : Y × (X → Z.obj ⟨0⟩)) : Type :=
{ o : P.toSliceDomPFunctor.Obj (pullbackProj Z yf.2) // P.obj (pullbackProj Z yf.2) o = yf.1 }
An element of the regrouped level-1 part reassembled from its
components along an equation of its output index is the original element.
theorem levelsFibre_ext {f₀ : X → Z.obj ⟨0⟩} {y : Y}
(o : P.toSliceDomPFunctor.Obj (pullbackProj Z f₀)) (h : P.obj (pullbackProj Z f₀) o = y) :
(⟨(P.obj (pullbackProj Z f₀) o, f₀), ⟨o, rfl⟩⟩ :
Σ yf : Y × (X → Z.obj ⟨0⟩), levelsFibre P Z yf) = ⟨(y, f₀), ⟨o, h⟩⟩ := X:TypeY:TypeP:SlicePFunctor X YZ:(Fin 2)ᵒᵖ ⥤ Typef₀:X → Z.obj (Opposite.op 0)y:Yo:P.Obj (pullbackProj Z f₀)h:P.obj (pullbackProj Z f₀) o = y⊢ ⟨(P.obj (pullbackProj Z f₀) o, f₀), ⟨o, ⋯⟩⟩ = ⟨(y, f₀), ⟨o, h⟩⟩
X:TypeY:TypeP:SlicePFunctor X YZ:(Fin 2)ᵒᵖ ⥤ Typef₀:X → Z.obj (Opposite.op 0)o:P.Obj (pullbackProj Z f₀)⊢ ⟨(P.obj (pullbackProj Z f₀) o, f₀), ⟨o, ⋯⟩⟩ = ⟨(P.obj (pullbackProj Z f₀) o, f₀), ⟨o, ⋯⟩⟩
All goals completed! 🐙
Regrouping the level-1 part over the level-0 part.
def levelsFibreEquiv :
(Σ f₀ : X → Z.obj ⟨0⟩, P.toSliceDomPFunctor.Obj (pullbackProj Z f₀)) ≃
Σ yf : Y × (X → Z.obj ⟨0⟩), levelsFibre P Z yf where
toFun s := ⟨(P.obj (pullbackProj Z s.1) s.2, s.1), ⟨s.2, rfl⟩⟩
invFun s := ⟨s.1.2, s.2.1⟩
left_inv _ := rfl
right_inv s := levelsFibre_ext P Z s.2.1 s.2.2
GebProto.LargeIR.Levels as a walking-arrow presheaf: the
projection of the regrouped level-1 part onto the level-0
part.
def levelsPsh : (Fin 2)ᵒᵖ ⥤ Type :=
ofSlice (Sigma.fst : (Σ yf : Y × (X → Z.obj ⟨0⟩), levelsFibre P Z yf) → Y × (X → Z.obj ⟨0⟩))
The transcription's output presheaf is levelsPsh: the two level
equivalences, commuting with the restriction along 0 ⟶ 1 by
GebProto.LargeIR.toLevels_objRestr.
def objPresheafEquiv : PshEquiv ((arrowPsh P).objPresheaf Z) (levelsPsh P Z) where
base := levelZeroEquiv P Z
total := (levelOneEquiv P Z).trans (levelsFibreEquiv P Z)
map_total t :=
match t with
| ⟨⟨⟨⟨.inl _, _⟩, _⟩, _⟩, ht⟩ => absurd ht Fin.zero_ne_one
| ⟨⟨⟨⟨.inr _, _⟩, _⟩, _⟩, _⟩ => rflThe code's interpretation as a family
The level-0 part of GebProto.LargeIR.Levels is the index
type of the code's interpretation: a σ index, a δ assignment,
and the ι point.
def codeBaseEquiv :
(Y × (X → Z.obj ⟨0⟩)) ≃ (IR.interpObj Type Type (code P) (famOfPsh Z)).1 where
toFun yf := ⟨yf.1, yf.2, ⟨()⟩⟩
invFun s := (s.1, s.2.1)
left_inv _ := rfl
right_inv s :=
match s with
| ⟨_, _, ⟨⟨⟩⟩⟩ => rfl
Over (y, f₀), the slice functor's value at the pullback along
f₀ with output index y is the code's decoding: the fibre at
y applied to the decoded family T ∘ f₀.
def codeFibreEquiv (yf : Y × (X → Z.obj ⟨0⟩)) :
levelsFibre P Z yf ≃ fibreValue P yf.1 ((famOfPsh Z).2 ∘ yf.2) where
toFun o := ⟨⟨o.1.1.1, o.2⟩,
fun b ↦ ⟨(o.1.1.2 b).2.1, (o.1.1.2 b).2.2.trans (congrArg yf.2 (congrFun o.1.2 b))⟩⟩
invFun w := ⟨⟨⟨w.1.1, fun b ↦ ⟨P.r ⟨w.1.1, b⟩, w.2 b⟩⟩, rfl⟩, w.1.2⟩
left_inv o :=
Subtype.ext (Subtype.ext (Sigma.ext rfl (heq_of_eq (funext fun b ↦
pullbackAlong_ext Z (o.1.1.2 b) _ (congrFun o.1.2 b)))))
right_inv _ := rfl
levelsPsh is the presheaf of the code's interpretation at the
family of the input.
def levelsCodeEquiv :
PshEquiv (levelsPsh P Z) (pshOfFam (IR.interpObj Type Type (code P) (famOfPsh Z))) where
base := codeBaseEquiv P Z
total :=
{ toFun := fun s ↦ ⟨codeBaseEquiv P Z s.1, codeFibreEquiv P Z s.1 s.2⟩
invFun := fun s ↦
match s with
| ⟨⟨y, g, ⟨⟨⟩⟩⟩, w⟩ => ⟨(y, g), (codeFibreEquiv P Z (y, g)).symm w⟩
left_inv := fun s ↦
congrArg (Sigma.mk s.1) ((codeFibreEquiv P Z s.1).left_inv s.2)
right_inv := fun s ↦
match s with
| ⟨⟨y, g, ⟨⟨⟩⟩⟩, w⟩ =>
Sigma.ext rfl (heq_of_eq ((codeFibreEquiv P Z (y, g)).right_inv w)) }
map_total _ := rfl
The transcription's output presheaf at Z is the presheaf of the
interpretation of code P at the family of Z: the transcription
of a slice polynomial functor is the large inductive-recursive code
σ Y (fun y ↦ δ X (fun A ↦ ι (fibreValue P y A))).
def arrowPshCodeEquiv :
PshEquiv ((arrowPsh P).objPresheaf Z)
(pshOfFam (IR.interpObj Type Type (code P) (famOfPsh Z))) :=
(objPresheafEquiv P Z).trans (levelsCodeEquiv P Z)end GebProto.LargeIR