Zulip Chat Archive
Stream: lean4
Topic: Prove decreasing list size
Alex Sweeney (Oct 14 2023 at 17:43):
I have a function called List.chunk
that turns a list into a list of chunks of a given size. I know it terminates but I have no idea how to prove it.
-- Helper: Move n elements from source to acc. This terminates.
def extract : Nat → List α → List α → (List α × List α)
| _, [], acc => ([], acc.reverse)
| 0, source, acc => (source, acc.reverse)
| n + 1, a :: rest, acc =>
let m := extract n rest (a :: acc)
(m.fst, m.snd)
#eval extract 2 [1, 2, 3, 4, 5] []
-- ([3, 4, 5], [1, 2])
def List.chunk : List α → Nat → List (List α)
| [], _ => []
| _, 0 => []
| list, n =>
let (rest, chunk) := extract n list []
chunk :: List.chunk rest n -- failed to prove termination.
termination_by _ l _ => l.length
It wants me to prove ⊢ length rest < length list
which sounds right but I don't know how to do that. Clearly n
is positive, so (rest, chunk) := extract n list []
should take n
items thus length rest < length list
. I also don't fully understand what termination_by
is doing, but it seemed to be a step in the right direction. Any help is appreciated.
Henrik Böving (Oct 14 2023 at 18:17):
You want to write a lemma that shows that if you call extract n xs acc
where n > 0
(which is the case in your thing, you can prove it in that particular match arm but also just use the match arm| list, n + 1
to get this more easily) then the rest
part of the output is smaller than xs
, probably by induction, potentially generalizing on the acc
argument. Once you have that lemma you can go on to prove the thing that termination_by
wants you to do in a have
. You can find general information about the workings of termination_by here: https://lean-lang.org/theorem_proving_in_lean4/induction_and_recursion.html#well-founded-recursion-and-induction
Last updated: Dec 20 2023 at 11:08 UTC