Zulip Chat Archive
Stream: general
Topic: How to solve 'index in targets type is not a variable'
Jelmer Firet (Dec 06 2024 at 12:48):
I am trying to formalize a type theory inside Lean.
I currently have:
inductive Term : Nat → Type where [...]
def subst (k : Fin n.succ) (u : Term k) (t : Term n.succ) : Term n := [...]
def Context (n : Nat) := (x : Fin n) → (Term x)
def subst_ctx (k : Fin n.succ) (u : Term k) (Γ : Context n.succ) : Context n := [...]
inductive xtyped : (Context n) → (Term n) → (Term n) → Prop where [...]
Now I want to prove that substitution is consistent with typing:
lemma subst_consistent (tA : xtyped Γ t A) : xtyped (subst_ctx k u Γ) (subst k u t) (subst k u A)
But when I start with induction tA
it gives an error:
index in target's type is not a variable (consider using the `cases` tactic instead)
n.succ
But for the proof I need induction, how can I fix this?
Asei Inoue (Jan 29 2025 at 13:54):
using generalize
tactic?
Jelmer Firet (Jan 29 2025 at 17:59):
Already tried that, it doesn't work:
generalize n.succ = m at *
gives
tactic 'generalize' failed, result is not type correct
That is because fundamentally subst
takes a Term n.succ
(and something to substitute in) and returns a Term n
. After generalize this does not fit anymore since Term m
is not of the form Term n.succ
and thus rejected as argument for subst
.
Henrik Böving (Jan 29 2025 at 18:05):
Can you give a full #mwe?
Jelmer Firet (Jan 29 2025 at 18:19):
I removed the terms related to pairs and equalities:
term.lean
import Mathlib.Data.Finset.Basic
inductive sort where
| succ : sort -> sort
| prod : sort -> sort -> sort
inductive Term : Nat → Type where
| rel (m : Fin n) : Term n
| sort (s : sort) : Term n
| prod (A : Term n) (B : Term n.succ) : Term n
| lambda (A : Term n) (B t : Term n.succ) : Term n
| app (A : Term n) (B : Term n.succ) (t u : Term n) : Term n
lemma Nat.succ_eq_succ {n m : Nat} (eq : n = m) : n.succ = m.succ := by {
rewrite [eq]
apply Eq.refl
}
@[simp]
def Term.cast (t : Term n) (h : n = m) : Term m :=
match t with
| rel m => rel (m.cast h)
| sort s => sort s
| prod A B => prod (A.cast h) (B.cast (Nat.succ_eq_succ h))
| lambda A B t => lambda (A.cast h) (B.cast (Nat.succ_eq_succ h)) (t.cast (Nat.succ_eq_succ h))
| app A B t u => app (A.cast h) (B.cast (Nat.succ_eq_succ h)) (t.cast h) (u.cast h)
-- def Term.cast (t : Term n) (eq : n = m) : Term m := Eq.rec t eq
@[simp] theorem test.cast_rfl (t : Term n) : t.cast rfl = t := by {
induction t <;> simp <;> tauto
}
instance : Coe (Term (n.succ + k)) (Term (n + k).succ) where
coe x := x.cast (Nat.succ_add n k)
instance : Coe (Term (n.succ.succ + k)) (Term (n + k).succ.succ) where
coe x := x.cast (by rw [Nat.succ_add, Nat.succ_add])
subst.lean
import EttItt.term
import Mathlib.Tactic.Convert
import Mathlib.Tactic.Linarith
instance : Coe (Fin n) (Fin n.succ) where
coe x := {
val := x
isLt := by
apply Nat.lt_succ_of_lt
apply x.isLt
}
@[simp]
def pad (t : Term n) : (Term n.succ) :=
match t with
| Term.rel x => Term.rel x
| Term.sort s => Term.sort s
| Term.prod A B => Term.prod (pad A) (pad B)
| Term.lambda A B t => Term.lambda (pad A) (pad B) (pad t)
| Term.app A B t u => Term.app (pad A) (pad B) (pad t) (pad u)
instance : Coe (Term n) (Term n.succ) where
coe x := pad x
def pad_greater (le : n ≤ m) (t : Term n) : (Term m) :=
match Nat.decLt n m with
| isTrue lt => by
apply @pad_greater n.succ m _ t
assumption
| isFalse eq => by
convert t
apply eq_of_ge_of_not_gt le eq
@[simp]
def subst (k : Fin n.succ) (u : Term k) (t : Term n.succ) : Term n :=
match t with
| Term.rel x => match Fin.decLt k x with
| isFalse _ => match Fin.decLe k x with
| isFalse k_gt_x => Term.rel { val := x, isLt := Nat.lt_of_lt_of_le (Nat.lt_of_not_le k_gt_x) (Nat.le_of_lt_succ k.isLt) }
| isTrue _ => pad_greater ( Nat.le_of_lt_succ k.isLt) u
| isTrue k_lt_x => Term.rel {
val := x.val.pred
isLt := by
apply Nat.lt_of_succ_lt_succ
rewrite [Nat.succ_pred]
· exact x.isLt
· apply Nat.not_eq_zero_of_lt
exact k_lt_x
}
| Term.sort s => Term.sort s
| Term.prod A B => Term.prod (subst k u A) (subst k u B)
| Term.lambda A B t => Term.lambda (subst k u A) (subst k u B) (subst k u t)
| Term.app A B t x => Term.app (subst k u A) (subst k u B) (subst k u t) (subst k u x)
@[simp]
def subst' (u : Term n) (t : Term n.succ) : Term n := subst {
val := n
isLt := Nat.le.refl
} u t
ett.lean
import EttItt.term
import EttItt.subst
def Context (n : Nat) := (x : Fin n) → (Term x)
def Context.add (Γ : Context n) (t : Term n) : Context (n.succ) :=
fun (k : Fin n.succ) =>
match Nat.decLt k n with
| isFalse k_ge_n => (@Term.cast n ↑k t (Nat.le_antisymm (Nat.le_of_not_lt k_ge_n) (Nat.le_of_lt_succ k.isLt)))
| isTrue k_lt_n => Γ {val := k.val, isLt := k_lt_n}
@[simp]
def Context.cast (Γ : Context n) (eq : n = m) : Context m := Eq.rec Γ eq
notation Γ ",," t => Context.add Γ t
inductive xtyped : (Context n) → (Term n) → (Term n) → Prop where
| rel : xtyped Γ (Term.rel k) (pad_greater k.isLt (Γ k))
| sort : xtyped Γ (Term.sort s) (Term.sort (sort.succ s))
| prod ( tyA : xtyped Γ A (Term.sort s1) )
( tyB : xtyped (Γ,,A) B (Term.sort s2) )
: xtyped Γ (Term.prod A B) (Term.sort (sort.prod s1 s2))
| lambda ( tyA : xtyped Γ A (Term.sort s1) )
( tyB : xtyped (Γ,,A) B (Term.sort s2) )
( tyt : xtyped (Γ,,A) t B )
: xtyped Γ (Term.lambda A B t) (Term.prod A B)
| app ( tyA : xtyped Γ A (Term.sort s1) )
( tyB : xtyped (Γ,,A) B (Term.sort s2) )
( tyt : xtyped Γ t (Term.prod A B) )
( tyu : xtyped Γ u A )
: xtyped Γ (Term.app A B t u) (subst' u B)
def subst_ctx (k : Fin n.succ) (u : Term k) (Γ : Context n.succ) : Context n :=
fun x => match Nat.decLt x k with
| isTrue _ => Γ x
| isFalse k_ge_x => subst {val := k.val, isLt := Nat.lt_succ_of_le (Nat.le_of_not_lt (k_ge_x))} u (Γ x.succ)
lemma subst_consistent (n : Nat) (k : Fin n.succ) (u : Term k) (t A : Term n.succ) (Γ : Context n.succ) (tA : @xtyped n.succ Γ t A) : @xtyped n (subst_ctx k u Γ) (subst k u t) (subst k u A) := by
induction tA
admit
Last updated: May 02 2025 at 03:31 UTC