Zulip Chat Archive

Stream: Is there code for X?

Topic: accessing the source case during induction


Jared green (Feb 26 2025 at 17:01):

im trying to do induction over length of a list.

variable (p : List a -> Prop)
theorem t  (n : List a) (hn : n  []): p n :=
  let m := n.length
  induction' m with m m' ih
  --i should be able to get a contradiction here
  ...

i could have done this another way, but p calls head n hn in my code so hn has to be a variable

Etienne Marion (Feb 26 2025 at 17:12):

Your code does not work in the playground, please post a #mwe.

Aaron Liu (Feb 26 2025 at 17:15):

Do you want something like this?

def List.recNeNil {α : Type u} {motive : (l : List α)  l  []  Sort v}
    (singleton :  x, motive [x] (List.cons_ne_nil x []))
    (cons :  x xs hxs, motive xs hxs  motive (x :: xs) (List.cons_ne_nil x xs))
    (l : List α) (hl : l  []) : motive l hl :=
  match l with
  | [x] => singleton x
  | x :: y :: xs =>
    cons x (y :: xs) (List.cons_ne_nil y xs)
      (List.recNeNil singleton cons (y :: xs) (List.cons_ne_nil y xs))

variable (p : List a  Prop)
example (n : List a) (hn : n  []) : p n := by
  induction n, hn using List.recNeNil with
  | singleton x => sorry
  | cons x xs hxs ih => sorry

Riccardo Brasca (Feb 26 2025 at 17:27):

This is basically the same as Aaron's answer, but depending on what you are doing precisely you can use directly strucutral induction, without introducing a new theorem.

import Mathlib

variable {a : Type*} (p : List a -> Prop)

theorem t  (n : List a) (hn : n  []): p n :=
match n, hn with
| x::L, _ => by
  by_cases hL : L = []
  · simp [hL] --singleton case
    sorry
  have := t L hL --now `this` is a proof of `p L` and you have to prove `p (x::L)`
  sorry

Giacomo Stevanato (Feb 26 2025 at 17:35):

Jared green said:

theorem t (n : List a) (hn : n ≠ []): p n

This is saying that if you have a list, and it's not empty, then any property holds for it. This seems clearly false to me, so you probably won't be able to find a proof for it.

Jared green (Feb 26 2025 at 18:15):

it would be more like this

variable (p q : List a -> Prop)
theorem t  (n : List a) (hn : n  []): (n.length > 1 -> q n ->  l : List a, l.length = n.length - 1  q l  (p l -> p n) ) -> (length n = 1 -> q n -> p n) -> q n -> p n :=
  let m := n.length
  induction' m with m m' ih
  --i should be able to get a contradiction here
  ...

Jared green (Feb 26 2025 at 18:29):

and, l is not necessarily (tail n)

Kyle Miller (Feb 26 2025 at 18:51):

With your original example, you can give n.length as an induction target directly. Using let causes it to not know that m is the length.

You can also use h : syntax to introduce the necessary hypothesis to make use of n.length in each case.

variable (p : List a -> Prop)
theorem t  (n : List a) (hn : n  []): p n := by
  induction' h : n.length with m m' ih
  · cases n <;> simp_all
  · sorry -- induction step

(The h : syntax should work with the let variable too.)

suhr (Feb 26 2025 at 19:40):

Two more versions of the same thing:

import Mathlib

variable (p : List a -> Prop)
example (n : List a) (hn : n  []): p n := by
  suffices h: l, n.length = l  p n from h n.length rfl
  intro l
  induction l with
  | zero => sorry       -- ⊢ n.length = 0 → p n
  | succ l ih => sorry  -- ⊢ n.length = l + 1 → p n

example (n : List a) (hn : n  []): p n := by
  suffices h: l, n.length = l  p n from h n.length rfl
  refine λl => l.recOn
    (λh: n.length = 0 => ?zero)
    (λl (ih: n.length = l  p n)(h: n.length = l.succ) => ?succ)
  case zero => cases n <;> simp_all
  case succ => sorry

Note that the last version does not require you to know much about tactics... If you mastered terms, you always find a way.

Kyle Miller (Feb 26 2025 at 21:23):

@suhr Can I ask why you are preferring to write suffices/intro instead of generalize?

import Mathlib

variable (p : List a -> Prop)
example (n : List a) (hn : n  []): p n := by
  generalize h : n.length = l
  induction l with
  | zero => sorry       -- h : n.length = 0 ⊢ p n
  | succ l ih => sorry  -- h : n.length = l + 1 ⊢ p n

(Note: in the next lean release, we will be able to write induction h : n.length with to have the same effect.)

suhr (Feb 26 2025 at 21:51):

I often write proofs in term mode, and suffices is both a term and a tactic. And I just forgot that generalize exists.
The proof indeed looks nicer with generalize.


Last updated: May 02 2025 at 03:31 UTC