Zulip Chat Archive

Stream: new members

Topic: Indexing after List.findIdx?


Mark Fischer (Feb 13 2024 at 02:00):

I may have worked myself into a corner. Maybe somebody more experienced than me can help me navigate my way out. While I'm sure there's a theorem in Mathlib for this, I can't find it, so I've been trying to prove this for myself. It's also just for practice anyway, but I think I'm just not fully there yet with proofs by induction.

example (l : List α) (p : α  Bool) (i : ) (h : List.findIdx? p l = some i) : i < l.length := by
  induction l with
  | nil => simp only [List.findIdx?_nil] at h
  | cons x xs ih =>
    by_cases hb : p x
    . simp_all only [List.findIdx?_cons, zero_add, List.findIdx?_succ, ite_true, Option.some.injEq,List.length_cons]
      linarith
    . simp_all only [List.findIdx?_cons, zero_add, List.findIdx?_succ, ite_false,
      Option.map_eq_some', Bool.not_eq_true, List.length_cons]
      obtain i', ih', ip := h
      rw [ ip]
      refine Nat.succ_lt_succ ?_
      sorry

Timo Carlin-Burns (Feb 13 2024 at 02:32):

With proofs by induction, it's important to choose your induction hypothesis carefully. In this case, I think your induction hypothesis is not strong enough. Consider the goal state in the cons case:

ih: List.findIdx? p xs = some i  i < List.length xs
h: List.findIdx? p (x :: xs) = some i
hb: ¬p x = true
 i < List.length (x :: xs)

We can only use ih if the first match in xs is at position i, but that's not possible.h tells that the first match in x :: xs is at position i, which would mean the first match in xs is at position i - 1.

You can use induction ... generalizing ... to get a stronger induction hypothesis like this:

example (l : List α) (p : α  Bool) (i : ) (h : List.findIdx? p l = some i) : i < l.length := by
  induction l generalizing i with -- we need our induction hypothesis to apply for all `i`
  | nil => simp only [List.findIdx?_nil] at h
  | cons x xs ih =>
    by_cases hb : p x
    . simp_all only [List.findIdx?_cons, zero_add, List.findIdx?_succ, ite_true, Option.some.injEq,List.length_cons]
      linarith
    . simp_all only [List.findIdx?_cons, zero_add, List.findIdx?_succ, ite_false,
      Option.map_eq_some', Bool.not_eq_true, List.length_cons]
      obtain i', ih', ip := h
      rw [ ip]
      refine Nat.succ_lt_succ ?_
      apply ih
      exact ih'

(Note that this is not magic. You could do this manually with revert i; induction l; intro i)

Mark Fischer (Feb 13 2024 at 02:48):

Ah, revert i! I see. thanks


Last updated: May 02 2025 at 03:31 UTC