I would like to inductively rewrite terms in conv mode. My application would be to compute derivatives of recursively defined functions.
I have a buggy prototype that can do induction over natural numbers. You can rewrite: n+n to Nat.recOn n 0 fun n' xₙ => xₙ + 2 using conv command induction n (simp) (rw[thm1,eq]).
Here is the full code:
code
importLeanimportQqopenLeanMetaQqElabTacticConvsyntax(name:=conv_induction)"induction"identconvconv:conv@[tacticconv_induction]defconvInduction:Tactic|`(conv|induction$n$baseConv$succConv)=>doletmvarId←getMainGoalmvarId.withContextdoletlhs←getLhslet.somedecl:=(←getLCtx).findFromUserName?n.getId|throwErrors!"local variable {n} not found"letn:=Expr.fvardecl.fvarIdletlhsFun←mkLambdaFVars#[n]lhslet(x₀,eq₀)←convert(lhsFun.beta#[(.const``Nat.zero[])])(Tactic.evalTacticbaseConv)let(lhs',prf)←withLocalDeclD`n'(.const``Nat[])funn'=>dowithLocalDeclD`xₙ(←inferTypelhs)funxₙ'=>dowithLocalDeclD`eq(←mkEq(lhsFun.beta#[n'])xₙ')funeqₙ'=>dolet(xSucc,eqSucc)←convert(lhsFun.beta#[(←mkAppM``Nat.succ#[n'])])(Tactic.evalTacticsuccConv)letmotive:=Expr.lamdefaultq(Nat)(←inferTypelhs)defaultletbase:=x₀letsucc←mkLambdaFVars#[n',xₙ']xSuccletrecDef←mkLambdaFVars#[n'](←mkAppOptM``Nat.recOn#[motive,n',base,succ])letmotive←mkLambdaFVars#[n']((←inferTypeeqₙ').replaceFVarxₙ'(recDef.beta#[n']))withLocalDeclD`eq(motive.beta#[n'])funeqₙ''=>doletbase:=eq₀letsucc←mkLambdaFVars#[n',eqₙ''](eqSucc.replaceFVars#[xₙ',eqₙ'']#[recDef.beta#[n'],eqₙ''])letrecProof←mkAppOptM``Nat.recOn#[motive,n,base,succ]return(recDef.beta#[n],recProof)updateLhslhs'prf|_=>throwUnsupportedSyntaxtheoremthm1{n}:n.succ+n.succ=n+n+2:=sorryexample(n:Nat):n+n=(Nat.recOnn0funn'xₙ=>xₙ+2):=byconv=>lhsinductionn(simp)(rw[thm1,eq])
Unfortunately it produces an error (kernel) declaration has free variables '_example'. What did I do wrong?
Also compiler can't work with Nat.recOn, what should I do to produce executable code? How can I generalize this to any inductive type?
Check out compile_inductive% in mathlib. It's used to autogenerate compiled definitions for recursors, and for example there's compile_inductive% Nat already in Mathlib.Util.CompileInductive