Zulip Chat Archive
Stream: new members
Topic: Can't use proof that list contains item to prove l[n] = v
aron (Jun 12 2025 at 20:46):
I've tried to write HasType.at_ctx_index so many different ways but there always seems to be some sort of problem preventing me from doing it. This is the closest I've come (it was a good idea to do cases ht before doing induction on ctx) but now I'm getting a totally inscrutable error that I've never seen before and don't understand. All I want to do is use HasType n ctx ty to prove that ctx[n] = ty. Which should be trivial
inductive HasType {α : Type u} : (index : Nat) → List α → α → Prop where
| stop : HasType 0 (ty :: ctx) ty
| pop {ctx : List α} : HasType n ctx ty → HasType (n+1) (otherTy :: ctx) ty
@[reducible] def HasType.lte_ctxLen {α} {ctx : List α} {ty : α} (h : HasType n ctx ty) : n < ctx.length :=
match ctx, h with
| _ :: [], .stop => by simp
| head :: tail, @HasType.pop _ n _ _ _ h => by
simp
exact h.lte_ctxLen
| head :: tail, .stop => by simp [List.length]
theorem HasType.at_ctx_index (ht : HasType n ctx ty) : ctx[n]'ht.lte_ctxLen = ty := by
cases ht with
| stop => simp
| pop htt =>
expose_names
induction ctx with
| nil => cases htt
| cons head tail ih =>
have := HasType.at_ctx_index htt
trivial
aron (Jun 12 2025 at 20:48):
Actually it would be amazing if I could do this both ways:
HasType n ctx ty ↔ ctx[n] = ty
which should also be totally possible just by looking at their definitions. I just can't actually work out how to do it without running into errors :big_frown:
Aaron Liu (Jun 12 2025 at 21:10):
This is a bug
Aaron Liu (Jun 12 2025 at 21:13):
This way seems to avoid it
theorem HasType.at_ctx_index (ht : HasType n ctx ty) : ctx[n]'ht.lte_ctxLen = ty := by
induction ht with
| stop => simp
| @pop _ _ _ ctx htt ih =>
cases ctx with
| nil => cases htt
| cons head tail => exact ih
aron (Jun 12 2025 at 21:16):
oh whoa. that's so so much simpler than any of the things i tried. how does ih : (head :: tail)[n✝] = ty✝ fulfil the goal of (otherTy✝ :: head :: tail)[n✝ + 1] = ty✝ here?
aron (Jun 12 2025 at 21:17):
it's not even using simp, so this wouldn't even reduce definitions marked with reducible, as far as i understand
aron (Jun 12 2025 at 21:20):
also, here's my attempt at creating a HasType. I get stuck at the end bc the goal has become HasType (nn + 1) ctx ctx[nn + 1] but i think it should be HasType (nn + 1) (other :: ctx) (other :: ctx)[nn + 1], no?
def HasType.from_prf {ctx : List α} (dblLtCtxLen : dbl < ctx.length) : HasType dbl ctx ctx[dbl] := by
let ty := ctx[dbl]'dblLtCtxLen
have tyIsAtIndex : ty = ctx[dbl]'dblLtCtxLen := by trivial
induction dbl with
| zero =>
have : ∀ x, ctx[0] = x → ctx ≠ [] := by
(expose_names; exact fun x a => List.ne_nil_of_length_pos dblLtCtxLen)
cases ctx with
| nil => contradiction
| cons head tail =>
have : ty = (head :: tail)[0] := by (expose_names; exact tyIsAtIndex)
exact @HasType.stop _ ty tail
| succ nn ih =>
expose_names
have : nn < ctx.length := by exact Nat.lt_of_succ_lt dblLtCtxLen
have := ih this rfl
refine HasType.pop this
sorry
aron (Jun 12 2025 at 21:30):
but i think it should be
HasType (nn + 1) (other :: ctx) (other :: ctx)[nn + 1]
ah no the last type index is fine to still be ctx[nn] because you only need the + 1 here if it was (other :: ctx)[n + 1] but since we're putting this in terms of ctx that's fine.
but yeah, i still think it should be HasType (nn + 1) (other :: ctx) ctx[nn], not HasType (nn + 1) ctx ctx[nn]
aron (Jun 12 2025 at 21:35):
More streamlined attempt of HasType.from_prf:
def HasType.from_prf {ctx : List α} (dblLtCtxLen : dbl < ctx.length) : HasType dbl ctx ctx[dbl] := by
induction dbl with
| zero =>
have : ∀ x, ctx[0] = x → ctx ≠ [] := by
(expose_names; exact fun x a => List.ne_nil_of_length_pos dblLtCtxLen)
cases ctx with
| nil => contradiction
| cons head tail =>
exact @HasType.stop _ head tail
| succ nn ih =>
expose_names
have : nn < ctx.length := by exact Nat.lt_of_succ_lt dblLtCtxLen
have := ih this
refine @HasType.pop α nn ctx[nn] ?head ctx ?_
sorry
aron (Jun 13 2025 at 11:53):
Woohoo I managed to prove construction of a HasType n ctx ctx[n] using only a proof that n < ctx.length:
theorem HasType.from_prf (ctx : List α) (h : n < ctx.length) : HasType n ctx ctx[n] := by
cases ctx with
| nil => contradiction
| cons head tail =>
cases tail with
| nil =>
have unwrap: [head][n] = head := by exact List.getElem_singleton h
have n_eq_0: n = 0 := by exact Nat.lt_one_iff.mp h
rw [unwrap, n_eq_0]
exact .stop
| cons neck taill =>
cases n with
| zero => exact .stop
| succ nn =>
refine .pop ?_
exact HasType.from_prf (neck :: taill) _
aron (Jun 13 2025 at 12:04):
And now the whole thing together, including a function to convert to and from HasType n ctx ty ↔ ctx[n] = ty:
inductive HasType {α : Type u} : (index : Nat) → List α → α → Prop where
| stop : HasType 0 (ty :: ctx) ty
| pop {ctx : List α} : HasType n ctx ty → HasType (n+1) (otherTy :: ctx) ty
@[reducible] def HasType.lte_ctxLen {α} {ctx : List α} {ty : α} (h : HasType n ctx ty) : n < ctx.length :=
match ctx, h with
| _ :: [], .stop => by simp
| head :: tail, @HasType.pop _ n _ _ _ h => by
simp
exact h.lte_ctxLen
| head :: tail, .stop => by simp [List.length]
theorem HasType.at_ctx_index {ctx : List α} (ht : HasType n ctx ty) : ctx[n]'ht.lte_ctxLen = ty := by
induction ht with
| stop => simp
| @pop _ _ _ ctx htt ih =>
cases ctx with
| nil => cases htt
| cons head tail => exact ih
theorem HasType.from_prf (ctx : List α) (h : n < ctx.length) : HasType n ctx ctx[n] := by
cases ctx with
| nil => contradiction
| cons head tail =>
cases tail with
| nil =>
have unwrap: [head][n] = head := by exact List.getElem_singleton h
have n_eq_0: n = 0 := by exact Nat.lt_one_iff.mp h
rw [unwrap, n_eq_0]
exact .stop
| cons neck taill =>
cases n with
| zero => exact .stop
| succ nn =>
refine .pop ?_
exact HasType.from_prf (neck :: taill) _
theorem HasType.ctx_both_ways {α n ty} (ctx : List α) {lenPrf : n < ctx.length} : ctx[n] = ty ↔ HasType n ctx ty := by
apply Iff.intro
intro h
rw [←h]
refine HasType.from_prf ctx ?_
intro h
refine HasType.at_ctx_index h
Last updated: Dec 20 2025 at 21:32 UTC