Skip to content

swap example with monad tactics#78

Draft
miriampolzer wants to merge 1 commit intoAeneasVerif:mainfrom
miriampolzer:swap_with_steps
Draft

swap example with monad tactics#78
miriampolzer wants to merge 1 commit intoAeneasVerif:mainfrom
miriampolzer:swap_with_steps

Conversation

@miriampolzer
Copy link
Copy Markdown
Collaborator

Drafted up tactics and used andres approach from #75 to step through the swap proof rather nicely. The tactics are very drafty, first time I am doing this. I dont want to merge this as is, just wanted to share what I tried out.

@miriampolzer miriampolzer changed the title learning tactics swap example with monad tactics Apr 16, 2026
Comment thread Kraken/Examples.lean

set_simple mvarId tail

elab "set_simple " t:term : tactic => do
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the same as let +generalize this := t?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so, thank you!

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's a difference:

example : (1 + 1) + 1 = 2 + 1 := by
    -- set_simple (2+1) -- works as expected (modifies RHS only)
    let +generalize y := 2+1 -- modifies both sides, new goal is `y = y`

Copy link
Copy Markdown
Contributor

@eric-wieser eric-wieser Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this only happens for Nat, which Lean unifies very agressively even with with_reducible applied.

If the numerals are Int or UInt64 then with_reducible let +generalize y := 2 + 1 behaves in the way you requested.

Lean frequently takes the viewpoint that exact expression matches don't matter, and all that matters is definitional matching up to some reducibility. Typeclasses basically force it to take this viewpoint:

import Mathlib -- for typeclasses

open Lean Elab Tactic Meta

-- as in this PR
def set_simple (mvarId : MVarId) (t : Expr): MetaM MVarId := do
  mvarId.withContext do
    let target ← mvarId.getType
    let type ← inferType t
    let lctx ← getLCtx
    let name := lctx.getUnusedName `x

    let (fvarId, mvarId) ← (← mvarId.define name type t).intro name

    mvarId.withContext do
      let newTarget := target.replace fun e =>
        if e == t then some (mkFVar fvarId) else none -- this line should use `isDefEq` instead
      mvarId.replaceTargetDefEq newTarget

elab "set_simple " t:term : tactic => do
  let mvarId ← getMainGoal
  let term ← elabTerm t none
  let newMvarId ← set_simple mvarId term
  replaceMainGoal [newMvarId]

example : (1 + 2) + 1 = (3 : Int) := by
  rw [add_assoc]  -- Int.add_assoc is ok here, but `add_assoc` introduces `AddSemigroup.toAdd`
  set_simple (2 + 1 : Int)
  -- didn't work, goal doesn't contain `x`

Copy link
Copy Markdown
Collaborator Author

@miriampolzer miriampolzer Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For me to learn: Say we wanted to have a version that doesn't reduce while replacing but can handle the Typeclass issue, would there be a somewhat more limited reduction than isDefEq one could e.g. call on target in the first line of set_simple to avoid this?

Now I am also wondering if the replaceTargetDefEq would blow up on terms that get too large when reduced.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants