Zulip Chat Archive
Stream: new members
Topic: Pattern matching in tactics
Enrico Borba (Jan 30 2021 at 19:06):
What's the proper way to use an anonymous constructor as a pattern-matching expression in a tactic proof? For example, I have p: ∃ (h: a ∈ A), a ∉ B
, and when outside of a tactic context I can do let ⟨a, ha⟩ := p in ...
. I'd love to be able to do something like this inside of tactics. Right now what I usually do is
exact let ⟨a, ha⟩ := p in begin
...
end
which is kind of clunky.
Is there a better or more standard way to do this?
Kevin Buzzard (Jan 30 2021 at 19:07):
Does cases p with h1 h2
work for you? I'm a bit unclear about whether you're constructing data or not.
Kevin Buzzard (Jan 30 2021 at 19:10):
example (X : Type) (A B : set X) (a : X) (p: ∃ (h: a ∈ A), a ∉ B) : false :=
begin
cases p with h1 h2,
/-
X : Type
A B : set X
a : X
h1 : a ∈ A
h2 : a ∉ B
-/
sorry
end
Kevin Buzzard (Jan 30 2021 at 19:11):
I am a bit confused about what you are calling a
here. In your example you'd get a : a ∈ A
. As well as cases
there are the tactics tactic#rcases and tactic#obtain
Enrico Borba (Jan 30 2021 at 19:14):
This is what I was looking for I think. Sorry the example is pretty contrived, I was more asking about just destructing the existential quantifier into it's two parts. I'm a little confused why this works, but thanks again!
Kevin Buzzard (Jan 30 2021 at 19:14):
A proof of an existential quantifier is a pair of pieces of information, and cases just takes it apart into the two pieces.
Enrico Borba (Jan 30 2021 at 19:17):
I understand that yeah, but I thought that cases
only works with inductively defined types, and I hadn't really considered existential quantification as an inductively defined type.
Enrico Borba (Jan 30 2021 at 19:18):
But I think I see now that it really only has one constructor, so no additional subgoals are created. As opposed to doing cases
on a disjunction.
Mario Carneiro (Jan 30 2021 at 19:22):
obtain <a, ha> := p
works inside tactics you know
Enrico Borba (Jan 30 2021 at 19:23):
obtain
is exactly what I'm looking for, and is especially useful since it uses rcases
, thanks for pointing that out, hadn't seen it before.
Mario Carneiro (Jan 30 2021 at 19:24):
I think it's strictly better than the let-match you have in term mode
Enrico Borba (Jan 30 2021 at 19:25):
Yeah, and reads better than cases
/rcases
. Thanks again
Patrick Massot (Jan 30 2021 at 19:39):
Enrico Borba said:
I understand that yeah, but I thought that
cases
only works with inductively defined types, and I hadn't really considered existential quantification as an inductively defined type.
You can ask Lean to show you the definition of exists. It's a bit shocking that forall is absolutely core builtin while exists is one of hundreds of inductive types. But that's how it is in dependent type theory. In real life you don't have to care about such foundational issues, just learn the relevant syntax and tactics (did you go through https://leanprover-community.github.io/learn.html?)
Mario Carneiro (Jan 30 2021 at 19:56):
By the way, in some approaches to DTT forall is a coinductive type (where application is the destructor and funext
is the bisimulation theorem)
Last updated: Dec 20 2023 at 11:08 UTC