Zulip Chat Archive
Stream: lean4
Topic: missing tactics
Kevin Buzzard (Mar 23 2021 at 16:00):
In Lean 3 I could make cheap and dirty tactics with the \[tac...]
trick. I see that Lean 4 doesn't have a split
tactic yet, but my users (who never write term mode proofs) will be used to this. What is the Lean 4 version of
meta def tactic.interactive.split := `[apply And.intro]
?
Sebastian Ullrich (Mar 23 2021 at 16:02):
See https://leanprover.github.io/lean4/doc/tactics.html#extensible-tactics :)
Kevin Buzzard (Mar 23 2021 at 16:13):
Sorry. I read through the entire manual about a month ago but stuff doesn't stick in my brain like it used to.
Kevin Buzzard (Mar 23 2021 at 16:21):
This is great -- I now have split
, left
and right
. Can I get cases (h : p \and q) with hp hq
this way? Where can I read about how to do this? Or should I just wait?
Jason Rute (Mar 24 2021 at 02:22):
Do you not like the built-in Lean 4 cases
tactic (found on the same page)?
theorem ex1 : p ∨ q → q ∨ p := by
intro h
cases h with
| inl h1 =>
apply Or.inr
exact h1
| inr h2 =>
apply Or.inl
assumption
Jason Rute (Mar 24 2021 at 02:23):
Wait, that is \or
...
Jason Rute (Mar 24 2021 at 02:51):
Ok, yeah, I guess the built in version of cases (h : p \and q)
is a bit awkward:
theorem ex1 : p ∧ q → q ∧ p := by
intro h
cases h with
| intro hp hq =>
skip
Kevin Buzzard (Mar 24 2021 at 07:37):
Yes I don't like it because by default it doesn't name variables and in the examples you give the user needs to know the names of the constructors eg inl and intro. Mathematicians can use this software in a way which involves knowing nothing about what's going on under the hood you see, not even knowing what an inductive type or a constructor is for example.
Yakov Pechersky (Mar 24 2021 at 07:42):
By the way, you don't have to know intro
in the And
example, this is fine:
theorem ex1 : p ∧ q → q ∧ p := by
intro h
cases h with
| _ hp hq =>
skip
Mario Carneiro (Mar 24 2021 at 07:43):
I think I will port rcases
for this stuff
Damiano Testa (Mar 24 2021 at 07:44):
In my personal experience, cases
was a very good tactic to have at the beginning. Now that I am more familiar with the system, I tend to prefer rcases
, but I was intimidated by it, when I was starting to use Lean.
pcpthm (Mar 24 2021 at 07:47):
let
can be used to destruct a term (but it leaves unnamed hypothesis in the local context currently):
theorem ex1 : p ∧ q → q ∧ p := by
intro h
let ⟨p, q⟩ := h
exact ⟨q, p⟩
Also, intro
accepts patterns:
theorem ex1' : p ∧ q → q ∧ p := by
intro ⟨p, q⟩
exact ⟨q, p⟩
It is missing "or patterns" of rcases
/ rintro
, though.
Leonardo de Moura (Mar 25 2021 at 01:39):
@pcpthm We already have intro+match notation
theorem ex : p ∨ (q ∧ r) → q ∨ p := by
intro
| Or.inl h => exact Or.inr h
| Or.inr ⟨h, _⟩ => exact Or.inl h
pcpthm (Mar 25 2021 at 13:21):
Ah, I didn't think about combining intro
and the pattern patching syntax in that way.
While I experimenting with this kind of code I found this example:
example (a b : Nat) : a = 0 ∨ b = 0 → a * b = 0 := by
intro h
cases h with
| inl h => rw h; simp
| inr h => rw h; simp
-- Can I remove duplication from the proof above?
-- Using the "preprocessing" tactics feature of `cases`, I get an error "alternative 'inl' is not"
cases h with (rw h; simp)
| inl h => done
| inr h => done
-- I cannot use the patternless form of `cases` either because I cannot access resulting hypotheses:
cases h <;> (rw ???; simp) -- Can I refer to the unnamed variable?
-- it is ugly but works
refine (match h with | Or.inl h => ?_ | Or.inr h => ?_)
allGoals (rw h; simp)
With mathlib rintro
the above example can be written concisely:
by rintro (rfl | rfl); simp
-- Or without using the `rfl` feature
by rintro (h | h); rw h; simp
Sebastian Ullrich (Mar 25 2021 at 13:26):
You can use simp_all
to use all hypotheses: cases h <;> simp_all
Yakov Pechersky (Mar 25 2021 at 13:27):
This also worked for me:
example (a b : Nat) : a = 0 ∨ b = 0 → a * b = 0 := by
intro h
cases h with | _ h' => ?_ <;>
{ rw h';
simp }
pcpthm (Mar 25 2021 at 13:27):
Sebastian Ullrich said:
You can use
simp_all
to use all hypotheses:cases h <;> simp_all
That is an another new tactic I missed. Thank you!
pcpthm (Mar 25 2021 at 13:36):
Yakov Pechersky said:
This also worked for me:
example (a b : Nat) : a = 0 ∨ b = 0 → a * b = 0 := by intro h cases h with | _ h' => ?_ <;> { rw h'; simp }
More simply
example (a b : Nat) : a = 0 ∨ b = 0 → a * b = 0 := by
intro h
cases h with | _ h => rw h; simp
just worked for me. It is a surprise and I didn't know cases
works this way. It almost looks like goals are in superposition or something. I don't quite understand how it works yet.
<del>Unfortunately simp_all
fails with an error message "unknown free variable '_uniq.1038'" for some reason:</del>
Edit: I updated Lean to current master and it now works!
example (a b : Nat) : a = 0 ∨ b = 0 → a * b = 0 := by
intro h
cases h <;> simp_all
Leonardo de Moura (Mar 25 2021 at 14:42):
<del>Unfortunately simp_all fails with an error message "unknown free variable '_uniq.1038'" for some reason:</del>
Edit: I updated Lean to current master and it now works!
I fixed a bug that produced this error message last night. Could you please try the master
branch?
Last updated: Dec 20 2023 at 11:08 UTC