Zulip Chat Archive
Stream: Is there code for X?
Topic: Some missing prod stuff
Bernd Losert (Feb 05 2022 at 15:27):
I search around and I couldn't find these guys:
import data.prod
import order.filter.basic
open filter
open_locale filter
variables {α β γ : Type*}
def prod.dup (x : α) : α × α := (x, x)
def prod.mk' (f : α → β) (g : α → γ) (x : α) : β × γ :=
prod.map f g (prod.dup x)
lemma prod.mk'_fst_snd : prod.mk' (@prod.fst α β) (@prod.snd α β) = id :=
begin
funext,
unfold prod.mk',
unfold prod.dup,
simp,
end
lemma filter.prod_map_fst_snd_eq {f : filter (α × β)} :
f ≤ filter.map prod.fst f ×ᶠ map prod.snd f :=
begin
unfold filter.prod,
have hle₁ : f ≤ comap prod.fst (map prod.fst f), from le_comap_map,
have hle₂ : f ≤ comap prod.snd (map prod.snd f), from le_comap_map,
exact le_inf hle₁ hle₂,
end
Would anyone be against adding these to mathlib?
Eric Wieser (Feb 05 2022 at 21:43):
So mk' f g x = (f x, g x)
?
Eric Wieser (Feb 05 2022 at 21:44):
That's similar to docs#linear_map.prod and docs#add_monoid_hom.prod, so should probably be called function.prod
or pi.prod
Adam Topaz (Feb 05 2022 at 21:47):
Do we have docs#prod.lift ?
Adam Topaz (Feb 05 2022 at 21:48):
Your prod.mk
is just prod.lift f g x
, for a correctly defined prod.lift
...
Eric Wieser (Feb 05 2022 at 22:01):
Doesn't lift usually go in the other direction? (in which case lift
is just prod.rec
)
Adam Topaz (Feb 05 2022 at 22:05):
No, look at e.g. docs#category_theory.limits.prod.lift
Adam Topaz (Feb 05 2022 at 22:05):
Do we even have docs#prod.rec ?
Eric Wieser (Feb 05 2022 at 22:06):
I think we want something like:
def pi.prod {α} {β γ : α → Type*}
(f : Π a, β a) (g : Π a, γ a) (a) : β a × γ a :=
(f a, g a)
Eric Wieser (Feb 05 2022 at 22:06):
prod.rec
is built-in like most .rec
s
Eric Wieser (Feb 05 2022 at 22:08):
I think lift
goes the other way outside category_theory
, eg docs#quotient.lift, docs#tensor_algebra.lift.
Adam Topaz (Feb 05 2022 at 22:08):
It is well know that quotient.lift
should be called quotient.desc
.
Adam Topaz (Feb 05 2022 at 22:09):
lift
is a general word used for limits, and products are limits.
Eric Wieser (Feb 05 2022 at 22:12):
My understanding was that foo.lift
was for building maps out of foo
from "simpler" maps
Eric Wieser (Feb 05 2022 at 22:12):
But your proposed prod.lift
builds a map into prod
Eric Wieser (Feb 05 2022 at 22:13):
Maybe that naming convention is bad, but that was the pattern I recall us having right now
Adam Topaz (Feb 05 2022 at 22:13):
I think of lift
outside of the CT library more as "get the thing given by the universal property"
Adam Topaz (Feb 05 2022 at 22:13):
Whatever that universal property might be.
Eric Wieser (Feb 05 2022 at 22:14):
What's the universal property of prod
? Isn't it prod.rec
?
Eric Wieser (Feb 05 2022 at 22:14):
Or are there multiple universal properties?
Reid Barton (Feb 05 2022 at 22:16):
This is some weird type theory thing about "positive" and "negative" types.
Reid Barton (Feb 05 2022 at 22:16):
In category theory, the universal property of the product is that mapping into the product is the same as mapping into both factors.
Bernd Losert (Feb 06 2022 at 09:30):
The way I see it, since prod
is a negative type, there should be a prod.corec
that would be what I called prod.mk'
.
Eric Wieser (Feb 06 2022 at 12:52):
I PR'd prod.mk'
as pi.prod
in #11877, and found some downstream foo.prod
s that could be reimplemented using pi.prod
.
Bernd Losert (Feb 06 2022 at 18:59):
I will make a PR for filter.prod_map_fst_snd_eq
then.
Eric Wieser (Feb 06 2022 at 22:02):
It should probably not have eq
in the name since the statement is about le
!
Bernd Losert (Feb 07 2022 at 08:55):
Yes, you're right.
Bernd Losert (Feb 09 2022 at 21:57):
I think mathlib is also missing α × (β × γ) ↔ (α × β) × γ
. Or maybe this exists for pi
, and I just can't find it.
Kevin Buzzard (Feb 09 2022 at 21:58):
Does that even typecheck? Can you give a #mwe ?
Yaël Dillies (Feb 09 2022 at 21:58):
Bernd Losert (Feb 09 2022 at 22:00):
Ah, nice. Thanks.
Bernd Losert (Feb 12 2022 at 16:53):
I was looking for this lemma
lemma filter.prod_map_rlassoc (f : filter α) (g : filter β) (h : filter γ) :
map (equiv.prod_assoc α β γ).inv_fun (f ×ᶠ (g ×ᶠ h)) = (f ×ᶠ g) ×ᶠ h := sorry
but I could not find it. Would someone confirm that mathlib does have this? Also, proving this is turning into a challenge.
Bernd Losert (Feb 12 2022 at 17:09):
The set
version of this lemma is also missing and I need it to prove the filter version above.
Yaël Dillies (Feb 12 2022 at 17:20):
I think we have neither.
Yaël Dillies (Feb 12 2022 at 17:21):
Is this some kind of general result about monads?
Bernd Losert (Feb 12 2022 at 18:08):
I don't think so. In my mind, these are just "lifted" versions of prod_assoc.
Bernd Losert (Feb 12 2022 at 18:13):
It's probably possible to get the set and filter versions of prod_assoc via applicative.seq?
Yaël Dillies (Feb 12 2022 at 18:15):
It's also true for finset
. So I guess the criterion is a functor with a notion of product.
Bernd Losert (Feb 12 2022 at 18:24):
Monoidal functors perhaps? https://en.wikipedia.org/wiki/Monoidal_functor
Bernd Losert (Feb 12 2022 at 18:25):
Applicatives are basically what those are.
Yaël Dillies (Feb 12 2022 at 18:26):
Sounds like it.
Kevin Buzzard (Feb 12 2022 at 19:37):
@Bernd Losert I did half of it, the other half is just mutatis mutandis:
import tactic
import order.filter.basic
open_locale filter
open filter
variables (α β γ : Type*)
lemma filter.prod_map_rlassoc (f : filter α) (g : filter β) (h : filter γ) :
map (equiv.prod_assoc α β γ).inv_fun (f ×ᶠ (g ×ᶠ h)) = (f ×ᶠ g) ×ᶠ h :=
begin
ext U,
simp only [mem_map, mem_prod_iff],
split, -- can't see how to do it any other way
{ rintro ⟨tα, hα, tβγ, hβγ, hαβγ⟩,
rw mem_prod_iff at hβγ,
rcases hβγ with ⟨tβ, hβ, tγ, hγ, hβγ⟩,
refine ⟨tα.prod tβ, _, tγ, hγ, _⟩,
{ rw mem_prod_iff,
refine ⟨tα, hα, tβ, hβ, rfl.subset⟩ },
{ rintros ⟨⟨a, b⟩, c⟩ ⟨⟨ha, hb⟩, hc⟩,
exact @hαβγ ⟨a, b, c⟩ ⟨ha, hβγ (⟨hb, hc⟩ : (b, c) ∈ tβ.prod tγ)⟩ } },
{ -- same again
sorry }
end
Kevin Buzzard (Feb 12 2022 at 19:39):
I would love to see a proof using all that monadery stuff.
Yaël Dillies (Feb 12 2022 at 19:42):
I fear that the answer to the monadic stuff is that "It's what defines an associative functor" or however it's called and that what you're proving is precisely that set
and filter
are associative functors or however they are called.
Kevin Buzzard (Feb 12 2022 at 19:47):
If you're talking about applicative functors and your claim is true then no doubt this is just the sort of thing which people like Johannes Hoelzl and @Simon Hudon were doing years and years ago.
Simon Hudon (Feb 12 2022 at 20:07):
If you're using finset
with applicative functions, indeed you need associativity and commutativity in order to map an effect to every element of the set. If you're looking at set
and not finset
, you need the operator of your applicative functor to be a big operator, applicable to arbitrary sets. I've never seen something like that though
Patrick Massot (Feb 12 2022 at 20:46):
Ok, you succeeded again to trick me into playing with filters.
import order.filter.bases
open_locale filter
open filter equiv
variables (α β γ : Type*)
lemma filter.has_basis.equiv {α : Type*} {ι ι' : Sort*} {p : ι → Prop} {s : ι → set α}
{f : filter α} (h : f.has_basis p s) (e : ι' ≃ ι) : f.has_basis (p ∘ e) (s ∘ e) :=
⟨by simp [h.mem_iff, e.exists_congr_left]⟩
lemma filter.prod_map_rlassoc (f : filter α) (g : filter β) (h : filter γ) :
map (prod_assoc α β γ) ((f ×ᶠ g) ×ᶠ h) = f ×ᶠ (g ×ᶠ h) :=
begin
rw map_eq_comap_of_inverse (prod_assoc α β γ).self_comp_symm (prod_assoc α β γ).symm_comp_self,
apply ((((basis_sets f).prod $ basis_sets g).prod $ basis_sets h).comap _).eq_of_same_basis,
convert ((basis_sets f).prod (((basis_sets g)).prod (basis_sets h))).equiv (prod_assoc _ _ _) ;
{ ext, simp [and_assoc] },
end
Note that I modified slightly the statement since I didn't see the point of going against equiv.prod_assoc
.
Eric Wieser (Feb 12 2022 at 20:48):
Does that first lemma generalize to surjective e?
Patrick Massot (Feb 12 2022 at 20:53):
Sure
Patrick Massot (Feb 12 2022 at 20:54):
I wrote this lemma very quickly since it's a complete tautology that is exactly what is needed here.
Patrick Massot (Feb 12 2022 at 20:54):
Do you mean the surjective case is already there?
Patrick Massot (Feb 12 2022 at 20:56):
Let's do it for Eric:
lemma filter.has_basis.comp_of_surjective {α : Type*} {ι ι' : Sort*} {p : ι → Prop} {s : ι → set α}
{f : filter α} (h : f.has_basis p s) {g : ι' → ι} (hg : surjective g) :
f.has_basis (p ∘ g) (s ∘ g) :=
⟨begin
intros t,
rw h.mem_iff,
split,
{ rintros ⟨i, hi, ht⟩,
rcases hg i with ⟨i', rfl⟩,
exact ⟨i', hi, ht⟩ },
{ rintros ⟨i', hi', ht⟩,
exact ⟨g i', hi', ht⟩ }
end⟩
lemma filter.has_basis.equiv {α : Type*} {ι ι' : Sort*} {p : ι → Prop} {s : ι → set α}
{f : filter α} (h : f.has_basis p s) (e : ι' ≃ ι) : f.has_basis (p ∘ e) (s ∘ e) :=
h.comp_of_surjective e.surjective
Patrick Massot (Feb 12 2022 at 20:57):
Now the required lemma has a more complicated proof, but it looks shorter on screen :stuck_out_tongue_wink:
Patrick Massot (Feb 12 2022 at 21:04):
Eric Wieser (Feb 12 2022 at 22:54):
Well you didn't have to write it so long!
lemma has_basis.comp_of_surjective (h : l.has_basis p s) {g : ι' → ι} (hg : function.surjective g) :
l.has_basis (p ∘ g) (s ∘ g) :=
⟨λ t, h.mem_iff.trans hg.exists⟩
Eric Wieser (Feb 12 2022 at 23:03):
(apologies, it was unkind of me to trick you into proving the surjective case without telling you that I had docs#function.surjective.exists in mind as the proof)
Kevin Buzzard (Feb 12 2022 at 23:37):
So in fact it's now a one-liner. I really like these kinds of questions, it's the community at its best.
Last updated: Dec 20 2023 at 11:08 UTC