Motivation
While implementing elaborate_circuit_with, we used Lean meta dsimp on an expression to normalize a generated term before assigning it. This is useful beyond tactics that close goals: sometimes we want to simplify a term, keep the simplified term, and optionally keep the equality proof relating it to the original term.
A possible surface API could look like:
let ⟨x', hx⟩ := dsimp_term x only [explicit_circuit_norm]
-- x' : same type as x
-- hx : x = x'
let ⟨y', hy⟩ := simp_term y only [foo, bar]
-- hy : y = y'
For the common definitional-normalization case, a projection is enough:
let x' := (dsimp_term x only [explicit_circuit_norm]).1
Proposed implementation
Add a term elaborator, likely starting with the conservative dsimp_term version.
Implementation sketch:
- Elaborate the input term, preserving the expected type when available.
- Parse simp-style arguments, or initially support only
only [...] for a smaller MVP.
- Build a
Simp.Context/dsimp context from those arguments.
- Run meta-level normalization on the elaborated expression:
let r ← dsimp e dsimpCtx
let e' := r.expr
- Return a pair containing the normalized expression and a proof. For
dsimp, mkEqRefl e is often enough after definitional reduction; for full simp, use the proof returned by simp.
- Add an expected type hint or check the normalized expression against the original expected type. If full
simp changes the type only propositionally, either reject that case initially or return a cast/proof shape that makes transport explicit.
Notes
dsimp_term is the safer first primitive because the output should remain definitionally compatible with the input type. simp_term is more general, but it needs a careful story for proof transport and cases where the simplified expression no longer checks at the expected type by definitional equality.
Motivation
While implementing
elaborate_circuit_with, we used Lean metadsimpon an expression to normalize a generated term before assigning it. This is useful beyond tactics that close goals: sometimes we want to simplify a term, keep the simplified term, and optionally keep the equality proof relating it to the original term.A possible surface API could look like:
For the common definitional-normalization case, a projection is enough:
Proposed implementation
Add a term elaborator, likely starting with the conservative
dsimp_termversion.Implementation sketch:
only [...]for a smaller MVP.Simp.Context/dsimpcontext from those arguments.dsimp,mkEqRefl eis often enough after definitional reduction; for fullsimp, use the proof returned by simp.simpchanges the type only propositionally, either reject that case initially or return a cast/proof shape that makes transport explicit.Notes
dsimp_termis the safer first primitive because the output should remain definitionally compatible with the input type.simp_termis more general, but it needs a careful story for proof transport and cases where the simplified expression no longer checks at the expected type by definitional equality.