Zulip Chat Archive
Stream: lean4
Topic: It is possible to induct on recursive function calls?
Alex Zani (Apr 06 2025 at 17:39):
So I'm working on a parser and I have functions that look like this MWE. acceptNext
steps through the input. advanceWhile
skips through characters as long as a predicate is true. (In the real code, acceptNext does some bookkeeping for things like line and column numbers which is why it is a separate function)
def acceptNext : List Char → Option (List Char × Char)
| (c :: cs) => some (cs, c)
| [] => none
def advanceWhile (l : List Char) (pred : Char → Bool) : List Char :=
match isSome : acceptNext l with
| some (ls, c) =>
if pred c
then advanceWhile ls pred
else l
| none => l
termination_by (l.length)
decreasing_by
simp_wf
revert isSome
induction l with
| nil => unfold acceptNext; simp
| cons c' ls' =>
unfold acceptNext
simp
intro hls _
rw [hls]
simp
In order to help me prove that some callers terminate, I would like to prove that
theorem advanceWhile_progresses (l : List Char) (pred : Char → Bool) :
(advanceWhile l pred).length ≤ l.length := by
I'm very confused by how to go about it. If I was doing it on paper, I would probably do something like induction on the size of the call stack. But I'm not sure how I would do that here.
Edward van de Meent (Apr 06 2025 at 17:40):
if the proof follows the same shape as the function, i imagine advanceWhile.induct
might help
Bhavik Mehta (Apr 06 2025 at 17:40):
Lean generates acceptNext.induct
and advanceWhile.induct
, one of these might be helpful to you
Bhavik Mehta (Apr 06 2025 at 17:41):
In particular, acceptNext.induct
will do induction on the size of the call stack, since that's the shape of that definition. You could alternatively induct on l
itself, which should do something similar, and will induct on the shape of the list
Alex Zani (Apr 06 2025 at 18:04):
Thanks. acceptNext.induct
does not appear to exist. I'm also a bit unsure how I'm supposed to go about using acceptWhile.induct
. I assume I should constructure an assumption using it, but the first thing it wants is a function from my parameters to Prop.
Ruben Van de Velde (Apr 06 2025 at 18:11):
Does the fun_induction
tactic work now?
Alex Zani (Apr 06 2025 at 18:21):
I'm getting "unknown tactic"
Kyle Miller (Apr 06 2025 at 18:27):
What does #version
say for you?
Alex Zani (Apr 06 2025 at 18:31):
unexpected token '#'; expected command
eval Lean.versionString
gives 4.10.0
Kyle Miller (Apr 06 2025 at 18:39):
I see — the latest stable release is 4.18, and 4.19 is currently under testing. Would you be able to upgrade?
Alex Zani (Apr 06 2025 at 18:39):
I'll see if I can.
Last updated: May 02 2025 at 03:31 UTC