Zulip Chat Archive
Stream: general
Topic: Apply theorem to subexpression
David Richey (Feb 20 2022 at 22:49):
In a previous thread, I was suggested the following way to prove this theorem, which works perfectly:
import data.pfun
theorem foo {α β : Type*} {f : α →. β} {x y} : f x = part.some y ↔ ∃ev, f.fn x ev = y :=
begin
exact part.eq_some_iff,
end
however, I really want f x = part.some y ↔ ∃ev, y = f.fn x ev
(notice that this is y = ...
instead of ... = y
). Upon making this change, I can no longer use exact part.eq_some_iff
. I think I could use something like eq.symm
to first change it to the form eq_some_iff
expects, but I cannot figure out how.
Does anyone have any suggestions?
David Richey (Feb 20 2022 at 22:51):
Also, to be honest, I do not really understand why part.eq_some_iff
is applicable in the first place either... It says o = part.some a ↔ a ∈ o
which doesn't look exactly like what I'm trying to prove. Is there multiple steps going on somehow?
Eric Wieser (Feb 20 2022 at 23:05):
Regarding your last question, It's just unfolding the definition of docs#part.has_mem
David Richey (Feb 20 2022 at 23:17):
Thanks, I guess it is also implicitly using pfun.fn_apply
? I thought exact
would only apply if the goal were exactly the same. How can I know what it is really doing under the hood?
Eric Rodriguez (Feb 20 2022 at 23:19):
exact is the same up to definitional equality, if you know what that means
David Richey (Feb 20 2022 at 23:25):
ah, I see now. It is not using pfun.fn_apply
but pfun.fn
. So two def
s, makes sense in the context of definitional equality
David Richey (Feb 20 2022 at 23:27):
thanks for your help with that second question! I derailed us from the original question though, oops. I think it is probably quite simple, but I just can't seem to write the right thing
Yakov Pechersky (Feb 20 2022 at 23:46):
Your original question might involve docs#eq_comm
David Richey (Feb 20 2022 at 23:56):
I agree, I'm just not sure how to tell it which subexpression to apply the rewrite to. For example, if I do rewrite eq_comm
, I get
⊢ part.some y = f x ↔ ∃ (ev : f.dom x), y = f.fn x ev
but now I have part.some y = f x
on the left which is just as bad
David Richey (Feb 20 2022 at 23:57):
oh, actually, it only did the first occurrence, not both occurrences
Yakov Pechersky (Feb 21 2022 at 00:02):
"simp_rw @eq_comm _ y" might work
David Richey (Feb 21 2022 at 00:47):
that does indeed work. I also found conv
, and I'm working to understand how I can use it in this case. Is there a way to navigate into an existential in conv mode?
Eric Wieser (Feb 21 2022 at 01:00):
conv in (∃ x, _) { sorry }
perhaps
David Richey (Feb 21 2022 at 01:20):
hmmm doesn't seem to work unfortunately
theorem foo {α β : Type*} {f : α →. β} {x y} : f x = part.some y ↔ ∃ev, y = f.fn x ev :=
begin
conv in (∃ev, _) {
rewrite eq_comm,
},
exact part.eq_some_iff,
end
gives find converter failed, pattern was not found
David Richey (Feb 21 2022 at 01:21):
that gave me the idea to try conv in (y = _)
, but then doing rewrite eq_comm
in that gives
exact tactic failed, type mismatch, given expression has type
(λ (_a : Prop), y = f.fn x h = _a) (f.fn x h = y)
but is expected to have type
y = f.fn x h ↔ f.fn x h = y
and I'm not quite sure what that's saying
Julian Berman (Feb 21 2022 at 03:35):
This seems to do it:
import data.pfun
theorem foo {α β : Type*} {f : α →. β} {x y} : f x = part.some y ↔ ∃ev, y = f.fn x ev :=
begin
conv_rhs {
congr,
funext,
rw eq_comm,
},
exact part.eq_some_iff,
end
I can't say I know what I'm doing in conv
mode though I just looked up some previous example here from Zulip and copied it. simp_rw
seems easier to use I think.
Julian Berman (Feb 21 2022 at 03:36):
(You can do it with the conv in
thing Eric showed as well, the trick was using congr
and funext
to again jump inside the binder I think)
Mario Carneiro (Feb 21 2022 at 05:49):
If I can #xy your question, why do you want this theorem? You should just be able to use the original one by applying .symm
whenever you need the equality
Mario Carneiro (Feb 21 2022 at 05:52):
Anyway you can prove this version too using defeq tricks
theorem foo {α β : Type*} {f : α →. β} {x y} : f x = part.some y ↔ ∃ev, y = f.fn x ev :=
part.eq_some_iff.trans $ exists_congr $ λ _, eq_comm
David Richey (Feb 21 2022 at 06:24):
thank you for the suggestions! @Mario Carneiro I ultimately wanted this theorem to do a rewrite from y
to f.fn x ev
. I can of course just rewrite in the other direction (which is what I ended up doing), but I'm also just taking my time and exploring rabbit holes as I come across them :)
This is what I actually ended up with (absolutely open to comments if you have any!)
import data.pfun
inductive iarith
| var : string -> iarith
inductive iarith_big_steps : iarith → (string →. int) → int → Prop
| abs_var {σ v h} : iarith_big_steps (iarith.var v) σ (σ.fn v h)
theorem store_bound_imp_var_bound {σ : string →. int} {v n} (h : σ v = part.some n) : iarith_big_steps (iarith.var v) σ n :=
begin
have exists_ev : ∃ev, σ.fn v ev = n, by exact part.eq_some_iff.mp h,
cases exists_ev with _ apply_is_n,
rewrite ←apply_is_n,
apply iarith_big_steps.abs_var,
end
Mario Carneiro (Feb 21 2022 at 06:25):
indeed, I would write that as
theorem store_bound_imp_var_bound {σ : string →. int} {v n} (h : σ v = part.some n) : iarith_big_steps (iarith.var v) σ n :=
begin
rcases part.eq_some_iff.1 h with ⟨a, rfl⟩,
apply iarith_big_steps.abs_var,
end
David Richey (Feb 21 2022 at 06:26):
haha I will have to look into rcases!
Mario Carneiro (Feb 21 2022 at 06:26):
or even better
theorem store_bound_imp_var_bound {σ : string →. int} {v n} (h : n ∈ σ v) : iarith_big_steps (iarith.var v) σ n :=
begin
rcases h with ⟨a, rfl⟩,
apply iarith_big_steps.abs_var,
end
Mario Carneiro (Feb 21 2022 at 06:29):
you might also consider writing the inductive type this way instead of using fn
/ get
inductive iarith_big_steps : iarith → (string →. int) → int → Prop
| abs_var {σ : string →. int} {v n} : n ∈ σ v → iarith_big_steps (iarith.var v) σ n
David Richey (Feb 21 2022 at 06:55):
reading the docs for rcases
, picking out the relevant parts...
An rcases pattern has the following grammar:
- A name like x, which names the active hypothesis as x.
- The keyword rfl, which expects the hypothesis to be h : a = b, and calls subst on the hypothesis (which has the effect of replacing b with a everywhere or vice versa).
- A tuple pattern ⟨p1, p2, p3⟩, which matches a constructor with many arguments, or a series of nested conjunctions or existentials. For example if the active hypothesis is a ∧ b ∧ c, then the conjunction will be destructured, and p1 will be matched against a, p2 against b and so on.
So would it be correct to say that rcases part.eq_some_iff.1 h with ⟨_, rfl⟩
is shorthand for cases part.eq_some_iff.1 h with _ h1, subst h1
?
(by the way, I couldn't get your second rcases example to compile)
Mario Carneiro (Feb 21 2022 at 06:56):
you probably missed that I changed the signature of the theorem in the second example
David Richey (Feb 21 2022 at 06:56):
I did indeed
Mario Carneiro (Feb 21 2022 at 06:56):
and yes your desugaring example is correct
David Richey (Feb 21 2022 at 06:57):
and here what is the "constructor with many arguments" that the tuple pattern is matching?
Mario Carneiro (Feb 21 2022 at 06:57):
exists
Mario Carneiro (Feb 21 2022 at 06:57):
David Richey (Feb 21 2022 at 06:58):
thank you very much, Mario, you've been a really great help :)
Last updated: Dec 20 2023 at 11:08 UTC