Zulip Chat Archive

Stream: general

Topic: Making auxiliary goals when `refine` fails by type mismatch


nrs (Dec 09 2024 at 03:31):

I'm trying to figure out a workflow to make finding terms for Fin2 easier by using tactics. Consider the following function:

def makeSuccNTimesFunc {n : Nat} : (m : Nat) -> Fin2 n.succ -> Fin2 (n.succ + m)
| .zero => id
| .succ mm => (Fin2.fs .)  (makeSuccNTimesFunc mm)

Attempting to use refine with it in a proof causes a type mismatch:

example {n : Nat} : Fin2 n.succ := by
  refine @makeSuccNTimesFunc ?firstUnknown n ?finToSucc

The error is: has type Fin2 (Nat.succ ?firstUnknown + n) but Fin2 n.succ is expected. This particular case is easy to solve just by reading off the types, but it's a mwe for more difficult cases. I've rewritten the function in the following way for there to be a proof that will simplify the x : Nat in the goal Fin2 x:

def makeSuccNTimesFunc' {n : Nat} : (m x : Nat) -> n.succ + m = x -> Fin2 n.succ -> Fin2 x
| .zero, x, p => by rw [<- p]; exact id
| .succ mm, x, p => by rw [<- p]; exact @makeSuccNTimesFunc _ _

which allows me to help me prove the statement using refine like so:

example {n : Nat} : Fin2 n.succ := by
  refine @makeSuccNTimesFunc' ?whichn ?applyAmount n.succ ?eqproof ?fin
  case applyAmount => exact n
  case whichn => exact 0
  case eqproof => simp_arith
  case fin => exact .fz

We can then rewrite it in term mode now that we know what goes where and use our previous function makeSuccNTimesFunc instead of the new one.

My question is this: is there a way to produce auxiliary goals, which behave like the result of rewriting the function makeSuccNTimesFunc into makeSuccNTimesFunc', without needing to actually rewrite the function, when refine fails to produce auxiliary goals?

nrs (Dec 09 2024 at 03:53):

hm combining convert with named holes does seem like an intermediary solution (didn't know you could use ?var holes with convert). edit: hm but it's hard to control it this way and it will resolve holes that you want to keep open

nrs (Dec 09 2024 at 15:12):

in case it helps someone: I've turned the let/revert/refold/intro sequence in the following piece of code into a macro and found using it provided the same benefits as refactoring the function to allow the typechecker to help finding a desired value (it plays the role of ?eqproof above). This solution is inspired by comments at https://github.com/leanprover-community/mathlib4/pull/12745

example {n : Nat} : Fin2 n.succ := by
  have ha := @makeSuccNTimesFunc ?n ?applyAmount ?finToApplyTo
  let x := Nat.succ ?n + ?applyAmount
  revert ha
  refold_let x
  intro ha
  suffices x = n.succ by rwa [<-this]
  case finToApplyTo := .fz
  case applyAmount := n
  unfold x
  case n := 0
  simp_arith

edit: whoops I think this is effectively the same as using convert ... using 1


Last updated: May 02 2025 at 03:31 UTC