In Ctx/Ctx.v we have instanciated the relevant part of the abstract interface for concrete contexts. Here we tackle the rest of the structure. Basically, we need to provide case-splitting for deciding if a variable i : (Ξ +βΆ Ξ) β x is in Ξ or in Ξ. We could do this directly but we prove a slight generalization, going through the definition of coverings, a ternary relationship on concrete contexts witnessing that a context is covered by the two others (respecting order).
This inductive family provides proofs that some context zs is obtained by "zipping" together two other contexts xs and ys.
Inductive cover : ctx X -> ctx X -> ctx X -> Type := | CNil : β β β β β β‘ β β | CLeft {x xs ys zs} : xs β ys β‘ zs -> (xs βΆβ x) β ys β‘ (zs βΆβ x) | CRight {x xs ys zs} : xs β ys β‘ zs -> xs β (ys βΆβ x) β‘ (zs βΆβ x) where "a β b β‘ c" := (cover a b c).
Basic useful coverings.
Equations cover_nil_r xs : xs β β β β‘ xs := cover_nil_r β β := CNil ; cover_nil_r (xs βΆβ _) := CLeft (cover_nil_r xs) . #[global] Arguments cover_nil_r {xs}. Equations cover_nil_l xs : β β β xs β‘ xs := cover_nil_l β β := CNil ; cover_nil_l (xs βΆβ _) := CRight (cover_nil_l xs) . #[global] Arguments cover_nil_l {xs}.
This is the crucial one: the concatenation is covered by its two components.
Equations cover_cat {xs} ys : xs β ys β‘ (xs +βΆ ys) := cover_cat β β := cover_nil_r ; cover_cat (ys βΆβ _) := CRight (cover_cat ys) . #[global] Arguments cover_cat {xs ys}.
A covering gives us two injective renamings, left embedding and right embedding.
Equations r_cover_l {xs ys zs} : xs β ys β‘ zs -> xs β zs := r_cover_l (CLeft c) _ top := top ; r_cover_l (CLeft c) _ (pop i) := pop (r_cover_l c _ i) ; r_cover_l (CRight c) _ i := pop (r_cover_l c _ i) . Equations r_cover_r {xs ys zs} : xs β ys β‘ zs -> ys β zs := r_cover_r (CLeft c) _ i := pop (r_cover_r c _ i) ; r_cover_r (CRight c) _ top := top ; r_cover_r (CRight c) _ (pop i) := pop (r_cover_r c _ i) .
Injectivity.
X: Type
F: Famβ X (ctx X)
xs, ys, zs: ctx X
p: xs β ys β‘ zs
x: X
i, j: xs β x
H: r_cover_l p x i = r_cover_l p x ji = jX: Type
F: Famβ X (ctx X)
xs, ys, zs: ctx X
p: xs β ys β‘ zs
x: X
i, j: xs β x
H: r_cover_l p x i = r_cover_l p x ji = jX: Type
F: Famβ X (ctx X)
x: X
i, j: β β β x
H: r_cover_l CNil x i = r_cover_l CNil x ji = jX: Type
F: Famβ X (ctx X)
x0: X
xs, ys, zs: ctx X
p: xs β ys β‘ zs
x: X
i, j: xs βΆβ x0 β x
H: r_cover_l (CLeft p) x i = r_cover_l (CLeft p) x j
IHp: forall i j : xs β x, r_cover_l p x i = r_cover_l p x j -> i = ji = jX: Type
F: Famβ X (ctx X)
x0: X
xs, ys, zs: ctx X
p: xs β ys β‘ zs
x: X
i, j: xs β x
H: r_cover_l (CRight p) x i = r_cover_l (CRight p) x j
IHp: forall i j : xs β x, r_cover_l p x i = r_cover_l p x j -> i = ji = jdependent elimination i.X: Type
F: Famβ X (ctx X)
x: X
i, j: β β β x
H: r_cover_l CNil x i = r_cover_l CNil x ji = jX: Type
F: Famβ X (ctx X)
x0: X
xs, ys, zs: ctx X
p: xs β ys β‘ zs
x: X
i, j: xs βΆβ x0 β x
H: r_cover_l (CLeft p) x i = r_cover_l (CLeft p) x j
IHp: forall i j : xs β x, r_cover_l p x i = r_cover_l p x j -> i = ji = jX: Type
F: Famβ X (ctx X)
y0: X
Ξ1, ys, zs: ctx X
p: Ξ1 β ys β‘ zs
x: X
v, v0: var x Ξ1
H: r_cover_l (CLeft p) x (pop v) = r_cover_l (CLeft p) x (pop v0)
IHp: forall i j : Ξ1 β x, r_cover_l p x i = r_cover_l p x j -> i = jpop v = pop v0f_equal; now apply IHp.X: Type
F: Famβ X (ctx X)
y0: X
Ξ1, ys, zs: ctx X
p: Ξ1 β ys β‘ zs
x: X
v, v0: var x Ξ1
H: NoConfusion (r_cover_l (CLeft p) x (pop v)) (r_cover_l (CLeft p) x (pop v0))
IHp: forall i j : Ξ1 β x, r_cover_l p x i = r_cover_l p x j -> i = jpop v = pop v0X: Type
F: Famβ X (ctx X)
x0: X
xs, ys, zs: ctx X
p: xs β ys β‘ zs
x: X
i, j: xs β x
H: r_cover_l (CRight p) x i = r_cover_l (CRight p) x j
IHp: forall i j : xs β x, r_cover_l p x i = r_cover_l p x j -> i = ji = jnow apply IHp. Qed.X: Type
F: Famβ X (ctx X)
x0: X
xs, ys, zs: ctx X
p: xs β ys β‘ zs
x: X
i, j: xs β x
H: NoConfusion (r_cover_l (CRight p) x i) (r_cover_l (CRight p) x j)
IHp: forall i j : xs β x, r_cover_l p x i = r_cover_l p x j -> i = ji = jX: Type
F: Famβ X (ctx X)
xs, ys, zs: ctx X
p: xs β ys β‘ zs
y: X
i, j: ys β y
H: r_cover_r p y i = r_cover_r p y ji = jX: Type
F: Famβ X (ctx X)
xs, ys, zs: ctx X
p: xs β ys β‘ zs
y: X
i, j: ys β y
H: r_cover_r p y i = r_cover_r p y ji = jX: Type
F: Famβ X (ctx X)
y: X
i, j: β β β y
H: r_cover_r CNil y i = r_cover_r CNil y ji = jX: Type
F: Famβ X (ctx X)
x: X
xs, ys, zs: ctx X
p: xs β ys β‘ zs
y: X
i, j: ys β y
H: r_cover_r (CLeft p) y i = r_cover_r (CLeft p) y j
IHp: forall i j : ys β y, r_cover_r p y i = r_cover_r p y j -> i = ji = jX: Type
F: Famβ X (ctx X)
x: X
xs, ys, zs: ctx X
p: xs β ys β‘ zs
y: X
i, j: ys βΆβ x β y
H: r_cover_r (CRight p) y i = r_cover_r (CRight p) y j
IHp: forall i j : ys β y, r_cover_r p y i = r_cover_r p y j -> i = ji = jdependent elimination i.X: Type
F: Famβ X (ctx X)
y: X
i, j: β β β y
H: r_cover_r CNil y i = r_cover_r CNil y ji = japply noConfusion_inv in H; now apply IHp.X: Type
F: Famβ X (ctx X)
x: X
xs, ys, zs: ctx X
p: xs β ys β‘ zs
y: X
i, j: ys β y
H: r_cover_r (CLeft p) y i = r_cover_r (CLeft p) y j
IHp: forall i j : ys β y, r_cover_r p y i = r_cover_r p y j -> i = ji = jX: Type
F: Famβ X (ctx X)
x: X
xs, ys, zs: ctx X
p: xs β ys β‘ zs
y: X
i, j: ys βΆβ x β y
H: r_cover_r (CRight p) y i = r_cover_r (CRight p) y j
IHp: forall i j : ys β y, r_cover_r p y i = r_cover_r p y j -> i = ji = jX: Type
F: Famβ X (ctx X)
y1: X
xs, Ξ1, zs: ctx X
p: xs β Ξ1 β‘ zs
y: X
v, v0: var y Ξ1
H: r_cover_r (CRight p) y (pop v) = r_cover_r (CRight p) y (pop v0)
IHp: forall i j : Ξ1 β y, r_cover_r p y i = r_cover_r p y j -> i = jpop v = pop v0f_equal; now apply IHp. Qed.X: Type
F: Famβ X (ctx X)
y1: X
xs, Ξ1, zs: ctx X
p: xs β Ξ1 β‘ zs
y: X
v, v0: var y Ξ1
H: NoConfusion (r_cover_r (CRight p) y (pop v)) (r_cover_r (CRight p) y (pop v0))
IHp: forall i j : Ξ1 β y, r_cover_r p y i = r_cover_r p y j -> i = jpop v = pop v0
The two embeddings have disjoint images.
X: Type
F: Famβ X (ctx X)
xs, ys, zs: ctx X
p: xs β ys β‘ zs
a: X
i: xs β a
j: ys β a
H: r_cover_l p a i = r_cover_r p a jT0X: Type
F: Famβ X (ctx X)
xs, ys, zs: ctx X
p: xs β ys β‘ zs
a: X
i: xs β a
j: ys β a
H: r_cover_l p a i = r_cover_r p a jT0X: Type
F: Famβ X (ctx X)
a: X
i, j: β β β a
H: r_cover_l CNil a i = r_cover_r CNil a jT0X: Type
F: Famβ X (ctx X)
x: X
xs, ys, zs: ctx X
p: xs β ys β‘ zs
a: X
i: xs βΆβ x β a
j: ys β a
H: r_cover_l (CLeft p) a i = r_cover_r (CLeft p) a j
IHp: forall (i : xs β a) (j : ys β a), Β¬ (r_cover_l p a i = r_cover_r p a j)T0X: Type
F: Famβ X (ctx X)
x: X
xs, ys, zs: ctx X
p: xs β ys β‘ zs
a: X
i: xs β a
j: ys βΆβ x β a
H: r_cover_l (CRight p) a i = r_cover_r (CRight p) a j
IHp: forall (i : xs β a) (j : ys β a), Β¬ (r_cover_l p a i = r_cover_r p a j)T0inversion i.X: Type
F: Famβ X (ctx X)
a: X
i, j: β β β a
H: r_cover_l CNil a i = r_cover_r CNil a jT0X: Type
F: Famβ X (ctx X)
x: X
xs, ys, zs: ctx X
p: xs β ys β‘ zs
a: X
i: xs βΆβ x β a
j: ys β a
H: r_cover_l (CLeft p) a i = r_cover_r (CLeft p) a j
IHp: forall (i : xs β a) (j : ys β a), Β¬ (r_cover_l p a i = r_cover_r p a j)T0X: Type
F: Famβ X (ctx X)
a: X
Ξ, ys, zs: ctx X
p: Ξ β ys β‘ zs
j: ys β a
H: r_cover_l (CLeft p) a top = r_cover_r (CLeft p) a j
IHp: forall (i : Ξ β a) (j : ys β a), Β¬ (r_cover_l p a i = r_cover_r p a j)T0X: Type
F: Famβ X (ctx X)
y: X
Ξ0, ys, zs: ctx X
p: Ξ0 β ys β‘ zs
a: X
v: var a Ξ0
j: ys β a
H: r_cover_l (CLeft p) a (pop v) = r_cover_r (CLeft p) a j
IHp: forall (i : Ξ0 β a) (j : ys β a), Β¬ (r_cover_l p a i = r_cover_r p a j)T0inversion H.X: Type
F: Famβ X (ctx X)
a: X
Ξ, ys, zs: ctx X
p: Ξ β ys β‘ zs
j: ys β a
H: r_cover_l (CLeft p) a top = r_cover_r (CLeft p) a j
IHp: forall (i : Ξ β a) (j : ys β a), Β¬ (r_cover_l p a i = r_cover_r p a j)T0X: Type
F: Famβ X (ctx X)
y: X
Ξ0, ys, zs: ctx X
p: Ξ0 β ys β‘ zs
a: X
v: var a Ξ0
j: ys β a
H: r_cover_l (CLeft p) a (pop v) = r_cover_r (CLeft p) a j
IHp: forall (i : Ξ0 β a) (j : ys β a), Β¬ (r_cover_l p a i = r_cover_r p a j)T0exact (IHp v j H).X: Type
F: Famβ X (ctx X)
y: X
Ξ0, ys, zs: ctx X
p: Ξ0 β ys β‘ zs
a: X
v: var a Ξ0
j: ys β a
H: r_cover_l p a v = r_cover_r p a j
IHp: forall (i : Ξ0 β a) (j : ys β a), Β¬ (r_cover_l p a i = r_cover_r p a j)T0X: Type
F: Famβ X (ctx X)
x: X
xs, ys, zs: ctx X
p: xs β ys β‘ zs
a: X
i: xs β a
j: ys βΆβ x β a
H: r_cover_l (CRight p) a i = r_cover_r (CRight p) a j
IHp: forall (i : xs β a) (j : ys β a), Β¬ (r_cover_l p a i = r_cover_r p a j)T0X: Type
F: Famβ X (ctx X)
a: X
xs, Ξ, zs: ctx X
p: xs β Ξ β‘ zs
i: xs β a
H: r_cover_l (CRight p) a i = r_cover_r (CRight p) a top
IHp: forall (i : xs β a) (j : Ξ β a), Β¬ (r_cover_l p a i = r_cover_r p a j)T0X: Type
F: Famβ X (ctx X)
y: X
xs, Ξ0, zs: ctx X
p: xs β Ξ0 β‘ zs
a: X
i: xs β a
v: var a Ξ0
H: r_cover_l (CRight p) a i = r_cover_r (CRight p) a (pop v)
IHp: forall (i : xs β a) (j : Ξ0 β a), Β¬ (r_cover_l p a i = r_cover_r p a j)T0inversion H.X: Type
F: Famβ X (ctx X)
a: X
xs, Ξ, zs: ctx X
p: xs β Ξ β‘ zs
i: xs β a
H: r_cover_l (CRight p) a i = r_cover_r (CRight p) a top
IHp: forall (i : xs β a) (j : Ξ β a), Β¬ (r_cover_l p a i = r_cover_r p a j)T0X: Type
F: Famβ X (ctx X)
y: X
xs, Ξ0, zs: ctx X
p: xs β Ξ0 β‘ zs
a: X
i: xs β a
v: var a Ξ0
H: r_cover_l (CRight p) a i = r_cover_r (CRight p) a (pop v)
IHp: forall (i : xs β a) (j : Ξ0 β a), Β¬ (r_cover_l p a i = r_cover_r p a j)T0exact (IHp i v H). Qed.X: Type
F: Famβ X (ctx X)
y: X
xs, Ξ0, zs: ctx X
p: xs β Ξ0 β‘ zs
a: X
i: xs β a
v: var a Ξ0
H: r_cover_l p a i = r_cover_r p a v
IHp: forall (i : xs β a) (j : Ξ0 β a), Β¬ (r_cover_l p a i = r_cover_r p a j)T0
Now we can start proving that the copairing of the two embeddings has non-empty fibers, ie, we can case split.
Variant cover_view {xs ys zs} (p : xs β ys β‘ zs) [z] : zs β z -> Type := | Vcov_l (i : xs β z) : cover_view p (r_cover_l p _ i) | Vcov_r (j : ys β z) : cover_view p (r_cover_r p _ j) . #[global] Arguments Vcov_l {xs ys zs p z}. #[global] Arguments Vcov_r {xs ys zs p z}.
Indeed!
X: Type
F: Famβ X (ctx X)
xs, ys, zs: ctx X
p: xs β ys β‘ zs
z: X
i: zs β zcover_view p iX: Type
F: Famβ X (ctx X)
xs, ys, zs: ctx X
p: xs β ys β‘ zs
z: X
i: zs β zcover_view p iX: Type
F: Famβ X (ctx X)
Ξ: ctx X
z: X
IHzs: forall (i : Ξ β z) (xs ys : ctx X) (p : xs β ys β‘ Ξ), cover_view p i
xs, ys: ctx X
p: xs β ys β‘ (Ξ βΆβ z)cover_view p topX: Type
F: Famβ X (ctx X)
Ξ0: ctx X
y, z: X
v: var z Ξ0
IHzs: forall (i : Ξ0 β z) (xs ys : ctx X) (p : xs β ys β‘ Ξ0), cover_view p i
xs, ys: ctx X
p: xs β ys β‘ (Ξ0 βΆβ y)cover_view p (pop v)dependent elimination p; [ exact (Vcov_l top) | exact (Vcov_r top) ].X: Type
F: Famβ X (ctx X)
Ξ: ctx X
z: X
IHzs: forall (i : Ξ β z) (xs ys : ctx X) (p : xs β ys β‘ Ξ), cover_view p i
xs, ys: ctx X
p: xs β ys β‘ (Ξ βΆβ z)cover_view p topX: Type
F: Famβ X (ctx X)
Ξ0: ctx X
y, z: X
v: var z Ξ0
IHzs: forall (i : Ξ0 β z) (xs ys : ctx X) (p : xs β ys β‘ Ξ0), cover_view p i
xs, ys: ctx X
p: xs β ys β‘ (Ξ0 βΆβ y)cover_view p (pop v)X: Type
F: Famβ X (ctx X)
zs: ctx X
x, z: X
v: var z zs
IHzs: forall (i : zs β z) (xs ys : ctx X) (p : xs β ys β‘ zs), cover_view p i
xs0, ys0: ctx X
c: xs0 β ys0 β‘ zscover_view (CLeft c) (pop v)X: Type
F: Famβ X (ctx X)
zs0: ctx X
x0, z: X
v: var z zs0
IHzs: forall (i : zs0 β z) (xs ys : ctx X) (p : xs β ys β‘ zs0), cover_view p i
xs1, ys1: ctx X
c0: xs1 β ys1 β‘ zs0cover_view (CRight c0) (pop v)destruct (IHzs v _ _ c); [ exact (Vcov_l (pop i)) | exact (Vcov_r j) ].X: Type
F: Famβ X (ctx X)
zs: ctx X
x, z: X
v: var z zs
IHzs: forall (i : zs β z) (xs ys : ctx X) (p : xs β ys β‘ zs), cover_view p i
xs0, ys0: ctx X
c: xs0 β ys0 β‘ zscover_view (CLeft c) (pop v)destruct (IHzs v _ _ c0); [ exact (Vcov_l i) | exact (Vcov_r (pop j)) ]. Qed.X: Type
F: Famβ X (ctx X)
zs0: ctx X
x0, z: X
v: var z zs0
IHzs: forall (i : zs0 β z) (xs ys : ctx X) (p : xs β ys β‘ zs0), cover_view p i
xs1, ys1: ctx X
c0: xs1 β ys1 β‘ zs0cover_view (CRight c0) (pop v)
Finishing the instanciation of the abstract interface for ctx X.
#[global] Instance free_context_cat_wkn : context_cat_wkn X (ctx X) := {| r_cat_l _ _ := r_cover_l cover_cat ; r_cat_r _ _ := r_cover_r cover_cat |}. #[global] Program Instance free_context_laws : context_laws X (ctx X).dependent elimination i. Qed.X: Type
F: Famβ X (ctx X)
t: X
i: cvar β β tc_emp_view t iX: Type
F: Famβ X (ctx X)
Ξ, Ξ: ctx X
t: X
i: cvar (ccat Ξ Ξ) tc_cat_view Ξ Ξ t iX: Type
F: Famβ X (ctx X)
Ξ, Ξ: ctx X
t: X
i: Ξ β tc_cat_view Ξ Ξ t (r_cover_l cover_cat t i)X: Type
F: Famβ X (ctx X)
Ξ, Ξ: ctx X
t: X
j: Ξ β tc_cat_view Ξ Ξ t (r_cover_r cover_cat t j)now refine (Vcat_r _). Qed.X: Type
F: Famβ X (ctx X)
Ξ, Ξ: ctx X
t: X
j: Ξ β tc_cat_view Ξ Ξ t (r_cover_r cover_cat t j)intros ?? H; now apply r_cover_l_inj in H. Qed.X: Type
F: Famβ X (ctx X)
Ξ, Ξ: ctx X
t: Xinjective (r_cover_l cover_cat t)intros ?? H; now apply r_cover_r_inj in H. Qed.X: Type
F: Famβ X (ctx X)
Ξ, Ξ: ctx X
t: Xinjective (r_cover_r cover_cat t)now apply r_cover_disj in H. Qed.X: Type
F: Famβ X (ctx X)
Ξ, Ξ: ctx X
t: X
i: cvar Ξ t
j: cvar Ξ t
H: r_cover_l cover_cat t i = r_cover_r cover_cat t jT0
Additional utilities.
Definition a_cover {Ξ1 Ξ2 Ξ3 Ξ} (p : Ξ1 β Ξ2 β‘ Ξ3) (u : Ξ1 =[F]> Ξ) (v : Ξ2 =[F]> Ξ) : Ξ3 =[F]> Ξ := fun _ i => match view_cover p i with | Vcov_l i => u _ i | Vcov_r j => v _ j end . #[global] Arguments a_cover _ _ _ _ _ _ _ _ /.X: Type
F: Famβ X (ctx X)
Ξ1, Ξ2, Ξ3, Ξ: ctx X
H: Ξ1 β Ξ2 β‘ Ξ3Proper (asgn_eq Ξ1 Ξ ==> asgn_eq Ξ2 Ξ ==> asgn_eq Ξ3 Ξ) (a_cover H)X: Type
F: Famβ X (ctx X)
Ξ1, Ξ2, Ξ3, Ξ: ctx X
H: Ξ1 β Ξ2 β‘ Ξ3Proper (asgn_eq Ξ1 Ξ ==> asgn_eq Ξ2 Ξ ==> asgn_eq Ξ3 Ξ) (a_cover H)destruct (view_cover H i); [ now apply H1 | now apply H2 ]. Qed. End with_param. #[global] Notation "a β b β‘ c" := (cover a b c). #[global] Notation "a βΆβ v" := (a_append a v) : asgn_scope. #[global] Notation "[ u , H , v ]" := (a_cover H u v) : asgn_scope.X: Type
F: Famβ X (ctx X)
Ξ1, Ξ2, Ξ3, Ξ: ctx X
H: Ξ1 β Ξ2 β‘ Ξ3
x, y: Ξ1 =[ F ]> Ξ
H1: x β‘β y
x0, y0: Ξ2 =[ F ]> Ξ
H2: x0 β‘β y0
a: X
i: Ξ3 β amatch view_cover H i with | Vcov_l i => x a i | Vcov_r j => x0 a j end = match view_cover H i with | Vcov_l i => y a i | Vcov_r j => y0 a j end