l3lab/ntp-mathlib huggingface dataset:
/-- Evaluation at a fixed point is uniformly continuous on `α →ᵤ β`. -/
theorem uniformContinuous_eval (x : α) :
    UniformContinuous (Function.eval x ∘ toFun : (α →ᵤ β) → β) := by
  change _ ≤ _
  rw [map_le_iff_le_comap,
    (UniformFun.hasBasis_uniformity α β).le_basis_iff ((𝓤 _).basis_sets.comap _)]
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x✝ : α
p : Filter ι
g : ι → α
inst✝ : UniformSpace β
x : α
⊢ ∀ i' ∈ 𝓤 β,
    ∃ i ∈ 𝓤 β,
      UniformFun.gen α β i ⊆ (fun x_1 => ((Function.eval x ∘ ⇑toFun) x_1.1, (Function.eval x ∘ ⇑toFun) x_1.2)) ⁻¹' id i'

Next tactic:
exact fun U hU => ⟨U, hU, fun uv huv => huv x⟩
/-- If `u` is a family of uniform structures on `γ`, then
`𝒰(α, γ, (⨅ i, u i)) = ⨅ i, 𝒰(α, γ, u i)`. -/
protected theorem iInf_eq {u : ι → UniformSpace γ} : 𝒰(α, γ, (⨅ i, u i)) = ⨅ i, 𝒰(α, γ, u i) := by
  -- This follows directly from the fact that the upper adjoint in a Galois connection maps
  -- infimas to infimas.
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x : α
p : Filter ι
g : ι → α
inst✝ : UniformSpace β
u : ι → UniformSpace γ
⊢ uniformSpace α γ = ⨅ i, uniformSpace α γ

Next tactic:
ext : 1
/-- If `u` is a family of uniform structures on `γ`, then
`𝒰(α, γ, (⨅ i, u i)) = ⨅ i, 𝒰(α, γ, u i)`. -/
protected theorem iInf_eq {u : ι → UniformSpace γ} : 𝒰(α, γ, (⨅ i, u i)) = ⨅ i, 𝒰(α, γ, u i) := by
  -- This follows directly from the fact that the upper adjoint in a Galois connection maps
  -- infimas to infimas.
  ext : 1
  

Proof state:
case a
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x : α
p : Filter ι
g : ι → α
inst✝ : UniformSpace β
u : ι → UniformSpace γ
⊢ 𝓤 (α →ᵤ γ) = 𝓤 (α →ᵤ γ)

Next tactic:
change UniformFun.filter α γ 𝓤[⨅ i, u i] = 𝓤[⨅ i, 𝒰(α, γ, u i)]
/-- If `u` is a family of uniform structures on `γ`, then
`𝒰(α, γ, (⨅ i, u i)) = ⨅ i, 𝒰(α, γ, u i)`. -/
protected theorem iInf_eq {u : ι → UniformSpace γ} : 𝒰(α, γ, (⨅ i, u i)) = ⨅ i, 𝒰(α, γ, u i) := by
  -- This follows directly from the fact that the upper adjoint in a Galois connection maps
  -- infimas to infimas.
  ext : 1
  change UniformFun.filter α γ 𝓤[⨅ i, u i] = 𝓤[⨅ i, 𝒰(α, γ, u i)]
  

Proof state:
case a
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x : α
p : Filter ι
g : ι → α
inst✝ : UniformSpace β
u : ι → UniformSpace γ
⊢ UniformFun.filter α γ (𝓤 γ) = 𝓤 (α →ᵤ γ)

Next tactic:
rw [iInf_uniformity, iInf_uniformity]
/-- If `u` is a family of uniform structures on `γ`, then
`𝒰(α, γ, (⨅ i, u i)) = ⨅ i, 𝒰(α, γ, u i)`. -/
protected theorem iInf_eq {u : ι → UniformSpace γ} : 𝒰(α, γ, (⨅ i, u i)) = ⨅ i, 𝒰(α, γ, u i) := by
  -- This follows directly from the fact that the upper adjoint in a Galois connection maps
  -- infimas to infimas.
  ext : 1
  change UniformFun.filter α γ 𝓤[⨅ i, u i] = 𝓤[⨅ i, 𝒰(α, γ, u i)]
  rw [iInf_uniformity, iInf_uniformity]
  

Proof state:
case a
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x : α
p : Filter ι
g : ι → α
inst✝ : UniformSpace β
u : ι → UniformSpace γ
⊢ UniformFun.filter α γ (⨅ i, 𝓤 γ) = ⨅ i, 𝓤 (α →ᵤ γ)

Next tactic:
exact (UniformFun.gc α γ).u_iInf
/-- If `u₁` and `u₂` are two uniform structures on `γ`, then
`𝒰(α, γ, u₁ ⊓ u₂) = 𝒰(α, γ, u₁) ⊓ 𝒰(α, γ, u₂)`. -/
protected theorem inf_eq {u₁ u₂ : UniformSpace γ} :
    𝒰(α, γ, u₁ ⊓ u₂) = 𝒰(α, γ, u₁) ⊓ 𝒰(α, γ, u₂) := by
  -- This follows directly from the fact that the upper adjoint in a Galois connection maps
  -- infimas to infimas.
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x : α
p : Filter ι
g : ι → α
inst✝ : UniformSpace β
u₁ u₂ : UniformSpace γ
⊢ uniformSpace α γ = uniformSpace α γ ⊓ uniformSpace α γ

Next tactic:
rw [inf_eq_iInf, inf_eq_iInf, UniformFun.iInf_eq]
/-- If `u₁` and `u₂` are two uniform structures on `γ`, then
`𝒰(α, γ, u₁ ⊓ u₂) = 𝒰(α, γ, u₁) ⊓ 𝒰(α, γ, u₂)`. -/
protected theorem inf_eq {u₁ u₂ : UniformSpace γ} :
    𝒰(α, γ, u₁ ⊓ u₂) = 𝒰(α, γ, u₁) ⊓ 𝒰(α, γ, u₂) := by
  -- This follows directly from the fact that the upper adjoint in a Galois connection maps
  -- infimas to infimas.
  rw [inf_eq_iInf, inf_eq_iInf, UniformFun.iInf_eq]
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x : α
p : Filter ι
g : ι → α
inst✝ : UniformSpace β
u₁ u₂ : UniformSpace γ
⊢ ⨅ i, uniformSpace α γ = ⨅ b, bif b then uniformSpace α γ else uniformSpace α γ

Next tactic:
refine' iInf_congr fun i => _
/-- If `u₁` and `u₂` are two uniform structures on `γ`, then
`𝒰(α, γ, u₁ ⊓ u₂) = 𝒰(α, γ, u₁) ⊓ 𝒰(α, γ, u₂)`. -/
protected theorem inf_eq {u₁ u₂ : UniformSpace γ} :
    𝒰(α, γ, u₁ ⊓ u₂) = 𝒰(α, γ, u₁) ⊓ 𝒰(α, γ, u₂) := by
  -- This follows directly from the fact that the upper adjoint in a Galois connection maps
  -- infimas to infimas.
  rw [inf_eq_iInf, inf_eq_iInf, UniformFun.iInf_eq]
  refine' iInf_congr fun i => _
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x : α
p : Filter ι
g : ι → α
inst✝ : UniformSpace β
u₁ u₂ : UniformSpace γ
i : Bool
⊢ uniformSpace α γ = bif i then uniformSpace α γ else uniformSpace α γ

Next tactic:
cases i
/-- If `u₁` and `u₂` are two uniform structures on `γ`, then
`𝒰(α, γ, u₁ ⊓ u₂) = 𝒰(α, γ, u₁) ⊓ 𝒰(α, γ, u₂)`. -/
protected theorem inf_eq {u₁ u₂ : UniformSpace γ} :
    𝒰(α, γ, u₁ ⊓ u₂) = 𝒰(α, γ, u₁) ⊓ 𝒰(α, γ, u₂) := by
  -- This follows directly from the fact that the upper adjoint in a Galois connection maps
  -- infimas to infimas.
  rw [inf_eq_iInf, inf_eq_iInf, UniformFun.iInf_eq]
  refine' iInf_congr fun i => _
  cases i <;> 

Proof state:
case false
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x : α
p : Filter ι
g : ι → α
inst✝ : UniformSpace β
u₁ u₂ : UniformSpace γ
⊢ uniformSpace α γ = bif false then uniformSpace α γ else uniformSpace α γ

Next tactic:
rfl
/-- If `u₁` and `u₂` are two uniform structures on `γ`, then
`𝒰(α, γ, u₁ ⊓ u₂) = 𝒰(α, γ, u₁) ⊓ 𝒰(α, γ, u₂)`. -/
protected theorem inf_eq {u₁ u₂ : UniformSpace γ} :
    𝒰(α, γ, u₁ ⊓ u₂) = 𝒰(α, γ, u₁) ⊓ 𝒰(α, γ, u₂) := by
  -- This follows directly from the fact that the upper adjoint in a Galois connection maps
  -- infimas to infimas.
  rw [inf_eq_iInf, inf_eq_iInf, UniformFun.iInf_eq]
  refine' iInf_congr fun i => _
  cases i <;> 

Proof state:
case true
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x : α
p : Filter ι
g : ι → α
inst✝ : UniformSpace β
u₁ u₂ : UniformSpace γ
⊢ uniformSpace α γ = bif true then uniformSpace α γ else uniformSpace α γ

Next tactic:
rfl
/-- If `u` is a uniform structures on `β` and `f : γ → β`, then
`𝒰(α, γ, comap f u) = comap (fun g ↦ f ∘ g) 𝒰(α, γ, u₁)`. -/
protected theorem comap_eq {f : γ → β} :
    𝒰(α, γ, ‹UniformSpace β›.comap f) = 𝒰(α, β, _).comap (f ∘ ·) := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x : α
p : Filter ι
g : ι → α
inst✝ : UniformSpace β
f : γ → β
⊢ uniformSpace α γ = UniformSpace.comap (fun x => f ∘ x) (uniformSpace α β)

Next tactic:
letI : UniformSpace γ := .comap f ‹_›
/-- If `u` is a uniform structures on `β` and `f : γ → β`, then
`𝒰(α, γ, comap f u) = comap (fun g ↦ f ∘ g) 𝒰(α, γ, u₁)`. -/
protected theorem comap_eq {f : γ → β} :
    𝒰(α, γ, ‹UniformSpace β›.comap f) = 𝒰(α, β, _).comap (f ∘ ·) := by
  letI : UniformSpace γ := .comap f ‹_›
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x : α
p : Filter ι
g : ι → α
inst✝ : UniformSpace β
f : γ → β
this : UniformSpace γ := UniformSpace.comap f inst✝
⊢ uniformSpace α γ = UniformSpace.comap (fun x => f ∘ x) (uniformSpace α β)

Next tactic:
exact (UniformFun.postcomp_uniformInducing (f := f) ⟨rfl⟩).comap_uniformSpace.symm
/-- Post-composition by a uniformly continuous function is uniformly continuous on `α →ᵤ β`.

More precisely, if `f : γ → β` is uniformly continuous, then `(fun g ↦ f ∘ g) : (α →ᵤ γ) → (α →ᵤ β)`
is uniformly continuous. -/
protected theorem postcomp_uniformContinuous [UniformSpace γ] {f : γ → β}
    (hf : UniformContinuous f) :
    UniformContinuous (ofFun ∘ (f ∘ ·) ∘ toFun : (α →ᵤ γ) → α →ᵤ β) := by
  -- This is a direct consequence of `UniformFun.comap_eq`
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x : α
p : Filter ι
g : ι → α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
f : γ → β
hf : UniformContinuous f
⊢ UniformContinuous (⇑ofFun ∘ (fun x => f ∘ x) ∘ ⇑toFun)

Next tactic:
refine uniformContinuous_iff.mpr ?_
/-- Post-composition by a uniformly continuous function is uniformly continuous on `α →ᵤ β`.

More precisely, if `f : γ → β` is uniformly continuous, then `(fun g ↦ f ∘ g) : (α →ᵤ γ) → (α →ᵤ β)`
is uniformly continuous. -/
protected theorem postcomp_uniformContinuous [UniformSpace γ] {f : γ → β}
    (hf : UniformContinuous f) :
    UniformContinuous (ofFun ∘ (f ∘ ·) ∘ toFun : (α →ᵤ γ) → α →ᵤ β) := by
  -- This is a direct consequence of `UniformFun.comap_eq`
    refine uniformContinuous_iff.mpr ?_
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x : α
p : Filter ι
g : ι → α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
f : γ → β
hf : UniformContinuous f
⊢ uniformSpace α γ ≤ UniformSpace.comap (⇑ofFun ∘ (fun x => f ∘ x) ∘ ⇑toFun) (uniformSpace α β)

Next tactic:
exact (UniformFun.mono (uniformContinuous_iff.mp hf)).trans_eq UniformFun.comap_eq
/-- Pre-composition by any function is uniformly continuous for the uniform structures of
uniform convergence.

More precisely, for any `f : γ → α`, the function `(· ∘ f) : (α →ᵤ β) → (γ →ᵤ β)` is uniformly
continuous. -/
protected theorem precomp_uniformContinuous {f : γ → α} :
    UniformContinuous fun g : α →ᵤ β => ofFun (toFun g ∘ f) := by
  -- Here we simply go back to filter bases.
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x : α
p : Filter ι
g : ι → α
inst✝ : UniformSpace β
f : γ → α
⊢ UniformContinuous fun g => ofFun (toFun g ∘ f)

Next tactic:
rw [uniformContinuous_iff]
/-- Pre-composition by any function is uniformly continuous for the uniform structures of
uniform convergence.

More precisely, for any `f : γ → α`, the function `(· ∘ f) : (α →ᵤ β) → (γ →ᵤ β)` is uniformly
continuous. -/
protected theorem precomp_uniformContinuous {f : γ → α} :
    UniformContinuous fun g : α →ᵤ β => ofFun (toFun g ∘ f) := by
  -- Here we simply go back to filter bases.
  rw [uniformContinuous_iff]
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x : α
p : Filter ι
g : ι → α
inst✝ : UniformSpace β
f : γ → α
⊢ uniformSpace α β ≤ UniformSpace.comap (fun g => ofFun (toFun g ∘ f)) (uniformSpace γ β)

Next tactic:
change
    𝓤 (α →ᵤ β) ≤ (𝓤 (γ →ᵤ β)).comap (Prod.map (fun g : α →ᵤ β => g ∘ f) fun g : α →ᵤ β => g ∘ f)
/-- Pre-composition by any function is uniformly continuous for the uniform structures of
uniform convergence.

More precisely, for any `f : γ → α`, the function `(· ∘ f) : (α →ᵤ β) → (γ →ᵤ β)` is uniformly
continuous. -/
protected theorem precomp_uniformContinuous {f : γ → α} :
    UniformContinuous fun g : α →ᵤ β => ofFun (toFun g ∘ f) := by
  -- Here we simply go back to filter bases.
  rw [uniformContinuous_iff]
  change
    𝓤 (α →ᵤ β) ≤ (𝓤 (γ →ᵤ β)).comap (Prod.map (fun g : α →ᵤ β => g ∘ f) fun g : α →ᵤ β => g ∘ f)
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x : α
p : Filter ι
g : ι → α
inst✝ : UniformSpace β
f : γ → α
⊢ 𝓤 (α →ᵤ β) ≤ comap (Prod.map (fun g => g ∘ f) fun g => g ∘ f) (𝓤 (γ →ᵤ β))

Next tactic:
rw [(UniformFun.hasBasis_uniformity α β).le_basis_iff
      ((UniformFun.hasBasis_uniformity γ β).comap _)]
/-- Pre-composition by any function is uniformly continuous for the uniform structures of
uniform convergence.

More precisely, for any `f : γ → α`, the function `(· ∘ f) : (α →ᵤ β) → (γ →ᵤ β)` is uniformly
continuous. -/
protected theorem precomp_uniformContinuous {f : γ → α} :
    UniformContinuous fun g : α →ᵤ β => ofFun (toFun g ∘ f) := by
  -- Here we simply go back to filter bases.
  rw [uniformContinuous_iff]
  change
    𝓤 (α →ᵤ β) ≤ (𝓤 (γ →ᵤ β)).comap (Prod.map (fun g : α →ᵤ β => g ∘ f) fun g : α →ᵤ β => g ∘ f)
  rw [(UniformFun.hasBasis_uniformity α β).le_basis_iff
      ((UniformFun.hasBasis_uniformity γ β).comap _)]
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x : α
p : Filter ι
g : ι → α
inst✝ : UniformSpace β
f : γ → α
⊢ ∀ i' ∈ 𝓤 β, ∃ i ∈ 𝓤 β, UniformFun.gen α β i ⊆ (Prod.map (fun g => g ∘ f) fun g => g ∘ f) ⁻¹' UniformFun.gen γ β i'

Next tactic:
exact fun U hU => ⟨U, hU, fun uv huv x => huv (f x)⟩
/-- The natural map `UniformFun.toFun` from `α →ᵤ β` to `α → β` is uniformly continuous.

In other words, the uniform structure of uniform convergence is finer than that of pointwise
convergence, aka the product uniform structure. -/
protected theorem uniformContinuous_toFun : UniformContinuous (toFun : (α →ᵤ β) → α → β) := by
  -- By definition of the product uniform structure, this is just `uniform_continuous_eval`.
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x : α
p : Filter ι
g : ι → α
inst✝ : UniformSpace β
⊢ UniformContinuous ⇑toFun

Next tactic:
rw [uniformContinuous_pi]
/-- The natural map `UniformFun.toFun` from `α →ᵤ β` to `α → β` is uniformly continuous.

In other words, the uniform structure of uniform convergence is finer than that of pointwise
convergence, aka the product uniform structure. -/
protected theorem uniformContinuous_toFun : UniformContinuous (toFun : (α →ᵤ β) → α → β) := by
  -- By definition of the product uniform structure, this is just `uniform_continuous_eval`.
  rw [uniformContinuous_pi]
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x : α
p : Filter ι
g : ι → α
inst✝ : UniformSpace β
⊢ ∀ (i : α), UniformContinuous fun x => toFun x i

Next tactic:
intro x
/-- The natural map `UniformFun.toFun` from `α →ᵤ β` to `α → β` is uniformly continuous.

In other words, the uniform structure of uniform convergence is finer than that of pointwise
convergence, aka the product uniform structure. -/
protected theorem uniformContinuous_toFun : UniformContinuous (toFun : (α →ᵤ β) → α → β) := by
  -- By definition of the product uniform structure, this is just `uniform_continuous_eval`.
  rw [uniformContinuous_pi]
  intro x
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x✝ : α
p : Filter ι
g : ι → α
inst✝ : UniformSpace β
x : α
⊢ UniformContinuous fun x_1 => toFun x_1 x

Next tactic:
exact uniformContinuous_eval β x
/-- The topology of uniform convergence indeed gives the same notion of convergence as
`TendstoUniformly`. -/
protected theorem tendsto_iff_tendstoUniformly {F : ι → α →ᵤ β} {f : α →ᵤ β} :
    Tendsto F p (𝓝 f) ↔ TendstoUniformly (toFun ∘ F) (toFun f) p := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x : α
p : Filter ι
g : ι → α
inst✝ : UniformSpace β
F : ι → α →ᵤ β
f : α →ᵤ β
⊢ Tendsto F p (𝓝 f) ↔ TendstoUniformly (⇑toFun ∘ F) (toFun f) p

Next tactic:
rw [(UniformFun.hasBasis_nhds α β f).tendsto_right_iff, TendstoUniformly]
/-- The topology of uniform convergence indeed gives the same notion of convergence as
`TendstoUniformly`. -/
protected theorem tendsto_iff_tendstoUniformly {F : ι → α →ᵤ β} {f : α →ᵤ β} :
    Tendsto F p (𝓝 f) ↔ TendstoUniformly (toFun ∘ F) (toFun f) p := by
  rw [(UniformFun.hasBasis_nhds α β f).tendsto_right_iff, TendstoUniformly]
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x : α
p : Filter ι
g : ι → α
inst✝ : UniformSpace β
F : ι → α →ᵤ β
f : α →ᵤ β
⊢ (∀ i ∈ 𝓤 β, ∀ᶠ (x : ι) in p, F x ∈ {g | (f, g) ∈ UniformFun.gen α β i}) ↔
    ∀ u ∈ 𝓤 β, ∀ᶠ (n : ι) in p, ∀ (x : α), (toFun f x, (⇑toFun ∘ F) n x) ∈ u

Next tactic:
simp only [mem_setOf, UniformFun.gen, Function.comp_def]
/-- The natural bijection between `α → β × γ` and `(α → β) × (α → γ)`, upgraded to a uniform
isomorphism between `α →ᵤ β × γ` and `(α →ᵤ β) × (α →ᵤ γ)`. -/
protected def uniformEquivProdArrow [UniformSpace γ] : (α →ᵤ β × γ) ≃ᵤ (α →ᵤ β) × (α →ᵤ γ) :=
  -- Denote `φ` this bijection. We want to show that
  -- `comap φ (𝒰(α, β, uβ) × 𝒰(α, γ, uγ)) = 𝒰(α, β × γ, uβ × uγ)`.
  -- But `uβ × uγ` is defined as `comap fst uβ ⊓ comap snd uγ`, so we just have to apply
  -- `UniformFun.inf_eq` and `UniformFun.comap_eq`, which leaves us to check
  -- that some square commutes.
  Equiv.toUniformEquivOfUniformInducing (Equiv.arrowProdEquivProdArrow _ _ _) <| by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x : α
p : Filter ι
g : ι → α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
⊢ UniformInducing ⇑(Equiv.arrowProdEquivProdArrow β γ α)

Next tactic:
constructor
/-- The natural bijection between `α → β × γ` and `(α → β) × (α → γ)`, upgraded to a uniform
isomorphism between `α →ᵤ β × γ` and `(α →ᵤ β) × (α →ᵤ γ)`. -/
protected def uniformEquivProdArrow [UniformSpace γ] : (α →ᵤ β × γ) ≃ᵤ (α →ᵤ β) × (α →ᵤ γ) :=
  -- Denote `φ` this bijection. We want to show that
  -- `comap φ (𝒰(α, β, uβ) × 𝒰(α, γ, uγ)) = 𝒰(α, β × γ, uβ × uγ)`.
  -- But `uβ × uγ` is defined as `comap fst uβ ⊓ comap snd uγ`, so we just have to apply
  -- `UniformFun.inf_eq` and `UniformFun.comap_eq`, which leaves us to check
  -- that some square commutes.
  Equiv.toUniformEquivOfUniformInducing (Equiv.arrowProdEquivProdArrow _ _ _) <| by
    constructor
    

Proof state:
case comap_uniformity
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x : α
p : Filter ι
g : ι → α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
⊢ comap (fun x => ((Equiv.arrowProdEquivProdArrow β γ α) x.1, (Equiv.arrowProdEquivProdArrow β γ α) x.2))
      (𝓤 ((α →ᵤ β) × (α →ᵤ γ))) =
    𝓤 (α →ᵤ β × γ)

Next tactic:
change
      comap (Prod.map (Equiv.arrowProdEquivProdArrow _ _ _) (Equiv.arrowProdEquivProdArrow _ _ _))
          _ = _
/-- The natural bijection between `α → β × γ` and `(α → β) × (α → γ)`, upgraded to a uniform
isomorphism between `α →ᵤ β × γ` and `(α →ᵤ β) × (α →ᵤ γ)`. -/
protected def uniformEquivProdArrow [UniformSpace γ] : (α →ᵤ β × γ) ≃ᵤ (α →ᵤ β) × (α →ᵤ γ) :=
  -- Denote `φ` this bijection. We want to show that
  -- `comap φ (𝒰(α, β, uβ) × 𝒰(α, γ, uγ)) = 𝒰(α, β × γ, uβ × uγ)`.
  -- But `uβ × uγ` is defined as `comap fst uβ ⊓ comap snd uγ`, so we just have to apply
  -- `UniformFun.inf_eq` and `UniformFun.comap_eq`, which leaves us to check
  -- that some square commutes.
  Equiv.toUniformEquivOfUniformInducing (Equiv.arrowProdEquivProdArrow _ _ _) <| by
    constructor
    change
      comap (Prod.map (Equiv.arrowProdEquivProdArrow _ _ _) (Equiv.arrowProdEquivProdArrow _ _ _))
          _ = _
    

Proof state:
case comap_uniformity
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x : α
p : Filter ι
g : ι → α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
⊢ comap (Prod.map ⇑(Equiv.arrowProdEquivProdArrow β γ α) ⇑(Equiv.arrowProdEquivProdArrow β γ α))
      (𝓤 ((α →ᵤ β) × (α →ᵤ γ))) =
    𝓤 (α →ᵤ β × γ)

Next tactic:
simp_rw [UniformFun]
/-- The natural bijection between `α → β × γ` and `(α → β) × (α → γ)`, upgraded to a uniform
isomorphism between `α →ᵤ β × γ` and `(α →ᵤ β) × (α →ᵤ γ)`. -/
protected def uniformEquivProdArrow [UniformSpace γ] : (α →ᵤ β × γ) ≃ᵤ (α →ᵤ β) × (α →ᵤ γ) :=
  -- Denote `φ` this bijection. We want to show that
  -- `comap φ (𝒰(α, β, uβ) × 𝒰(α, γ, uγ)) = 𝒰(α, β × γ, uβ × uγ)`.
  -- But `uβ × uγ` is defined as `comap fst uβ ⊓ comap snd uγ`, so we just have to apply
  -- `UniformFun.inf_eq` and `UniformFun.comap_eq`, which leaves us to check
  -- that some square commutes.
  Equiv.toUniformEquivOfUniformInducing (Equiv.arrowProdEquivProdArrow _ _ _) <| by
    constructor
    change
      comap (Prod.map (Equiv.arrowProdEquivProdArrow _ _ _) (Equiv.arrowProdEquivProdArrow _ _ _))
          _ = _
    simp_rw [UniformFun]
    

Proof state:
case comap_uniformity
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x : α
p : Filter ι
g : ι → α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
⊢ comap (Prod.map ⇑(Equiv.arrowProdEquivProdArrow β γ α) ⇑(Equiv.arrowProdEquivProdArrow β γ α))
      (𝓤 ((α → β) × (α → γ))) =
    𝓤 (α → β × γ)

Next tactic:
rw [← uniformity_comap]
/-- The natural bijection between `α → β × γ` and `(α → β) × (α → γ)`, upgraded to a uniform
isomorphism between `α →ᵤ β × γ` and `(α →ᵤ β) × (α →ᵤ γ)`. -/
protected def uniformEquivProdArrow [UniformSpace γ] : (α →ᵤ β × γ) ≃ᵤ (α →ᵤ β) × (α →ᵤ γ) :=
  -- Denote `φ` this bijection. We want to show that
  -- `comap φ (𝒰(α, β, uβ) × 𝒰(α, γ, uγ)) = 𝒰(α, β × γ, uβ × uγ)`.
  -- But `uβ × uγ` is defined as `comap fst uβ ⊓ comap snd uγ`, so we just have to apply
  -- `UniformFun.inf_eq` and `UniformFun.comap_eq`, which leaves us to check
  -- that some square commutes.
  Equiv.toUniformEquivOfUniformInducing (Equiv.arrowProdEquivProdArrow _ _ _) <| by
    constructor
    change
      comap (Prod.map (Equiv.arrowProdEquivProdArrow _ _ _) (Equiv.arrowProdEquivProdArrow _ _ _))
          _ = _
    simp_rw [UniformFun]
    rw [← uniformity_comap]
    

Proof state:
case comap_uniformity
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x : α
p : Filter ι
g : ι → α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
⊢ 𝓤 (α → β × γ) = 𝓤 (α → β × γ)

Next tactic:
congr
/-- The natural bijection between `α → β × γ` and `(α → β) × (α → γ)`, upgraded to a uniform
isomorphism between `α →ᵤ β × γ` and `(α →ᵤ β) × (α →ᵤ γ)`. -/
protected def uniformEquivProdArrow [UniformSpace γ] : (α →ᵤ β × γ) ≃ᵤ (α →ᵤ β) × (α →ᵤ γ) :=
  -- Denote `φ` this bijection. We want to show that
  -- `comap φ (𝒰(α, β, uβ) × 𝒰(α, γ, uγ)) = 𝒰(α, β × γ, uβ × uγ)`.
  -- But `uβ × uγ` is defined as `comap fst uβ ⊓ comap snd uγ`, so we just have to apply
  -- `UniformFun.inf_eq` and `UniformFun.comap_eq`, which leaves us to check
  -- that some square commutes.
  Equiv.toUniformEquivOfUniformInducing (Equiv.arrowProdEquivProdArrow _ _ _) <| by
    constructor
    change
      comap (Prod.map (Equiv.arrowProdEquivProdArrow _ _ _) (Equiv.arrowProdEquivProdArrow _ _ _))
          _ = _
    simp_rw [UniformFun]
    rw [← uniformity_comap]
    congr
    

Proof state:
case comap_uniformity.h.e_2.h
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x : α
p : Filter ι
g : ι → α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
⊢ UniformSpace.comap (⇑(Equiv.arrowProdEquivProdArrow β γ α)) instUniformSpaceProd = uniformSpace α (β × γ)

Next tactic:
unfold instUniformSpaceProd
/-- The natural bijection between `α → β × γ` and `(α → β) × (α → γ)`, upgraded to a uniform
isomorphism between `α →ᵤ β × γ` and `(α →ᵤ β) × (α →ᵤ γ)`. -/
protected def uniformEquivProdArrow [UniformSpace γ] : (α →ᵤ β × γ) ≃ᵤ (α →ᵤ β) × (α →ᵤ γ) :=
  -- Denote `φ` this bijection. We want to show that
  -- `comap φ (𝒰(α, β, uβ) × 𝒰(α, γ, uγ)) = 𝒰(α, β × γ, uβ × uγ)`.
  -- But `uβ × uγ` is defined as `comap fst uβ ⊓ comap snd uγ`, so we just have to apply
  -- `UniformFun.inf_eq` and `UniformFun.comap_eq`, which leaves us to check
  -- that some square commutes.
  Equiv.toUniformEquivOfUniformInducing (Equiv.arrowProdEquivProdArrow _ _ _) <| by
    constructor
    change
      comap (Prod.map (Equiv.arrowProdEquivProdArrow _ _ _) (Equiv.arrowProdEquivProdArrow _ _ _))
          _ = _
    simp_rw [UniformFun]
    rw [← uniformity_comap]
    congr
    unfold instUniformSpaceProd
    

Proof state:
case comap_uniformity.h.e_2.h
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
s s' : Set α
x : α
p : Filter ι
g : ι → α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
⊢ UniformSpace.comap (⇑(Equiv.arrowProdEquivProdArrow β γ α))
      (UniformSpace.comap Prod.fst (uniformSpace α β) ⊓ UniformSpace.comap Prod.snd (uniformSpace α γ)) =
    uniformSpace α (β × γ)

Next tactic:
rw [UniformSpace.comap_inf, ← UniformSpace.comap_comap, ← UniformSpace.comap_comap]