Zulip Chat Archive
Stream: new members
Topic: showing termination with pattern matching
Mark Aagaard (Nov 28 2024 at 16:04):
I'm exploring methods of showing termination in recursive functions. Lean is able to determine that quot4
below terminates because d > 0
is in the if-then-else condition.
def quot4 : (n d : Nat) → Nat
| 0, d => 0
| n, d => if n ≥ d ∧ d > 0 then 1 + quot4 (n-d) d else 0
If I incorporate the d > 0
condition into the pattern matching, Lean needs help to show termination:
abbrev quot3 : (n d : Nat) → Nat
| 0, 0 => 0
| n, 0 => 0
| n, d =>
have : d > 0 := sorry
if n ≥ d then 1 + quot3 (n-d) d else 0
Is there a preferred tactic to replace the sorry
in quot3
or is quot4
the best method for handling this form of recursion?
-mark
Eric Wieser (Nov 28 2024 at 16:34):
This works:
abbrev quot3 : (n d : Nat) → Nat
| 0, 0 => 0
| n, 0 => 0
| n, d@ h : (_ + 1) =>
if n ≥ d then 1 + quot3 (n-d) d else 0
Mark Aagaard (Nov 28 2024 at 17:05):
Eric, thanks. Do you know where this @ notation is documented? I'm familiar with "@" as a prefix for a name to get at implicit arguments, but this seems different.
-mark
Kyle Miller (Nov 28 2024 at 20:03):
It's got to be documented somewhere, but the gist is that x@patt
is a way to bind the value of the matched value to x
.
Kyle Miller (Nov 28 2024 at 20:08):
This suffices:
def quot3 : (n d : Nat) → Nat
| 0, 0 => 0
| n, 0 => 0
| n, d@(_+1) =>
if n ≥ d then 1 + quot3 (n-d) d else 0
The key is that in a match
, each match arm does not know that the previous cases do not apply, so you need the pattern _ + 1
to know for sure d
is not zero.
(By the way, you probably don't want a recursive abbrev
.)
Mark Aagaard (Nov 28 2024 at 20:31):
Kyle, thanks; that makes sense. Thanks also for the heads up about abbrev
. I had remembered that there were some differences between abbrev
and def
, and was tinkering, then forgot to clean up my code before posting.
-mark
Last updated: May 02 2025 at 03:31 UTC