|
| 1 | + |
| 2 | +import LeanSubst |
| 3 | +import LeanSysF.Term |
| 4 | +import LeanSysF.FreeVar |
| 5 | + |
| 6 | +open LeanSubst |
| 7 | + |
| 8 | +inductive Kinding : Ctx Term -> Term -> Prop where |
| 9 | +| var {Γ : Ctx Term} {x} : |
| 10 | + Γ[x] = ★ -> |
| 11 | + Kinding Γ #x |
| 12 | +| arr {Γ A B} : |
| 13 | + Kinding Γ A -> |
| 14 | + Kinding Γ B -> |
| 15 | + Kinding Γ (A -:> B) |
| 16 | +| all {Γ P} : |
| 17 | + Kinding (★::Γ) P -> |
| 18 | + Kinding Γ (:∀ P) |
| 19 | + |
| 20 | +notation:170 Γ:170 " ⊢ " A:170 " type" => Kinding Γ A |
| 21 | + |
| 22 | +theorem Ctx.strong_rename_lift {A : Term} {Δ Γ : Ctx Term} {r : Ren} B : |
| 23 | + (∀ x T, x + 1 ∈ A -> Γ[x] = T -> Δ[r x] = T[r]) -> |
| 24 | + ∀ x T, x ∈ A -> (B::Γ)[x] = T -> (B[r]::Δ)[r.lift x] = T[r.lift] |
| 25 | +:= by |
| 26 | + intro h1 x T h2 h3 |
| 27 | + cases x <;> simp at * |
| 28 | + case zero => |
| 29 | + subst h3; simp [Ren.lift] |
| 30 | + rw [Ren.to_lift]; simp |
| 31 | + case succ x => |
| 32 | + replace h1 := h1 x h2 |
| 33 | + subst h3; simp [Ren.lift] |
| 34 | + rw [Ren.to_lift]; rw [h1]; simp |
| 35 | + |
| 36 | +theorem Ctx.rename_lift {Δ Γ : Ctx Term} {r : Ren} B : |
| 37 | + (∀ x T, Γ[x] = T -> Δ[r x] = T[r]) -> |
| 38 | + ∀ x T, (B::Γ)[x] = T -> (B[r]::Δ)[r.lift x] = T[r.lift] |
| 39 | +:= by |
| 40 | + intro h1 x T h3 |
| 41 | + cases x <;> simp at * |
| 42 | + case zero => |
| 43 | + subst h3; simp [Ren.lift] |
| 44 | + rw [Ren.to_lift]; simp |
| 45 | + case succ x => |
| 46 | + replace h1 := h1 x |
| 47 | + subst h3; simp [Ren.lift] |
| 48 | + rw [Ren.to_lift]; rw [h1]; simp |
| 49 | + |
| 50 | +theorem Ctx.subst_re_lift {Γ Δ : Ctx Term} A {σ : Subst Term} : |
| 51 | + (∀ x T y, Γ[x] = T -> σ x = re y -> Δ[y] = T[σ]) -> |
| 52 | + ∀ x T y, (A::Γ)[x] = T -> σ.lift x = re y -> (A[σ]::Δ)[y] = T[σ.lift] |
| 53 | +:= by |
| 54 | + intro h1 x T y h2 h3 |
| 55 | + cases x <;> simp at * |
| 56 | + case zero => subst h2; subst h3; simp |
| 57 | + case succ x => |
| 58 | + simp [Subst.compose] at h3 |
| 59 | + generalize zdef : σ x = z at * |
| 60 | + cases z <;> simp at h3 |
| 61 | + case _ z => |
| 62 | + subst h3 |
| 63 | + replace h1 := h1 x Γ[x] z rfl zdef |
| 64 | + subst h2; simp; rw [h1]; simp |
| 65 | + |
| 66 | +theorem Kinding.strong_rename {Γ A} (Δ : Ctx Term) (r : Ren) : |
| 67 | + Γ ⊢ A type -> |
| 68 | + (∀ x T, x ∈ A -> Γ[x] = T -> Δ[r x] = T[r]) -> |
| 69 | + Δ ⊢ A[r] type |
| 70 | +:= by |
| 71 | + intro j h |
| 72 | + induction j generalizing Δ r |
| 73 | + case var Γ x j => |
| 74 | + replace h := h x ★ FV.found j; simp at h |
| 75 | + simp; apply Kinding.var h |
| 76 | + case arr Γ A B j1 j2 ih1 ih2 => |
| 77 | + have h1 := λ x T (e : x ∈ A) => h x T (by simp; apply Or.inl e) |
| 78 | + have h2 := λ x T (e : x ∈ B) => h x T (by simp; apply Or.inr e) |
| 79 | + simp; apply Kinding.arr |
| 80 | + apply ih1 Δ r h1 |
| 81 | + apply ih2 Δ r h2 |
| 82 | + case all Γ P j ih => |
| 83 | + have h2 : ∀ x T, x + 1 ∈ P -> Γ[x] = T -> Δ[r x] = T[r] := by |
| 84 | + intro x T q1 q2; simp at h |
| 85 | + replace h := h x q1; subst q2 |
| 86 | + apply h |
| 87 | + simp; apply Kinding.all |
| 88 | + have lem1 := Ctx.strong_rename_lift ★ h2; simp at lem1 |
| 89 | + have lem2 := ih (★::Δ) r.lift; simp at lem2 |
| 90 | + replace lem2 := lem2 lem1 |
| 91 | + rw [Ren.to_lift] at lem2; simp at lem2; exact lem2 |
| 92 | + |
| 93 | +theorem Kinding.rename {Γ A} (Δ : Ctx Term) (r : Ren) : |
| 94 | + Γ ⊢ A type -> |
| 95 | + (∀ x T, Γ[x] = T -> Δ[r x] = T[r]) -> |
| 96 | + Δ ⊢ A[r] type |
| 97 | +:= by |
| 98 | + intro j h |
| 99 | + apply strong_rename _ _ j _ |
| 100 | + intro x T h1 h2 |
| 101 | + apply h x T h2 |
| 102 | + |
| 103 | +theorem Kinding.weaken : Γ ⊢ A type -> (P::Γ) ⊢ A[+1] type := by |
| 104 | + intro j |
| 105 | + have lem := rename (P::Γ) (· + 1) j |
| 106 | + simp at lem; exact lem |
| 107 | + |
| 108 | +theorem Kinding.strengthen : (P::Γ) ⊢ A[+1] type -> Γ ⊢ A type := by |
| 109 | + intro j |
| 110 | + have lem := strong_rename Γ (· - 1) j (by { |
| 111 | + intro x T h1 h2 |
| 112 | + cases x <;> simp at * |
| 113 | + case zero => exfalso; apply FV.zero_not_in_succ h1 |
| 114 | + case succ x => subst h2; simp |
| 115 | + }) |
| 116 | + simp at lem; apply lem |
| 117 | + |
| 118 | +theorem Kinding.subst_lift {Γ Δ : Ctx Term} A {σ : Subst Term} : |
| 119 | + (∀ x t, Γ[x] = ★ -> σ x = su t -> Δ ⊢ t type) -> |
| 120 | + ∀ x t, (A::Γ)[x] = ★ -> σ.lift x = su t -> (A[σ]::Δ) ⊢ t type |
| 121 | +:= by |
| 122 | + intro h1 x t h2 h3 |
| 123 | + cases x <;> simp at * |
| 124 | + case _ x => |
| 125 | + replace h2 := Term.ren_eq_star h2 |
| 126 | + simp [Subst.compose] at h3 |
| 127 | + generalize zdef : σ x = z at * |
| 128 | + cases z <;> simp at * |
| 129 | + case _ s => |
| 130 | + subst h3 |
| 131 | + replace h1 := h1 x s h2 zdef |
| 132 | + have lem := rename (A[σ]::Δ) (· + 1) h1 |
| 133 | + simp at lem; exact lem |
| 134 | + |
| 135 | +theorem Kinding.subst {Γ A} (Δ : Ctx Term) (σ : Subst Term) : |
| 136 | + Γ ⊢ A type -> |
| 137 | + (∀ x T y, Γ[x] = T -> σ x = re y -> Δ[y] = T[σ]) -> |
| 138 | + (∀ x t, Γ[x] = ★ -> σ x = su t -> Δ ⊢ t type) -> |
| 139 | + Δ ⊢ A[σ] type |
| 140 | +:= by |
| 141 | + intro j h1 h2 |
| 142 | + induction j generalizing Δ σ |
| 143 | + case var Γ x j => |
| 144 | + simp; generalize zdef : σ x = z at * |
| 145 | + cases z <;> simp at * |
| 146 | + case _ y => |
| 147 | + apply Kinding.var |
| 148 | + have lem := h1 x ★ y j zdef; simp at lem |
| 149 | + exact lem |
| 150 | + case _ t => apply h2 x t j zdef |
| 151 | + case arr Γ A B j1 j2 ih1 ih2 => |
| 152 | + simp; apply Kinding.arr |
| 153 | + apply ih1 Δ σ h1 h2 |
| 154 | + apply ih2 Δ σ h1 h2 |
| 155 | + case all Γ P j ih => |
| 156 | + -- TODO: Why does Lean unfold Subst.lift? |
| 157 | + have lem0 : ★[σ] = ★ := by simp |
| 158 | + have lem1 := Ctx.subst_re_lift ★ h1; rw [lem0] at lem1 |
| 159 | + have lem2 := Kinding.subst_lift ★ h2; rw [lem0] at lem2 |
| 160 | + simp; apply Kinding.all |
| 161 | + have lem3 := ih (★::Δ) σ.lift lem1 lem2; simp at lem3 |
| 162 | + exact lem3 |
| 163 | + |
| 164 | +theorem Kinding.beta : (A::Γ) ⊢ P type -> Γ ⊢ B type -> Γ ⊢ P[su B::+0] type := by |
| 165 | + intro j1 j2 |
| 166 | + apply subst Γ (su B::+0) j1 |
| 167 | + case _ => |
| 168 | + intro x T y h1 h2 |
| 169 | + cases x <;> simp at * |
| 170 | + case _ n => subst h1; subst h2; simp |
| 171 | + case _ => |
| 172 | + intro x t h1 h2 |
| 173 | + cases x <;> simp at * |
| 174 | + case zero => |
| 175 | + replace h1 := Term.ren_eq_star h1 |
| 176 | + subst h1; subst h2; apply j2 |
| 177 | + |
| 178 | +theorem Kinding.injection_arrow : Γ ⊢ (A -:> B) type -> Γ ⊢ A type ∧ Γ ⊢ B type := by |
| 179 | + intro j; generalize zdef : A -:> B = z at * |
| 180 | + cases j; all_goals injection zdef |
| 181 | + case arr A' B' j1 j2 e1 e2 => |
| 182 | + have lem1 : ∀ x, (λ i => mk2 A B i) x = (λ i => mk2 A' B' i) x := by |
| 183 | + intro x; rw [e2] |
| 184 | + have lem2 := lem1 0; simp [mk2] at lem2 |
| 185 | + have lem3 := lem1 1; simp [mk2] at lem3 |
| 186 | + subst lem2; subst lem3 |
| 187 | + apply And.intro j1 j2 |
0 commit comments