Zulip Chat Archive

Stream: new members

Topic: Proof irrelevance ignored?


aron (Jul 19 2025 at 22:17):

My attempt to prove a goal fails with this error:

type mismatch
  this
has type
  (@set' α len tail j'  a)[n'] = tail[n'] : Prop
but is expected to have type
  (@set' α len tail j'  a)[n'] = tail[n'] : Prop

The only difference between these two is the proof. The former has proof:

?m.67165 tail n' j' (Nat.succ_lt_succ_iff.mp jlt) nneqj : j' < len

And the latter:

Nat.succ_lt_succ_iff.mp jlt : j' < len

But why is this causing an issue if proofs are irrelevant anyway?

import Mathlib

section Vec

inductive Vec (α : Type u) : Nat  Type u
  | nil : Vec α 0
  | cons : α  Vec α n  Vec α (n + 1)


@[match_pattern] infixr:67 " :: " => Vec.cons
@[match_pattern] notation "[]" => Vec.nil
@[match_pattern] notation "[" t "]" => Vec.cons t []

example : Vec Nat 3 := 1 :: 2 :: 3 :: []

def Vec.map (vec : Vec α n) (f : α  β) : Vec β n :=
  match vec with
  | [] => []
  | head :: tail => f head :: tail.map f

instance : Functor (Vec · n) where
  map f a := Vec.map a f

def Vec.mem [DecidableEq α] (vec : Vec α n) (item : α) : Prop :=
  match vec with
  | [] => False
  | head :: tail => if head = item then True else mem tail item


instance [DecidableEq α] : Membership α (Vec α n) where
  mem := Vec.mem





@[reducible] def Vec.length (_vec : Vec α n) : Nat := n

@[reducible,simp] def Vec.set' (vec : Vec α n) (i : Nat) {h : i < n} (newItem : α) : Vec α n :=
  match vec, i with
  | .cons head tail, 0 => .cons newItem tail
  | .cons head tail, n+1 => by
    refine .cons head (tail.set' (h:= ?_) n newItem)
    exact Nat.succ_lt_succ_iff.mp h

@[reducible,simp] def Vec.set (vec : Vec α n) (index : Fin n) (newItem : α) : Vec α n :=
  vec.set' index (h:=index.prop) newItem


@[reducible,simp] def Vec.setIndexPrf (vec : Vec α n) (index : Nat) (h : index < n) (newItem : α) : Vec α n :=
  vec.set index,h newItem

theorem Vec.sets_eq {vec : Vec α n} : vec.set index,h = vec.setIndexPrf index h := by simp


@[reducible,simp] def Vec.get (vec : Vec α n) (index : Fin n) : α :=
  match vec, index with
  | .cons head tail,  0, _  => head
  | .cons head tail,  n+1, _  => by
    refine tail.get  n, ?_ 
    expose_names
    exact Nat.succ_lt_succ_iff.mp isLt


@[reducible,simp] def Vec.getIndexPrf (vec : Vec α n) (index : Nat) (h : index < n) : α :=
  vec.get index,h

theorem Vec.gets_eq {vec : Vec α n} : vec.get index,h = vec.getIndexPrf index h := by simp


@[simp,reducible] instance : GetElem (Vec α n) Nat α (valid := fun _ i => i < n) where
  getElem as i h := as.get i,h

@[simp,reducible] instance : GetElem (Vec α n) (Fin n) α (valid := fun _ _ => True) where
  getElem as i _ := as.get i




theorem Vec.get_at_zero {tail : Vec α len} {h : 0 < len+1} : (head :: tail)[0] = head := by simp only [instGetElemVecNatLt]





theorem Vec.get_at_zero_prf {tail : Vec α len} {index : Fin (len+1)} {h : index.val = 0} : (head :: tail)[index] = head := by
  simp
  let inner,prf := index
  have : inner = 0 := h
  simp_rw [this]

theorem Vec.get_elem {vec : Vec α len} {h : index < len} : vec[index] = vec.get index,h := by simp
theorem Vec.get_elem_to_prf {vec : Vec α len} {h : index < len} : vec[index] = vec[Fin.mk index h] := by simp





theorem Vec.get_prf_succ {tail : Vec α n} {i : Nat} {hlt : i < n} : (head :: tail : Vec α (n+1))[i + 1]'(by simp; exact hlt) = tail[i] := by
  simp

theorem Vec.get_succ {tail : Vec α n} {i : Fin n} : (head :: tail : Vec α (n+1))[Fin.mk (i.val + 1) (by simp : i.val + 1 < n+1)] = tail[i] := by
  simp


theorem Vec.cons_uncons {vec : Vec α len} {n : Nat} {h : n < len} : (head :: vec)[n+1] = vec[n] := by simp [instGetElemVecNatLt,Vec.get]



theorem Vec.get_nat_fin_eq {α len index h} {vec : Vec α len} : vec.get index, h = vec[index]'h := by
  cases vec <;> simp [instGetElemVecNatLt]


theorem Vec.set_at_zero {tail : Vec α len} {h : 0 < len+1} : (head :: tail).set 0, h newThing = newThing :: tail := by simp

theorem Vec.set_at_succ {tail : Vec α len} {i : Nat} {h : i < len+1} {hsucc : i = i' + 1} : (head :: tail).set i, h newThing = (head :: tail.set i', by omega newThing : Vec _ _) := by
  simp only [Vec.set]
  subst_eqs
  simp

theorem Vec.set'_at_succ {tail : Vec α len} {i : Nat} {h : i < len+1} {hsucc : i = i' + 1} : (head :: tail).set' (h:=h) i newThing = (head :: tail.set' i' (h:=by omega) newThing : Vec _ _) := by
  subst_eqs
  simp


theorem Vec.set_has_at {ctx : Vec α len} : (ctx.set index newThing)[index] = newThing := by
  simp only [Vec.set]
  exact Vec.set'.induct ctx index.val (h:=index.prop)
    (motive := fun {len} ctx i {h} => (ctx.set' i (h:=h) newThing)[i] = newThing)
    (case1 := fun a head tail isLt => by simp)
    (case2 := fun a b c d e f => f)


theorem Vec.set_other_unchanged {ctx : Vec α len} (j : Nat) (hj : j < len) (i : Nat) (hi : i < len) (hneq : i  j) : (ctx.set' (h:=hj) j a)[i] = ctx[i] := by
  revert i
  have :=
    Vec.set'.induct
      (motive := fun {len} vec i =>  (j : Nat) (hj : j < len) (jneq : i  j), (vec.set' j a)[i] = vec[i])
      (case1 :=
        by
        intro len head tail isLt j jlt jneq
        rw [Vec.get_at_zero]
        cases j with
        | zero => contradiction
        | succ j' =>
          have : ((head :: tail).set' (h:=?_) (j' + 1) a) = (head :: (tail.set' (h:=?_) j' a)) := Vec.set'_at_succ (i:=j'+1) (hsucc:=rfl)
          rw [this]
          rw [Vec.get_at_zero]
          exact Nat.succ_lt_succ_iff.mp jlt
          exact jlt)
      (case2 :=
        by
        intro len head tail n' hn ih
        have pl1 : n'.succ = n'+1 := by exact rfl
        simp only [pl1]
        intro j jlt jneq
        cases j with
        | zero => simp
        | succ j' =>
          have : ((head :: tail).set' (h:= jlt) (j' + 1) a) = (head :: (tail.set' (h:=Nat.succ_lt_succ_iff.mp jlt) j' a)) := Vec.set'_at_succ (i:=j'+1) (hsucc:=rfl)
          rw [this]
          have := Vec.get_prf_succ (i:=n') (n:=len) (hlt:= Nat.succ_lt_succ_iff.mp hn) (head:=head) (tail:=tail)
          rw [this]
          have := Vec.get_prf_succ (i:=n') (n:=len) (hlt:= Nat.succ_lt_succ_iff.mp hn) (head:=head) (tail:=tail.set' (h:=Nat.succ_lt_succ_iff.mp jlt) j' a)
          rw [this]
          have jlen : j' < len := by exact Nat.succ_lt_succ_iff.mp jlt
          have nneqj : n'  j' := by exact fun a => jneq (congrFun (congrArg HAdd.hAdd a) 1)
          have := ih j' (Nat.succ_lt_succ_iff.mp jlt) nneqj
          -- simp at this ⊢
          -- rw [←this]
          refine this)

  refine this

Aaron Liu (Jul 19 2025 at 22:26):

On one side the proof is a metavariable that defeq can't figure out how to assign and I'm guessing this is blocking it from applying proof irrelevance

Aaron Liu (Jul 19 2025 at 22:29):

in particular if you go to that metavariable and sorry it the refine this goes through but you get more "failed to infer" problems elsewhere

aron (Jul 19 2025 at 22:30):

how do i "go" to that metavariable?

aron (Jul 19 2025 at 22:30):

but why can't it figure out how to assign it? i'm literally providing it with Nat.succ_lt_succ_iff.mp jlt

Aaron Liu (Jul 19 2025 at 22:50):

  have :=
    Vec.set'.induct
      (motive := fun {len} vec i =>  (j : Nat) (hj : j < len) (jneq : i  j), (vec.set' j a (h := sorry))[i] = vec[i])

is what I did and it got me a bunch of new errors

Aaron Liu (Jul 19 2025 at 22:50):

By the way, why are you taking the proof implicitly?

aron (Jul 19 2025 at 22:51):

idk, why not? ease of use

aron (Jul 19 2025 at 22:54):

right so it looks like all I needed to do was

    Vec.set'.induct (n:=len) (vec:=ctx)
      (motive := fun {len} vec i =>  (j : Nat) (hj : j < len) (jneq : i  j), (vec.set' (h:=hj) j a)[i] = vec[i])

Then all that was left was massaging the params a bit and it worked

theorem Vec.set_other_unchanged {ctx : Vec α len} (j : Nat) (hj : j < len) (i : Nat) (hi : i < len) (hneq : i  j) : (ctx.set' (h:=hj) j a)[i] = ctx[i] := by
  revert i
  have this :=
    Vec.set'.induct (n:=len) (vec:=ctx)
      (motive := fun {len} vec i =>  (j : Nat) (hj : j < len) (jneq : i  j), (vec.set' (h:=hj) j a)[i] = vec[i])
      (case1 :=
        by
        intro len head tail isLt j jlt jneq
        rw [Vec.get_at_zero]
        cases j with
        | zero => contradiction
        | succ j' =>
          have : ((head :: tail).set' (h:=?_) (j' + 1) a) = (head :: (tail.set' (h:=?_) j' a)) := Vec.set'_at_succ (i:=j'+1) (hsucc:=rfl)
          rw [this]
          rw [Vec.get_at_zero]
          exact Nat.succ_lt_succ_iff.mp jlt
          exact jlt)
      (case2 :=
        by
        intro len head tail n' hn ih
        have pl1 : n'.succ = n'+1 := by exact rfl
        simp only [pl1]
        intro j jlt jneq
        induction j with
        | zero => simp
        | succ j' iih =>
          have : ((head :: tail).set' (h:= jlt) (j' + 1) a) = (head :: (tail.set' (h:=Nat.succ_lt_succ_iff.mp jlt) j' a)) := Vec.set'_at_succ (i:=j'+1) (hsucc:=rfl)
          rw [this]
          have := Vec.get_prf_succ (i:=n') (n:=len) (hlt:= Nat.succ_lt_succ_iff.mp hn) (head:=head) (tail:=tail)
          rw [this]
          have := Vec.get_prf_succ (i:=n') (n:=len) (hlt:= Nat.succ_lt_succ_iff.mp hn) (head:=head) (tail:=tail.set' (h:=Nat.succ_lt_succ_iff.mp jlt) j' a)
          rw [this]
          have jlen : j' < len := by exact Nat.succ_lt_succ_iff.mp jlt
          have nneqj : n'  j' := by exact fun a => jneq (congrFun (congrArg HAdd.hAdd a) 1)
          have this : (tail.set' j' a)[n'] = tail[n'] := ih j' (Nat.succ_lt_succ_iff.mp jlt) nneqj
          refine this)

  exact fun i hi hneq => this i j hj hneq

Aaron Liu (Jul 19 2025 at 23:03):

aron said:

idk, why not? ease of use

It only seems harder to use so far, since it can rarely actually be inferred so you always have to specify it


Last updated: Dec 20 2025 at 21:32 UTC