doc-next-gen

Mathlib.Data.FunLike.Equiv

Module docstring

{"# Typeclass for a type F with an injective map to A ≃ B

This typeclass is primarily for use by isomorphisms like MonoidEquiv and LinearEquiv.

Basic usage of EquivLike

A typical type of isomorphisms should be declared as: ``` structure MyIso (A B : Type*) [MyClass A] [MyClass B] extends Equiv A B where (map_op' : ∀ (x y : A), toFun (MyClass.op x y) = MyClass.op (toFun x) (toFun y))

namespace MyIso

variable (A B : Type*) [MyClass A] [MyClass B]

instance instEquivLike : EquivLike (MyIso A B) A B where coe f := f.toFun inv f := f.invFun leftinv f := f.leftinv rightinv f := f.rightinv coeinjective' f g h₁ h₂ := by cases f; cases g; congr; exact EquivLike.coeinjective' _ _ h₁ h₂

@[ext] theorem ext {f g : MyIso A B} (h : ∀ x, f x = g x) : f = g := DFunLike.ext f g h

/-- Copy of a MyIso with a new toFun equal to the old one. Useful to fix definitional equalities. -/ protected def copy (f : MyIso A B) (f' : A → B) (finv : B → A) (h₁ : f' = f) (h₂ : finv = f.invFun) : MyIso A B where toFun := f' invFun := finv leftinv := h₁.symm ▸ h₂.symm ▸ f.leftinv rightinv := h₁.symm ▸ h₂.symm ▸ f.rightinv mapop' := h₁.symm ▸ f.map_op'

end MyIso ```

This file will then provide a CoeFun instance and various extensionality and simp lemmas.

Isomorphism classes extending EquivLike

The EquivLike design provides further benefits if you put in a bit more work. The first step is to extend EquivLike to create a class of those types satisfying the axioms of your new type of isomorphisms. Continuing the example above:

`` /--MyIsoClass F A Bstates thatFis a type ofMyClass.op-preserving morphisms. You should extend this class when you extendMyIso`. -/ class MyIsoClass (F : Type) (A B : outParam Type) [MyClass A] [MyClass B] [EquivLike F A B] extends MyHomClass F A B

namespace MyIso

variable {A B : Type*} [MyClass A] [MyClass B]

-- This goes after MyIsoClass.instEquivLike: instance : MyIsoClass (MyIso A B) A B where mapop := MyIso.mapop'

-- [Insert ext and copy here]

end MyIso ```

The second step is to add instances of your new MyIsoClass for all types extending MyIso. Typically, you can just declare a new class analogous to MyIsoClass:

``` structure CoolerIso (A B : Type*) [CoolClass A] [CoolClass B] extends MyIso A B where (map_cool' : toFun CoolClass.cool = CoolClass.cool)

class CoolerIsoClass (F : Type) (A B : outParam Type) [CoolClass A] [CoolClass B] [EquivLike F A B] extends MyIsoClass F A B where (map_cool : ∀ (f : F), f CoolClass.cool = CoolClass.cool)

@[simp] lemma mapcool {F A B : Type*} [CoolClass A] [CoolClass B] [EquivLike F A B] [CoolerIsoClass F A B] (f : F) : f CoolClass.cool = CoolClass.cool := CoolerIsoClass.mapcool _

namespace CoolerIso

variable {A B : Type*} [CoolClass A] [CoolClass B]

instance : EquivLike (CoolerIso A B) A B where coe f := f.toFun inv f := f.invFun leftinv f := f.leftinv rightinv f := f.rightinv coeinjective' f g h₁ h₂ := by cases f; cases g; congr; exact EquivLike.coeinjective' _ _ h₁ h₂

instance : CoolerIsoClass (CoolerIso A B) A B where mapop f := f.mapop' mapcool f := f.mapcool'

-- [Insert ext and copy here]

end CoolerIso ```

Then any declaration taking a specific type of morphisms as parameter can instead take the class you just defined: -- Compare with: lemma do_something (f : MyIso A B) : sorry := sorry lemma do_something {F : Type*} [EquivLike F A B] [MyIsoClass F A B] (f : F) : sorry := sorry

This means anything set up for MyIsos will automatically work for CoolerIsoClasses, and defining CoolerIsoClass only takes a constant amount of effort, instead of linearly increasing the work per MyIso-related declaration.

"}

EquivLike structure
(E : Sort*) (α β : outParam (Sort*))
Full source
/-- The class `EquivLike E α β` expresses that terms of type `E` have an
injective coercion to bijections between `α` and `β`.

Note that this does not directly extend `FunLike`, nor take `FunLike` as a parameter,
so we can state `coe_injective'` in a nicer way.

This typeclass is used in the definition of the isomorphism (or equivalence) typeclasses,
such as `ZeroEquivClass`, `MulEquivClass`, `MonoidEquivClass`, ....
-/
class EquivLike (E : Sort*) (α β : outParam (Sort*)) where
  /-- The coercion to a function in the forward direction. -/
  coe : E → α → β
  /-- The coercion to a function in the backwards direction. -/
  inv : E → β → α
  /-- The coercions are left inverses. -/
  left_inv : ∀ e, Function.LeftInverse (inv e) (coe e)
  /-- The coercions are right inverses. -/
  right_inv : ∀ e, Function.RightInverse (inv e) (coe e)
  /-- The two coercions to functions are jointly injective. -/
  coe_injective' : ∀ e g, coe e = coe g → inv e = inv g → e = g
Equivalence-like class for bijective coercions
Informal description
The class `EquivLike E α β` expresses that terms of type `E` can be injectively coerced to bijections between types `α` and `β`. This class is used as a foundation for defining various isomorphism and equivalence typeclasses, such as `ZeroEquivClass`, `MulEquivClass`, and `MonoidEquivClass`.
EquivLike.inv_injective theorem
: Function.Injective (EquivLike.inv : E → β → α)
Full source
theorem inv_injective : Function.Injective (EquivLike.inv : E → β → α) := fun e g h ↦
  coe_injective' e g ((right_inv e).eq_rightInverse (h.symmleft_inv g)) h
Injectivity of Inverse Function in EquivLike Types
Informal description
For any type `E` that is an instance of `EquivLike` with parameters `α` and `β`, the function `EquivLike.inv` mapping elements of `E` to their inverse functions (from `β` to `α`) is injective. That is, if two elements of `E` have the same inverse function, then they must be equal.
EquivLike.toFunLike instance
: FunLike E α β
Full source
instance (priority := 100) toFunLike : FunLike E α β where
  coe := (coe : E → α → β)
  coe_injective' e g h :=
    coe_injective' e g h ((left_inv e).eq_rightInverse (h.symmright_inv g))
Equivalence-like Types as Function-like Types
Informal description
For any type `E` that is an instance of `EquivLike` with parameters `α` and `β`, there is a canonical `FunLike` instance that allows elements of `E` to be treated as functions from `α` to `β`.
EquivLike.toEmbeddingLike instance
: EmbeddingLike E α β
Full source
instance (priority := 100) toEmbeddingLike : EmbeddingLike E α β where
  injective' e := (left_inv e).injective
Equivalence-like Types as Embedding-like Types
Informal description
For any type `E` that is an instance of `EquivLike` with parameters `α` and `β`, there is a canonical `EmbeddingLike` instance that allows elements of `E` to be treated as injective functions from `α` to `β`.
EquivLike.injective theorem
(e : E) : Function.Injective e
Full source
protected theorem injective (e : E) : Function.Injective e :=
  EmbeddingLike.injective e
Injectivity of EquivLike Elements
Informal description
For any element $e$ of type $E$ in the `EquivLike` class, the function $e : \alpha \to \beta$ is injective.
EquivLike.surjective theorem
(e : E) : Function.Surjective e
Full source
protected theorem surjective (e : E) : Function.Surjective e :=
  (right_inv e).surjective
Surjectivity of EquivLike Elements
Informal description
For any element $e$ of type $E$ in the `EquivLike` class, the function $e : \alpha \to \beta$ is surjective.
EquivLike.bijective theorem
(e : E) : Function.Bijective (e : α → β)
Full source
protected theorem bijective (e : E) : Function.Bijective (e : α → β) :=
  ⟨EquivLike.injective e, EquivLike.surjective e⟩
Bijectivity of EquivLike Elements
Informal description
For any element $e$ of a type $E$ that is an instance of `EquivLike` with parameters $\alpha$ and $\beta$, the function $e : \alpha \to \beta$ is bijective.
EquivLike.apply_eq_iff_eq theorem
(f : E) {x y : α} : f x = f y ↔ x = y
Full source
theorem apply_eq_iff_eq (f : E) {x y : α} : f x = f y ↔ x = y :=
  EmbeddingLike.apply_eq_iff_eq f
Injectivity Criterion for EquivLike Elements: $f(x) = f(y) \leftrightarrow x = y$
Informal description
For any element $f$ of a type $E$ that is an instance of `EquivLike` with parameters $\alpha$ and $\beta$, and for any elements $x, y \in \alpha$, we have $f(x) = f(y)$ if and only if $x = y$.
EquivLike.injective_comp theorem
(e : E) (f : β → γ) : Function.Injective (f ∘ e) ↔ Function.Injective f
Full source
@[simp]
theorem injective_comp (e : E) (f : β → γ) : Function.InjectiveFunction.Injective (f ∘ e) ↔ Function.Injective f :=
  Function.Injective.of_comp_iff' f (EquivLike.bijective e)
Injectivity of Composition with EquivLike Element: $f \circ e$ is injective iff $f$ is injective
Informal description
For any element $e$ of a type $E$ that is an instance of `EquivLike` with parameters $\alpha$ and $\beta$, and for any function $f : \beta \to \gamma$, the composition $f \circ e$ is injective if and only if $f$ is injective.
EquivLike.surjective_comp theorem
(e : E) (f : β → γ) : Function.Surjective (f ∘ e) ↔ Function.Surjective f
Full source
@[simp]
theorem surjective_comp (e : E) (f : β → γ) : Function.SurjectiveFunction.Surjective (f ∘ e) ↔ Function.Surjective f :=
  (EquivLike.surjective e).of_comp_iff f
Surjectivity of Composition with EquivLike Element: $f \circ e$ is surjective iff $f$ is surjective
Informal description
For any element $e$ of a type $E$ that is an instance of `EquivLike` with parameters $\alpha$ and $\beta$, and for any function $f : \beta \to \gamma$, the composition $f \circ e$ is surjective if and only if $f$ is surjective.
EquivLike.bijective_comp theorem
(e : E) (f : β → γ) : Function.Bijective (f ∘ e) ↔ Function.Bijective f
Full source
@[simp]
theorem bijective_comp (e : E) (f : β → γ) : Function.BijectiveFunction.Bijective (f ∘ e) ↔ Function.Bijective f :=
  (EquivLike.bijective e).of_comp_iff f
Bijectivity of Composition with EquivLike Element: $f \circ e$ is bijective iff $f$ is bijective
Informal description
For any element $e$ of a type $E$ that is an instance of `EquivLike` with parameters $\alpha$ and $\beta$, and for any function $f : \beta \to \gamma$, the composition $f \circ e$ is bijective if and only if $f$ is bijective.
EquivLike.inv_apply_apply theorem
(e : E) (a : α) : EquivLike.inv e (e a) = a
Full source
/-- This lemma is only supposed to be used in the generic context, when working with instances
of classes extending `EquivLike`.
For concrete isomorphism types such as `Equiv`, you should use `Equiv.symm_apply_apply`
or its equivalent.

TODO: define a generic form of `Equiv.symm`. -/
@[simp]
theorem inv_apply_apply (e : E) (a : α) : EquivLike.inv e (e a) = a :=
  left_inv _ _
Inverse Application Property for Equivalence-like Types: $e^{-1}(e(a)) = a$
Informal description
For any element $e$ of a type $E$ that is an instance of `EquivLike` with parameters $\alpha$ and $\beta$, and for any element $a \in \alpha$, applying the inverse of $e$ to the result of applying $e$ to $a$ yields $a$ back, i.e., $e^{-1}(e(a)) = a$.
EquivLike.apply_inv_apply theorem
(e : E) (b : β) : e (EquivLike.inv e b) = b
Full source
/-- This lemma is only supposed to be used in the generic context, when working with instances
of classes extending `EquivLike`.
For concrete isomorphism types such as `Equiv`, you should use `Equiv.apply_symm_apply`
or its equivalent.

TODO: define a generic form of `Equiv.symm`. -/
@[simp]
theorem apply_inv_apply (e : E) (b : β) : e (EquivLike.inv e b) = b :=
  right_inv _ _
Inverse Application Property for Equivalence-like Types: $e(e^{-1}(b)) = b$
Informal description
For any element $e$ of a type $E$ that is an instance of `EquivLike` with parameters $\alpha$ and $\beta$, and for any element $b \in \beta$, applying $e$ to the inverse of $e$ at $b$ yields $b$ back, i.e., $e(e^{-1}(b)) = b$.
EquivLike.inv_apply_eq_iff_eq_apply theorem
{e : E} {b : β} {a : α} : (EquivLike.inv e b) = a ↔ b = e a
Full source
lemma inv_apply_eq_iff_eq_apply {e : E} {b : β} {a : α} : (EquivLike.inv e b) = a ↔ b = e a := by
  constructor <;> rintro ⟨_, rfl⟩ <;> simp
Inverse Application Equivalence: $e^{-1}(b) = a \leftrightarrow b = e(a)$
Informal description
For any element $e$ of a type $E$ that is an instance of `EquivLike` with parameters $\alpha$ and $\beta$, and for any elements $a \in \alpha$ and $b \in \beta$, the inverse of $e$ applied to $b$ equals $a$ if and only if $b$ equals $e$ applied to $a$, i.e., $e^{-1}(b) = a \leftrightarrow b = e(a)$.
EquivLike.comp_injective theorem
(f : α → β) (e : F) : Function.Injective (e ∘ f) ↔ Function.Injective f
Full source
theorem comp_injective (f : α → β) (e : F) : Function.InjectiveFunction.Injective (e ∘ f) ↔ Function.Injective f :=
  EmbeddingLike.comp_injective f e
Injectivity Preservation under Composition with Equivalence-like Maps: $e \circ f$ injective $\leftrightarrow$ $f$ injective
Informal description
For any function $f : \alpha \to \beta$ and any element $e$ of a type $F$ that is an instance of `EquivLike` with parameters $\alpha$ and $\beta$, the composition $e \circ f$ is injective if and only if $f$ is injective.
EquivLike.comp_surjective theorem
(f : α → β) (e : F) : Function.Surjective (e ∘ f) ↔ Function.Surjective f
Full source
@[simp]
theorem comp_surjective (f : α → β) (e : F) : Function.SurjectiveFunction.Surjective (e ∘ f) ↔ Function.Surjective f :=
  Function.Surjective.of_comp_iff' (EquivLike.bijective e) f
Surjectivity Preservation under Composition with Equivalence-like Maps: $e \circ f$ surjective $\leftrightarrow$ $f$ surjective
Informal description
For any function $f \colon \alpha \to \beta$ and any element $e$ of a type $F$ that is an instance of `EquivLike` with parameters $\alpha$ and $\beta$, the composition $e \circ f$ is surjective if and only if $f$ is surjective.
EquivLike.comp_bijective theorem
(f : α → β) (e : F) : Function.Bijective (e ∘ f) ↔ Function.Bijective f
Full source
@[simp]
theorem comp_bijective (f : α → β) (e : F) : Function.BijectiveFunction.Bijective (e ∘ f) ↔ Function.Bijective f :=
  (EquivLike.bijective e).of_comp_iff' f
Bijectivity Preservation under Composition with Equivalence-like Maps: $e \circ f$ bijective $\leftrightarrow$ $f$ bijective
Informal description
For any function $f \colon \alpha \to \beta$ and any element $e$ of a type $F$ that is an instance of `EquivLike` with parameters $\alpha$ and $\beta$, the composition $e \circ f$ is bijective if and only if $f$ is bijective.
EquivLike.subsingleton_dom theorem
[FunLike F β γ] [Subsingleton β] : Subsingleton F
Full source
/-- This is not an instance to avoid slowing down every single `Subsingleton` typeclass search. -/
lemma subsingleton_dom [FunLike F β γ] [Subsingleton β] : Subsingleton F :=
  ⟨fun f g ↦ DFunLike.ext f g fun _ ↦ (right_inv f).injective <| Subsingleton.elim _ _⟩
Subsingleton property of function types with subsingleton domain
Informal description
For any type `F` with a `FunLike` instance from `β` to `γ`, if `β` is a subsingleton (i.e., all elements of `β` are equal), then `F` is also a subsingleton.