Zulip Chat Archive
Stream: lean4
Topic: How do I tell the termination checker about a theorem?
Alex Zani (Mar 28 2025 at 02:39):
Ok, so I have the following function which makes the termination checker unhappy:
def advanceWhile (state : ParseState) (pred : (Char → Bool)) : ParseState :=
match isOk: state.acceptNext with
| ParseResult.ok state' c => if pred c then state'.advanceWhile pred else state
| _ => state
It's telling me that it cannot prove this:
state : ParseState
pred : Char → Bool
state' : ParseState
c : Char
isOk : state.acceptNext = ParseResult.ok state' c
h✝ : pred c = true
⊢ sizeOf state' < sizeOf state
Now, I actually proved this in a separate theorem.
theorem acceptNext_shrinks_state (state state' : ParseState) :
state.acceptNext = ParseResult.ok state' v → sizeOf state' < sizeOf state := ...
How do I tell the termination checker to look at that theorem?
Mario Carneiro (Mar 28 2025 at 03:10):
decreasing_by exact acceptNext_shrinks_state
at the end of the definition
Mario Carneiro (Mar 28 2025 at 03:11):
give or take
Alex Zani (Mar 28 2025 at 03:23):
When I open decreasing_by, the goal is now:
⊢ (invImage (fun x => PSigma.casesOn x fun state pred => state) instWellFoundedRelationOfSizeOf).1 ⟨state', pred⟩ ⟨state, pred⟩
which is quite different from "sizeOf state' < sizeOf state".
I then have to do a whole bunch of unfolding to get through the multiple layers of typeclasses. Is there a way around that?
Mario Carneiro (Mar 28 2025 at 03:43):
hm, try adding termination_by state
before the decreasing_by
Alex Zani (Mar 28 2025 at 03:50):
Mario Carneiro said:
hm, try adding
termination_by state
before thedecreasing_by
It get "no extra parameters bounds, please omit the =>
"
Mario Carneiro (Mar 28 2025 at 04:02):
note the edit
Alex Zani (Mar 28 2025 at 04:03):
Ah yes. I tried that and it didn't change anything.
Mario Carneiro (Mar 28 2025 at 04:03):
the goal in the decreasing_by should be different
Mario Carneiro (Mar 28 2025 at 04:05):
you could also try termination_by sizeOf state
, which should produce the same goal but maybe with a less obfuscated statement
Alex Zani (Mar 28 2025 at 04:11):
Mario Carneiro said:
you could also try
termination_by sizeOf state
, which should produce the same goal but maybe with a less obfuscated statement
I tried it three ways and it unfortunately isn't any simpler. (I do appreciate the help though)
-- No termination_by
-- ⊢ (invImage (fun x => PSigma.casesOn x fun state pred => state) instWellFoundedRelationOfSizeOf).1 ⟨state', pred⟩ ⟨state, pred⟩
-- termination_by state
-- ⊢ (invImage (fun x => PSigma.casesOn x fun state pred => state) instWellFoundedRelationOfSizeOf).1 ⟨state', pred⟩ ⟨state, pred⟩
-- termination_by (sizeOf state)
-- ⊢ (invImage (fun x => PSigma.casesOn x fun state pred => sizeOf state) instWellFoundedRelationOfSizeOf).1 ⟨state', pred⟩ ⟨state, pred⟩
Mario Carneiro (Mar 28 2025 at 04:36):
i guess it's fine, all three statements are really sizeOf state' < sizeOf state
in disguise
Mario Carneiro (Mar 28 2025 at 04:36):
simp_wf
will clean them up
Alex Zani (Mar 28 2025 at 14:12):
Mario Carneiro said:
simp_wf
will clean them up
Forgot to reply earlier, but thanks, yes. simp_wf is a godsend.
Last updated: May 02 2025 at 03:31 UTC