Tactics using elaborators
Let's start by writing a basic elaborator that retrieves and displays the expression representing the type of the main goal.
elab "goalExpr" : tactic => do
let goalExpr ← getMainTarget
logInfo m!"Main Target Expression: {goalExpr}"
example: 2 + 3 = 5 := ⊢ 2 + 3 = 5
⊢ 2 + 3 = 5
All goals completed! 🐙
If you formalize mathematics in Lean, you are likely familiar with the sorry tactic. We use it frequently as a placeholder for proofs yet to be written. The sorry tactic artificially closes the current main goal but leaves a warning in the Infoview.
example : 847 + 153 = 1000 := ⊢ 847 + 153 = 1000 All goals completed! 🐙
Under the hood, the sorry tactic works by creating a term of the main goal's type using the sorryAx axiom. You can inspect these internal components directly:
#check sorryAx
-- sorryAx.{u} (α : Sort u) (synthetic : Bool) : α
Now, let's write a custom tactic called toDo using elab and sorryAx. The toDo tactic will close the main goal just like sorry, but it will also accept a string argument to log a custom reminder to the Infoview.
elab "toDo" s: str : tactic => do
withMainContext do
logInfo m!"Message:{s}"
let targetExpr ← getMainTarget
let sorryExpr ←
mkAppM ``sorryAx #[targetExpr, mkConst ``false]
closeMainGoal `todo sorryExpr
example : 34 ≤ 47 := ⊢ 34 ≤ 47
All goals completed! 🐙
Let's break down the specific metaprogramming functions used to make this work:
-
getMainTargetretrieves the expression for the type of the current main goal. -
mkAppMis a highly useful function that constructs a function application expression. It takes theNameof the function, in this casesorryAx, and an array of expressions representing the arguments you want to pass to it.