This module implements the preprocessing of function definitions involved in well-founded recursion.
The goal is to change higher order functions to add more information to the context, e.g. change
List.map (fun x => …) xs to List.map (fun ⟨x, h⟩ => …) xs.attach. This extra information can
then be used by the termination proof tactic to determine that a recursive call is indeed
decreasing.
The process proceeds in these steps, to guide the transformation:
The parameters of the function are annotated with the
wfParamgadget.We could be more selective here and only annotate those that have a
SizeOfinstance. We cannot (easily) only consider the parameters that appear in the termination measure, as that is not known yet.The
wfParamgadget is pushed around:f (wfParam x) ==> wfParam (f x)iffis a projectionmatch (wfParam x) with con y => alt[y] ==> match x with con y => alt[wfParam y]In a match with multiple targets it suffices for any of the targets to be annotated with
wfParam, and all parameters of the match arms are annotated withwfParam. This is an overapproximation.
The
wf_preprocesssimpset is applied to do the actual transformation. It typically contains two rules for each higher-order function of interest(wfParam xs).map f = xs.attach.unattach.map fxs.unattach.map f = xs.map (fun ⟨x, h⟩ => binderNameHint x f (f (wfParam x)))
The first rule “activates” the call, the second rule actually performs it. They are separated like this so that for chains of the form
(xs.reverse.filter p).map fthe.attachis attached toxsand we get the basicx ∈ xsin the context off.The
binderNameHintpreserves the user-chosen name infif that is a lambda.The
wfParamon the right hand side ensurses that doubly-nested recursion works.All left-over
wfParamgadgets are removed.
The simplifier is used to perform steps 2 (using simprocs) and 3 (using rewrite rules) together.
Equations
- Lean.Elab.WF.mkWfParam e = Lean.Meta.mkAppM `wfParam #[e]
Instances For
f (wfParam x) ==> wfParam (f x) if f is a projection
Equations
- One or more equations did not get rendered due to their size.
Instances For
`match (wfParam x) with con y => alt[y] ==> match x with con y => alt[wfParam y]
Equations
- One or more equations did not get rendered due to their size.
Instances For
let x : T := (wfParam e); body[x] ==> let x : T := e; body[wfParam y] if T is not a proposition,
otherwise ... ==> let x : T := e; body[x]. (Applies to haves too.)
Note: simprocs are provided the head of a let telescope, but not intermediate lets.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.