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.Code meta import GebMeta -- shake: keep; supplies the cite docstring role
set_option doc.verso true

Prototype: base-cartesian presheaf polynomial endofunctors on the walking arrow are codes

Throwaway exploration, not upstream-eligible content. Every declaration here is Classical.­choice-free.

GebProto.­LargeIR.­arrowPshCodeEquiv reads one presheaf polynomial endofunctor on the walking arrow, the transcription of a slice polynomial functor, as a large inductive-recursive code on Fam(Type). This module states the general case. A presheaf polynomial endofunctor F on the walking arrow has shapes at two levels, each shape a having directions D₀ a at level 0 and D₁ a at level 1 with a restriction ρ : D₁ a → D₀ a, and a level-1 shape a₁ restricting to a level-0 shape with reindexings of directions at each level. Its value at a walking-arrow presheaf Z, read as the family (U, T), is computed by elemEquiv: an element is a shape a, a base assignment g : D₀ a → U, and an assignment w : Π d : D₁ a, T (g (ρ d)).

The reading as a code needs one condition, BaseCartesian: for every level-1 shape, the reindexing of level-0 directions from its restriction is a bijection. Then the code is

σ (Shape 0) (fun a ↦ δ (D₀ a) (fun A ↦ σ (Π d : D₁ a, A (ρ d)) (fun w ↦ ι (fibre a A w)))),

genCode, whose σ indices are the level-0 shapes and the level-1 assignments of a level-0 shape, whose δ arities are its level-0 directions, and whose ι decodes to the level-1 shapes over it with the assignments restricting to w, genFibre. genCodeEquiv is the isomorphism of the functor's output presheaf with the presheaf of the code's interpretation at the family of the input, and arrowPshBaseCartesian exhibits the transcription of a slice polynomial functor as an instance.

The condition is not an artefact. Without it a level-1 shape carries a level-0 direction not reached from its restriction, whose value under a base assignment is an element of U unconstrained by the level-0 element below, so the fibre of the output family over that element has the index type U itself as a factor. The decoding of a code mentions U only through T ∘ g, and the interpretation of every code preserves the cartesian morphisms of families, those whose decoding maps are bijections, while a functor with such a factor does not; that argument is not formalized here.

Main definitions

  • Elem, elemEquiv — the value of a presheaf polynomial endofunctor on the walking arrow in dependent-type terms.

  • ElemAt, objLevel — the elements over a level, and restrElem the restriction from level 1 to level 0 on them.

  • BaseCartesian — the condition on reindexing at level 0.

  • genFibre, genCode — the fibre type and the code.

  • arrowPshBaseCartesian — the transcription of a slice polynomial functor is base-cartesian.

Main statements

  • objLevel_objRestr — the restriction of the output presheaf is restrElem on elements.

  • genCodeEquiv — the output presheaf of a base-cartesian functor is the presheaf of the code's interpretation.

References

Tags

prototype, presheaf, walking arrow, parametric right adjoint, inductive-recursive, code, cartesian

@[expose] public sectionopen CategoryTheory PresheafIRUniv IndRecnamespace GebProto.LargeIRvariable (F : PresheafPFunctor.{0, 0, 0, 0, 0, 0} (Fin 2) (Fin 2))

The value in dependent-type terms

The restriction of a shape's directions from level 1 to level 0.

abbrev dirRestr (a : F.A) : F.Direction a 1 F.Direction a 0 := F.directionRestr a waHom

The restriction of a level-1 shape to level 0.

abbrev restrShape₁ (a₁ : F.Shape 1) : F.Shape 0 := F.shapeRestr waHom a₁

The reindexing of level-0 directions from the restricted shape.

abbrev reindex₀ (a₁ : F.Shape 1) : F.Direction (restrShape₁ F a₁).1 0 F.Direction a₁.1 0 := F.reindex waHom a₁ (i := 0)

The reindexing of level-1 directions from the restricted shape.

abbrev reindex₁ (a₁ : F.Shape 1) : F.Direction (restrShape₁ F a₁).1 1 F.Direction a₁.1 1 := F.reindex waHom a₁ (i := 1)

Reindexing commutes with the restriction of directions.

theorem dirRestr_reindex₁ (a₁ : F.Shape 1) (d : F.Direction (restrShape₁ F a₁).1 1) : dirRestr F a₁.1 (reindex₁ F a₁ d) = reindex₀ F a₁ (dirRestr F _ d) := congrFun (F.isFunctorial.reindex_naturality waHom a₁ waHom) d
variable (Z : (Fin 2)ᵒᵖ Type)

The value of F at Z in dependent-type terms: a shape, a base assignment of its level-0 directions in Z 0, and an assignment of its level-1 directions in the fibres of Z 1 → Z 0 over the base assignment at the restricted directions.

def Elem : Type := Σ a : F.A, Σ g : F.Direction a 0 Z.obj 0, d : F.Direction a 1, (famOfPsh Z).2 (g (dirRestr F a d))

The other index of the walking arrow.

theorem eq_one_of_ne_zero {i : Fin 2} (h : i 0) : i = 1 := i:Fin 2h:i 0i = 1 All goals completed! 🐙

The raw assignment of an element built from a base assignment and a level-1 assignment: at a direction over 0 the base assignment, at one over 1 the level-1 assignment.

def assign {a : F.A} (g : F.Direction a 0 Z.obj 0) (w : d : F.Direction a 1, (famOfPsh Z).2 (g (dirRestr F a d))) (b : F.B a) : Σ i : Fin 2, Z.obj i := if h : F.r a, b = 0 then 0, g b, h else 1, (w b, eq_one_of_ne_zero h).1

The raw assignment at a direction over 0.

theorem assign_zero {a : F.A} (g : F.Direction a 0 Z.obj 0) (w : d : F.Direction a 1, (famOfPsh Z).2 (g (dirRestr F a d))) {b : F.B a} (h : F.r a, b = 0) : assign F Z g w b = 0, g b, h := dite_eq_left h

The raw assignment at a direction over 1.

theorem assign_one {a : F.A} (g : F.Direction a 0 Z.obj 0) (w : d : F.Direction a 1, (famOfPsh Z).2 (g (dirRestr F a d))) {b : F.B a} (h : F.r a, b = 1) : assign F Z g w b = 1, (w b, h).1 := dite_eq_right fun h' Fin.zero_ne_one (h'.symm.trans h)

The raw assignment is compatible with the direction-input map.

theorem assign_compatible {a : F.A} (g : F.Direction a 0 Z.obj 0) (w : d : F.Direction a 1, (famOfPsh Z).2 (g (dirRestr F a d))) : F.Compatible (PresheafDomPFunctorData.elemProj Z) a (assign F Z g w) := F:PresheafPFunctor (Fin 2) (Fin 2)Z:(Fin 2)ᵒᵖ Typea:F.Ag:F.Direction a 0 Z.obj (Opposite.op 0)w:(d : F.Direction a 1) (famOfPsh Z).snd (g (dirRestr F a d))F.Compatible (PresheafDomPFunctorData.elemProj Z) a (assign F Z g w) F:PresheafPFunctor (Fin 2) (Fin 2)Z:(Fin 2)ᵒᵖ Typea:F.Ag:F.Direction a 0 Z.obj (Opposite.op 0)w:(d : F.Direction a 1) (famOfPsh Z).snd (g (dirRestr F a d))b:F.B a(PresheafDomPFunctorData.elemProj Z assign F Z g w) b = (F.r Sigma.mk a) b F:PresheafPFunctor (Fin 2) (Fin 2)Z:(Fin 2)ᵒᵖ Typea:F.Ag:F.Direction a 0 Z.obj (Opposite.op 0)w:(d : F.Direction a 1) (famOfPsh Z).snd (g (dirRestr F a d))b:F.B ah:F.r a, b = 0(PresheafDomPFunctorData.elemProj Z assign F Z g w) b = (F.r Sigma.mk a) bF:PresheafPFunctor (Fin 2) (Fin 2)Z:(Fin 2)ᵒᵖ Typea:F.Ag:F.Direction a 0 Z.obj (Opposite.op 0)w:(d : F.Direction a 1) (famOfPsh Z).snd (g (dirRestr F a d))b:F.B ah:¬F.r a, b = 0(PresheafDomPFunctorData.elemProj Z assign F Z g w) b = (F.r Sigma.mk a) b F:PresheafPFunctor (Fin 2) (Fin 2)Z:(Fin 2)ᵒᵖ Typea:F.Ag:F.Direction a 0 Z.obj (Opposite.op 0)w:(d : F.Direction a 1) (famOfPsh Z).snd (g (dirRestr F a d))b:F.B ah:F.r a, b = 0(PresheafDomPFunctorData.elemProj Z assign F Z g w) b = (F.r Sigma.mk a) b F:PresheafPFunctor (Fin 2) (Fin 2)Z:(Fin 2)ᵒᵖ Typea:F.Ag:F.Direction a 0 Z.obj (Opposite.op 0)w:(d : F.Direction a 1) (famOfPsh Z).snd (g (dirRestr F a d))b:F.B ah:F.r a, b = 0(assign F Z g w b).fst = F.r a, b F:PresheafPFunctor (Fin 2) (Fin 2)Z:(Fin 2)ᵒᵖ Typea:F.Ag:F.Direction a 0 Z.obj (Opposite.op 0)w:(d : F.Direction a 1) (famOfPsh Z).snd (g (dirRestr F a d))b:F.B ah:F.r a, b = 00, g b, h.fst = F.r a, b All goals completed! 🐙 F:PresheafPFunctor (Fin 2) (Fin 2)Z:(Fin 2)ᵒᵖ Typea:F.Ag:F.Direction a 0 Z.obj (Opposite.op 0)w:(d : F.Direction a 1) (famOfPsh Z).snd (g (dirRestr F a d))b:F.B ah:¬F.r a, b = 0(PresheafDomPFunctorData.elemProj Z assign F Z g w) b = (F.r Sigma.mk a) b F:PresheafPFunctor (Fin 2) (Fin 2)Z:(Fin 2)ᵒᵖ Typea:F.Ag:F.Direction a 0 Z.obj (Opposite.op 0)w:(d : F.Direction a 1) (famOfPsh Z).snd (g (dirRestr F a d))b:F.B ah:¬F.r a, b = 0(assign F Z g w b).fst = F.r a, b F:PresheafPFunctor (Fin 2) (Fin 2)Z:(Fin 2)ᵒᵖ Typea:F.Ag:F.Direction a 0 Z.obj (Opposite.op 0)w:(d : F.Direction a 1) (famOfPsh Z).snd (g (dirRestr F a d))b:F.B ah:¬F.r a, b = 01, (w b, ).fst = F.r a, b All goals completed! 🐙

The element built from a base assignment and a level-1 assignment, before its naturality.

def assignObj {a : F.A} (g : F.Direction a 0 Z.obj 0) (w : d : F.Direction a 1, (famOfPsh Z).2 (g (dirRestr F a d))) : F.toSliceDomPFunctor.Obj (PresheafDomPFunctorData.elemProj Z) := a, assign F Z g w, assign_compatible F Z g w

The value the built element gives a level-0 direction is the base assignment.

theorem value_assignObj_zero {a : F.A} (g : F.Direction a 0 Z.obj 0) (w : d : F.Direction a 1, (famOfPsh Z).2 (g (dirRestr F a d))) (d : F.Direction a 0) : F.value (assignObj F Z g w) d = g d := eq_of_heq (Sigma.mk.inj_iff.mp ((sigma_value Z F.toPresheafDomPFunctorData (assignObj F Z g w) d).trans (assign_zero F Z g w d.2))).2

The value the built element gives a level-1 direction is the level-1 assignment.

theorem value_assignObj_one {a : F.A} (g : F.Direction a 0 Z.obj 0) (w : d : F.Direction a 1, (famOfPsh Z).2 (g (dirRestr F a d))) (d : F.Direction a 1) : F.value (assignObj F Z g w) d = (w d).1 := eq_of_heq (Sigma.mk.inj_iff.mp ((sigma_value Z F.toPresheafDomPFunctorData (assignObj F Z g w) d).trans (assign_one F Z g w d.2))).2

Two elements of Elem with the same shape are equal when their base assignments agree and their level-1 assignments agree in Z 1.

theorem gw_ext {a : F.A} {g g' : F.Direction a 0 Z.obj 0} (hg : g' = g) {w : d : F.Direction a 1, (famOfPsh Z).2 (g (dirRestr F a d))} {w' : d : F.Direction a 1, (famOfPsh Z).2 (g' (dirRestr F a d))} (hw : d, (w' d).1 = (w d).1) : (g', w' : Σ g : F.Direction a 0 Z.obj 0, d : F.Direction a 1, (famOfPsh Z).2 (g (dirRestr F a d))) = g, w := F:PresheafPFunctor (Fin 2) (Fin 2)Z:(Fin 2)ᵒᵖ Typea:F.Ag:F.Direction a 0 Z.obj (Opposite.op 0)g':F.Direction a 0 Z.obj (Opposite.op 0)hg:g' = gw:(d : F.Direction a 1) (famOfPsh Z).snd (g (dirRestr F a d))w':(d : F.Direction a 1) (famOfPsh Z).snd (g' (dirRestr F a d))hw: (d : F.Direction a 1), (w' d) = (w d)g', w' = g, w F:PresheafPFunctor (Fin 2) (Fin 2)Z:(Fin 2)ᵒᵖ Typea:F.Ag':F.Direction a 0 Z.obj (Opposite.op 0)w':(d : F.Direction a 1) (famOfPsh Z).snd (g' (dirRestr F a d))w:(d : F.Direction a 1) (famOfPsh Z).snd (g' (dirRestr F a d))hw: (d : F.Direction a 1), (w' d) = (w d)g', w' = g', w All goals completed! 🐙

The value of F at Z is Elem F Z.

def elemEquiv : F.obj Z Elem F Z where toFun x := x.shape, fun d F.value x.1 d, fun d F.value x.1 d, (x.2 waHom d).symm invFun e := assignObj F Z e.2.1 e.2.2, (isNatural_iff F.toPresheafDomPFunctorData F.isFunctorial.directionRestr_id Z _).mpr fun d (value_assignObj_zero F Z _ _ _).trans ((e.2.2 d).2.symm.trans (congrArg _ (value_assignObj_one F Z _ _ d).symm)) left_inv x := F:PresheafPFunctor (Fin 2) (Fin 2)Z:(Fin 2)ᵒᵖ Typex:F.obj Z(fun e assignObj F Z e.snd.fst e.snd.snd, ) ((fun x x.shape, fun d F.value (↑x) d, fun d F.value (↑x) d, ) x) = x F:PresheafPFunctor (Fin 2) (Fin 2)Z:(Fin 2)ᵒᵖ Typex:F.obj Zb:F.B (↑((fun e assignObj F Z e.snd.fst e.snd.snd, ) ((fun x x.shape, fun d F.value (↑x) d, fun d F.value (↑x) d, ) x))).fst(↑((fun e assignObj F Z e.snd.fst e.snd.snd, ) ((fun x x.shape, fun d F.value (↑x) d, fun d F.value (↑x) d, ) x))).snd b = (↑x).snd b F:PresheafPFunctor (Fin 2) (Fin 2)Z:(Fin 2)ᵒᵖ Typex:F.obj Zb:F.B (↑((fun e assignObj F Z e.snd.fst e.snd.snd, ) ((fun x x.shape, fun d F.value (↑x) d, fun d F.value (↑x) d, ) x))).fsth:F.r x.shape, b = 0(↑((fun e assignObj F Z e.snd.fst e.snd.snd, ) ((fun x x.shape, fun d F.value (↑x) d, fun d F.value (↑x) d, ) x))).snd b = (↑x).snd bF:PresheafPFunctor (Fin 2) (Fin 2)Z:(Fin 2)ᵒᵖ Typex:F.obj Zb:F.B (↑((fun e assignObj F Z e.snd.fst e.snd.snd, ) ((fun x x.shape, fun d F.value (↑x) d, fun d F.value (↑x) d, ) x))).fsth:¬F.r x.shape, b = 0(↑((fun e assignObj F Z e.snd.fst e.snd.snd, ) ((fun x x.shape, fun d F.value (↑x) d, fun d F.value (↑x) d, ) x))).snd b = (↑x).snd b F:PresheafPFunctor (Fin 2) (Fin 2)Z:(Fin 2)ᵒᵖ Typex:F.obj Zb:F.B (↑((fun e assignObj F Z e.snd.fst e.snd.snd, ) ((fun x x.shape, fun d F.value (↑x) d, fun d F.value (↑x) d, ) x))).fsth:F.r x.shape, b = 0(↑((fun e assignObj F Z e.snd.fst e.snd.snd, ) ((fun x x.shape, fun d F.value (↑x) d, fun d F.value (↑x) d, ) x))).snd b = (↑x).snd b All goals completed! 🐙 F:PresheafPFunctor (Fin 2) (Fin 2)Z:(Fin 2)ᵒᵖ Typex:F.obj Zb:F.B (↑((fun e assignObj F Z e.snd.fst e.snd.snd, ) ((fun x x.shape, fun d F.value (↑x) d, fun d F.value (↑x) d, ) x))).fsth:¬F.r x.shape, b = 0(↑((fun e assignObj F Z e.snd.fst e.snd.snd, ) ((fun x x.shape, fun d F.value (↑x) d, fun d F.value (↑x) d, ) x))).snd b = (↑x).snd b All goals completed! 🐙 right_inv e := Sigma.ext rfl (heq_of_eq (gw_ext F Z (funext fun d value_assignObj_zero F Z _ _ d) fun d value_assignObj_one F Z _ _ d))

Elements by level, and the restriction

The elements over a level: those of Elem whose shape lies over it.

def ElemAt (j : Fin 2) : Type := Σ a : F.Shape j, Σ g : F.Direction a.1 0 Z.obj 0, d : F.Direction a.1 1, (famOfPsh Z).2 (g (dirRestr F a.1 d))

Two elements of Elem reassembled with their shapes' level conditions are equal when they are.

theorem elemAt_congr {j : Fin 2} (t s : Elem F Z) (e : t = s) (h : F.q t.1 = j) : (t.1, h, t.2 : ElemAt F Z j) = s.1, e h, s.2 := F:PresheafPFunctor (Fin 2) (Fin 2)Z:(Fin 2)ᵒᵖ Typej:Fin 2t:Elem F Zs:Elem F Ze:t = sh:F.q t.fst = jt.fst, h, t.snd = s.fst, , s.snd F:PresheafPFunctor (Fin 2) (Fin 2)Z:(Fin 2)ᵒᵖ Typej:Fin 2t:Elem F Zh:F.q t.fst = jt.fst, h, t.snd = t.fst, , t.snd All goals completed! 🐙

The elements of the output presheaf over a level are the elements of Elem over it.

def objLevel (j : Fin 2) : { x : F.obj Z // F.q x.shape = j } ElemAt F Z j where toFun x := (elemEquiv F Z x.1).1, x.2, (elemEquiv F Z x.1).2 invFun e := (elemEquiv F Z).symm e.1.1, e.2, e.1.2 left_inv x := Subtype.ext ((elemEquiv F Z).left_inv x.1) right_inv e := elemAt_congr F Z _ _ ((elemEquiv F Z).right_inv e.1.1, e.2) _

The restriction from level 1 to level 0 on elements: restrict the shape and precompose the assignments with the reindexings.

def restrElem (e : ElemAt F Z 1) : ElemAt F Z 0 := restrShape₁ F e.1, fun d e.2.1 (reindex₀ F e.1 d), fun d (e.2.2 (reindex₁ F e.1 d)).1, (e.2.2 (reindex₁ F e.1 d)).2.trans (congrArg e.2.1 (dirRestr_reindex₁ F e.1 d))

The value the restriction of an element gives a direction is the value the element gives its reindexing.

theorem value_objRestr (x : F.obj Z) (hx : F.q x.shape = 1) i : Fin 2 (d : F.Direction (F.objRestr waHom x hx).shape i) : F.value (F.objRestr waHom x hx).1 d = F.value x.1 (F.reindex waHom x.shape, hx d) := F:PresheafPFunctor (Fin 2) (Fin 2)Z:(Fin 2)ᵒᵖ Typex:F.obj Zhx:F.q x.shape = 1i:Fin 2d:F.Direction (F.objRestr waHom x hx).shape iF.value (↑(F.objRestr waHom x hx)) d = F.value (↑x) (F.reindex waHom x.shape, hx d) F:PresheafPFunctor (Fin 2) (Fin 2)Z:(Fin 2)ᵒᵖ Typex:F.obj Zhx:F.q x.shape = 1b:F.B (F.objRestr waHom x hx).shapeF.value (F.objRestr waHom x hx) b, = F.value (↑x) (F.reindex waHom x.shape, hx b, ) All goals completed! 🐙

The restriction of the output presheaf is restrElem on elements.

theorem objLevel_objRestr (x : F.obj Z) (hx : F.q x.shape = 1) : objLevel F Z 0 F.objRestr waHom x hx, (F.shapeRestr waHom x.shape, hx).2 = restrElem F Z (objLevel F Z 1 x, hx) := Sigma.ext rfl (heq_of_eq (gw_ext F Z (funext fun d value_objRestr F Z x hx d) fun d value_objRestr F Z x hx d))

The condition and the code

A presheaf polynomial endofunctor on the walking arrow is base-cartesian when, for every level-1 shape, the reindexing of level-0 directions from its restriction is a bijection.

The inverse of the reindexing at level 0.

The inverse is a left inverse.

The inverse is a right inverse.

structure BaseCartesian where inv : a₁ : F.Shape 1, F.Direction a₁.1 0 F.Direction (restrShape₁ F a₁).1 0 inv_reindex : (a₁ : F.Shape 1) d, inv a₁ (reindex₀ F a₁ d) = d reindex_inv : (a₁ : F.Shape 1) d, reindex₀ F a₁ (inv a₁ d) = d
variable {F} (hF : BaseCartesian F)

The inverse reindexing sends the restriction of a reindexed direction to the restriction of the direction.

theorem BaseCartesian.inv_dirRestr_reindex₁ (a₁ : F.Shape 1) (d : F.Direction (restrShape₁ F a₁).1 1) : hF.inv a₁ (dirRestr F a₁.1 (reindex₁ F a₁ d)) = dirRestr F _ d := F:PresheafPFunctor (Fin 2) (Fin 2)hF:BaseCartesian Fa₁:F.toSlicePFunctor.Shape 1d:F.Direction (↑(restrShape₁ F a₁)) 1hF.inv a₁ (dirRestr F (↑a₁) (reindex₁ F a₁ d)) = dirRestr F (↑(restrShape₁ F a₁)) d F:PresheafPFunctor (Fin 2) (Fin 2)hF:BaseCartesian Fa₁:F.toSlicePFunctor.Shape 1d:F.Direction (↑(restrShape₁ F a₁)) 1hF.inv a₁ (reindex₀ F a₁ (dirRestr F (↑(restrShape₁ F a₁)) d)) = dirRestr F (↑(restrShape₁ F a₁)) d All goals completed! 🐙

The fibre at a level-1 shape: assignments of its level-1 directions, the family read at the inverse reindexing of the restricted direction, that restrict along the reindexing to a given assignment of the restricted shape.

def genFibre₁ (a₁ : F.Shape 1) (A : F.Direction (restrShape₁ F a₁).1 0 Type) (w : d : F.Direction (restrShape₁ F a₁).1 1, A (dirRestr F _ d)) : Type := { w₁ : d₁ : F.Direction a₁.1 1, A (hF.inv a₁ (dirRestr F a₁.1 d₁)) // d, HEq (w₁ (reindex₁ F a₁ d)) (w d) }

The fibre at a level-1 shape over a level-0 shape it restricts to, by transport along the restriction equation.

def genFibreAt (a₁ : F.Shape 1) : (a : F.Shape 0) restrShape₁ F a₁ = a (A : F.Direction a.1 0 Type) ( d : F.Direction a.1 1, A (dirRestr F a.1 d)) Type | _, rfl, A, w => genFibre₁ hF a₁ A w

The decoding of the code at a level-0 element: the level-1 shapes over its shape, each with its fibre.

def genFibre (a : F.Shape 0) (A : F.Direction a.1 0 Type) (w : d : F.Direction a.1 1, A (dirRestr F a.1 d)) : Type := Σ a₁ : { a₁ : F.Shape 1 // restrShape₁ F a₁ = a }, genFibreAt hF a₁.1 a a₁.2 A w

The code of a base-cartesian presheaf polynomial endofunctor on the walking arrow.

def genCode : IR.{0, 0, 1, 1} Type Type := IR.sigma Type Type (F.Shape 0) fun a IR.delta Type Type (F.Direction a.1 0) fun A IR.sigma Type Type ( d : F.Direction a.1 1, A (dirRestr F a.1 d)) fun w IR.iota Type Type (genFibre hF a A w)

The isomorphism

The level-0 elements are the index type of the code's interpretation.

def genBaseEquiv : ElemAt F Z 0 (IR.interpObj Type Type (genCode hF) (famOfPsh Z)).1 where toFun e := e.1, e.2.1, e.2.2, () invFun s := s.1, s.2.1, s.2.2.1 left_inv _ := rfl right_inv s := match s with | _, _, _, => rfl

Two elements of the fibre over equal points are heterogeneously equal when they agree in Z 1.

theorem fibre_heq {u u' : Z.obj 0} (e : u = u') (x : (famOfPsh Z).2 u) (y : (famOfPsh Z).2 u') (h : x.1 = y.1) : HEq x y := Z:(Fin 2)ᵒᵖ Typeu:Z.obj (Opposite.op 0)u':Z.obj (Opposite.op 0)e:u = u'x:(famOfPsh Z).snd uy:(famOfPsh Z).snd u'h:x = yx y Z:(Fin 2)ᵒᵖ Typeu:Z.obj (Opposite.op 0)x:(famOfPsh Z).snd uy:(famOfPsh Z).snd uh:x = yx y All goals completed! 🐙

Heterogeneously equal elements of the fibre over equal points agree in Z 1.

theorem fst_of_fibre_heq {u u' : Z.obj 0} (e : u = u') {x : (famOfPsh Z).2 u} {y : (famOfPsh Z).2 u'} (h : HEq x y) : x.1 = y.1 := Z:(Fin 2)ᵒᵖ Typeu:Z.obj (Opposite.op 0)u':Z.obj (Opposite.op 0)e:u = u'x:(famOfPsh Z).snd uy:(famOfPsh Z).snd u'h:x yx = y Z:(Fin 2)ᵒᵖ Typeu:Z.obj (Opposite.op 0)x:(famOfPsh Z).snd uy:(famOfPsh Z).snd uh:x yx = y All goals completed! 🐙

An element of the code's total space with a level-1 shape at its own restriction, from the base assignment, the level-1 assignment and the fibre element.

def genTotalMk (a₁ : F.Shape 1) (g : F.Direction (restrShape₁ F a₁).1 0 Z.obj 0) (w : d : F.Direction (restrShape₁ F a₁).1 1, (famOfPsh Z).2 (g (dirRestr F _ d))) (f : genFibre₁ hF a₁ ((famOfPsh Z).2 g) w) : Σ p : (IR.interpObj Type Type (genCode hF) (famOfPsh Z)).1, (IR.interpObj Type Type (genCode hF) (famOfPsh Z)).2 p := restrShape₁ F a₁, g, w, (), a₁, rfl, f

Two elements of the code's total space at the same level-1 shape are equal when their base assignments agree and their assignments agree in Z 1.

theorem genTotalMk_ext (a₁ : F.Shape 1) {g g' : F.Direction (restrShape₁ F a₁).1 0 Z.obj 0} (hg : g' = g) {w : d : F.Direction (restrShape₁ F a₁).1 1, (famOfPsh Z).2 (g (dirRestr F _ d))} {w' : d : F.Direction (restrShape₁ F a₁).1 1, (famOfPsh Z).2 (g' (dirRestr F _ d))} (hw : d, (w' d).1 = (w d).1) {f : genFibre₁ hF a₁ ((famOfPsh Z).2 g) w} {f' : genFibre₁ hF a₁ ((famOfPsh Z).2 g') w'} (hf : d₁, (f'.1 d₁).1 = (f.1 d₁).1) : genTotalMk Z hF a₁ g' w' f' = genTotalMk Z hF a₁ g w f := F:PresheafPFunctor (Fin 2) (Fin 2)Z:(Fin 2)ᵒᵖ TypehF:BaseCartesian Fa₁:F.toSlicePFunctor.Shape 1g:F.Direction (↑(restrShape₁ F a₁)) 0 Z.obj (Opposite.op 0)g':F.Direction (↑(restrShape₁ F a₁)) 0 Z.obj (Opposite.op 0)hg:g' = gw:(d : F.Direction (↑(restrShape₁ F a₁)) 1) (famOfPsh Z).snd (g (dirRestr F (↑(restrShape₁ F a₁)) d))w':(d : F.Direction (↑(restrShape₁ F a₁)) 1) (famOfPsh Z).snd (g' (dirRestr F (↑(restrShape₁ F a₁)) d))hw: (d : F.Direction (↑(restrShape₁ F a₁)) 1), (w' d) = (w d)f:genFibre₁ hF a₁ ((famOfPsh Z).snd g) wf':genFibre₁ hF a₁ ((famOfPsh Z).snd g') w'hf: (d₁ : F.Direction (↑a₁) 1), (f' d₁) = (f d₁)genTotalMk Z hF a₁ g' w' f' = genTotalMk Z hF a₁ g w f F:PresheafPFunctor (Fin 2) (Fin 2)Z:(Fin 2)ᵒᵖ TypehF:BaseCartesian Fa₁:F.toSlicePFunctor.Shape 1g':F.Direction (↑(restrShape₁ F a₁)) 0 Z.obj (Opposite.op 0)w':(d : F.Direction (↑(restrShape₁ F a₁)) 1) (famOfPsh Z).snd (g' (dirRestr F (↑(restrShape₁ F a₁)) d))f':genFibre₁ hF a₁ ((famOfPsh Z).snd g') w'w:(d : F.Direction (↑(restrShape₁ F a₁)) 1) (famOfPsh Z).snd (g' (dirRestr F (↑(restrShape₁ F a₁)) d))hw: (d : F.Direction (↑(restrShape₁ F a₁)) 1), (w' d) = (w d)f:genFibre₁ hF a₁ ((famOfPsh Z).snd g') whf: (d₁ : F.Direction (↑a₁) 1), (f' d₁) = (f d₁)genTotalMk Z hF a₁ g' w' f' = genTotalMk Z hF a₁ g' w f F:PresheafPFunctor (Fin 2) (Fin 2)Z:(Fin 2)ᵒᵖ TypehF:BaseCartesian Fa₁:F.toSlicePFunctor.Shape 1g':F.Direction (↑(restrShape₁ F a₁)) 0 Z.obj (Opposite.op 0)w':(d : F.Direction (↑(restrShape₁ F a₁)) 1) (famOfPsh Z).snd (g' (dirRestr F (↑(restrShape₁ F a₁)) d))f':genFibre₁ hF a₁ ((famOfPsh Z).snd g') w'hw: (d : F.Direction (↑(restrShape₁ F a₁)) 1), (w' d) = (w' d)f:genFibre₁ hF a₁ ((famOfPsh Z).snd g') w'hf: (d₁ : F.Direction (↑a₁) 1), (f' d₁) = (f d₁)genTotalMk Z hF a₁ g' w' f' = genTotalMk Z hF a₁ g' w' f F:PresheafPFunctor (Fin 2) (Fin 2)Z:(Fin 2)ᵒᵖ TypehF:BaseCartesian Fa₁:F.toSlicePFunctor.Shape 1g':F.Direction (↑(restrShape₁ F a₁)) 0 Z.obj (Opposite.op 0)w':(d : F.Direction (↑(restrShape₁ F a₁)) 1) (famOfPsh Z).snd (g' (dirRestr F (↑(restrShape₁ F a₁)) d))f':genFibre₁ hF a₁ ((famOfPsh Z).snd g') w'hw: (d : F.Direction (↑(restrShape₁ F a₁)) 1), (w' d) = (w' d)hf: (d₁ : F.Direction (↑a₁) 1), (f' d₁) = (f' d₁)genTotalMk Z hF a₁ g' w' f' = genTotalMk Z hF a₁ g' w' f' All goals completed! 🐙

The inverse of the level-1 equivalence at a level-1 shape over a level-0 shape it restricts to.

def genTotalInv (a₁ : F.Shape 1) : (a : F.Shape 0) (h : restrShape₁ F a₁ = a) (g : F.Direction a.1 0 Z.obj 0) (w : d : F.Direction a.1 1, (famOfPsh Z).2 (g (dirRestr F a.1 d))) genFibreAt hF a₁ a h ((famOfPsh Z).2 g) w ElemAt F Z 1 | _, rfl, g, _, f => a₁, fun d g (hF.inv a₁ d), fun d₁ f.1 d₁

The level-1 equivalence on an element: restrict to the level-0 element below, and keep the level-1 assignment as the fibre element, reindexed by the inverse at level 0.

def genTotalTo (e : ElemAt F Z 1) : Σ p : (IR.interpObj Type Type (genCode hF) (famOfPsh Z)).1, (IR.interpObj Type Type (genCode hF) (famOfPsh Z)).2 p := genTotalMk Z hF e.1 (fun d e.2.1 (reindex₀ F e.1 d)) (fun d (e.2.2 (reindex₁ F e.1 d)).1, (e.2.2 (reindex₁ F e.1 d)).2.trans (congrArg e.2.1 (dirRestr_reindex₁ F e.1 d))) fun d₁ (e.2.2 d₁).1, (e.2.2 d₁).2.trans (congrArg e.2.1 (hF.reindex_inv e.1 _).symm), fun d fibre_heq Z (congrArg (fun d e.2.1 (reindex₀ F e.1 d)) (hF.inv_dirRestr_reindex₁ e.1 d)) _ _ rfl

The level-1 equivalence inverts its inverse.

theorem genTotalTo_genTotalInv (a₁ : F.Shape 1) (a : F.Shape 0) (h : restrShape₁ F a₁ = a) (g : F.Direction a.1 0 Z.obj 0) (w : d : F.Direction a.1 1, (famOfPsh Z).2 (g (dirRestr F a.1 d))) (f : genFibreAt hF a₁ a h ((famOfPsh Z).2 g) w) : genTotalTo Z hF (genTotalInv Z hF a₁ a h g w f) = a, g, w, (), a₁, h, f := F:PresheafPFunctor (Fin 2) (Fin 2)Z:(Fin 2)ᵒᵖ TypehF:BaseCartesian Fa₁:F.toSlicePFunctor.Shape 1a:F.toSlicePFunctor.Shape 0h:restrShape₁ F a₁ = ag:F.Direction (↑a) 0 Z.obj (Opposite.op 0)w:(d : F.Direction (↑a) 1) (famOfPsh Z).snd (g (dirRestr F (↑a) d))f:genFibreAt hF a₁ a h ((famOfPsh Z).snd g) wgenTotalTo Z hF (genTotalInv Z hF a₁ a h g w f) = a, g, w, { down := () }, a₁, h, f F:PresheafPFunctor (Fin 2) (Fin 2)Z:(Fin 2)ᵒᵖ TypehF:BaseCartesian Fa₁:F.toSlicePFunctor.Shape 1g:F.Direction (↑(restrShape₁ F a₁)) 0 Z.obj (Opposite.op 0)w:(d : F.Direction (↑(restrShape₁ F a₁)) 1) (famOfPsh Z).snd (g (dirRestr F (↑(restrShape₁ F a₁)) d))f:genFibreAt hF a₁ (restrShape₁ F a₁) ((famOfPsh Z).snd g) wgenTotalTo Z hF (genTotalInv Z hF a₁ (restrShape₁ F a₁) g w f) = restrShape₁ F a₁, g, w, { down := () }, a₁, , f All goals completed! 🐙

The level-1 elements are the total space of the code's interpretation: the level-0 element below, and the fibre element.

def genTotalEquiv : ElemAt F Z 1 Σ p : (IR.interpObj Type Type (genCode hF) (famOfPsh Z)).1, (IR.interpObj Type Type (genCode hF) (famOfPsh Z)).2 p where toFun := genTotalTo Z hF invFun s := genTotalInv Z hF s.2.1.1 s.1.1 s.2.1.2 s.1.2.1 s.1.2.2.1 s.2.2 left_inv e := Sigma.ext rfl (heq_of_eq (gw_ext F Z (funext fun d congrArg e.2.1 (hF.reindex_inv e.1 d)) fun _ rfl)) right_inv s := genTotalTo_genTotalInv Z hF s.2.1.1 s.1.1 s.2.1.2 s.1.2.1 s.1.2.2.1 s.2.2

The output presheaf of a base-cartesian presheaf polynomial endofunctor on the walking arrow is the presheaf of the interpretation of its code at the family of the input.

def genCodeEquiv : PshEquiv (F.objPresheaf Z) (pshOfFam (IR.interpObj Type Type (genCode hF) (famOfPsh Z))) where base := (objLevel F Z 0).trans (genBaseEquiv Z hF) total := (objLevel F Z 1).trans (genTotalEquiv Z hF) map_total t := congrArg (fun e : ElemAt F Z 0 genBaseEquiv Z hF e) (objLevel_objRestr F Z t.1 t.2).symm

The transcription is an instance

The transcription of a slice polynomial functor is base-cartesian: every shape has the level-0 directions X, on which reindexing is the identity.

def arrowPshBaseCartesian {X Y : Type} (P : SlicePFunctor.{0, 0, 0, 0} X Y) : BaseCartesian (arrowPsh P) where inv a₁ d := match a₁, d with | .inl _, h, _ => absurd h Fin.zero_ne_one | .inr _, _, .inl x, _ => .inl x, rfl | .inr _, _, .inr _, h => absurd h Fin.zero_ne_one.symm inv_reindex a₁ d := match a₁, d with | .inl _, h, _ => absurd h Fin.zero_ne_one | .inr _, _, .inl _, _ => rfl | .inr _, _, .inr e, _ => PEmpty.elim e reindex_inv a₁ d := match a₁, d with | .inl _, h, _ => absurd h Fin.zero_ne_one | .inr _, _, .inl _, _ => rfl | .inr _, _, .inr _, h => absurd h Fin.zero_ne_one.symm
end GebProto.LargeIR