Warning: This was written for Lean v4.5.0. To make the accepted answer work, please use v4.6.0-rc1.
I would like to define an elementary quicksort
function for lists in Lean 4. The following declaration can be used in computations but I want to fill the sorry
:
def qsort (L : List Int) : List Int :=
match L with
| [] => []
| x :: l => qsort (p1 x l) ++ [x] ++ qsort (p2 x l)
where
p1 (x : Int) (l : List Int) : List Int := (l.filter (· ≤ x))
p2 (x : Int) (l : List Int) : List Int := (l.filter (· > x))
decreasing_by {sorry}
#eval qsort [1, -3, 4, 5, 2] -- [-3, 1, 2, 4, 5]
The tactic state that I see in the Lean infoview is the following:
2 goals
x: Int
l: List Int
⊢ (invImage (fun a => sizeOf a) instWellFoundedRelation).1 (qsort.p1 x l) (x :: l)
x: Int
l: List Int
⊢ (invImage (fun a => sizeOf a) instWellFoundedRelation).1 (qsort.p2 x l) (x :: l)
I think that, to prove that the recursion terminates, it should be enough to prove the following proposition:
List.length (qsort.p1 x l) < List.length (x::l) : Prop
and similarly for qsort.p2
. So I would like the expression
invImage (fun a => sizeOf a) instWellFoundedRelation
that I see in the Lean infoview to be
invImage (List.length : List Int → Nat) Nat.lt_wfRel
but I have not been able to make this appear in the goal. Indeed, this is a term of type WellFoundedRelation (List Int)
whose first projection is the relation r L1 L2
defined by List.length L1 < List.length L2
.
If I could make this appear in the goal, then I should to be able to conclude by proving the proposition List.length (qsort.p1 x l) < List.length (x::l)
.
I have looked at the answers to the following question
but I have not been able to use termination_by
in my example, so I am trying to use decreasing_by
instead, which has the effect of making Lean enter tactic mode and display a goal.