[System] You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.Geometry.Manifold.IsManifold.ExtChartAt).

[User]
Prove the following theorem. The retrieved context below may help.

```lean
theorem extChartAt_target_subset_range (x : M) : (extChartAt I x).target ⊆ range I
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend (L75-L77)
def extend : PartialEquiv M E :=
f.toPartialEquiv ≫ I.toPartialEquiv
```

-- snippet 2
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_coe (L78-L80)
theorem extend_coe : ⇑(f.extend I) = I ∘ f :=
rfl
```

-- snippet 3
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_coe_symm (L81-L83)
theorem extend_coe_symm : ⇑(f.extend I).symm = f.symm ∘ I.symm :=
rfl
```

-- snippet 4
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_source (L84-L86)
theorem extend_source : (f.extend I).source = f.source := by
rw [extend, PartialEquiv.trans_source, I.source_eq, preimage_univ, inter_univ]
```

-- snippet 5
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.isOpen_extend_source (L87-L90)
theorem isOpen_extend_source : IsOpen (f.extend I).source := by
rw [extend_source]
  exact f.open_source
```

-- snippet 6
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_target (L91-L93)
theorem extend_target : (f.extend I).target = I.symm ⁻¹' f.target ∩ range I := by
simp_rw [extend, PartialEquiv.trans_target, I.target_eq, I.toPartialEquiv_coe_symm, inter_comm]
```

-- snippet 7
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_target' (L94-L96)
theorem extend_target' : (f.extend I).target = I '' f.target := by
rw [extend, PartialEquiv.trans_target'', I.source_eq, univ_inter, I.toPartialEquiv_coe]
```

-- snippet 8
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_target_eq_image_source (L97-L99)
theorem extend_target_eq_image_source : (f.extend I).target = (f.extend I) '' f.source := by
rw [f.extend_target', ← f.image_source_eq_target, ← image_comp, f.extend_coe]
```

-- snippet 9
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.isOpen_extend_target (L100-L103)
lemma isOpen_extend_target [I.Boundaryless] : IsOpen (f.extend I).target := by
rw [extend_target, I.range_eq_univ, inter_univ]
  exact I.continuous_symm.isOpen_preimage _ f.open_target
```

-- snippet 10
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.mapsTo_extend (L104-L109)
theorem mapsTo_extend (hs : s ⊆ f.source) :
    MapsTo (f.extend I) s ((f.extend I).symm ⁻¹' s ∩ range I) := by
rw [mapsTo_iff_image_subset, extend_coe, extend_coe_symm, preimage_comp, ← I.image_eq, image_comp,
    f.image_eq_target_inter_inv_preimage hs]
  exact image_mono inter_subset_right
```

-- snippet 11
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_left_inv (L110-L113)
theorem extend_left_inv {x : M} (hxf : x ∈ f.source) : (f.extend I).symm (f.extend I x) = x :=
(f.extend I).left_inv <| by rwa [f.extend_source]

/-- Variant of `f.extend_left_inv I`, stated in terms of images. -/
```

-- snippet 12
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_left_inv' (L114-L116)
lemma extend_left_inv' (ht : t ⊆ f.source) : ((f.extend I).symm ∘ (f.extend I)) '' t = t :=
EqOn.image_eq_self (fun _ hx ↦ f.extend_left_inv (ht hx))
```

-- snippet 13
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_source_mem_nhds (L117-L119)
theorem extend_source_mem_nhds {x : M} (h : x ∈ f.source) : (f.extend I).source ∈ 𝓝 x :=
(isOpen_extend_source f).mem_nhds <| by rwa [f.extend_source]
```

-- snippet 14
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_source_mem_nhdsWithin (L120-L122)
theorem extend_source_mem_nhdsWithin {x : M} (h : x ∈ f.source) : (f.extend I).source ∈ 𝓝[s] x :=
mem_nhdsWithin_of_mem_nhds <| extend_source_mem_nhds f h
```

-- snippet 15
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.continuousOn_extend (L123-L127)
theorem continuousOn_extend : ContinuousOn (f.extend I) (f.extend I).source := by
refine I.continuous.comp_continuousOn ?_
  rw [extend_source]
  exact f.continuousOn
```

-- snippet 16
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.continuousAt_extend (L128-L130)
theorem continuousAt_extend {x : M} (h : x ∈ f.source) : ContinuousAt (f.extend I) x :=
(continuousOn_extend f).continuousAt <| extend_source_mem_nhds f h
```

-- snippet 17
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.map_extend_nhds (L131-L134)
theorem map_extend_nhds {x : M} (hy : x ∈ f.source) :
    map (f.extend I) (𝓝 x) = 𝓝[range I] f.extend I x := by
rwa [extend_coe, comp_apply, ← I.map_nhds_eq, ← f.map_nhds_eq, map_map]
```

-- snippet 18
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.map_extend_nhds_of_mem_interior_range (L135-L140)
theorem map_extend_nhds_of_mem_interior_range {x : M} (hx : x ∈ f.source)
    (h'x : f.extend I x ∈ interior (range I)) :
    map (f.extend I) (𝓝 x) = 𝓝 (f.extend I x) := by
rw [f.map_extend_nhds hx, nhdsWithin_eq_nhds]
  exact mem_of_superset (isOpen_interior.mem_nhds h'x) interior_subset
```

-- snippet 19
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.map_extend_nhds_of_boundaryless (L141-L144)
theorem map_extend_nhds_of_boundaryless [I.Boundaryless] {x : M} (hx : x ∈ f.source) :
    map (f.extend I) (𝓝 x) = 𝓝 (f.extend I x) := by
rw [f.map_extend_nhds hx, I.range_eq_univ, nhdsWithin_univ]
```

-- snippet 20
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_target_mem_nhdsWithin (L145-L149)
theorem extend_target_mem_nhdsWithin {y : M} (hy : y ∈ f.source) :
    (f.extend I).target ∈ 𝓝[range I] f.extend I y := by
rw [← PartialEquiv.image_source_eq_target, ← map_extend_nhds f hy]
  exact image_mem_map (extend_source_mem_nhds _ hy)
```

-- snippet 21
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_image_target_mem_nhds (L150-L155)
lemma extend_image_target_mem_nhds {x : M} (hx : x ∈ f.source) :
    I '' f.target ∈ 𝓝[range I] (f.extend I) x := by
rw [← f.map_extend_nhds hx, Filter.mem_map,
    f.extend_coe, Set.preimage_comp, I.preimage_image f.target]
  exact (f.continuousAt hx).preimage_mem_nhds (f.open_target.mem_nhds (f.map_source hx))
```

-- snippet 22
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_image_nhds_mem_nhds_of_boundaryless (L156-L160)
theorem extend_image_nhds_mem_nhds_of_boundaryless [I.Boundaryless] {x} (hx : x ∈ f.source)
    {s : Set M} (h : s ∈ 𝓝 x) : (f.extend I) '' s ∈ 𝓝 ((f.extend I) x) := by
rw [← f.map_extend_nhds_of_boundaryless hx, Filter.mem_map]
  filter_upwards [h] using subset_preimage_image (f.extend I) s
```

-- snippet 23
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_image_nhds_mem_nhds_of_mem_interior_range (L161-L166)
theorem extend_image_nhds_mem_nhds_of_mem_interior_range {x} (hx : x ∈ f.source)
    (h'x : f.extend I x ∈ interior (range I)) {s : Set M} (h : s ∈ 𝓝 x) :
    (f.extend I) '' s ∈ 𝓝 ((f.extend I) x) := by
rw [← f.map_extend_nhds_of_mem_interior_range hx h'x, Filter.mem_map]
  filter_upwards [h] using subset_preimage_image (f.extend I) s
```

-- snippet 24
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_target_subset_range (L167-L168)
theorem extend_target_subset_range : (f.extend I).target ⊆ range I := by simp only [mfld_simps]
```

-- snippet 25
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.interior_extend_target_subset_interior_range (L169-L175)
lemma interior_extend_target_subset_interior_range :
    interior (f.extend I).target ⊆ interior (range I) := by
rw [f.extend_target, interior_inter, (f.open_target.preimage I.continuous_symm).interior_eq]
  exact inter_subset_right

/-- If `y ∈ f.target` and `I y ∈ interior (range I)`,
then `I y` is an interior point of `(I ∘ f).target`. -/
```

-- snippet 26
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiffAt_mul_left (L144-L146)
theorem contMDiffAt_mul_left {a b : G} : CMDiffAt n (a * ·) b :=
contMDiff_mul_left.contMDiffAt
```

-- snippet 27
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.mdifferentiableAt_mul_left (L166-L168)
theorem mdifferentiableAt_mul_left {a b : G} : MDiffAt (a * ·) b :=
contMDiffAt_mul_left.mdifferentiableAt one_ne_zero
```

-- snippet 28
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiffOn_finprod (L375-L379)
theorem contMDiffOn_finprod
    (lf : LocallyFinite fun i ↦ Function.mulSupport <| f i) (h : ∀ i, CMDiff[s] n (f i)) :
    CMDiff[s] n (fun x ↦ ∏ᶠ i, f i x) := fun x hx ↦
contMDiffWithinAt_finprod lf fun i ↦ h i x hx
```

-- snippet 29
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.toFun_eq_coe (L75-L77)
theorem toFun_eq_coe : X.toFun = ⇑X :=
rfl
```

-- snippet 30
```lean
-- Mathlib.Geometry.Manifold.Algebra.SmoothFunctions.coe_mul (L41-L44)
theorem coe_mul {G : Type*} [Mul G] [TopologicalSpace G] [ChartedSpace H' G] [ContMDiffMul I' n G]
    (f g : C^n⟮I, N; I', G⟯) : ⇑(f * g) = f * g :=
rfl
```

-- snippet 31
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiff_finset_prod' (L396-L398)
theorem contMDiff_finset_prod' (h : ∀ i ∈ t, CMDiff n (f i)) :
    CMDiff n (∏ i ∈ t, f i) := fun x ↦ contMDiffAt_finset_prod' fun i hi ↦ h i hi x
```

-- snippet 32
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.coe_sub (L140-L142)
theorem coe_sub : ⇑(X - Y) = X - Y :=
rfl
```

-- snippet 33
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.smoothRightMul_one (L232-L234)
theorem smoothRightMul_one : (𝑹 I g') 1 = g' :=
one_mul g'
```

-- snippet 34
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.lift_zero (L148-L151)
theorem lift_zero :
    (↑(0 : LeftInvariantDerivation I G) : Derivation 𝕜 C^∞⟮I, G; 𝕜⟯ C^∞⟮I, G; 𝕜⟯) = 0 :=
rfl
```

-- snippet 35
```lean
-- Mathlib.Geometry.Manifold.Algebra.LieGroup.instNormedSpaceLieAddGroup (L197-L217)
instance instNormedSpaceLieAddGroup {𝕜 : Type*} [NontriviallyNormedField 𝕜] {n : WithTop ℕ∞}
    {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] : LieAddGroup 𝓘(𝕜, E) n E where
  contMDiff_neg := contDiff_neg.contMDiff
/-! ## `C^n` manifolds with `C^n` inversion away from zero

Typeclass for `C^n` manifolds with `0` and `Inv` such that inversion is `C^n` at all non-zero
points. (This includes multiplicative Lie groups, but also complete normed semifields.)
Point-wise inversion is `C^n` when the function/denominator is non-zero. -/
section ContMDiffInv₀

-- See note [Design choices about smooth algebraic structures]
/-- A `C^n` manifold with `0` and `Inv` such that `fun x ↦ x⁻¹` is `C^n` at all nonzero points.
Any complete normed (semi)field has this property. -/
class ContMDiffInv₀ {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalSpace H]
    {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] (I : ModelWithCorners 𝕜 E H)
    (n : WithTop ℕ∞) (G : Type*)
    [Inv G] [Zero G] [TopologicalSpace G] [ChartedSpace H G] : Prop where
  /-- Inversion is `C^n` away from `0`. -/
  contMDiffAt_inv₀ : ∀ ⦃x : G⦄, x ≠ 0 → CMDiffAt n (fun (y : G) ↦ y⁻¹) x
```

-- snippet 36
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.ContMDiff (L136-L138)
theorem ContMDiff.mul (hf : CMDiff n f) (hg : CMDiff n g) : CMDiff n (f * g) :=
fun x ↦ (hf x).mul (hg x)
```

-- snippet 37
```lean
-- Mathlib.Geometry.Manifold.Algebra.SmoothFunctions.instPow (L61-L65)
instance instPow {G : Type*} [Monoid G] [TopologicalSpace G] [ChartedSpace H' G]
    [ContMDiffMul I' n G] :
    Pow C^n⟮I, N; I', G⟯ ℕ where
  pow f n := ⟨(f : N → G) ^ n, (contMDiff_pow n).comp f.contMDiff⟩
```

-- snippet 38
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.lift_smul (L172-L177)
theorem lift_smul (k : 𝕜) : (k • X).1 = k • X.1 :=
rfl

variable (I G)

/-- The coercion to function is a monoid homomorphism. -/
```

-- snippet 39
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.commutator_apply (L237-L239)
theorem commutator_apply : ⁅X, Y⁆ f = X (Y f) - Y (X f) :=
rfl
```

-- snippet 40
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.evalAt (L189-L193)
def evalAt : LeftInvariantDerivation I G →ₗ[𝕜] PointDerivation I g where
  toFun X := Derivation.evalAt g X.1
map_add' _ _ := rfl
  map_smul' _ _ := rfl
```

-- snippet 41
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.smoothLeftMul (L186-L192)
def smoothLeftMul : C^∞⟮I, G; I, G⟯ :=
⟨(g * ·), contMDiff_mul_left⟩

/-- Right multiplication by `g`. It is meant to mimic the usual notation in Lie groups.
Used mostly through the notation `𝑹`.
Lemmas involving `smoothRightMul` with the notation `𝑹` usually use `R` instead of `𝑹` in the
names. -/
```

-- snippet 42
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiffOn_finset_prod' (L381-L384)
theorem contMDiffOn_finset_prod' (h : ∀ i ∈ t, CMDiff[s] n (f i)) :
    CMDiff[s] n (∏ i ∈ t, f i) :=
fun x hx ↦ contMDiffWithinAt_finset_prod' fun i hi ↦ h i hi x hx
```

-- snippet 43
```lean
-- Mathlib.Geometry.Manifold.Algebra.LieGroup.ContMDiffAt (L145-L148)
theorem ContMDiffAt.inv {f : M → G} {x₀ : M} (hf : CMDiffAt n f x₀) :
    CMDiffAt n (fun x ↦ (f x)⁻¹) x₀ :=
(contMDiff_inv I n).contMDiffAt.comp x₀ hf
```

-- snippet 44
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiffWithinAt_finset_prod (L347-L351)
theorem contMDiffWithinAt_finset_prod (h : ∀ i ∈ t, CMDiffAt[s] n (f i) x) :
    CMDiffAt[s] n (fun x ↦ ∏ i ∈ t, f i x) x := by
simp only [← Finset.prod_apply]
  exact contMDiffWithinAt_finset_prod' h
```

-- snippet 45
```lean
-- Mathlib.Geometry.Manifold.Algebra.SmoothFunctions.mul_comp (L46-L49)
theorem mul_comp {G : Type*} [Mul G] [TopologicalSpace G] [ChartedSpace H' G] [ContMDiffMul I' n G]
    (f g : C^n⟮I'', N'; I', G⟯) (h : C^n⟮I, N; I'', N'⟯) : (f * g).comp h = f.comp h * g.comp h :=
rfl
```

-- snippet 46
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.mdifferentiable_mul_left (L162-L164)
theorem mdifferentiable_mul_left {a : G} : MDiff (a * ·) :=
contMDiff_mul_left.mdifferentiable one_ne_zero
```

-- snippet 47
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiffAt_finset_prod' (L365-L368)
theorem contMDiffAt_finset_prod' (h : ∀ i ∈ t, CMDiffAt n (f i) x) :
    CMDiffAt n (∏ i ∈ t, f i) x :=
contMDiffWithinAt_finset_prod' h
```

-- snippet 48
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiff_mul (L105-L110)
theorem contMDiff_mul [ContMDiffMul I n G] : CMDiff n fun p : G × G ↦ p.1 * p.2 :=
ContMDiffMul.contMDiff_mul

include I n in
/-- If the multiplication is `C^n`, then it is continuous. This is not an instance for technical
reasons, see note [Design choices about smooth algebraic structures]. -/
```

-- snippet 49
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.coeFnAddMonoidHom (L179-L183)
def coeFnAddMonoidHom : LeftInvariantDerivation I G →+ C^∞⟮I, G; 𝕜⟯ → C^∞⟮I, G; 𝕜⟯ :=
⟨⟨DFunLike.coe, coe_zero⟩, coe_add⟩

variable {I G}
```

-- snippet 50
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.lift_add (L144-L146)
theorem lift_add : (↑(X + Y) : Derivation 𝕜 C^∞⟮I, G; 𝕜⟯ C^∞⟮I, G; 𝕜⟯) = X + Y :=
rfl
```

-- snippet 51
```lean
-- Mathlib.Geometry.Manifold.Algebra.LieGroup.Prod (L184-L196)
instance Prod.instLieGroup {𝕜 : Type*} [NontriviallyNormedField 𝕜] {n : WithTop ℕ∞}
    {H : Type*} [TopologicalSpace H] {E : Type*}
    [NormedAddCommGroup E] [NormedSpace 𝕜 E] {I : ModelWithCorners 𝕜 E H} {G : Type*}
    [TopologicalSpace G] [ChartedSpace H G] [Group G] [LieGroup I n G] {E' : Type*}
    [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H' : Type*} [TopologicalSpace H']
    {I' : ModelWithCorners 𝕜 E' H'} {G' : Type*} [TopologicalSpace G'] [ChartedSpace H' G']
    [Group G'] [LieGroup I' n G'] : LieGroup (I.prod I') n (G × G') :=
{ ContMDiffMul.prod _ _ _ _ with contMDiff_inv := contMDiff_fst.inv.prodMk contMDiff_snd.inv }

end Product

/-! ### Normed spaces are Lie groups -/
```

-- snippet 52
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.L_apply (L205-L207)
theorem L_apply : (𝑳 I g) h = g * h :=
rfl
```

-- snippet 53
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiffAt_finprod (L359-L363)
theorem contMDiffAt_finprod
    (lf : LocallyFinite fun i ↦ mulSupport <| f i) (h : ∀ i, CMDiffAt n (f i) x₀) :
    CMDiffAt n (fun x ↦ ∏ᶠ i, f i x) x₀ :=
contMDiffWithinAt_finprod lf h
```

-- snippet 54
```lean
-- Mathlib.Geometry.Manifold.Algebra.LieGroup.ContMDiff (L154-L156)
theorem ContMDiff.inv {f : M → G} (hf : CMDiff n f) : CMDiff n fun x ↦ (f x)⁻¹ :=
fun x ↦ (hf x).inv
```

-- snippet 55
```lean
-- Mathlib.Geometry.Manifold.Algebra.SmoothFunctions.coe_one (L56-L59)
theorem coe_one {G : Type*} [One G] [TopologicalSpace G] [ChartedSpace H' G] :
    ⇑(1 : C^n⟮I, N; I', G⟯) = 1 :=
rfl
```

-- snippet 56
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiffOn_finset_prod (L386-L389)
theorem contMDiffOn_finset_prod (h : ∀ i ∈ t, CMDiff[s] n (f i)) :
    CMDiff[s] n (fun x ↦ ∏ i ∈ t, f i x) :=
fun x hx ↦ contMDiffWithinAt_finset_prod fun i hi ↦ h i hi x hx
```

-- snippet 57
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.mdifferentiableAt_mul_right (L174-L176)
theorem mdifferentiableAt_mul_right {a b : G} : MDiffAt (· * a) b :=
contMDiffAt_mul_right.mdifferentiableAt one_ne_zero
```

-- snippet 58
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.leibniz (L107-L109)
theorem leibniz : X (f * f') = f • X f' + f' • X f :=
X.leibniz' _ _
```

-- snippet 59
```lean
-- Mathlib.Geometry.Manifold.Algebra.LieGroup.contMDiffOn_inv₀ (L268-L272)
theorem contMDiffOn_inv₀ : CMDiff[{0}ᶜ] n (Inv.inv : G → G) :=
fun _x hx ↦ (contMDiffAt_inv₀ hx).contMDiffWithinAt

variable {s : Set M} {a : M}
```

-- snippet 60
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiff_finprod (L405-L408)
theorem contMDiff_finprod (h : ∀ i, CMDiff n (f i))
    (hfin : LocallyFinite fun i ↦ mulSupport (f i)) : CMDiff n fun x ↦ ∏ᶠ i, f i x :=
fun x ↦ contMDiffAt_finprod hfin fun i ↦ h i x
```

-- snippet 61
```lean
-- Mathlib.Geometry.Manifold.Algebra.LieGroup.continuousInv₀_of_contMDiffInv₀ (L265-L267)
theorem continuousInv₀_of_contMDiffInv₀ : ContinuousInv₀ G :=
{ continuousAt_inv₀ := fun _ hx ↦ (contMDiffAt_inv₀ (I := I) (n := n) hx).continuousAt }
```

-- snippet 62
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.smoothLeftMul_one (L229-L231)
theorem smoothLeftMul_one : (𝑳 I g') 1 = g' :=
mul_one g'
```

-- snippet 63
```lean
-- Mathlib.Geometry.Manifold.Algebra.LieGroup.contMDiffAt_inv₀ (L258-L264)
theorem contMDiffAt_inv₀ {x : G} (hx : x ≠ 0) : ContMDiffAt I I n (fun y ↦ y⁻¹) x :=
ContMDiffInv₀.contMDiffAt_inv₀ hx

include I n in
/-- In a manifold with `C^n` inverse away from `0`, the inverse is continuous away from `0`.
This is not an instance for technical reasons, see
note [Design choices about smooth algebraic structures]. -/
```

-- snippet 64
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiff_mul_left (L140-L142)
theorem contMDiff_mul_left {a : G} : CMDiff n (a * ·) :=
contMDiff_const.mul contMDiff_id
```

-- snippet 65
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.instContMDiffAddSelf (L445-L449)
instance instContMDiffAddSelf : ContMDiffAdd 𝓘(𝕜, E) n E := by
constructor
  rw [← modelWithCornersSelf_prod, chartedSpaceSelf_prod]
  exact contDiff_add.contMDiff
```

-- snippet 66
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiffAt_mul_right (L152-L154)
theorem contMDiffAt_mul_right {a b : G} : CMDiffAt n (· * a) b :=
contMDiff_mul_right.contMDiffAt
```

-- snippet 67
```lean
-- Mathlib.Geometry.Manifold.Algebra.SmoothFunctions.semigroup (L82-L85)
instance semigroup {G : Type*} [Semigroup G] [TopologicalSpace G] [ChartedSpace H' G]
    [ContMDiffMul I' n G] : Semigroup C^n⟮I, N; I', G⟯ :=
DFunLike.coe_injective.semigroup _ coe_mul
```

-- snippet 68
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.toDerivation_injective (L61-L64)
theorem toDerivation_injective :
    Function.Injective (toDerivation : LeftInvariantDerivation I G → _) :=
fun X Y h => by cases X; cases Y; congr
```

-- snippet 69
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.ContMDiffAt (L353-L357)
theorem ContMDiffAt.prod (h : ∀ i ∈ t, CMDiffAt n (f i) x₀) :
    CMDiffAt n (fun x ↦ ∏ i ∈ t, f i x) x₀ := by
simp only [← contMDiffWithinAt_univ] at *
  exact ContMDiffWithinAt.prod h
```

-- snippet 70
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.mdifferentiable_mul_right (L170-L172)
theorem mdifferentiable_mul_right {a : G} : MDiff (· * a) :=
contMDiff_mul_right.mdifferentiable one_ne_zero
```

-- snippet 71
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.smoothRightMul (L193-L196)
def smoothRightMul : C^∞⟮I, G; I, G⟯ :=
⟨(· * g), contMDiff_mul_right⟩

-- Left multiplication. The abbreviation is `MIL`.
```

-- snippet 72
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.comp_L (L212-L216)
theorem comp_L : (X f).comp (𝑳 I g) = X (f.comp (𝑳 I g)) := by
ext h
  rw [ContMDiffMap.comp_apply, L_apply, ← evalAt_apply, evalAt_mul, hfdifferential_apply,
    fdifferential_apply, evalAt_apply]
```

-- snippet 73
```lean
-- Mathlib.Geometry.Manifold.Algebra.LieGroup.ContMDiffWithinAt (L140-L143)
theorem ContMDiffWithinAt.inv {f : M → G} {s : Set M} {x₀ : M}
    (hf : CMDiffAt[s] n f x₀) : CMDiffAt[s] n (fun x ↦ (f x)⁻¹) x₀ :=
(contMDiff_inv I n).contMDiffAt.contMDiffWithinAt.comp x₀ hf <| Set.mapsTo_univ _ _
```

-- snippet 74
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.R_apply (L209-L211)
theorem R_apply : (𝑹 I g) h = h * g :=
rfl
```

-- snippet 75
```lean
-- Mathlib.Geometry.Manifold.Algebra.LieGroup.ContMDiffOn (L150-L152)
theorem ContMDiffOn.inv {f : M → G} {s : Set M} (hf : CMDiff[s] n f) :
    CMDiff[s] n (fun x ↦ (f x)⁻¹) := fun x hx ↦ (hf x hx).inv
```

-- snippet 76
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.coe_derivation (L87-L91)
theorem coe_derivation :
    ⇑(X : Derivation 𝕜 C^∞⟮I, G; 𝕜⟯ C^∞⟮I, G; 𝕜⟯) = (X : C^∞⟮I, G; 𝕜⟯ → C^∞⟮I, G; 𝕜⟯) :=
rfl

/-- Premature version of the lemma. Prefer using `left_invariant` instead. -/
```

-- snippet 77
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.commutator_coe_derivation (L231-L236)
theorem commutator_coe_derivation :
    ⇑⁅X, Y⁆ =
      (⁅(X : Derivation 𝕜 C^∞⟮I, G; 𝕜⟯ C^∞⟮I, G; 𝕜⟯), Y⁆ :
        Derivation 𝕜 C^∞⟮I, G; 𝕜⟯ C^∞⟮I, G; 𝕜⟯) :=
rfl
```

-- snippet 78
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.L_mul (L213-L217)
theorem L_mul {G : Type*} [Semigroup G] [TopologicalSpace G] [ChartedSpace H G] [ContMDiffMul I ∞ G]
    (g h : G) : 𝑳 I (g * h) = (𝑳 I g).comp (𝑳 I h) := by
ext
  simp only [ContMDiffMap.comp_apply, L_apply, mul_assoc]
```

-- snippet 79
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.R_mul (L219-L223)
theorem R_mul {G : Type*} [Semigroup G] [TopologicalSpace G] [ChartedSpace H G] [ContMDiffMul I ∞ G]
    (g h : G) : 𝑹 I (g * h) = (𝑹 I h).comp (𝑹 I g) := by
ext
  simp only [ContMDiffMap.comp_apply, R_apply, mul_assoc]
```

-- snippet 80
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.hasNatScalar (L152-L154)
instance hasNatScalar : SMul ℕ (LeftInvariantDerivation I G) where
  smul r X := ⟨r • X.1, fun g => by simp_rw [LinearMap.map_smul_of_tower _ r, left_invariant']⟩
```

-- snippet 81
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.coe_neg (L136-L138)
theorem coe_neg : ⇑(-X) = -X :=
rfl
```

-- snippet 82
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.coe_zero (L132-L134)
theorem coe_zero : ⇑(0 : LeftInvariantDerivation I G) = 0 :=
rfl
```

-- snippet 83
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.ContMDiffOn (L132-L134)
theorem ContMDiffOn.mul (hf : CMDiff[s] n f) (hg : CMDiff[s] n g) : CMDiff[s] n (f * g) :=
fun x hx ↦ (hf x hx).mul (hg x hx)
```

-- snippet 84
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.ContMDiffMul (L239-L260)
instance ContMDiffMul.prod {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*}
    [NormedAddCommGroup E] [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H]
    (I : ModelWithCorners 𝕜 E H) (G : Type*) [TopologicalSpace G] [ChartedSpace H G] [Mul G]
    [ContMDiffMul I n G] {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H' : Type*}
    [TopologicalSpace H'] (I' : ModelWithCorners 𝕜 E' H') (G' : Type*) [TopologicalSpace G']
    [ChartedSpace H' G'] [Mul G'] [ContMDiffMul I' n G'] : ContMDiffMul (I.prod I') n (G × G') :=
{ IsManifold.prod G G' with
    contMDiff_mul :=
      ((contMDiff_fst.comp contMDiff_fst).mul (contMDiff_fst.comp contMDiff_snd)).prodMk
        ((contMDiff_snd.comp contMDiff_fst).mul (contMDiff_snd.comp contMDiff_snd)) }

end ContMDiffMul

section Monoid

variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {n : WithTop ℕ∞}
  {H : Type*} [TopologicalSpace H] {E : Type*}
  [NormedAddCommGroup E] [NormedSpace 𝕜 E] {I : ModelWithCorners 𝕜 E H} {G : Type*} [Monoid G]
  [TopologicalSpace G] [ChartedSpace H G] [ContMDiffMul I n G] {H' : Type*} [TopologicalSpace H']
  {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {I' : ModelWithCorners 𝕜 E' H'}
  {G' : Type*} [Monoid G'] [TopologicalSpace G'] [ChartedSpace H' G'] [ContMDiffMul I' n G']
```

-- snippet 85
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiffWithinAt_finset_prod' (L341-L345)
theorem contMDiffWithinAt_finset_prod' (h : ∀ i ∈ t, CMDiffAt[s] n (f i) x) :
    CMDiffAt[s] n (∏ i ∈ t, f i) x :=
Finset.prod_induction f (fun f ↦ CMDiffAt[s] n f x) (fun _ _ hf hg ↦ hf.mul hg)
    (contMDiffWithinAt_const (c := 1)) h
```

-- snippet 86
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.hasIntScalar (L155-L157)
instance hasIntScalar : SMul ℤ (LeftInvariantDerivation I G) where
  smul r X := ⟨r • X.1, fun g => by simp_rw [LinearMap.map_smul_of_tower _ r, left_invariant']⟩
```

-- snippet 87
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiff_finset_prod (L400-L403)
theorem contMDiff_finset_prod (h : ∀ i ∈ t, CMDiff n (f i)) :
    CMDiff n fun x ↦ ∏ i ∈ t, f i x :=
fun x ↦ contMDiffAt_finset_prod fun i hi ↦ h i hi x
```

-- snippet 88
```lean
-- Mathlib.Geometry.Manifold.Algebra.LieGroup.topologicalGroup_of_lieGroup (L134-L136)
theorem topologicalGroup_of_lieGroup : IsTopologicalGroup G :=
{ continuousMul_of_contMDiffMul I n with continuous_inv := (contMDiff_inv I n).continuous }
```

-- snippet 89
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.evalAt_apply (L194-L196)
theorem evalAt_apply : evalAt g X f = (X f) g :=
rfl
```

-- snippet 90
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.left_invariant (L201-L204)
theorem left_invariant : 𝒅ₕ (smoothLeftMul_one I g) (evalAt (1 : G) X) = evalAt g X :=
X.left_invariant'' g

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 91
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.evalAt_coe (L198-L200)
theorem evalAt_coe : Derivation.evalAt g ↑X = evalAt g X :=
rfl
```

-- snippet 92
```lean
-- Mathlib.Geometry.Manifold.Algebra.SmoothFunctions.coe_pow (L67-L80)
theorem coe_pow {G : Type*} [Monoid G] [TopologicalSpace G] [ChartedSpace H' G]
    [ContMDiffMul I' n G] (f : C^n⟮I, N; I', G⟯) (n : ℕ) :
    ⇑(f ^ n) = (f : N → G) ^ n :=
rfl

section GroupStructure

/-!
### Group structure

In this section we show that `C^n` functions valued in a Lie group inherit a group structure
under pointwise multiplication.
-/
```

-- snippet 93
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.coe_smul (L168-L170)
theorem coe_smul : ⇑(r • X) = r • ⇑X :=
rfl
```

-- snippet 94
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.ext (L83-L86)
theorem ext (h : ∀ f, X f = Y f) : X = Y := DFunLike.ext _ _ h
variable (X Y f)
```

-- snippet 95
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiffWithinAt_finprod (L333-L339)
theorem contMDiffWithinAt_finprod (lf : LocallyFinite fun i ↦ mulSupport <| f i) {x₀ : M}
    (h : ∀ i, CMDiffAt[s] n (f i) x₀) :
    CMDiffAt[s] n (fun x ↦ ∏ᶠ i, f i x) x₀ :=
let ⟨_I, hI⟩ := finprod_eventually_eq_prod lf x₀
  (ContMDiffWithinAt.prod fun i _hi ↦ h i).congr_of_eventuallyEq
    (eventually_nhdsWithin_of_eventually_nhds hI) hI.self_of_nhds
```

-- snippet 96
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiff_mul_right (L148-L150)
theorem contMDiff_mul_right {a : G} : CMDiff n (· * a) :=
contMDiff_id.mul contMDiff_const
```

-- snippet 97
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.ContMDiffWithinAt (L123-L126)
theorem ContMDiffWithinAt.mul (hf : CMDiffAt[s] n f x) (hg : CMDiffAt[s] n g x) :
    CMDiffAt[s] n (f * g) x :=
(contMDiff_mul I n).contMDiffAt.comp_contMDiffWithinAt x (hf.prodMk hg)
```

-- snippet 98
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiffAt_finset_prod (L370-L373)
theorem contMDiffAt_finset_prod (h : ∀ i ∈ t, CMDiffAt n (f i) x) :
    CMDiffAt n (fun x ↦ ∏ i ∈ t, f i x) x :=
contMDiffWithinAt_finset_prod h
```

-- snippet 99
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.left_invariant' (L92-L105)
theorem left_invariant' :
    𝒅ₕ (smoothLeftMul_one I g) (Derivation.evalAt (1 : G) ↑X) = Derivation.evalAt g ↑X :=
left_invariant'' X g

protected theorem map_add : X (f + f') = X f + X f' := by simp

protected theorem map_zero : X 0 = 0 := by simp

protected theorem map_neg : X (-f) = -X f := by simp

protected theorem map_sub : X (f - f') = X f - X f' := by simp

protected theorem map_smul : X (r • f) = r • X f := by simp
```

-- snippet 100
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.evalAt_mul (L205-L211)
theorem evalAt_mul : evalAt (g * h) X = 𝒅ₕ (L_apply I g h) (evalAt h X) := by
ext f
  rw [← left_invariant, hfdifferential_apply, hfdifferential_apply, L_mul, fdifferential_comp,
    fdifferential_apply]
  simp only [ContMDiffMap.comp_apply, LinearMap.comp_apply]
  rw [fdifferential_apply, ← hfdifferential_apply (smoothLeftMul_one I h), left_invariant]
```

-- snippet 101
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.continuousMul_of_contMDiffMul (L113-L115)
theorem continuousMul_of_contMDiffMul [ContMDiffMul I n G] : ContinuousMul G :=
⟨(contMDiff_mul I n).continuous⟩
```

-- snippet 102
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.coe_injective (L78-L81)
theorem coe_injective :
    @Function.Injective (LeftInvariantDerivation I G) (_ → C^∞⟮I, G; 𝕜⟯) DFunLike.coe :=
DFunLike.coe_injective
```

-- snippet 103
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiff_finprod_cond (L410-L417)
theorem contMDiff_finprod_cond (hc : ∀ i, p i → CMDiff n (f i))
    (hf : LocallyFinite fun i ↦ mulSupport (f i)) :
    CMDiff n fun x ↦ ∏ᶠ (i) (_ : p i), f i x := by
simp only [← finprod_subtype_eq_finprod_cond]
  exact contMDiff_finprod (fun i ↦ hc i i.2) (hf.comp_injective Subtype.coe_injective)

variable {g : M → G}
```

-- snippet 104
```lean
-- Mathlib.Geometry.Manifold.Algebra.LieGroup.contMDiff_inv (L126-L131)
theorem contMDiff_inv : CMDiff n fun x : G ↦ x⁻¹ :=
LieGroup.contMDiff_inv

include I n in
/-- A Lie group is a topological group. This is not an instance for technical reasons,
see note [Design choices about smooth algebraic structures]. -/
```

-- snippet 105
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.coe_add (L128-L130)
theorem coe_add : ⇑(X + Y) = X + Y :=
rfl
```

<s>[SYSTEM_PROMPT]You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.Geometry.Manifold.IsManifold.ExtChartAt).[/SYSTEM_PROMPT][MODEL_SETTINGS]{"reasoning_effort": "none"}[/MODEL_SETTINGS][INST]Prove the following theorem. The retrieved context below may help.

```lean
theorem extChartAt_target_subset_range (x : M) : (extChartAt I x).target ⊆ range I
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend (L75-L77)
def extend : PartialEquiv M E :=
f.toPartialEquiv ≫ I.toPartialEquiv
```

-- snippet 2
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_coe (L78-L80)
theorem extend_coe : ⇑(f.extend I) = I ∘ f :=
rfl
```

-- snippet 3
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_coe_symm (L81-L83)
theorem extend_coe_symm : ⇑(f.extend I).symm = f.symm ∘ I.symm :=
rfl
```

-- snippet 4
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_source (L84-L86)
theorem extend_source : (f.extend I).source = f.source := by
rw [extend, PartialEquiv.trans_source, I.source_eq, preimage_univ, inter_univ]
```

-- snippet 5
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.isOpen_extend_source (L87-L90)
theorem isOpen_extend_source : IsOpen (f.extend I).source := by
rw [extend_source]
  exact f.open_source
```

-- snippet 6
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_target (L91-L93)
theorem extend_target : (f.extend I).target = I.symm ⁻¹' f.target ∩ range I := by
simp_rw [extend, PartialEquiv.trans_target, I.target_eq, I.toPartialEquiv_coe_symm, inter_comm]
```

-- snippet 7
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_target' (L94-L96)
theorem extend_target' : (f.extend I).target = I '' f.target := by
rw [extend, PartialEquiv.trans_target'', I.source_eq, univ_inter, I.toPartialEquiv_coe]
```

-- snippet 8
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_target_eq_image_source (L97-L99)
theorem extend_target_eq_image_source : (f.extend I).target = (f.extend I) '' f.source := by
rw [f.extend_target', ← f.image_source_eq_target, ← image_comp, f.extend_coe]
```

-- snippet 9
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.isOpen_extend_target (L100-L103)
lemma isOpen_extend_target [I.Boundaryless] : IsOpen (f.extend I).target := by
rw [extend_target, I.range_eq_univ, inter_univ]
  exact I.continuous_symm.isOpen_preimage _ f.open_target
```

-- snippet 10
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.mapsTo_extend (L104-L109)
theorem mapsTo_extend (hs : s ⊆ f.source) :
    MapsTo (f.extend I) s ((f.extend I).symm ⁻¹' s ∩ range I) := by
rw [mapsTo_iff_image_subset, extend_coe, extend_coe_symm, preimage_comp, ← I.image_eq, image_comp,
    f.image_eq_target_inter_inv_preimage hs]
  exact image_mono inter_subset_right
```

-- snippet 11
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_left_inv (L110-L113)
theorem extend_left_inv {x : M} (hxf : x ∈ f.source) : (f.extend I).symm (f.extend I x) = x :=
(f.extend I).left_inv <| by rwa [f.extend_source]

/-- Variant of `f.extend_left_inv I`, stated in terms of images. -/
```

-- snippet 12
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_left_inv' (L114-L116)
lemma extend_left_inv' (ht : t ⊆ f.source) : ((f.extend I).symm ∘ (f.extend I)) '' t = t :=
EqOn.image_eq_self (fun _ hx ↦ f.extend_left_inv (ht hx))
```

-- snippet 13
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_source_mem_nhds (L117-L119)
theorem extend_source_mem_nhds {x : M} (h : x ∈ f.source) : (f.extend I).source ∈ 𝓝 x :=
(isOpen_extend_source f).mem_nhds <| by rwa [f.extend_source]
```

-- snippet 14
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_source_mem_nhdsWithin (L120-L122)
theorem extend_source_mem_nhdsWithin {x : M} (h : x ∈ f.source) : (f.extend I).source ∈ 𝓝[s] x :=
mem_nhdsWithin_of_mem_nhds <| extend_source_mem_nhds f h
```

-- snippet 15
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.continuousOn_extend (L123-L127)
theorem continuousOn_extend : ContinuousOn (f.extend I) (f.extend I).source := by
refine I.continuous.comp_continuousOn ?_
  rw [extend_source]
  exact f.continuousOn
```

-- snippet 16
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.continuousAt_extend (L128-L130)
theorem continuousAt_extend {x : M} (h : x ∈ f.source) : ContinuousAt (f.extend I) x :=
(continuousOn_extend f).continuousAt <| extend_source_mem_nhds f h
```

-- snippet 17
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.map_extend_nhds (L131-L134)
theorem map_extend_nhds {x : M} (hy : x ∈ f.source) :
    map (f.extend I) (𝓝 x) = 𝓝[range I] f.extend I x := by
rwa [extend_coe, comp_apply, ← I.map_nhds_eq, ← f.map_nhds_eq, map_map]
```

-- snippet 18
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.map_extend_nhds_of_mem_interior_range (L135-L140)
theorem map_extend_nhds_of_mem_interior_range {x : M} (hx : x ∈ f.source)
    (h'x : f.extend I x ∈ interior (range I)) :
    map (f.extend I) (𝓝 x) = 𝓝 (f.extend I x) := by
rw [f.map_extend_nhds hx, nhdsWithin_eq_nhds]
  exact mem_of_superset (isOpen_interior.mem_nhds h'x) interior_subset
```

-- snippet 19
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.map_extend_nhds_of_boundaryless (L141-L144)
theorem map_extend_nhds_of_boundaryless [I.Boundaryless] {x : M} (hx : x ∈ f.source) :
    map (f.extend I) (𝓝 x) = 𝓝 (f.extend I x) := by
rw [f.map_extend_nhds hx, I.range_eq_univ, nhdsWithin_univ]
```

-- snippet 20
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_target_mem_nhdsWithin (L145-L149)
theorem extend_target_mem_nhdsWithin {y : M} (hy : y ∈ f.source) :
    (f.extend I).target ∈ 𝓝[range I] f.extend I y := by
rw [← PartialEquiv.image_source_eq_target, ← map_extend_nhds f hy]
  exact image_mem_map (extend_source_mem_nhds _ hy)
```

-- snippet 21
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_image_target_mem_nhds (L150-L155)
lemma extend_image_target_mem_nhds {x : M} (hx : x ∈ f.source) :
    I '' f.target ∈ 𝓝[range I] (f.extend I) x := by
rw [← f.map_extend_nhds hx, Filter.mem_map,
    f.extend_coe, Set.preimage_comp, I.preimage_image f.target]
  exact (f.continuousAt hx).preimage_mem_nhds (f.open_target.mem_nhds (f.map_source hx))
```

-- snippet 22
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_image_nhds_mem_nhds_of_boundaryless (L156-L160)
theorem extend_image_nhds_mem_nhds_of_boundaryless [I.Boundaryless] {x} (hx : x ∈ f.source)
    {s : Set M} (h : s ∈ 𝓝 x) : (f.extend I) '' s ∈ 𝓝 ((f.extend I) x) := by
rw [← f.map_extend_nhds_of_boundaryless hx, Filter.mem_map]
  filter_upwards [h] using subset_preimage_image (f.extend I) s
```

-- snippet 23
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_image_nhds_mem_nhds_of_mem_interior_range (L161-L166)
theorem extend_image_nhds_mem_nhds_of_mem_interior_range {x} (hx : x ∈ f.source)
    (h'x : f.extend I x ∈ interior (range I)) {s : Set M} (h : s ∈ 𝓝 x) :
    (f.extend I) '' s ∈ 𝓝 ((f.extend I) x) := by
rw [← f.map_extend_nhds_of_mem_interior_range hx h'x, Filter.mem_map]
  filter_upwards [h] using subset_preimage_image (f.extend I) s
```

-- snippet 24
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.extend_target_subset_range (L167-L168)
theorem extend_target_subset_range : (f.extend I).target ⊆ range I := by simp only [mfld_simps]
```

-- snippet 25
```lean
-- Mathlib.Geometry.Manifold.IsManifold.ExtChartAt.interior_extend_target_subset_interior_range (L169-L175)
lemma interior_extend_target_subset_interior_range :
    interior (f.extend I).target ⊆ interior (range I) := by
rw [f.extend_target, interior_inter, (f.open_target.preimage I.continuous_symm).interior_eq]
  exact inter_subset_right

/-- If `y ∈ f.target` and `I y ∈ interior (range I)`,
then `I y` is an interior point of `(I ∘ f).target`. -/
```

-- snippet 26
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiffAt_mul_left (L144-L146)
theorem contMDiffAt_mul_left {a b : G} : CMDiffAt n (a * ·) b :=
contMDiff_mul_left.contMDiffAt
```

-- snippet 27
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.mdifferentiableAt_mul_left (L166-L168)
theorem mdifferentiableAt_mul_left {a b : G} : MDiffAt (a * ·) b :=
contMDiffAt_mul_left.mdifferentiableAt one_ne_zero
```

-- snippet 28
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiffOn_finprod (L375-L379)
theorem contMDiffOn_finprod
    (lf : LocallyFinite fun i ↦ Function.mulSupport <| f i) (h : ∀ i, CMDiff[s] n (f i)) :
    CMDiff[s] n (fun x ↦ ∏ᶠ i, f i x) := fun x hx ↦
contMDiffWithinAt_finprod lf fun i ↦ h i x hx
```

-- snippet 29
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.toFun_eq_coe (L75-L77)
theorem toFun_eq_coe : X.toFun = ⇑X :=
rfl
```

-- snippet 30
```lean
-- Mathlib.Geometry.Manifold.Algebra.SmoothFunctions.coe_mul (L41-L44)
theorem coe_mul {G : Type*} [Mul G] [TopologicalSpace G] [ChartedSpace H' G] [ContMDiffMul I' n G]
    (f g : C^n⟮I, N; I', G⟯) : ⇑(f * g) = f * g :=
rfl
```

-- snippet 31
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiff_finset_prod' (L396-L398)
theorem contMDiff_finset_prod' (h : ∀ i ∈ t, CMDiff n (f i)) :
    CMDiff n (∏ i ∈ t, f i) := fun x ↦ contMDiffAt_finset_prod' fun i hi ↦ h i hi x
```

-- snippet 32
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.coe_sub (L140-L142)
theorem coe_sub : ⇑(X - Y) = X - Y :=
rfl
```

-- snippet 33
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.smoothRightMul_one (L232-L234)
theorem smoothRightMul_one : (𝑹 I g') 1 = g' :=
one_mul g'
```

-- snippet 34
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.lift_zero (L148-L151)
theorem lift_zero :
    (↑(0 : LeftInvariantDerivation I G) : Derivation 𝕜 C^∞⟮I, G; 𝕜⟯ C^∞⟮I, G; 𝕜⟯) = 0 :=
rfl
```

-- snippet 35
```lean
-- Mathlib.Geometry.Manifold.Algebra.LieGroup.instNormedSpaceLieAddGroup (L197-L217)
instance instNormedSpaceLieAddGroup {𝕜 : Type*} [NontriviallyNormedField 𝕜] {n : WithTop ℕ∞}
    {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] : LieAddGroup 𝓘(𝕜, E) n E where
  contMDiff_neg := contDiff_neg.contMDiff
/-! ## `C^n` manifolds with `C^n` inversion away from zero

Typeclass for `C^n` manifolds with `0` and `Inv` such that inversion is `C^n` at all non-zero
points. (This includes multiplicative Lie groups, but also complete normed semifields.)
Point-wise inversion is `C^n` when the function/denominator is non-zero. -/
section ContMDiffInv₀

-- See note [Design choices about smooth algebraic structures]
/-- A `C^n` manifold with `0` and `Inv` such that `fun x ↦ x⁻¹` is `C^n` at all nonzero points.
Any complete normed (semi)field has this property. -/
class ContMDiffInv₀ {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalSpace H]
    {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] (I : ModelWithCorners 𝕜 E H)
    (n : WithTop ℕ∞) (G : Type*)
    [Inv G] [Zero G] [TopologicalSpace G] [ChartedSpace H G] : Prop where
  /-- Inversion is `C^n` away from `0`. -/
  contMDiffAt_inv₀ : ∀ ⦃x : G⦄, x ≠ 0 → CMDiffAt n (fun (y : G) ↦ y⁻¹) x
```

-- snippet 36
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.ContMDiff (L136-L138)
theorem ContMDiff.mul (hf : CMDiff n f) (hg : CMDiff n g) : CMDiff n (f * g) :=
fun x ↦ (hf x).mul (hg x)
```

-- snippet 37
```lean
-- Mathlib.Geometry.Manifold.Algebra.SmoothFunctions.instPow (L61-L65)
instance instPow {G : Type*} [Monoid G] [TopologicalSpace G] [ChartedSpace H' G]
    [ContMDiffMul I' n G] :
    Pow C^n⟮I, N; I', G⟯ ℕ where
  pow f n := ⟨(f : N → G) ^ n, (contMDiff_pow n).comp f.contMDiff⟩
```

-- snippet 38
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.lift_smul (L172-L177)
theorem lift_smul (k : 𝕜) : (k • X).1 = k • X.1 :=
rfl

variable (I G)

/-- The coercion to function is a monoid homomorphism. -/
```

-- snippet 39
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.commutator_apply (L237-L239)
theorem commutator_apply : ⁅X, Y⁆ f = X (Y f) - Y (X f) :=
rfl
```

-- snippet 40
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.evalAt (L189-L193)
def evalAt : LeftInvariantDerivation I G →ₗ[𝕜] PointDerivation I g where
  toFun X := Derivation.evalAt g X.1
map_add' _ _ := rfl
  map_smul' _ _ := rfl
```

-- snippet 41
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.smoothLeftMul (L186-L192)
def smoothLeftMul : C^∞⟮I, G; I, G⟯ :=
⟨(g * ·), contMDiff_mul_left⟩

/-- Right multiplication by `g`. It is meant to mimic the usual notation in Lie groups.
Used mostly through the notation `𝑹`.
Lemmas involving `smoothRightMul` with the notation `𝑹` usually use `R` instead of `𝑹` in the
names. -/
```

-- snippet 42
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiffOn_finset_prod' (L381-L384)
theorem contMDiffOn_finset_prod' (h : ∀ i ∈ t, CMDiff[s] n (f i)) :
    CMDiff[s] n (∏ i ∈ t, f i) :=
fun x hx ↦ contMDiffWithinAt_finset_prod' fun i hi ↦ h i hi x hx
```

-- snippet 43
```lean
-- Mathlib.Geometry.Manifold.Algebra.LieGroup.ContMDiffAt (L145-L148)
theorem ContMDiffAt.inv {f : M → G} {x₀ : M} (hf : CMDiffAt n f x₀) :
    CMDiffAt n (fun x ↦ (f x)⁻¹) x₀ :=
(contMDiff_inv I n).contMDiffAt.comp x₀ hf
```

-- snippet 44
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiffWithinAt_finset_prod (L347-L351)
theorem contMDiffWithinAt_finset_prod (h : ∀ i ∈ t, CMDiffAt[s] n (f i) x) :
    CMDiffAt[s] n (fun x ↦ ∏ i ∈ t, f i x) x := by
simp only [← Finset.prod_apply]
  exact contMDiffWithinAt_finset_prod' h
```

-- snippet 45
```lean
-- Mathlib.Geometry.Manifold.Algebra.SmoothFunctions.mul_comp (L46-L49)
theorem mul_comp {G : Type*} [Mul G] [TopologicalSpace G] [ChartedSpace H' G] [ContMDiffMul I' n G]
    (f g : C^n⟮I'', N'; I', G⟯) (h : C^n⟮I, N; I'', N'⟯) : (f * g).comp h = f.comp h * g.comp h :=
rfl
```

-- snippet 46
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.mdifferentiable_mul_left (L162-L164)
theorem mdifferentiable_mul_left {a : G} : MDiff (a * ·) :=
contMDiff_mul_left.mdifferentiable one_ne_zero
```

-- snippet 47
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiffAt_finset_prod' (L365-L368)
theorem contMDiffAt_finset_prod' (h : ∀ i ∈ t, CMDiffAt n (f i) x) :
    CMDiffAt n (∏ i ∈ t, f i) x :=
contMDiffWithinAt_finset_prod' h
```

-- snippet 48
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiff_mul (L105-L110)
theorem contMDiff_mul [ContMDiffMul I n G] : CMDiff n fun p : G × G ↦ p.1 * p.2 :=
ContMDiffMul.contMDiff_mul

include I n in
/-- If the multiplication is `C^n`, then it is continuous. This is not an instance for technical
reasons, see note [Design choices about smooth algebraic structures]. -/
```

-- snippet 49
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.coeFnAddMonoidHom (L179-L183)
def coeFnAddMonoidHom : LeftInvariantDerivation I G →+ C^∞⟮I, G; 𝕜⟯ → C^∞⟮I, G; 𝕜⟯ :=
⟨⟨DFunLike.coe, coe_zero⟩, coe_add⟩

variable {I G}
```

-- snippet 50
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.lift_add (L144-L146)
theorem lift_add : (↑(X + Y) : Derivation 𝕜 C^∞⟮I, G; 𝕜⟯ C^∞⟮I, G; 𝕜⟯) = X + Y :=
rfl
```

-- snippet 51
```lean
-- Mathlib.Geometry.Manifold.Algebra.LieGroup.Prod (L184-L196)
instance Prod.instLieGroup {𝕜 : Type*} [NontriviallyNormedField 𝕜] {n : WithTop ℕ∞}
    {H : Type*} [TopologicalSpace H] {E : Type*}
    [NormedAddCommGroup E] [NormedSpace 𝕜 E] {I : ModelWithCorners 𝕜 E H} {G : Type*}
    [TopologicalSpace G] [ChartedSpace H G] [Group G] [LieGroup I n G] {E' : Type*}
    [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H' : Type*} [TopologicalSpace H']
    {I' : ModelWithCorners 𝕜 E' H'} {G' : Type*} [TopologicalSpace G'] [ChartedSpace H' G']
    [Group G'] [LieGroup I' n G'] : LieGroup (I.prod I') n (G × G') :=
{ ContMDiffMul.prod _ _ _ _ with contMDiff_inv := contMDiff_fst.inv.prodMk contMDiff_snd.inv }

end Product

/-! ### Normed spaces are Lie groups -/
```

-- snippet 52
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.L_apply (L205-L207)
theorem L_apply : (𝑳 I g) h = g * h :=
rfl
```

-- snippet 53
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiffAt_finprod (L359-L363)
theorem contMDiffAt_finprod
    (lf : LocallyFinite fun i ↦ mulSupport <| f i) (h : ∀ i, CMDiffAt n (f i) x₀) :
    CMDiffAt n (fun x ↦ ∏ᶠ i, f i x) x₀ :=
contMDiffWithinAt_finprod lf h
```

-- snippet 54
```lean
-- Mathlib.Geometry.Manifold.Algebra.LieGroup.ContMDiff (L154-L156)
theorem ContMDiff.inv {f : M → G} (hf : CMDiff n f) : CMDiff n fun x ↦ (f x)⁻¹ :=
fun x ↦ (hf x).inv
```

-- snippet 55
```lean
-- Mathlib.Geometry.Manifold.Algebra.SmoothFunctions.coe_one (L56-L59)
theorem coe_one {G : Type*} [One G] [TopologicalSpace G] [ChartedSpace H' G] :
    ⇑(1 : C^n⟮I, N; I', G⟯) = 1 :=
rfl
```

-- snippet 56
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiffOn_finset_prod (L386-L389)
theorem contMDiffOn_finset_prod (h : ∀ i ∈ t, CMDiff[s] n (f i)) :
    CMDiff[s] n (fun x ↦ ∏ i ∈ t, f i x) :=
fun x hx ↦ contMDiffWithinAt_finset_prod fun i hi ↦ h i hi x hx
```

-- snippet 57
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.mdifferentiableAt_mul_right (L174-L176)
theorem mdifferentiableAt_mul_right {a b : G} : MDiffAt (· * a) b :=
contMDiffAt_mul_right.mdifferentiableAt one_ne_zero
```

-- snippet 58
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.leibniz (L107-L109)
theorem leibniz : X (f * f') = f • X f' + f' • X f :=
X.leibniz' _ _
```

-- snippet 59
```lean
-- Mathlib.Geometry.Manifold.Algebra.LieGroup.contMDiffOn_inv₀ (L268-L272)
theorem contMDiffOn_inv₀ : CMDiff[{0}ᶜ] n (Inv.inv : G → G) :=
fun _x hx ↦ (contMDiffAt_inv₀ hx).contMDiffWithinAt

variable {s : Set M} {a : M}
```

-- snippet 60
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiff_finprod (L405-L408)
theorem contMDiff_finprod (h : ∀ i, CMDiff n (f i))
    (hfin : LocallyFinite fun i ↦ mulSupport (f i)) : CMDiff n fun x ↦ ∏ᶠ i, f i x :=
fun x ↦ contMDiffAt_finprod hfin fun i ↦ h i x
```

-- snippet 61
```lean
-- Mathlib.Geometry.Manifold.Algebra.LieGroup.continuousInv₀_of_contMDiffInv₀ (L265-L267)
theorem continuousInv₀_of_contMDiffInv₀ : ContinuousInv₀ G :=
{ continuousAt_inv₀ := fun _ hx ↦ (contMDiffAt_inv₀ (I := I) (n := n) hx).continuousAt }
```

-- snippet 62
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.smoothLeftMul_one (L229-L231)
theorem smoothLeftMul_one : (𝑳 I g') 1 = g' :=
mul_one g'
```

-- snippet 63
```lean
-- Mathlib.Geometry.Manifold.Algebra.LieGroup.contMDiffAt_inv₀ (L258-L264)
theorem contMDiffAt_inv₀ {x : G} (hx : x ≠ 0) : ContMDiffAt I I n (fun y ↦ y⁻¹) x :=
ContMDiffInv₀.contMDiffAt_inv₀ hx

include I n in
/-- In a manifold with `C^n` inverse away from `0`, the inverse is continuous away from `0`.
This is not an instance for technical reasons, see
note [Design choices about smooth algebraic structures]. -/
```

-- snippet 64
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiff_mul_left (L140-L142)
theorem contMDiff_mul_left {a : G} : CMDiff n (a * ·) :=
contMDiff_const.mul contMDiff_id
```

-- snippet 65
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.instContMDiffAddSelf (L445-L449)
instance instContMDiffAddSelf : ContMDiffAdd 𝓘(𝕜, E) n E := by
constructor
  rw [← modelWithCornersSelf_prod, chartedSpaceSelf_prod]
  exact contDiff_add.contMDiff
```

-- snippet 66
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiffAt_mul_right (L152-L154)
theorem contMDiffAt_mul_right {a b : G} : CMDiffAt n (· * a) b :=
contMDiff_mul_right.contMDiffAt
```

-- snippet 67
```lean
-- Mathlib.Geometry.Manifold.Algebra.SmoothFunctions.semigroup (L82-L85)
instance semigroup {G : Type*} [Semigroup G] [TopologicalSpace G] [ChartedSpace H' G]
    [ContMDiffMul I' n G] : Semigroup C^n⟮I, N; I', G⟯ :=
DFunLike.coe_injective.semigroup _ coe_mul
```

-- snippet 68
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.toDerivation_injective (L61-L64)
theorem toDerivation_injective :
    Function.Injective (toDerivation : LeftInvariantDerivation I G → _) :=
fun X Y h => by cases X; cases Y; congr
```

-- snippet 69
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.ContMDiffAt (L353-L357)
theorem ContMDiffAt.prod (h : ∀ i ∈ t, CMDiffAt n (f i) x₀) :
    CMDiffAt n (fun x ↦ ∏ i ∈ t, f i x) x₀ := by
simp only [← contMDiffWithinAt_univ] at *
  exact ContMDiffWithinAt.prod h
```

-- snippet 70
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.mdifferentiable_mul_right (L170-L172)
theorem mdifferentiable_mul_right {a : G} : MDiff (· * a) :=
contMDiff_mul_right.mdifferentiable one_ne_zero
```

-- snippet 71
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.smoothRightMul (L193-L196)
def smoothRightMul : C^∞⟮I, G; I, G⟯ :=
⟨(· * g), contMDiff_mul_right⟩

-- Left multiplication. The abbreviation is `MIL`.
```

-- snippet 72
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.comp_L (L212-L216)
theorem comp_L : (X f).comp (𝑳 I g) = X (f.comp (𝑳 I g)) := by
ext h
  rw [ContMDiffMap.comp_apply, L_apply, ← evalAt_apply, evalAt_mul, hfdifferential_apply,
    fdifferential_apply, evalAt_apply]
```

-- snippet 73
```lean
-- Mathlib.Geometry.Manifold.Algebra.LieGroup.ContMDiffWithinAt (L140-L143)
theorem ContMDiffWithinAt.inv {f : M → G} {s : Set M} {x₀ : M}
    (hf : CMDiffAt[s] n f x₀) : CMDiffAt[s] n (fun x ↦ (f x)⁻¹) x₀ :=
(contMDiff_inv I n).contMDiffAt.contMDiffWithinAt.comp x₀ hf <| Set.mapsTo_univ _ _
```

-- snippet 74
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.R_apply (L209-L211)
theorem R_apply : (𝑹 I g) h = h * g :=
rfl
```

-- snippet 75
```lean
-- Mathlib.Geometry.Manifold.Algebra.LieGroup.ContMDiffOn (L150-L152)
theorem ContMDiffOn.inv {f : M → G} {s : Set M} (hf : CMDiff[s] n f) :
    CMDiff[s] n (fun x ↦ (f x)⁻¹) := fun x hx ↦ (hf x hx).inv
```

-- snippet 76
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.coe_derivation (L87-L91)
theorem coe_derivation :
    ⇑(X : Derivation 𝕜 C^∞⟮I, G; 𝕜⟯ C^∞⟮I, G; 𝕜⟯) = (X : C^∞⟮I, G; 𝕜⟯ → C^∞⟮I, G; 𝕜⟯) :=
rfl

/-- Premature version of the lemma. Prefer using `left_invariant` instead. -/
```

-- snippet 77
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.commutator_coe_derivation (L231-L236)
theorem commutator_coe_derivation :
    ⇑⁅X, Y⁆ =
      (⁅(X : Derivation 𝕜 C^∞⟮I, G; 𝕜⟯ C^∞⟮I, G; 𝕜⟯), Y⁆ :
        Derivation 𝕜 C^∞⟮I, G; 𝕜⟯ C^∞⟮I, G; 𝕜⟯) :=
rfl
```

-- snippet 78
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.L_mul (L213-L217)
theorem L_mul {G : Type*} [Semigroup G] [TopologicalSpace G] [ChartedSpace H G] [ContMDiffMul I ∞ G]
    (g h : G) : 𝑳 I (g * h) = (𝑳 I g).comp (𝑳 I h) := by
ext
  simp only [ContMDiffMap.comp_apply, L_apply, mul_assoc]
```

-- snippet 79
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.R_mul (L219-L223)
theorem R_mul {G : Type*} [Semigroup G] [TopologicalSpace G] [ChartedSpace H G] [ContMDiffMul I ∞ G]
    (g h : G) : 𝑹 I (g * h) = (𝑹 I h).comp (𝑹 I g) := by
ext
  simp only [ContMDiffMap.comp_apply, R_apply, mul_assoc]
```

-- snippet 80
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.hasNatScalar (L152-L154)
instance hasNatScalar : SMul ℕ (LeftInvariantDerivation I G) where
  smul r X := ⟨r • X.1, fun g => by simp_rw [LinearMap.map_smul_of_tower _ r, left_invariant']⟩
```

-- snippet 81
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.coe_neg (L136-L138)
theorem coe_neg : ⇑(-X) = -X :=
rfl
```

-- snippet 82
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.coe_zero (L132-L134)
theorem coe_zero : ⇑(0 : LeftInvariantDerivation I G) = 0 :=
rfl
```

-- snippet 83
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.ContMDiffOn (L132-L134)
theorem ContMDiffOn.mul (hf : CMDiff[s] n f) (hg : CMDiff[s] n g) : CMDiff[s] n (f * g) :=
fun x hx ↦ (hf x hx).mul (hg x hx)
```

-- snippet 84
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.ContMDiffMul (L239-L260)
instance ContMDiffMul.prod {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*}
    [NormedAddCommGroup E] [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H]
    (I : ModelWithCorners 𝕜 E H) (G : Type*) [TopologicalSpace G] [ChartedSpace H G] [Mul G]
    [ContMDiffMul I n G] {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H' : Type*}
    [TopologicalSpace H'] (I' : ModelWithCorners 𝕜 E' H') (G' : Type*) [TopologicalSpace G']
    [ChartedSpace H' G'] [Mul G'] [ContMDiffMul I' n G'] : ContMDiffMul (I.prod I') n (G × G') :=
{ IsManifold.prod G G' with
    contMDiff_mul :=
      ((contMDiff_fst.comp contMDiff_fst).mul (contMDiff_fst.comp contMDiff_snd)).prodMk
        ((contMDiff_snd.comp contMDiff_fst).mul (contMDiff_snd.comp contMDiff_snd)) }

end ContMDiffMul

section Monoid

variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {n : WithTop ℕ∞}
  {H : Type*} [TopologicalSpace H] {E : Type*}
  [NormedAddCommGroup E] [NormedSpace 𝕜 E] {I : ModelWithCorners 𝕜 E H} {G : Type*} [Monoid G]
  [TopologicalSpace G] [ChartedSpace H G] [ContMDiffMul I n G] {H' : Type*} [TopologicalSpace H']
  {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {I' : ModelWithCorners 𝕜 E' H'}
  {G' : Type*} [Monoid G'] [TopologicalSpace G'] [ChartedSpace H' G'] [ContMDiffMul I' n G']
```

-- snippet 85
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiffWithinAt_finset_prod' (L341-L345)
theorem contMDiffWithinAt_finset_prod' (h : ∀ i ∈ t, CMDiffAt[s] n (f i) x) :
    CMDiffAt[s] n (∏ i ∈ t, f i) x :=
Finset.prod_induction f (fun f ↦ CMDiffAt[s] n f x) (fun _ _ hf hg ↦ hf.mul hg)
    (contMDiffWithinAt_const (c := 1)) h
```

-- snippet 86
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.hasIntScalar (L155-L157)
instance hasIntScalar : SMul ℤ (LeftInvariantDerivation I G) where
  smul r X := ⟨r • X.1, fun g => by simp_rw [LinearMap.map_smul_of_tower _ r, left_invariant']⟩
```

-- snippet 87
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiff_finset_prod (L400-L403)
theorem contMDiff_finset_prod (h : ∀ i ∈ t, CMDiff n (f i)) :
    CMDiff n fun x ↦ ∏ i ∈ t, f i x :=
fun x ↦ contMDiffAt_finset_prod fun i hi ↦ h i hi x
```

-- snippet 88
```lean
-- Mathlib.Geometry.Manifold.Algebra.LieGroup.topologicalGroup_of_lieGroup (L134-L136)
theorem topologicalGroup_of_lieGroup : IsTopologicalGroup G :=
{ continuousMul_of_contMDiffMul I n with continuous_inv := (contMDiff_inv I n).continuous }
```

-- snippet 89
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.evalAt_apply (L194-L196)
theorem evalAt_apply : evalAt g X f = (X f) g :=
rfl
```

-- snippet 90
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.left_invariant (L201-L204)
theorem left_invariant : 𝒅ₕ (smoothLeftMul_one I g) (evalAt (1 : G) X) = evalAt g X :=
X.left_invariant'' g

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 91
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.evalAt_coe (L198-L200)
theorem evalAt_coe : Derivation.evalAt g ↑X = evalAt g X :=
rfl
```

-- snippet 92
```lean
-- Mathlib.Geometry.Manifold.Algebra.SmoothFunctions.coe_pow (L67-L80)
theorem coe_pow {G : Type*} [Monoid G] [TopologicalSpace G] [ChartedSpace H' G]
    [ContMDiffMul I' n G] (f : C^n⟮I, N; I', G⟯) (n : ℕ) :
    ⇑(f ^ n) = (f : N → G) ^ n :=
rfl

section GroupStructure

/-!
### Group structure

In this section we show that `C^n` functions valued in a Lie group inherit a group structure
under pointwise multiplication.
-/
```

-- snippet 93
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.coe_smul (L168-L170)
theorem coe_smul : ⇑(r • X) = r • ⇑X :=
rfl
```

-- snippet 94
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.ext (L83-L86)
theorem ext (h : ∀ f, X f = Y f) : X = Y := DFunLike.ext _ _ h
variable (X Y f)
```

-- snippet 95
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiffWithinAt_finprod (L333-L339)
theorem contMDiffWithinAt_finprod (lf : LocallyFinite fun i ↦ mulSupport <| f i) {x₀ : M}
    (h : ∀ i, CMDiffAt[s] n (f i) x₀) :
    CMDiffAt[s] n (fun x ↦ ∏ᶠ i, f i x) x₀ :=
let ⟨_I, hI⟩ := finprod_eventually_eq_prod lf x₀
  (ContMDiffWithinAt.prod fun i _hi ↦ h i).congr_of_eventuallyEq
    (eventually_nhdsWithin_of_eventually_nhds hI) hI.self_of_nhds
```

-- snippet 96
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiff_mul_right (L148-L150)
theorem contMDiff_mul_right {a : G} : CMDiff n (· * a) :=
contMDiff_id.mul contMDiff_const
```

-- snippet 97
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.ContMDiffWithinAt (L123-L126)
theorem ContMDiffWithinAt.mul (hf : CMDiffAt[s] n f x) (hg : CMDiffAt[s] n g x) :
    CMDiffAt[s] n (f * g) x :=
(contMDiff_mul I n).contMDiffAt.comp_contMDiffWithinAt x (hf.prodMk hg)
```

-- snippet 98
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiffAt_finset_prod (L370-L373)
theorem contMDiffAt_finset_prod (h : ∀ i ∈ t, CMDiffAt n (f i) x) :
    CMDiffAt n (fun x ↦ ∏ i ∈ t, f i x) x :=
contMDiffWithinAt_finset_prod h
```

-- snippet 99
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.left_invariant' (L92-L105)
theorem left_invariant' :
    𝒅ₕ (smoothLeftMul_one I g) (Derivation.evalAt (1 : G) ↑X) = Derivation.evalAt g ↑X :=
left_invariant'' X g

protected theorem map_add : X (f + f') = X f + X f' := by simp

protected theorem map_zero : X 0 = 0 := by simp

protected theorem map_neg : X (-f) = -X f := by simp

protected theorem map_sub : X (f - f') = X f - X f' := by simp

protected theorem map_smul : X (r • f) = r • X f := by simp
```

-- snippet 100
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.evalAt_mul (L205-L211)
theorem evalAt_mul : evalAt (g * h) X = 𝒅ₕ (L_apply I g h) (evalAt h X) := by
ext f
  rw [← left_invariant, hfdifferential_apply, hfdifferential_apply, L_mul, fdifferential_comp,
    fdifferential_apply]
  simp only [ContMDiffMap.comp_apply, LinearMap.comp_apply]
  rw [fdifferential_apply, ← hfdifferential_apply (smoothLeftMul_one I h), left_invariant]
```

-- snippet 101
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.continuousMul_of_contMDiffMul (L113-L115)
theorem continuousMul_of_contMDiffMul [ContMDiffMul I n G] : ContinuousMul G :=
⟨(contMDiff_mul I n).continuous⟩
```

-- snippet 102
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.coe_injective (L78-L81)
theorem coe_injective :
    @Function.Injective (LeftInvariantDerivation I G) (_ → C^∞⟮I, G; 𝕜⟯) DFunLike.coe :=
DFunLike.coe_injective
```

-- snippet 103
```lean
-- Mathlib.Geometry.Manifold.Algebra.Monoid.contMDiff_finprod_cond (L410-L417)
theorem contMDiff_finprod_cond (hc : ∀ i, p i → CMDiff n (f i))
    (hf : LocallyFinite fun i ↦ mulSupport (f i)) :
    CMDiff n fun x ↦ ∏ᶠ (i) (_ : p i), f i x := by
simp only [← finprod_subtype_eq_finprod_cond]
  exact contMDiff_finprod (fun i ↦ hc i i.2) (hf.comp_injective Subtype.coe_injective)

variable {g : M → G}
```

-- snippet 104
```lean
-- Mathlib.Geometry.Manifold.Algebra.LieGroup.contMDiff_inv (L126-L131)
theorem contMDiff_inv : CMDiff n fun x : G ↦ x⁻¹ :=
LieGroup.contMDiff_inv

include I n in
/-- A Lie group is a topological group. This is not an instance for technical reasons,
see note [Design choices about smooth algebraic structures]. -/
```

-- snippet 105
```lean
-- Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation.coe_add (L128-L130)
theorem coe_add : ⇑(X + Y) = X + Y :=
rfl
```
[/INST]


[System] You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.CategoryTheory.Discrete.Basic).

[User]
Prove the following theorem. The retrieved context below may help.

```lean
theorem eq_of_hom {X Y : Discrete α} (i : X ⟶ Y) : X.as = Y.as
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.Discrete (L56-L59)
theorem Discrete.mk_as {α : Type u₁} (X : Discrete α) : Discrete.mk X.as = X :=
rfl

/-- `Discrete α` is equivalent to the original type `α`. -/
```

-- snippet 2
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.discreteEquiv (L61-L66)
def discreteEquiv {α : Type u₁} : Discrete α ≃ α where
  toFun := Discrete.as
invFun := Discrete.mk
  left_inv := by cat_disch
  right_inv := by cat_disch
```

-- snippet 3
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.discreteCategory (L75-L88)
instance discreteCategory (α : Type u₁) : SmallCategory (Discrete α) where
  Hom X Y := ULift (PLift (X.as = Y.as))
id _ := ULift.up (PLift.up rfl)
  comp {X Y Z} g f := by
    cases X
    cases Y
    cases Z
    rcases f with ⟨⟨⟨⟩⟩⟩
    exact g

namespace Discrete

variable {α : Type u₁}
```

-- snippet 4
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.instSubsingletonDiscreteHom (L95-L105)
instance instSubsingletonDiscreteHom (X Y : Discrete α) : Subsingleton (X ⟶ Y) :=
show Subsingleton (ULift (PLift _)) from inferInstance

/-- A simple tactic to run `cases` on any `Discrete α` hypotheses. -/
macro "discrete_cases" : tactic =>
  `(tactic| fail_if_no_progress casesm* Discrete _, (_ : Discrete _) ⟶ (_ : Discrete _), PLift _)

open Lean Elab Tactic in
/--
Use:
```
```

-- snippet 5
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.eqToHom' (L139-L142)
abbrev eqToHom' {a b : α} (h : a = b) : Discrete.mk a ⟶ Discrete.mk b :=
Discrete.eqToHom h

/-- A variant of `eqToIso` that lifts terms to the discrete category. -/
```

-- snippet 6
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.eqToIso' (L143-L145)
abbrev eqToIso' {a b : α} (h : a = b) : Discrete.mk a ≅ Discrete.mk b :=
Discrete.eqToIso h
```

-- snippet 7
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.id_def (L147-L149)
theorem id_def (X : Discrete α) : ULift.up (PLift.up (Eq.refl X.as)) = 𝟙 X :=
rfl
```

-- snippet 8
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.id_def' (L151-L155)
theorem id_def' (X : α) : ULift.up (PLift.up (Eq.refl X)) = 𝟙 (⟨X⟩ : Discrete α) :=
rfl

variable {C : Type u₂} [Category.{v₂} C]
```

-- snippet 9
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.functor (L163-L169)
def functor {I : Type u₁} (F : I → C) : Discrete I ⥤ C where
  obj := F ∘ Discrete.as
map {X Y} f := by
    dsimp
    rcases f with ⟨⟨h⟩⟩
    exact eqToHom (congrArg _ h)
```

-- snippet 10
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.functor_obj (L171-L174)
theorem functor_obj {I : Type u₁} (F : I → C) (i : I) :
    (Discrete.functor F).obj (Discrete.mk i) = F i :=
rfl
```

-- snippet 11
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.functor_map (L175-L177)
theorem functor_map {I : Type u₁} (F : I → C) {i : Discrete I} (f : i ⟶ i) :
    (Discrete.functor F).map f = 𝟙 (F i.as) := by cat_disch
```

-- snippet 12
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.functor_obj_eq_as (L179-L182)
theorem functor_obj_eq_as {I : Type u₁} (F : I → C) (X : Discrete I) :
    (Discrete.functor F).obj X = F X.as :=
rfl
```

-- snippet 13
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.functor_ext (L184-L192)
lemma functor_ext {I : Type u₁} {G F : Discrete I ⥤ C} (h : (i : I) → G.obj ⟨i⟩ = F.obj ⟨i⟩) :
    G = F := by
fapply Functor.ext
  · intro I; rw [h]
  · intro ⟨X⟩ ⟨Y⟩ ⟨⟨p⟩⟩; simp only at p; induction p; simp

/-- The discrete functor induced by a composition of maps can be written as a
composition of two discrete functors.
-/
```

-- snippet 14
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.functorComp (L194-L201)
def functorComp {I : Type u₁} {J : Type u₁'} (f : J → C) (g : I → J) :
    Discrete.functor (f ∘ g) ≅ Discrete.functor (Discrete.mk ∘ g) ⋙ Discrete.functor f :=
NatIso.ofComponents fun _ => Iso.refl _

/-- For functors out of a discrete category,
a natural transformation is just a collection of maps,
as the naturality squares are trivial.
-/
```

-- snippet 15
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.natTrans (L203-L215)
def natTrans {I : Type u₁} {F G : Discrete I ⥤ C} (f : ∀ i : Discrete I, F.obj i ⟶ G.obj i) :
    F ⟶ G where
  app := f
naturality := fun {X Y} ⟨⟨g⟩⟩ => by
    discrete_cases
    rcases g
    change F.map (𝟙 _) ≫ _ = _ ≫ G.map (𝟙 _)
    simp

/-- For functors out of a discrete category,
a natural isomorphism is just a collection of isomorphisms,
as the naturality squares are trivial.
-/
```

-- snippet 16
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.natIso (L217-L224)
def natIso {I : Type u₁} {F G : Discrete I ⥤ C} (f : ∀ i : Discrete I, F.obj i ≅ G.obj i) :
    F ≅ G :=
NatIso.ofComponents f fun ⟨⟨g⟩⟩ => by
    discrete_cases
    rcases g
    change F.map (𝟙 _) ≫ _ = _ ≫ G.map (𝟙 _)
    simp
```

-- snippet 17
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.natIso_app (L231-L235)
theorem natIso_app {I : Type u₁} {F G : Discrete I ⥤ C} (f : ∀ i : Discrete I, F.obj i ≅ G.obj i)
    (i : Discrete I) : (Discrete.natIso f).app i = f i := by cat_disch
/-- Every functor `F` from a discrete category is naturally isomorphic (actually, equal) to
  `Discrete.functor (F.obj)`. -/
```

-- snippet 18
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.natIsoFunctor (L237-L240)
def natIsoFunctor {I : Type u₁} {F : Discrete I ⥤ C} : F ≅ Discrete.functor (F.obj ∘ Discrete.mk) :=
natIso fun _ => Iso.refl _

/-- Composing `Discrete.functor F` with another functor `G` amounts to composing `F` with `G.obj` -/
```

-- snippet 19
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.compNatIsoDiscrete (L242-L248)
def compNatIsoDiscrete {I : Type u₁} {D : Type u₃} [Category.{v₃} D] (F : I → C) (G : C ⥤ D) :
    Discrete.functor F ⋙ G ≅ Discrete.functor (G.obj ∘ F) :=
natIso fun _ => Iso.refl _

/-- We can promote a type-level `Equiv` to
an equivalence between the corresponding `discrete` categories.
-/
```

-- snippet 20
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.equivalence (L250-L258)
def equivalence {I : Type u₁} {J : Type u₂} (e : I ≃ J) : Discrete I ≌ Discrete J where
  functor := Discrete.functor (Discrete.mk ∘ (e : I → J))
inverse := Discrete.functor (Discrete.mk ∘ (e.symm : J → I))
  unitIso :=
    Discrete.natIso fun i => eqToIso (by simp)
  counitIso :=
    Discrete.natIso fun j => eqToIso (by simp)

/-- We can convert an equivalence of `discrete` categories to a type-level `Equiv`. -/
```

-- snippet 21
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.equivOfEquivalence (L260-L274)
def equivOfEquivalence {α : Type u₁} {β : Type u₂} (h : Discrete α ≌ Discrete β) : α ≃ β where
  toFun := Discrete.as ∘ h.functor.obj ∘ Discrete.mk
invFun := Discrete.as ∘ h.inverse.obj ∘ Discrete.mk
  left_inv a := by simpa using eq_of_hom (h.unitIso.app (Discrete.mk a)).2
  right_inv a := by simpa using eq_of_hom (h.counitIso.app (Discrete.mk a)).1

end Discrete

namespace Discrete

variable {J : Type v₁}

open Opposite

/-- A discrete category is equivalent to its opposite category. -/
```

-- snippet 22
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.functor_map_id (L286-L293)
theorem functor_map_id (F : Discrete J ⥤ C) {j : Discrete J} (f : j ⟶ j) :
    F.map f = 𝟙 (F.obj j) := by
have h : f = 𝟙 j := by cat_disch
  rw [h]
  simp

end Discrete
```

-- snippet 23
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.Discrete (L295-L299)
lemma Discrete.forall {α : Type*} {p : Discrete α → Prop} :
    (∀ (a : Discrete α), p a) ↔ ∀ (a' : α), p ⟨a'⟩ := by
rw [iff_iff_eq, discreteEquiv.forall_congr_left]
  simp [discreteEquiv]
```

-- snippet 24
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.Discrete (L301-L306)
lemma Discrete.exists {α : Type*} {p : Discrete α → Prop} :
    (∃ (a : Discrete α), p a) ↔ ∃ (a' : α), p ⟨a'⟩ := by
rw [iff_iff_eq, discreteEquiv.exists_congr_left]
  simp [discreteEquiv]

/-- The equivalence of categories `(J → C) ≌ (Discrete J ⥤ C)`. -/
```

-- snippet 25
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.piEquivalenceFunctorDiscrete (L308-L329)
def piEquivalenceFunctorDiscrete (J : Type u₂) (C : Type u₁) [Category.{v₁} C] :
    (J → C) ≌ (Discrete J ⥤ C) where
  functor :=
{ obj := fun F => Discrete.functor F
      map := fun f => Discrete.natTrans (fun j => f j.as) }
  inverse :=
    { obj := fun F j => F.obj ⟨j⟩
      map := fun f j => f.app ⟨j⟩ }
  unitIso := Iso.refl _
  counitIso := NatIso.ofComponents (fun F => (NatIso.ofComponents (fun _ => Iso.refl _)
    (by
      rintro ⟨x⟩ ⟨y⟩ f
      obtain rfl : x = y := Discrete.eq_of_hom f
      obtain rfl : f = 𝟙 _ := rfl
      simp))) (by cat_disch)

/-- A category is discrete when there is at most one morphism between two objects,
in which case they are equal. -/
class IsDiscrete (C : Type*) [Category* C] : Prop where
  subsingleton (X Y : C) : Subsingleton (X ⟶ Y) := by infer_instance
  eq_of_hom {X Y : C} (f : X ⟶ Y) : X = Y
```

-- snippet 26
```lean
-- Mathlib.CategoryTheory.Discrete.StructuredArrow.costructuredArrowEquivalenceOfUnique (L46-L57)
def costructuredArrowEquivalenceOfUnique
    (F : C ⥤ Discrete T) (t : T) [Subsingleton T] :
    CostructuredArrow F (.mk t) ≌ C where
  functor := CostructuredArrow.proj _ _
inverse.obj X := CostructuredArrow.mk (Y := X) (eqToHom (by subsingleton))
  inverse.map f := CostructuredArrow.homMk f
  unitIso := NatIso.ofComponents (fun _ ↦ CostructuredArrow.isoMk (Iso.refl _))
  counitIso := Iso.refl _

end Discrete

end CategoryTheory
```

-- snippet 27
```lean
-- Mathlib.CategoryTheory.Discrete.SumsProducts.sumEquiv (L49-L71)
def sumEquiv {J K : Type*} : Discrete (J ⊕ K) ≌ Discrete J ⊕ Discrete K where
  functor := Discrete.functor <| fun t ↦
match t with
    | .inl j => Sum.inl (Discrete.mk j)
    | .inr k => Sum.inr (Discrete.mk k)
  inverse := (Discrete.functor <| fun t ↦ Discrete.mk (Sum.inl t)).sum'
    (Discrete.functor <| fun t ↦ Discrete.mk (Sum.inr t))
  unitIso := NatIso.ofComponents (fun ⟨x⟩ ↦
    match x with
    | .inl x => Iso.refl _
    | .inr x => Iso.refl _)
  counitIso := Functor.sumIsoExt
    (Discrete.natIso <| fun _ ↦ Iso.refl _)
    (Discrete.natIso <| fun _ ↦ Iso.refl _)

end Discrete

namespace IsDiscrete

variable (C C' : Type*) [Category* C] [Category* C'] (D : Type*) [Category* D]
  [IsDiscrete C] [IsDiscrete C'] [IsDiscrete D]

/-- A product of discrete categories is discrete. -/
```

-- snippet 28
```lean
-- Mathlib.CategoryTheory.Discrete.StructuredArrow.structuredArrowEquivalenceOfUnique (L34-L45)
def structuredArrowEquivalenceOfUnique
    (F : C ⥤ Discrete T) (t : T) [Subsingleton T] :
    StructuredArrow (.mk t) F ≌ C where
  functor := StructuredArrow.proj _ _
inverse.obj X := StructuredArrow.mk (Y := X) (eqToHom (by subsingleton))
  inverse.map f := StructuredArrow.homMk f
  unitIso := NatIso.ofComponents (fun _ ↦ StructuredArrow.isoMk (Iso.refl _))
  counitIso := Iso.refl _

/-- If `F : C ⥤ Discrete T` is a functor with `T` containing
a unique element `t`, then this is the equivalence
`CostructuredArrow F (Discrete.mk t) ≌ C`. -/
```

-- snippet 29
```lean
-- Mathlib.CategoryTheory.Discrete.SumsProducts.productEquiv (L38-L47)
def productEquiv {J K : Type*} : Discrete (J × K) ≌ Discrete J × Discrete K where
  functor := Discrete.functor <| fun ⟨j, k⟩ ↦ ⟨.mk j, .mk k⟩
inverse := {
    obj := fun ⟨x, y⟩ ↦ .mk (⟨x.as, y.as⟩)
    map := fun ⟨f₁, f₂⟩ ↦ eqToHom (by discrete_cases; dsimp; rw [f₁, f₂]) }
  unitIso := NatIso.ofComponents (fun _ ↦ Iso.refl _)
  counitIso := NatIso.ofComponents (fun _ ↦ Iso.refl _)

/-- The discrete category on a sum is equivalent to the sum of the
discrete categories. -/
```

-- snippet 30
```lean
-- Mathlib.CategoryTheory.Discrete.SumsProducts.sum (L77-L88)
instance sum : IsDiscrete (C ⊕ C') where
  subsingleton x y :=
{ allEq f g := by
        cases f <;> cases g
        · case inl x y f g => rw [((by assumption : IsDiscrete C).subsingleton x y).allEq f g]
        · case inr x y f g => rw [((by assumption : IsDiscrete C').subsingleton x y).allEq f g] }
  eq_of_hom {x y} f := by
    cases f with
    | inl x y f => rw [(by assumption : IsDiscrete C).eq_of_hom f]
    | inr x y f => rw [(by assumption : IsDiscrete C').eq_of_hom f]

end CategoryTheory.IsDiscrete
```

-- snippet 31
```lean
-- Mathlib.CategoryTheory.Discrete.SumsProducts.prod (L72-L76)
instance prod : IsDiscrete (C × D) where
  subsingleton x y := inferInstanceAs (Subsingleton ((x.1 ⟶ y.1) × (x.2 ⟶ y.2)))
eq_of_hom f := Prod.ext (IsDiscrete.eq_of_hom f.1) (IsDiscrete.eq_of_hom f.2)

/-- A product of discrete categories is discrete. -/
```

<s>[SYSTEM_PROMPT]You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.CategoryTheory.Discrete.Basic).[/SYSTEM_PROMPT][MODEL_SETTINGS]{"reasoning_effort": "none"}[/MODEL_SETTINGS][INST]Prove the following theorem. The retrieved context below may help.

```lean
theorem eq_of_hom {X Y : Discrete α} (i : X ⟶ Y) : X.as = Y.as
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.Discrete (L56-L59)
theorem Discrete.mk_as {α : Type u₁} (X : Discrete α) : Discrete.mk X.as = X :=
rfl

/-- `Discrete α` is equivalent to the original type `α`. -/
```

-- snippet 2
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.discreteEquiv (L61-L66)
def discreteEquiv {α : Type u₁} : Discrete α ≃ α where
  toFun := Discrete.as
invFun := Discrete.mk
  left_inv := by cat_disch
  right_inv := by cat_disch
```

-- snippet 3
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.discreteCategory (L75-L88)
instance discreteCategory (α : Type u₁) : SmallCategory (Discrete α) where
  Hom X Y := ULift (PLift (X.as = Y.as))
id _ := ULift.up (PLift.up rfl)
  comp {X Y Z} g f := by
    cases X
    cases Y
    cases Z
    rcases f with ⟨⟨⟨⟩⟩⟩
    exact g

namespace Discrete

variable {α : Type u₁}
```

-- snippet 4
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.instSubsingletonDiscreteHom (L95-L105)
instance instSubsingletonDiscreteHom (X Y : Discrete α) : Subsingleton (X ⟶ Y) :=
show Subsingleton (ULift (PLift _)) from inferInstance

/-- A simple tactic to run `cases` on any `Discrete α` hypotheses. -/
macro "discrete_cases" : tactic =>
  `(tactic| fail_if_no_progress casesm* Discrete _, (_ : Discrete _) ⟶ (_ : Discrete _), PLift _)

open Lean Elab Tactic in
/--
Use:
```
```

-- snippet 5
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.eqToHom' (L139-L142)
abbrev eqToHom' {a b : α} (h : a = b) : Discrete.mk a ⟶ Discrete.mk b :=
Discrete.eqToHom h

/-- A variant of `eqToIso` that lifts terms to the discrete category. -/
```

-- snippet 6
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.eqToIso' (L143-L145)
abbrev eqToIso' {a b : α} (h : a = b) : Discrete.mk a ≅ Discrete.mk b :=
Discrete.eqToIso h
```

-- snippet 7
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.id_def (L147-L149)
theorem id_def (X : Discrete α) : ULift.up (PLift.up (Eq.refl X.as)) = 𝟙 X :=
rfl
```

-- snippet 8
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.id_def' (L151-L155)
theorem id_def' (X : α) : ULift.up (PLift.up (Eq.refl X)) = 𝟙 (⟨X⟩ : Discrete α) :=
rfl

variable {C : Type u₂} [Category.{v₂} C]
```

-- snippet 9
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.functor (L163-L169)
def functor {I : Type u₁} (F : I → C) : Discrete I ⥤ C where
  obj := F ∘ Discrete.as
map {X Y} f := by
    dsimp
    rcases f with ⟨⟨h⟩⟩
    exact eqToHom (congrArg _ h)
```

-- snippet 10
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.functor_obj (L171-L174)
theorem functor_obj {I : Type u₁} (F : I → C) (i : I) :
    (Discrete.functor F).obj (Discrete.mk i) = F i :=
rfl
```

-- snippet 11
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.functor_map (L175-L177)
theorem functor_map {I : Type u₁} (F : I → C) {i : Discrete I} (f : i ⟶ i) :
    (Discrete.functor F).map f = 𝟙 (F i.as) := by cat_disch
```

-- snippet 12
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.functor_obj_eq_as (L179-L182)
theorem functor_obj_eq_as {I : Type u₁} (F : I → C) (X : Discrete I) :
    (Discrete.functor F).obj X = F X.as :=
rfl
```

-- snippet 13
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.functor_ext (L184-L192)
lemma functor_ext {I : Type u₁} {G F : Discrete I ⥤ C} (h : (i : I) → G.obj ⟨i⟩ = F.obj ⟨i⟩) :
    G = F := by
fapply Functor.ext
  · intro I; rw [h]
  · intro ⟨X⟩ ⟨Y⟩ ⟨⟨p⟩⟩; simp only at p; induction p; simp

/-- The discrete functor induced by a composition of maps can be written as a
composition of two discrete functors.
-/
```

-- snippet 14
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.functorComp (L194-L201)
def functorComp {I : Type u₁} {J : Type u₁'} (f : J → C) (g : I → J) :
    Discrete.functor (f ∘ g) ≅ Discrete.functor (Discrete.mk ∘ g) ⋙ Discrete.functor f :=
NatIso.ofComponents fun _ => Iso.refl _

/-- For functors out of a discrete category,
a natural transformation is just a collection of maps,
as the naturality squares are trivial.
-/
```

-- snippet 15
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.natTrans (L203-L215)
def natTrans {I : Type u₁} {F G : Discrete I ⥤ C} (f : ∀ i : Discrete I, F.obj i ⟶ G.obj i) :
    F ⟶ G where
  app := f
naturality := fun {X Y} ⟨⟨g⟩⟩ => by
    discrete_cases
    rcases g
    change F.map (𝟙 _) ≫ _ = _ ≫ G.map (𝟙 _)
    simp

/-- For functors out of a discrete category,
a natural isomorphism is just a collection of isomorphisms,
as the naturality squares are trivial.
-/
```

-- snippet 16
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.natIso (L217-L224)
def natIso {I : Type u₁} {F G : Discrete I ⥤ C} (f : ∀ i : Discrete I, F.obj i ≅ G.obj i) :
    F ≅ G :=
NatIso.ofComponents f fun ⟨⟨g⟩⟩ => by
    discrete_cases
    rcases g
    change F.map (𝟙 _) ≫ _ = _ ≫ G.map (𝟙 _)
    simp
```

-- snippet 17
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.natIso_app (L231-L235)
theorem natIso_app {I : Type u₁} {F G : Discrete I ⥤ C} (f : ∀ i : Discrete I, F.obj i ≅ G.obj i)
    (i : Discrete I) : (Discrete.natIso f).app i = f i := by cat_disch
/-- Every functor `F` from a discrete category is naturally isomorphic (actually, equal) to
  `Discrete.functor (F.obj)`. -/
```

-- snippet 18
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.natIsoFunctor (L237-L240)
def natIsoFunctor {I : Type u₁} {F : Discrete I ⥤ C} : F ≅ Discrete.functor (F.obj ∘ Discrete.mk) :=
natIso fun _ => Iso.refl _

/-- Composing `Discrete.functor F` with another functor `G` amounts to composing `F` with `G.obj` -/
```

-- snippet 19
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.compNatIsoDiscrete (L242-L248)
def compNatIsoDiscrete {I : Type u₁} {D : Type u₃} [Category.{v₃} D] (F : I → C) (G : C ⥤ D) :
    Discrete.functor F ⋙ G ≅ Discrete.functor (G.obj ∘ F) :=
natIso fun _ => Iso.refl _

/-- We can promote a type-level `Equiv` to
an equivalence between the corresponding `discrete` categories.
-/
```

-- snippet 20
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.equivalence (L250-L258)
def equivalence {I : Type u₁} {J : Type u₂} (e : I ≃ J) : Discrete I ≌ Discrete J where
  functor := Discrete.functor (Discrete.mk ∘ (e : I → J))
inverse := Discrete.functor (Discrete.mk ∘ (e.symm : J → I))
  unitIso :=
    Discrete.natIso fun i => eqToIso (by simp)
  counitIso :=
    Discrete.natIso fun j => eqToIso (by simp)

/-- We can convert an equivalence of `discrete` categories to a type-level `Equiv`. -/
```

-- snippet 21
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.equivOfEquivalence (L260-L274)
def equivOfEquivalence {α : Type u₁} {β : Type u₂} (h : Discrete α ≌ Discrete β) : α ≃ β where
  toFun := Discrete.as ∘ h.functor.obj ∘ Discrete.mk
invFun := Discrete.as ∘ h.inverse.obj ∘ Discrete.mk
  left_inv a := by simpa using eq_of_hom (h.unitIso.app (Discrete.mk a)).2
  right_inv a := by simpa using eq_of_hom (h.counitIso.app (Discrete.mk a)).1

end Discrete

namespace Discrete

variable {J : Type v₁}

open Opposite

/-- A discrete category is equivalent to its opposite category. -/
```

-- snippet 22
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.functor_map_id (L286-L293)
theorem functor_map_id (F : Discrete J ⥤ C) {j : Discrete J} (f : j ⟶ j) :
    F.map f = 𝟙 (F.obj j) := by
have h : f = 𝟙 j := by cat_disch
  rw [h]
  simp

end Discrete
```

-- snippet 23
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.Discrete (L295-L299)
lemma Discrete.forall {α : Type*} {p : Discrete α → Prop} :
    (∀ (a : Discrete α), p a) ↔ ∀ (a' : α), p ⟨a'⟩ := by
rw [iff_iff_eq, discreteEquiv.forall_congr_left]
  simp [discreteEquiv]
```

-- snippet 24
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.Discrete (L301-L306)
lemma Discrete.exists {α : Type*} {p : Discrete α → Prop} :
    (∃ (a : Discrete α), p a) ↔ ∃ (a' : α), p ⟨a'⟩ := by
rw [iff_iff_eq, discreteEquiv.exists_congr_left]
  simp [discreteEquiv]

/-- The equivalence of categories `(J → C) ≌ (Discrete J ⥤ C)`. -/
```

-- snippet 25
```lean
-- Mathlib.CategoryTheory.Discrete.Basic.piEquivalenceFunctorDiscrete (L308-L329)
def piEquivalenceFunctorDiscrete (J : Type u₂) (C : Type u₁) [Category.{v₁} C] :
    (J → C) ≌ (Discrete J ⥤ C) where
  functor :=
{ obj := fun F => Discrete.functor F
      map := fun f => Discrete.natTrans (fun j => f j.as) }
  inverse :=
    { obj := fun F j => F.obj ⟨j⟩
      map := fun f j => f.app ⟨j⟩ }
  unitIso := Iso.refl _
  counitIso := NatIso.ofComponents (fun F => (NatIso.ofComponents (fun _ => Iso.refl _)
    (by
      rintro ⟨x⟩ ⟨y⟩ f
      obtain rfl : x = y := Discrete.eq_of_hom f
      obtain rfl : f = 𝟙 _ := rfl
      simp))) (by cat_disch)

/-- A category is discrete when there is at most one morphism between two objects,
in which case they are equal. -/
class IsDiscrete (C : Type*) [Category* C] : Prop where
  subsingleton (X Y : C) : Subsingleton (X ⟶ Y) := by infer_instance
  eq_of_hom {X Y : C} (f : X ⟶ Y) : X = Y
```

-- snippet 26
```lean
-- Mathlib.CategoryTheory.Discrete.StructuredArrow.costructuredArrowEquivalenceOfUnique (L46-L57)
def costructuredArrowEquivalenceOfUnique
    (F : C ⥤ Discrete T) (t : T) [Subsingleton T] :
    CostructuredArrow F (.mk t) ≌ C where
  functor := CostructuredArrow.proj _ _
inverse.obj X := CostructuredArrow.mk (Y := X) (eqToHom (by subsingleton))
  inverse.map f := CostructuredArrow.homMk f
  unitIso := NatIso.ofComponents (fun _ ↦ CostructuredArrow.isoMk (Iso.refl _))
  counitIso := Iso.refl _

end Discrete

end CategoryTheory
```

-- snippet 27
```lean
-- Mathlib.CategoryTheory.Discrete.SumsProducts.sumEquiv (L49-L71)
def sumEquiv {J K : Type*} : Discrete (J ⊕ K) ≌ Discrete J ⊕ Discrete K where
  functor := Discrete.functor <| fun t ↦
match t with
    | .inl j => Sum.inl (Discrete.mk j)
    | .inr k => Sum.inr (Discrete.mk k)
  inverse := (Discrete.functor <| fun t ↦ Discrete.mk (Sum.inl t)).sum'
    (Discrete.functor <| fun t ↦ Discrete.mk (Sum.inr t))
  unitIso := NatIso.ofComponents (fun ⟨x⟩ ↦
    match x with
    | .inl x => Iso.refl _
    | .inr x => Iso.refl _)
  counitIso := Functor.sumIsoExt
    (Discrete.natIso <| fun _ ↦ Iso.refl _)
    (Discrete.natIso <| fun _ ↦ Iso.refl _)

end Discrete

namespace IsDiscrete

variable (C C' : Type*) [Category* C] [Category* C'] (D : Type*) [Category* D]
  [IsDiscrete C] [IsDiscrete C'] [IsDiscrete D]

/-- A product of discrete categories is discrete. -/
```

-- snippet 28
```lean
-- Mathlib.CategoryTheory.Discrete.StructuredArrow.structuredArrowEquivalenceOfUnique (L34-L45)
def structuredArrowEquivalenceOfUnique
    (F : C ⥤ Discrete T) (t : T) [Subsingleton T] :
    StructuredArrow (.mk t) F ≌ C where
  functor := StructuredArrow.proj _ _
inverse.obj X := StructuredArrow.mk (Y := X) (eqToHom (by subsingleton))
  inverse.map f := StructuredArrow.homMk f
  unitIso := NatIso.ofComponents (fun _ ↦ StructuredArrow.isoMk (Iso.refl _))
  counitIso := Iso.refl _

/-- If `F : C ⥤ Discrete T` is a functor with `T` containing
a unique element `t`, then this is the equivalence
`CostructuredArrow F (Discrete.mk t) ≌ C`. -/
```

-- snippet 29
```lean
-- Mathlib.CategoryTheory.Discrete.SumsProducts.productEquiv (L38-L47)
def productEquiv {J K : Type*} : Discrete (J × K) ≌ Discrete J × Discrete K where
  functor := Discrete.functor <| fun ⟨j, k⟩ ↦ ⟨.mk j, .mk k⟩
inverse := {
    obj := fun ⟨x, y⟩ ↦ .mk (⟨x.as, y.as⟩)
    map := fun ⟨f₁, f₂⟩ ↦ eqToHom (by discrete_cases; dsimp; rw [f₁, f₂]) }
  unitIso := NatIso.ofComponents (fun _ ↦ Iso.refl _)
  counitIso := NatIso.ofComponents (fun _ ↦ Iso.refl _)

/-- The discrete category on a sum is equivalent to the sum of the
discrete categories. -/
```

-- snippet 30
```lean
-- Mathlib.CategoryTheory.Discrete.SumsProducts.sum (L77-L88)
instance sum : IsDiscrete (C ⊕ C') where
  subsingleton x y :=
{ allEq f g := by
        cases f <;> cases g
        · case inl x y f g => rw [((by assumption : IsDiscrete C).subsingleton x y).allEq f g]
        · case inr x y f g => rw [((by assumption : IsDiscrete C').subsingleton x y).allEq f g] }
  eq_of_hom {x y} f := by
    cases f with
    | inl x y f => rw [(by assumption : IsDiscrete C).eq_of_hom f]
    | inr x y f => rw [(by assumption : IsDiscrete C').eq_of_hom f]

end CategoryTheory.IsDiscrete
```

-- snippet 31
```lean
-- Mathlib.CategoryTheory.Discrete.SumsProducts.prod (L72-L76)
instance prod : IsDiscrete (C × D) where
  subsingleton x y := inferInstanceAs (Subsingleton ((x.1 ⟶ y.1) × (x.2 ⟶ y.2)))
eq_of_hom f := Prod.ext (IsDiscrete.eq_of_hom f.1) (IsDiscrete.eq_of_hom f.2)

/-- A product of discrete categories is discrete. -/
```
[/INST]


[System] You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.CategoryTheory.Adjunction.Reflective).

[User]
You are editing a file in `Mathlib/CategoryTheory/Adjunction/Reflective.lean` (mathlib commit 5e932f97dd25535344f80f9dd8da3aab83df0fe6).

## Current excerpt (around `Mathlib.CategoryTheory.Adjunction.Reflective.unitCompPartialBijective_symm_natural`, L148-L152)
```lean
theorem unitCompPartialBijective_symm_natural [Reflective i] (A : C) {B B' : C} (h : B ⟶ B')
    (hB : i.essImage B) (hB' : i.essImage B') (f : i.obj ((reflector i).obj A) ⟶ B) :
    (unitCompPartialBijective A hB').symm (f ≫ h) = (unitCompPartialBijective A hB).symm f ≫ h := by
simp
```

## Edit instruction
Edit `unitCompPartialBijective_symm_natural` so it still compiles and the proof is simplified where possible. Return the full updated `unitCompPartialBijective_symm_natural` block.

<s>[SYSTEM_PROMPT]You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.CategoryTheory.Adjunction.Reflective).[/SYSTEM_PROMPT][MODEL_SETTINGS]{"reasoning_effort": "none"}[/MODEL_SETTINGS][INST]You are editing a file in `Mathlib/CategoryTheory/Adjunction/Reflective.lean` (mathlib commit 5e932f97dd25535344f80f9dd8da3aab83df0fe6).

## Current excerpt (around `Mathlib.CategoryTheory.Adjunction.Reflective.unitCompPartialBijective_symm_natural`, L148-L152)
```lean
theorem unitCompPartialBijective_symm_natural [Reflective i] (A : C) {B B' : C} (h : B ⟶ B')
    (hB : i.essImage B) (hB' : i.essImage B') (f : i.obj ((reflector i).obj A) ⟶ B) :
    (unitCompPartialBijective A hB').symm (f ≫ h) = (unitCompPartialBijective A hB).symm f ≫ h := by
simp
```

## Edit instruction
Edit `unitCompPartialBijective_symm_natural` so it still compiles and the proof is simplified where possible. Return the full updated `unitCompPartialBijective_symm_natural` block.
[/INST]


[System] You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.CategoryTheory.Limits.Shapes.Opposites.Products).

[User]
You are editing a file in `Mathlib/CategoryTheory/Limits/Shapes/Opposites/Products.lean` (mathlib commit 5e932f97dd25535344f80f9dd8da3aab83df0fe6).

## Current excerpt (around `Mathlib.CategoryTheory.Limits.Shapes.Opposites.Products.opProductIsoCoproduct'`, L228-L236)
```lean
def opProductIsoCoproduct' {f : Fan Z} {c : Cofan (op <| Z ·)}
    (hf : IsLimit f) (hc : IsColimit c) : op f.pt ≅ c.pt := IsColimit.coconePointUniqueUpToIso (Fan.IsLimit.op hf) hc

variable (Z) in
/--
The canonical isomorphism from the opposite of the product to the coproduct in the opposite
category.
-/
```

## Edit instruction
Edit `opProductIsoCoproduct'` so it still compiles and the proof is simplified where possible. Return the full updated `opProductIsoCoproduct'` block.

<s>[SYSTEM_PROMPT]You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.CategoryTheory.Limits.Shapes.Opposites.Products).[/SYSTEM_PROMPT][MODEL_SETTINGS]{"reasoning_effort": "none"}[/MODEL_SETTINGS][INST]You are editing a file in `Mathlib/CategoryTheory/Limits/Shapes/Opposites/Products.lean` (mathlib commit 5e932f97dd25535344f80f9dd8da3aab83df0fe6).

## Current excerpt (around `Mathlib.CategoryTheory.Limits.Shapes.Opposites.Products.opProductIsoCoproduct'`, L228-L236)
```lean
def opProductIsoCoproduct' {f : Fan Z} {c : Cofan (op <| Z ·)}
    (hf : IsLimit f) (hc : IsColimit c) : op f.pt ≅ c.pt := IsColimit.coconePointUniqueUpToIso (Fan.IsLimit.op hf) hc

variable (Z) in
/--
The canonical isomorphism from the opposite of the product to the coproduct in the opposite
category.
-/
```

## Edit instruction
Edit `opProductIsoCoproduct'` so it still compiles and the proof is simplified where possible. Return the full updated `opProductIsoCoproduct'` block.
[/INST]


[System] You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.MeasureTheory.Measure.Decomposition.RadonNikodym).

[User]
You are editing a file in `Mathlib/MeasureTheory/Measure/Decomposition/RadonNikodym.lean` (mathlib commit 5e932f97dd25535344f80f9dd8da3aab83df0fe6).

## Current excerpt (around `Mathlib.MeasureTheory.Measure.Decomposition.RadonNikodym.rnDeriv_eq_zero_ae_singularPart`, L204-L209)
```lean
lemma rnDeriv_eq_zero_ae_singularPart [SigmaFinite μ] [SigmaFinite ν] :
    ∀ᵐ x ∂(ν.singularPart μ), μ.rnDeriv ν x = 0 := by
refine rnDeriv_eq_zero_of_mutuallySingular (mutuallySingular_singularPart ν μ).symm ?_
  exact (Measure.singularPart_le _ _).absolutelyContinuous

/-- Auxiliary lemma for `rnDeriv_add_right_of_mutuallySingular`. -/
```

## Edit instruction
Edit `rnDeriv_eq_zero_ae_singularPart` so it still compiles and the proof is simplified where possible. Return the full updated `rnDeriv_eq_zero_ae_singularPart` block.

<s>[SYSTEM_PROMPT]You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.MeasureTheory.Measure.Decomposition.RadonNikodym).[/SYSTEM_PROMPT][MODEL_SETTINGS]{"reasoning_effort": "none"}[/MODEL_SETTINGS][INST]You are editing a file in `Mathlib/MeasureTheory/Measure/Decomposition/RadonNikodym.lean` (mathlib commit 5e932f97dd25535344f80f9dd8da3aab83df0fe6).

## Current excerpt (around `Mathlib.MeasureTheory.Measure.Decomposition.RadonNikodym.rnDeriv_eq_zero_ae_singularPart`, L204-L209)
```lean
lemma rnDeriv_eq_zero_ae_singularPart [SigmaFinite μ] [SigmaFinite ν] :
    ∀ᵐ x ∂(ν.singularPart μ), μ.rnDeriv ν x = 0 := by
refine rnDeriv_eq_zero_of_mutuallySingular (mutuallySingular_singularPart ν μ).symm ?_
  exact (Measure.singularPart_le _ _).absolutelyContinuous

/-- Auxiliary lemma for `rnDeriv_add_right_of_mutuallySingular`. -/
```

## Edit instruction
Edit `rnDeriv_eq_zero_ae_singularPart` so it still compiles and the proof is simplified where possible. Return the full updated `rnDeriv_eq_zero_ae_singularPart` block.
[/INST]


[System] You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.MeasureTheory.Measure.MeasureSpace).

[User]
You are editing a file in `Mathlib/MeasureTheory/Measure/MeasureSpace.lean` (mathlib commit 5e932f97dd25535344f80f9dd8da3aab83df0fe6).

## Current excerpt (around `Mathlib.MeasureTheory.Measure.MeasureSpace.measure_diff_add_inter`, L121-L123)
```lean
theorem measure_diff_add_inter (s : Set α) (ht : MeasurableSet t) : μ (s \ t) + μ (s ∩ t) = μ s := (add_comm _ _).trans (measure_inter_add_diff s ht)
```

## Edit instruction
Edit `measure_diff_add_inter` so it still compiles and the proof is simplified where possible. Return the full updated `measure_diff_add_inter` block.

<s>[SYSTEM_PROMPT]You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.MeasureTheory.Measure.MeasureSpace).[/SYSTEM_PROMPT][MODEL_SETTINGS]{"reasoning_effort": "none"}[/MODEL_SETTINGS][INST]You are editing a file in `Mathlib/MeasureTheory/Measure/MeasureSpace.lean` (mathlib commit 5e932f97dd25535344f80f9dd8da3aab83df0fe6).

## Current excerpt (around `Mathlib.MeasureTheory.Measure.MeasureSpace.measure_diff_add_inter`, L121-L123)
```lean
theorem measure_diff_add_inter (s : Set α) (ht : MeasurableSet t) : μ (s \ t) + μ (s ∩ t) = μ s := (add_comm _ _).trans (measure_inter_add_diff s ht)
```

## Edit instruction
Edit `measure_diff_add_inter` so it still compiles and the proof is simplified where possible. Return the full updated `measure_diff_add_inter` block.
[/INST]


[System] You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.CategoryTheory.Limits.HasLimits).

[User]
You are editing a file in `Mathlib/CategoryTheory/Limits/HasLimits.lean` (mathlib commit 5e932f97dd25535344f80f9dd8da3aab83df0fe6).

## Current excerpt (around `Mathlib.CategoryTheory.Limits.HasLimits.limMap_mono'`, L545-L547)
```lean
instance limMap_mono' {F G : J ⥤ C} [HasLimitsOfShape J C] (α : F ⟶ G) [Mono α] : Mono (limMap α) := (lim : (J ⥤ C) ⥤ C).map_mono α
```

## Edit instruction
Edit `limMap_mono'` so it still compiles and the proof is simplified where possible. Return the full updated `limMap_mono'` block.

<s>[SYSTEM_PROMPT]You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.CategoryTheory.Limits.HasLimits).[/SYSTEM_PROMPT][MODEL_SETTINGS]{"reasoning_effort": "none"}[/MODEL_SETTINGS][INST]You are editing a file in `Mathlib/CategoryTheory/Limits/HasLimits.lean` (mathlib commit 5e932f97dd25535344f80f9dd8da3aab83df0fe6).

## Current excerpt (around `Mathlib.CategoryTheory.Limits.HasLimits.limMap_mono'`, L545-L547)
```lean
instance limMap_mono' {F G : J ⥤ C} [HasLimitsOfShape J C] (α : F ⟶ G) [Mono α] : Mono (limMap α) := (lim : (J ⥤ C) ⥤ C).map_mono α
```

## Edit instruction
Edit `limMap_mono'` so it still compiles and the proof is simplified where possible. Return the full updated `limMap_mono'` block.
[/INST]