Zulip Chat Archive

Stream: lean4

Topic: bug of functional induction?


Asei Inoue (Nov 25 2025 at 16:42):

open Std

variable {α : Type} [LE α] [DecidableLE α]

@[simp]
def stalinSort (l : List α) : List α :=
  match l with
  | [] => []
  | [x] => [x]
  | x :: y :: xs =>
    if x  y then
      x :: stalinSort (y :: xs)
    else
      stalinSort (x :: xs)

@[grind <=]
theorem stalinSort_cons_mem (x : α) (xs : List α) :
    x  stalinSort (x :: xs) := by
  induction xs with
  | nil => simp
  | cons x xs ih =>
    grind [stalinSort]

example (x : α) (xs : List α) :
    x  stalinSort (x :: xs) := by
  fun_induction stalinSort (x :: xs) with
  | case1 =>
    -- impossible to show
    sorry
  | case2 x1 =>
    -- impossible to show
    sorry
  | case3 x1 x2 xs ih =>
    grind [stalinSort]
  | case4 x1 x2 xs ih =>
    grind [stalinSort]

Asei Inoue (Nov 25 2025 at 16:43):

Using fun_induction generates a goal which is impossible to show...
using induction works well. I don't know why this occurs.

Asei Inoue (Nov 25 2025 at 16:45):

@Joachim Breitner I think you were working on functional induction.

Aaron Liu (Nov 25 2025 at 16:47):

It's because you're inducting on x :: xs

Asei Inoue (Nov 25 2025 at 17:03):

sorry I don't understand what breaks the proof

Asei Inoue (Nov 25 2025 at 17:11):

Is there way to write a correct proof using fun_induction?

Edward van de Meent (Nov 25 2025 at 17:33):

sort of...
lean needs to know which case xs is in in order to know which branch to take. if you want to be able to (almost) directly use fun-induction, you can redefine stalinSortAux like so:

open Std

variable {α : Type} [LE α] [DecidableLE α]

@[simp]
def stalinSortAux (x : α) (l : List α) : List α :=
  match l with
  | [] => [x]
  | y :: ys => if x  y then
    x :: stalinSortAux y ys else
    stalinSortAux x ys

@[simp]
def stalinSort (l : List α) : List α :=
  match l with
  | [] => []
  | x :: ys => stalinSortAux x ys

@[grind <=]
theorem stalinSort_cons_mem (x : α) (xs : List α) :
    x  stalinSort (x :: xs) := by
  induction xs with
  | nil => simp
  | cons x xs ih =>
    grind [stalinSort, stalinSortAux]

example (x : α) (xs : List α) :
    x  stalinSort (x :: xs) := by
  rw [stalinSort]
  fun_induction stalinSortAux x xs with
  | case1 =>
    grind
    -- -- impossible to show
    -- sorry
  | case2 x1 =>
    grind
    -- -- impossible to show
    -- sorry
  | case3 x1 x2 xs ih =>
    grind [stalinSort]

Edward van de Meent (Nov 25 2025 at 17:35):

it is expected that in your case, fun_inducition fails, because the proof of your theorem depends on the fact that you aren't in the case where x :: xs = []

Robin Arnez (Nov 26 2025 at 08:58):

You can also generalize before using functional induction to get an equality hypothesis:

open Std

variable {α : Type} [LE α] [DecidableLE α]

@[simp]
def stalinSort (l : List α) : List α :=
  match l with
  | [] => []
  | [x] => [x]
  | x :: y :: xs =>
    if x  y then
      x :: stalinSort (y :: xs)
    else
      stalinSort (x :: xs)

@[grind <=]
theorem stalinSort_cons_mem (x : α) (xs : List α) :
    x  stalinSort (x :: xs) := by
  induction xs with
  | nil => simp
  | cons x xs ih =>
    grind [stalinSort]

example (x : α) (xs : List α) :
    x  stalinSort (x :: xs) := by
  generalize hxxs : x :: xs = xxs
  fun_induction stalinSort xxs with
  | case1 => contradiction
  | case2 x1 => simp_all
  | case3 x1 x2 xs ih => grind [stalinSort]
  | case4 x1 x2 xs ih => grind [stalinSort]

Last updated: Dec 20 2025 at 21:32 UTC