Zulip Chat Archive
Stream: lean4
Topic: Dependent version of `apply`
Freddie Nash (Apr 06 2025 at 15:53):
Is there a version of/syntax for the apply
tactic which allows you to give a name to early parameters? E.g. if I want to prove p /\ q
, having a proof of p
around may be handy when proving q
(obviously I can just bind a name to my proof of p
with have
, but could save a fair bit of ceremony in some situations).
I can get close (for two params) with
def dapp (f:p -> q -> r) : (p ∧ (p -> q)) -> r := by
intro ⟨hp, hpq⟩
exact f hp (hpq hp)
macro "dapply" f: term : tactic => `(tactic|
(apply dapp $f; constructor)
)
but struggling with idents in tactics (e.g. syntax like dapply And.intro as lhs
, performing intro lhs
on the second goal), and it feels like something that someone else must have done better, and I'm just not using the right keywords to find it.
Edward van de Meent (Apr 06 2025 at 16:00):
i did have something similar, once... although i called it have_goal
Edward van de Meent (Apr 06 2025 at 16:02):
find the code here (it's one of those, but i can't remember precisely what the differences are)
Edward van de Meent (Apr 06 2025 at 16:03):
i guess it would be called unidiomatic by current standards since it only works when there are multiple goals available
Edward van de Meent (Apr 06 2025 at 16:05):
it doesn't look it but it comes with big warning signs of don't use unless you really really really have to
Freddie Nash (Apr 06 2025 at 16:13):
Topmost elaboration seems to work, and is rather more general than what I was going for
Freddie Nash (Apr 06 2025 at 16:16):
If it's not too complicated a topic, why would use of such a tactic be problematic? From my side, I'd rather name things up front, and not have issues like "now I need to close the goal with have_goal
rather than throwing tactic of my choice at it" (though presumably it would be easy to adapt to use an arbitrary tactic rather than a term), but those would both be matters of style and convenience, which I expect is not what you're getting at.
Edward van de Meent (Apr 06 2025 at 16:22):
to be clear, i was talking about have_goal
being unidiomatic, since it acts on multiple goals at once, while not necessarily working on all goals. In particular, it fails when used in combination with a focussing dot.
Edward van de Meent (Apr 06 2025 at 16:23):
mathlib lints against this kind of tactic, because (i think?) it makes the structure of the proof unclear?
Freddie Nash (Apr 06 2025 at 16:23):
I see: yes, failing with a dot did throw me initially (code examples for comparison)
theorem have_goal_test (p q r:Prop) (f:p -> q -> r) (hp:p) (hpq:p -> q) : r := by
apply f
have_goal lhs := hp
exact hpq lhs
theorem dapply_test (p q r:Prop) (f:p -> q -> r) (hp:p) (hpq:p -> q) : r := by
dapply f
. exact hp
. intro lhs
exact hpq lhs
-- (not got this working)
theorem dapply_ideal (p q r:Prop) (f:p -> q -> r) (hp:p) (hpq:p -> q) : r := by
dapply f as lhs -- ideally want to give a list of identifiers
. exact hp
. exact hpq lhs
(obviously with the idea that the proof of the lhs would not be trivial, and that the type of the proposition is probably long and painful to read, so you don't really want to be binding it manually)
Kyle Miller (Apr 06 2025 at 17:45):
You can use refine
and named placeholders:
theorem dapply_ideal (p q r:Prop) (f:p -> q -> r) (hp:p) (hpq:p -> q) : r := by
refine f ?as ?lhs
. exact hp
. exact hpq ?as
Freddie Nash (Apr 06 2025 at 17:50):
Is that a recent addition? Not seeing any bindings with 4.14-rc2 (I probably ought to bump that)
Freddie Nash (Apr 06 2025 at 17:54):
(nor with 4.18)
Freddie Nash (Apr 06 2025 at 17:55):
Ah! I missed the ?
in the usage: that's exciting, and works with apply
also (I presume this allows you to talk about any filled hole)
Ruben Van de Velde (Apr 06 2025 at 18:12):
Oh wow, I didn't realize that worked
Kyle Miller (Apr 06 2025 at 18:14):
Freddie Nash said:
Is that a recent addition?
It's been there since before the first public release of Lean 4.
Freddie Nash (Apr 06 2025 at 18:15):
Yep, I'd missed the ?
in the exact hpq ?lhs
bit, and assumed it wasn't working because the holes don't appear in the list of hypotheses
Robin Arnez (Apr 24 2025 at 20:20):
My experience with named meta-variables is that they can really be inconsistent:
theorem dapply_ideal (p q r:Prop) (f : ¬¬p -> q -> r) (hp : p) (hpq : ¬¬p -> q) : r := by
refine f ?as ?lhs
· rw [Classical.not_not]
exact hp
· exact hpq ?as -- fails because ?as : p (=> takes meta-variable at the state of `exact hp`)
Last updated: May 02 2025 at 03:31 UTC