Here we instanciate our abstract notion of context structure with the most common example: lists and DeBruijn indices. More pedantically, this is the free context structure over a given set X.
Contexts are simply lists, with the purely aesthetic choice of representing cons as coming from the right. Note on paper: we write here "Ξ βΆ x" instead of "Ξ , x".
Inductive ctx (X : Type) : Type :=
| cnil : ctx X
| ccon : ctx X -> X -> ctx X.
#[global] Notation "β β" := (cnil) : ctx_scope. #[global] Notation "Ξ βΆβ x" := (ccon Ξ%ctx x) (at level 40, left associativity) : ctx_scope.
We wish to manipulate intrinsically typed terms. We hence need a tightly typed notion of position in the context: rather than a loose index, var x Ξ is a proof of membership of x to Ξ: a well-scoped and well-typed DeBruijn index.
Inductive var {X} (x : X) : ctx X -> Type := | top {Ξ} : var x (Ξ βΆβ x) | pop {Ξ y} : var x Ξ -> var x (Ξ βΆβ y). Definition cvar {X} Ξ x := @var X x Ξ.
A couple basic functions: length, concatenation and pointwise function application.
Equations c_length {X} (Ξ : ctx X) : nat := c_length β β := Datatypes.O ; c_length (Ξ βΆβ _) := Datatypes.S (c_length Ξ) . Equations ccat {X} : ctx X -> ctx X -> ctx X := ccat Ξ β β := Ξ ; ccat Ξ (Ξ βΆβ x) := ccat Ξ Ξ βΆβ x . Equations c_map {X Y} : (X -> Y) -> ctx X -> ctx Y := c_map f β β := cnil ; c_map f (Ξ βΆβ x) := c_map f Ξ βΆβ f x .
Implementation of the revelant part of the abstract context interface.
#[global] Instance free_context {X} : context X (ctx X) :=
{| c_emp := cnil ; c_cat := ccat ; c_var := cvar |}.
Basic theory.
X: Type
Ξ: ctx Xβ +βΆ Ξ = Ξinduction Ξ; eauto; cbn; f_equal; apply IHΞ. Qed.X: Type
Ξ: ctx Xβ +βΆ Ξ = ΞX: Type
Ξ: ctx XΞ +βΆ β = Ξreflexivity. Qed.X: Type
Ξ: ctx XΞ +βΆ β = ΞX, Y: Type
f: X -> Y
Ξ, Ξ: ctx Xc_map f (Ξ +βΆ Ξ) = c_map f Ξ +βΆ c_map f Ξinduction Ξ; eauto; cbn; f_equal; apply IHΞ. Qed.X, Y: Type
f: X -> Y
Ξ, Ξ: ctx Xc_map f (Ξ +βΆ Ξ) = c_map f Ξ +βΆ c_map f Ξ
A view-based inversion package for variables in mapped contexts.
Equations map_has {X Y} {f : X -> Y} (Ξ : ctx X) {x} (i : Ξ β x) : c_map f Ξ β f x := map_has (Ξ βΆβ _) top := top ; map_has (Ξ βΆβ _) (pop i) := pop (map_has Ξ i) . #[global] Arguments map_has {X Y f Ξ x}. Variant has_map_view {X Y} {f : X -> Y} {Ξ} : forall {y}, c_map f Ξ β y -> Type := | HasMapV {x} (i : Ξ β x) : has_map_view (map_has i).X, Y: Type
f: X -> Y
Ξ: ctx X
y: Y
i: c_map f Ξ β yhas_map_view iX, Y: Type
f: X -> Y
Ξ: ctx X
y: Y
i: c_map f Ξ β yhas_map_view iX, Y: Type
f: X -> Y
Ξ: ctx X
x: X
IHΞ: forall i : c_map f Ξ β f x, has_map_view ihas_map_view topX, Y: Type
f: X -> Y
Ξ: ctx X
x: X
y: Y
v: var y (c_map f Ξ)
IHΞ: forall i : c_map f Ξ β y, has_map_view ihas_map_view (pop v)exact (HasMapV top).X, Y: Type
f: X -> Y
Ξ: ctx X
x: X
IHΞ: forall i : c_map f Ξ β f x, has_map_view ihas_map_view topdestruct (IHΞ v); exact (HasMapV (pop i)). Qed.X, Y: Type
f: X -> Y
Ξ: ctx X
x: X
y: Y
v: var y (c_map f Ξ)
IHΞ: forall i : c_map f Ξ β y, has_map_view ihas_map_view (pop v)
Additional goodies.
Definition r_pop {X} {Ξ : ctx X} {x} : Ξ β (Ξ βΆβ x) := fun _ i => pop i. #[global] Arguments r_pop _ _ _ _/. Equations a_append {X} {Ξ Ξ : ctx X} {F : Famβ X (ctx X)} {a} : Ξ =[F]> Ξ -> F Ξ a -> (Ξ βΆβ a) =[F]> Ξ := a_append s z _ top := z ; a_append s z _ (pop i) := s _ i . #[global] Notation "[ u ,β x ]" := (a_append u x) (at level 9) : asgn_scope.X: Type
Ξ, Ξ: ctx X
F: Famβ X (ctx X)
a: XProper (asgn_eq Ξ Ξ ==> eq ==> asgn_eq (Ξ βΆβ a) Ξ) a_appendX: Type
Ξ, Ξ: ctx X
F: Famβ X (ctx X)
a: XProper (asgn_eq Ξ Ξ ==> eq ==> asgn_eq (Ξ βΆβ a) Ξ) a_appendX: Type
Ξ, Ξ: ctx X
F: Famβ X (ctx X)
a: X
x, y: Ξ =[ F ]> Ξ
Hu: x β‘β y
x0, y0: F Ξ a
Hx: x0 = y0
a0: X
i: Ξ βΆβ a β a0([x,β x0])%asgn a0 i = ([y,β y0])%asgn a0 iX: Type
Ξ0, Ξ: ctx X
F: Famβ X (ctx X)
a0: X
x, y: Ξ0 =[ F ]> Ξ
Hu: x β‘β y
x0, y0: F Ξ a0
Hx: x0 = y0x0 = y0X: Type
Ξ1, Ξ: ctx X
F: Famβ X (ctx X)
y1: X
x, y: Ξ1 =[ F ]> Ξ
Hu: x β‘β y
x0, y0: F Ξ y1
Hx: x0 = y0
a0: X
v: var a0 Ξ1x a0 v = y a0 vexact Hx.X: Type
Ξ0, Ξ: ctx X
F: Famβ X (ctx X)
a0: X
x, y: Ξ0 =[ F ]> Ξ
Hu: x β‘β y
x0, y0: F Ξ a0
Hx: x0 = y0x0 = y0now apply Hu. Qed.X: Type
Ξ1, Ξ: ctx X
F: Famβ X (ctx X)
y1: X
x, y: Ξ1 =[ F ]> Ξ
Hu: x β‘β y
x0, y0: F Ξ y1
Hx: x0 = y0
a0: X
v: var a0 Ξ1x a0 v = y a0 v
These concrete definition of shifts compute better than their generic counterpart.
Definition r_shift1 {X} {Ξ Ξ : ctx X} {a} (f : Ξ β Ξ) : (Ξ βΆβ a) β (Ξ βΆβ a) := [ f α΅£β r_pop ,β top ]. Definition r_shift2 {X} {Ξ Ξ : ctx X} {a b} (f : Ξ β Ξ) : (Ξ βΆβ a βΆβ b) β (Ξ βΆβ a βΆβ b) := [ [ f α΅£β r_pop α΅£β r_pop ,β pop top ] ,β top ]. Definition r_shift3 {X} {Ξ Ξ : ctx X} {a b c} (f : Ξ β Ξ) : (Ξ βΆβ a βΆβ b βΆβ c) β (Ξ βΆβ a βΆβ b βΆβ c) := [ [ [ f α΅£β r_pop α΅£β r_pop α΅£β r_pop ,β pop (pop top) ] ,β pop top ] ,β top ].X: Type
Ξ, Ξ: ctx X
a: XProper (asgn_eq Ξ Ξ ==> asgn_eq (Ξ βΆβ a) (Ξ βΆβ a)) r_shift1intros ?? Hu; unfold r_shift1; now rewrite Hu. Qed.X: Type
Ξ, Ξ: ctx X
a: XProper (asgn_eq Ξ Ξ ==> asgn_eq (Ξ βΆβ a) (Ξ βΆβ a)) r_shift1X: Type
Ξ, Ξ: ctx X
a, b: XProper (asgn_eq Ξ Ξ ==> asgn_eq (Ξ βΆβ a βΆβ b) (Ξ βΆβ a βΆβ b)) r_shift2intros ?? Hu; unfold r_shift2; now rewrite Hu. Qed.X: Type
Ξ, Ξ: ctx X
a, b: XProper (asgn_eq Ξ Ξ ==> asgn_eq (Ξ βΆβ a βΆβ b) (Ξ βΆβ a βΆβ b)) r_shift2X: Type
Ξ, Ξ: ctx X
a, b, c: XProper (asgn_eq Ξ Ξ ==> asgn_eq (Ξ βΆβ a βΆβ b βΆβ c) (Ξ βΆβ a βΆβ b βΆβ c)) r_shift3intros ?? Hu; unfold r_shift3; now rewrite Hu. Qed.X: Type
Ξ, Ξ: ctx X
a, b, c: XProper (asgn_eq Ξ Ξ ==> asgn_eq (Ξ βΆβ a βΆβ b βΆβ c) (Ξ βΆβ a βΆβ b βΆβ c)) r_shift3intros ? v; now repeat (dependent elimination v; auto). Qed.X: Type
Ξ: ctx X
a: Xr_shift1 r_id β‘β r_idintros ? v; now repeat (dependent elimination v; auto). Qed.X: Type
Ξ: ctx X
a, b: Xr_shift2 r_id β‘β r_idintros ? v; now repeat (dependent elimination v; auto). Qed.X: Type
Ξ: ctx X
a, b, c: Xr_shift3 r_id β‘β r_idintros ? v; now repeat (dependent elimination v; auto). Qed.X: Type
Ξ1, Ξ2, Ξ3: ctx X
a: X
r1: Ξ1 β Ξ2
r2: Ξ2 β Ξ3r_shift1 (r1 α΅£β r2) β‘β r_shift1 r1 α΅£β r_shift1 r2intros ? v; now repeat (dependent elimination v; auto). Qed.X: Type
Ξ1, Ξ2, Ξ3: ctx X
a, b: X
r1: Ξ1 β Ξ2
r2: Ξ2 β Ξ3r_shift2 (r1 α΅£β r2) β‘β r_shift2 r1 α΅£β r_shift2 r2intros ? v; now repeat (dependent elimination v; auto). Qed.X: Type
Ξ1, Ξ2, Ξ3: ctx X
a, b, c: X
r1: Ξ1 β Ξ2
r2: Ξ2 β Ξ3r_shift3 (r1 α΅£β r2) β‘β r_shift3 r1 α΅£β r_shift3 r2
This is the end for now, but we have not yet instanciated the rest of the abstract context structure. This is a bit more work, it takes place in another file: Ctx/Covering.v