Zulip Chat Archive
Stream: lean4
Topic: Functional induction cannot be performed on `List.getLast?`
Asei Inoue (Nov 28 2025 at 19:03):
Recently, I wrote the following proof:
variable {α : Type}
inductive List.IsChain (R : α → α → Prop) : List α → Prop
| nil : IsChain R []
| single (a : α) : IsChain R [a]
| cons_cons {a b : α} {l : List α} (hab : R a b) (hchain : IsChain R (b :: l)) :
IsChain R (a :: b :: l)
open List
attribute [grind cases] IsChain
attribute [simp] IsChain.nil IsChain.single
attribute [grind <=] IsChain.cons_cons IsChain.single IsChain.nil
namespace List
variable {R : α → α → Prop}
def List.last? (xs : List α) : Option α :=
match xs with
| [] => none
| [a] => some a
| _ :: b :: bs => last? (b :: bs)
theorem List.last?_cons_exists (xs : List α) (x : α) :
∃ y : α, some y = last? (x :: xs) := by
induction xs generalizing x with
| nil => exists x
| cons a as ih =>
obtain ⟨y, ih⟩ := ih a
dsimp [last?]
exists y
grind_pattern List.last?_cons_exists => List.last? (x :: xs)
@[grind =]
theorem IsChain.append {xs ys : List α} :
IsChain R (xs ++ ys) ↔
match xs.last?, ys with
| none, _ => IsChain R ys
| _, [] => IsChain R xs
| some x, b :: _ => IsChain R xs ∧ R x b ∧ IsChain R ys := by
fun_induction List.last? xs with grind
theorem IsChain.append_two {a b : α} {l : List α} :
IsChain R (l ++ [a, b]) ↔ IsChain R (l ++ [a]) ∧ R a b := by
induction l with grind
The auxiliary function List.last? that appears in this proof had to be newly defined specifically for this proof.
Although the standard library already provides a function List.getLast?, that function does not have an .induct theorem, so it cannot be used for functional induction.
It seems inconvenient that such a theorem does not exist, but is there a reason why it should not exist, or some fundamental difficulty in rewriting things so that such a theorem could exist?
Aaron Liu (Nov 28 2025 at 19:07):
it's not a recursive function
Asei Inoue (Nov 28 2025 at 19:09):
@Aaron Liu Thank you. You are right.
Asei Inoue (Nov 28 2025 at 19:11):
why it is not recursive? for performance?
Aaron Liu (Nov 28 2025 at 20:00):
I guess?
Asei Inoue (Nov 29 2025 at 03:39):
Thanks.
Markus Himmel (Nov 29 2025 at 07:45):
Non-recursive functions have a fun_cases theorem instead of a fun_induction theorem, and you can use the fun_cases tactic in place of the fun_induction tactic.
Last updated: Dec 20 2025 at 21:32 UTC