File: Mathlib/Logic/Equiv/Basic.lean

full_name: Equiv.pprodEquivProd
code: /-- `PProd α β` is equivalent to `α × β` -/
@[simps apply symm_apply]
def pprodEquivProd : PProd α β ≃ α × β 
goal: PProd α β ≃ α × β

full_name: Equiv.pprodEquivProd_symm_apply
code: /-- `PProd α β` is equivalent to `α × β` -/
@[simps apply symm_apply]
def pprodEquivProd : PProd α β ≃ α × β 
goal: Equiv.pprodEquivProd.symm x = ⟨x.1, x.2⟩

full_name: Equiv.pprodEquivProd_apply
code: /-- `PProd α β` is equivalent to `α × β` -/
@[simps apply symm_apply]
def pprodEquivProd : PProd α β ≃ α × β 
goal: Equiv.pprodEquivProd x = (x.fst, x.snd)

full_name: Equiv.pprodCongr
code: /-- Product of two equivalences, in terms of `PProd`. If `α ≃ β` and `γ ≃ δ`, then
`PProd α γ ≃ PProd β δ`. -/
-- Porting note: in Lean 3 this had `@[congr]`
@[simps apply]
def pprodCongr (e₁ : α ≃ β) (e₂ : γ ≃ δ) : PProd α γ ≃ PProd β δ 
goal: PProd α γ ≃ PProd β δ

full_name: Equiv.pprodCongr_apply
code: /-- Product of two equivalences, in terms of `PProd`. If `α ≃ β` and `γ ≃ δ`, then
`PProd α γ ≃ PProd β δ`. -/
-- Porting note: in Lean 3 this had `@[congr]`
@[simps apply]
def pprodCongr (e₁ : α ≃ β) (e₂ : γ ≃ δ) : PProd α γ ≃ PProd β δ 
goal: (e₁.pprodCongr e₂) x = ⟨e₁ x.fst, e₂ x.snd⟩

full_name: Equiv.pprodProd_apply
code: /-- Combine two equivalences using `PProd` in the domain and `Prod` in the codomain. -/
@[simps! apply symm_apply]
def pprodProd (ea : α₁ ≃ α₂) (eb : β₁ ≃ β₂) :
    PProd α₁ β₁ ≃ α₂ × β₂ 
goal: ∀ (a : PProd α₁ β₁), (ea.pprodProd eb) a = (ea a.fst, eb a.snd)

full_name: Equiv.pprodProd
code: /-- Combine two equivalences using `PProd` in the domain and `Prod` in the codomain. -/
@[simps! apply symm_apply]
def pprodProd (ea : α₁ ≃ α₂) (eb : β₁ ≃ β₂) :
    PProd α₁ β₁ ≃ α₂ × β₂ 
goal: PProd α₁ β₁ ≃ α₂ × β₂

full_name: Equiv.pprodProd_symm_apply
code: /-- Combine two equivalences using `PProd` in the domain and `Prod` in the codomain. -/
@[simps! apply symm_apply]
def pprodProd (ea : α₁ ≃ α₂) (eb : β₁ ≃ β₂) :
    PProd α₁ β₁ ≃ α₂ × β₂ 
goal: ∀ (a : α₂ × β₂), (ea.pprodProd eb).symm a = (ea.pprodCongr eb).symm ⟨a.1, a.2⟩

full_name: Equiv.prodPProd_symm_apply
code: /-- Combine two equivalences using `PProd` in the codomain and `Prod` in the domain. -/
@[simps! apply symm_apply]
def prodPProd (ea : α₁ ≃ α₂) (eb : β₁ ≃ β₂) :
    α₁ × β₁ ≃ PProd α₂ β₂ 
goal: ∀ (a : PProd α₂ β₂), (ea.prodPProd eb).symm a = (ea.symm a.fst, eb.symm a.snd)

full_name: Equiv.prodPProd
code: /-- Combine two equivalences using `PProd` in the codomain and `Prod` in the domain. -/
@[simps! apply symm_apply]
def prodPProd (ea : α₁ ≃ α₂) (eb : β₁ ≃ β₂) :
    α₁ × β₁ ≃ PProd α₂ β₂ 
goal: α₁ × β₁ ≃ PProd α₂ β₂

full_name: Equiv.prodPProd_apply
code: /-- Combine two equivalences using `PProd` in the codomain and `Prod` in the domain. -/
@[simps! apply symm_apply]
def prodPProd (ea : α₁ ≃ α₂) (eb : β₁ ≃ β₂) :
    α₁ × β₁ ≃ PProd α₂ β₂ 
goal: ∀ (a : α₁ × β₁), (ea.prodPProd eb) a = (ea.symm.pprodCongr eb.symm).symm ⟨a.1, a.2⟩

full_name: Equiv.pprodEquivProdPLift
code: /-- `PProd α β` is equivalent to `PLift α × PLift β` -/
@[simps! apply symm_apply]
def pprodEquivProdPLift : PProd α β ≃ PLift α × PLift β 
goal: PProd α β ≃ PLift α × PLift β

full_name: Equiv.pprodEquivProdPLift_symm_apply
code: /-- `PProd α β` is equivalent to `PLift α × PLift β` -/
@[simps! apply symm_apply]
def pprodEquivProdPLift : PProd α β ≃ PLift α × PLift β 
goal: ∀ (a : PLift α × PLift β),
  Equiv.pprodEquivProdPLift.symm a = (Equiv.plift.symm.pprodCongr Equiv.plift.symm).symm ⟨a.1, a.2⟩

full_name: Equiv.pprodEquivProdPLift_apply
code: /-- `PProd α β` is equivalent to `PLift α × PLift β` -/
@[simps! apply symm_apply]
def pprodEquivProdPLift : PProd α β ≃ PLift α × PLift β 
goal: ∀ (a : PProd α β), Equiv.pprodEquivProdPLift a = (Equiv.plift.symm a.fst, Equiv.plift.symm a.snd)

full_name: Equiv.prodCongr_apply
code: /-- Product of two equivalences. If `α₁ ≃ α₂` and `β₁ ≃ β₂`, then `α₁ × β₁ ≃ α₂ × β₂`. This is
`Prod.map` as an equivalence. -/
-- Porting note: in Lean 3 there was also a @[congr] tag
@[simps (config := .asFn) apply]
def prodCongr (e₁ : α₁ ≃ α₂) (e₂ : β₁ ≃ β₂) : α₁ × β₁ ≃ α₂ × β₂ 
goal: ⇑(e₁.prodCongr e₂) = Prod.map ⇑e₁ ⇑e₂

full_name: Equiv.prodCongr
code: /-- Product of two equivalences. If `α₁ ≃ α₂` and `β₁ ≃ β₂`, then `α₁ × β₁ ≃ α₂ × β₂`. This is
`Prod.map` as an equivalence. -/
-- Porting note: in Lean 3 there was also a @[congr] tag
@[simps (config := .asFn) apply]
def prodCongr (e₁ : α₁ ≃ α₂) (e₂ : β₁ ≃ β₂) : α₁ × β₁ ≃ α₂ × β₂ 
goal: α₁ × β₁ ≃ α₂ × β₂

full_name: Equiv.prodCongr_symm
code: @[simp]
theorem prodCongr_symm (e₁ : α₁ ≃ α₂) (e₂ : β₁ ≃ β₂) :
    (prodCongr e₁ e₂).symm = prodCongr e₁.symm e₂.symm 
goal: (e₁.prodCongr e₂).symm = e₁.symm.prodCongr e₂.symm

full_name: Equiv.prodComm
code: /-- Type product is commutative up to an equivalence: `α × β ≃ β × α`. This is `Prod.swap` as an
equivalence. -/
def prodComm (α β) : α × β ≃ β × α 
goal: α × β ≃ β × α

full_name: Equiv.coe_prodComm
code: @[simp]
theorem coe_prodComm (α β) : (⇑(prodComm α β) : α × β → β × α) = Prod.swap 
goal: ⇑(Equiv.prodComm α β) = Prod.swap

full_name: Equiv.prodComm_apply
code: @[simp]
theorem prodComm_apply (x : α × β) : prodComm α β x = x.swap 
goal: (Equiv.prodComm α β) x = x.swap

full_name: Equiv.prodComm_symm
code: @[simp]
theorem prodComm_symm (α β) : (prodComm α β).symm = prodComm β α 
goal: (Equiv.prodComm α β).symm = Equiv.prodComm β α

full_name: Equiv.prodAssoc_apply
code: /-- Type product is associative up to an equivalence. -/
@[simps]
def prodAssoc (α β γ) : (α × β) × γ ≃ α × β × γ 
goal: (Equiv.prodAssoc α β γ) p = (p.1.1, p.1.2, p.2)

full_name: Equiv.prodAssoc
code: /-- Type product is associative up to an equivalence. -/
@[simps]
def prodAssoc (α β γ) : (α × β) × γ ≃ α × β × γ 
goal: (α × β) × γ ≃ α × β × γ

full_name: Equiv.prodAssoc_symm_apply
code: /-- Type product is associative up to an equivalence. -/
@[simps]
def prodAssoc (α β γ) : (α × β) × γ ≃ α × β × γ 
goal: (Equiv.prodAssoc α β γ).symm p = ((p.1, p.2.1), p.2.2)

full_name: Equiv.prodProdProdComm
code: /-- Four-way commutativity of `prod`. The name matches `mul_mul_mul_comm`. -/
@[simps apply]
def prodProdProdComm (α β γ δ : Type*) : (α × β) × γ × δ ≃ (α × γ) × β × δ 
goal: (α × β) × γ × δ ≃ (α × γ) × β × δ

full_name: Equiv.prodProdProdComm_apply
code: /-- Four-way commutativity of `prod`. The name matches `mul_mul_mul_comm`. -/
@[simps apply]
def prodProdProdComm (α β γ δ : Type*) : (α × β) × γ × δ ≃ (α × γ) × β × δ 
goal: (Equiv.prodProdProdComm α β γ δ) abcd = ((abcd.1.1, abcd.2.1), abcd.1.2, abcd.2.2)

full_name: Equiv.prodProdProdComm_symm
code: @[simp]
theorem prodProdProdComm_symm (α β γ δ : Type*) :
    (prodProdProdComm α β γ δ).symm = prodProdProdComm α γ β δ 
goal: (Equiv.prodProdProdComm α β γ δ).symm = Equiv.prodProdProdComm α γ β δ

full_name: Equiv.curry_symm_apply
code: /-- `γ`-valued functions on `α × β` are equivalent to functions `α → β → γ`. -/
@[simps (config := .asFn)]
def curry (α β γ) : (α × β → γ) ≃ (α → β → γ) 
goal: ⇑(Equiv.curry α β γ).symm = Function.uncurry

full_name: Equiv.curry
code: /-- `γ`-valued functions on `α × β` are equivalent to functions `α → β → γ`. -/
@[simps (config := .asFn)]
def curry (α β γ) : (α × β → γ) ≃ (α → β → γ) 
goal: (α × β → γ) ≃ (α → β → γ)

full_name: Equiv.curry_apply
code: /-- `γ`-valued functions on `α × β` are equivalent to functions `α → β → γ`. -/
@[simps (config := .asFn)]
def curry (α β γ) : (α × β → γ) ≃ (α → β → γ) 
goal: ⇑(Equiv.curry α β γ) = Function.curry

full_name: Equiv.prodPUnit
code: /-- `PUnit` is a right identity for type product up to an equivalence. -/
@[simps]
def prodPUnit (α) : α × PUnit ≃ α 
goal: α × PUnit.{u_2 + 1} ≃ α

full_name: Equiv.prodPUnit_symm_apply
code: /-- `PUnit` is a right identity for type product up to an equivalence. -/
@[simps]
def prodPUnit (α) : α × PUnit ≃ α 
goal: (Equiv.prodPUnit α).symm a = (a, PUnit.unit)

full_name: Equiv.prodPUnit_apply
code: /-- `PUnit` is a right identity for type product up to an equivalence. -/
@[simps]
def prodPUnit (α) : α × PUnit ≃ α 
goal: (Equiv.prodPUnit α) p = p.1

full_name: Equiv.punitProd
code: /-- `PUnit` is a left identity for type product up to an equivalence. -/
@[simps!]
def punitProd (α) : PUnit × α ≃ α 
goal: PUnit.{u_2 + 1} × α ≃ α

full_name: Equiv.punitProd_symm_apply
code: /-- `PUnit` is a left identity for type product up to an equivalence. -/
@[simps!]
def punitProd (α) : PUnit × α ≃ α 
goal: ∀ (a : α), (Equiv.punitProd α).symm a = (PUnit.unit, a)

full_name: Equiv.punitProd_apply
code: /-- `PUnit` is a left identity for type product up to an equivalence. -/
@[simps!]
def punitProd (α) : PUnit × α ≃ α 
goal: ∀ (a : PUnit.{u_2 + 1} × α), (Equiv.punitProd α) a = a.2

full_name: Equiv.sigmaPUnit_apply
code: /-- `PUnit` is a right identity for dependent type product up to an equivalence. -/
@[simps]
def sigmaPUnit (α) : (_ : α) × PUnit ≃ α 
goal: (Equiv.sigmaPUnit α) p = p.fst

full_name: Equiv.sigmaPUnit_symm_apply_fst
code: /-- `PUnit` is a right identity for dependent type product up to an equivalence. -/
@[simps]
def sigmaPUnit (α) : (_ : α) × PUnit ≃ α 
goal: ((Equiv.sigmaPUnit α).symm a).fst = a

full_name: Equiv.sigmaPUnit
code: /-- `PUnit` is a right identity for dependent type product up to an equivalence. -/
@[simps]
def sigmaPUnit (α) : (_ : α) × PUnit ≃ α 
goal: (_ : α) × PUnit.{u_2 + 1} ≃ α

full_name: Equiv.sigmaPUnit_symm_apply_snd
code: /-- `PUnit` is a right identity for dependent type product up to an equivalence. -/
@[simps]
def sigmaPUnit (α) : (_ : α) × PUnit ≃ α 
goal: ((Equiv.sigmaPUnit α).symm a).snd = PUnit.unit

full_name: Equiv.prodUnique
code: /-- Any `Unique` type is a right identity for type product up to equivalence. -/
def prodUnique (α β) [Unique β] : α × β ≃ α 
goal: α × β ≃ α

full_name: Equiv.coe_prodUnique
code: @[simp]
theorem coe_prodUnique [Unique β] : (⇑(prodUnique α β) : α × β → α) = Prod.fst 
goal: ⇑(Equiv.prodUnique α β) = Prod.fst

full_name: Equiv.prodUnique_apply
code: theorem prodUnique_apply [Unique β] (x : α × β) : prodUnique α β x = x.1 
goal: (Equiv.prodUnique α β) x = x.1

full_name: Equiv.prodUnique_symm_apply
code: @[simp]
theorem prodUnique_symm_apply [Unique β] (x : α) :
    (prodUnique α β).symm x = (x, default) 
goal: (Equiv.prodUnique α β).symm x = (x, default)

full_name: Equiv.uniqueProd
code: /-- Any `Unique` type is a left identity for type product up to equivalence. -/
def uniqueProd (α β) [Unique β] : β × α ≃ α 
goal: β × α ≃ α

full_name: Equiv.coe_uniqueProd
code: @[simp]
theorem coe_uniqueProd [Unique β] : (⇑(uniqueProd α β) : β × α → α) = Prod.snd 
goal: ⇑(Equiv.uniqueProd α β) = Prod.snd

full_name: Equiv.uniqueProd_apply
code: theorem uniqueProd_apply [Unique β] (x : β × α) : uniqueProd α β x = x.2 
goal: (Equiv.uniqueProd α β) x = x.2

full_name: Equiv.uniqueProd_symm_apply
code: @[simp]
theorem uniqueProd_symm_apply [Unique β] (x : α) :
    (uniqueProd α β).symm x = (default, x) 
goal: (Equiv.uniqueProd α β).symm x = (default, x)

full_name: Equiv.sigmaUnique
code: /-- Any family of `Unique` types is a right identity for dependent type product up to
equivalence. -/
def sigmaUnique (α) (β : α → Type*) [∀ a, Unique (β a)] : (a : α) × (β a) ≃ α 
goal: (a : α) × β a ≃ α

full_name: Equiv.coe_sigmaUnique
code: @[simp]
theorem coe_sigmaUnique {β : α → Type*} [∀ a, Unique (β a)] :
    (⇑(sigmaUnique α β) : (a : α) × (β a) → α) = Sigma.fst 
goal: ⇑(Equiv.sigmaUnique α β) = Sigma.fst

full_name: Equiv.sigmaUnique_apply
code: theorem sigmaUnique_apply {β : α → Type*} [∀ a, Unique (β a)] (x : (a : α) × β a) :
    sigmaUnique α β x = x.1 
goal: (Equiv.sigmaUnique α β) x = x.fst

full_name: Equiv.sigmaUnique_symm_apply
code: @[simp]
theorem sigmaUnique_symm_apply {β : α → Type*} [∀ a, Unique (β a)] (x : α) :
    (sigmaUnique α β).symm x = ⟨x, default⟩ 
goal: (Equiv.sigmaUnique α β).symm x = ⟨x, default⟩

full_name: Equiv.prodEmpty
code: /-- `Empty` type is a right absorbing element for type product up to an equivalence. -/
def prodEmpty (α) : α × Empty ≃ Empty 
goal: α × Empty ≃ Empty

full_name: Equiv.emptyProd
code: /-- `Empty` type is a left absorbing element for type product up to an equivalence. -/
def emptyProd (α) : Empty × α ≃ Empty 
goal: Empty × α ≃ Empty

full_name: Equiv.prodPEmpty
code: /-- `PEmpty` type is a right absorbing element for type product up to an equivalence. -/
def prodPEmpty (α) : α × PEmpty ≃ PEmpty 
goal: α × PEmpty.{u_2 + 1} ≃ PEmpty.{u_3}

full_name: Equiv.pemptyProd
code: /-- `PEmpty` type is a left absorbing element for type product up to an equivalence. -/
def pemptyProd (α) : PEmpty × α ≃ PEmpty 
goal: PEmpty.{u_2 + 1} × α ≃ PEmpty.{u_3}

full_name: Equiv.psumEquivSum
code: /-- `PSum` is equivalent to `Sum`. -/
def psumEquivSum (α β) : α ⊕' β ≃ α ⊕ β 
goal: α ⊕' β ≃ α ⊕ β

full_name: Equiv.sumCongr_apply
code: /-- If `α ≃ α'` and `β ≃ β'`, then `α ⊕ β ≃ α' ⊕ β'`. This is `Sum.map` as an equivalence. -/
@[simps apply]
def sumCongr (ea : α₁ ≃ α₂) (eb : β₁ ≃ β₂) : α₁ ⊕ β₁ ≃ α₂ ⊕ β₂ 
goal: ∀ (a : α₁ ⊕ β₁), (ea.sumCongr eb) a = Sum.map (⇑ea) (⇑eb) a

full_name: Equiv.sumCongr
code: /-- If `α ≃ α'` and `β ≃ β'`, then `α ⊕ β ≃ α' ⊕ β'`. This is `Sum.map` as an equivalence. -/
@[simps apply]
def sumCongr (ea : α₁ ≃ α₂) (eb : β₁ ≃ β₂) : α₁ ⊕ β₁ ≃ α₂ ⊕ β₂ 
goal: α₁ ⊕ β₁ ≃ α₂ ⊕ β₂

full_name: Equiv.psumCongr
code: /-- If `α ≃ α'` and `β ≃ β'`, then `α ⊕' β ≃ α' ⊕' β'`. -/
def psumCongr (e₁ : α ≃ β) (e₂ : γ ≃ δ) : α ⊕' γ ≃ β ⊕' δ 
goal: α ⊕' γ ≃ β ⊕' δ

full_name: Equiv.psumSum
code: /-- Combine two `Equiv`s using `PSum` in the domain and `Sum` in the codomain. -/
def psumSum (ea : α₁ ≃ α₂) (eb : β₁ ≃ β₂) :
    α₁ ⊕' β₁ ≃ α₂ ⊕ β₂ 
goal: α₁ ⊕' β₁ ≃ α₂ ⊕ β₂

full_name: Equiv.sumPSum
code: /-- Combine two `Equiv`s using `Sum` in the domain and `PSum` in the codomain. -/
def sumPSum (ea : α₁ ≃ α₂) (eb : β₁ ≃ β₂) :
    α₁ ⊕ β₁ ≃ α₂ ⊕' β₂ 
goal: α₁ ⊕ β₁ ≃ α₂ ⊕' β₂

full_name: Equiv.sumCongr_trans
code: @[simp]
theorem sumCongr_trans (e : α₁ ≃ β₁) (f : α₂ ≃ β₂) (g : β₁ ≃ γ₁) (h : β₂ ≃ γ₂) :
    (Equiv.sumCongr e f).trans (Equiv.sumCongr g h) = Equiv.sumCongr (e.trans g) (f.trans h) 
goal: (e.sumCongr f).trans (g.sumCongr h) = (e.trans g).sumCongr (f.trans h)

full_name: Equiv.sumCongr_symm
code: @[simp]
theorem sumCongr_symm (e : α ≃ β) (f : γ ≃ δ) :
    (Equiv.sumCongr e f).symm = Equiv.sumCongr e.symm f.symm 
goal: (e.sumCongr f).symm = e.symm.sumCongr f.symm

full_name: Equiv.sumCongr_refl
code: @[simp]
theorem sumCongr_refl : Equiv.sumCongr (Equiv.refl α) (Equiv.refl β) = Equiv.refl (α ⊕ β) 
goal: (Equiv.refl α).sumCongr (Equiv.refl β) = Equiv.refl (α ⊕ β)

full_name: Equiv.subtypeSum
code: /-- A subtype of a sum is equivalent to a sum of subtypes. -/
def subtypeSum {p : α ⊕ β → Prop} : {c // p c} ≃ {a // p (Sum.inl a)} ⊕ {b // p (Sum.inr b)} 
goal: { c // p c } ≃ { a // p (Sum.inl a) } ⊕ { b // p (Sum.inr b) }

full_name: Equiv.Perm.sumCongr
code: /-- Combine a permutation of `α` and of `β` into a permutation of `α ⊕ β`. -/
abbrev sumCongr (ea : Equiv.Perm α) (eb : Equiv.Perm β) : Equiv.Perm (α ⊕ β) 
goal: Equiv.Perm (α ⊕ β)

full_name: Equiv.Perm.sumCongr_apply
code: @[simp]
theorem sumCongr_apply (ea : Equiv.Perm α) (eb : Equiv.Perm β) (x : α ⊕ β) :
    sumCongr ea eb x = Sum.map (⇑ea) (⇑eb) x 
goal: (ea.sumCongr eb) x = Sum.map (⇑ea) (⇑eb) x

full_name: Equiv.Perm.sumCongr_trans
code: theorem sumCongr_trans (e : Equiv.Perm α) (f : Equiv.Perm β) (g : Equiv.Perm α)
    (h : Equiv.Perm β) : (sumCongr e f).trans (sumCongr g h) = sumCongr (e.trans g) (f.trans h) 
goal: Equiv.trans (e.sumCongr f) (g.sumCongr h) = Equiv.Perm.sumCongr (Equiv.trans e g) (Equiv.trans f h)

full_name: Equiv.Perm.sumCongr_symm
code: theorem sumCongr_symm (e : Equiv.Perm α) (f : Equiv.Perm β) :
    (sumCongr e f).symm = sumCongr e.symm f.symm 
goal: Equiv.symm (e.sumCongr f) = Equiv.Perm.sumCongr (Equiv.symm e) (Equiv.symm f)

full_name: Equiv.Perm.sumCongr_refl
code: theorem sumCongr_refl : sumCongr (Equiv.refl α) (Equiv.refl β) = Equiv.refl (α ⊕ β) 
goal: Equiv.Perm.sumCongr (Equiv.refl α) (Equiv.refl β) = Equiv.refl (α ⊕ β)

full_name: Equiv.boolEquivPUnitSumPUnit
code: /-- `Bool` is equivalent the sum of two `PUnit`s. -/
def boolEquivPUnitSumPUnit : Bool ≃ PUnit.{u + 1} ⊕ PUnit.{v + 1} 
goal: Bool ≃ PUnit.{u + 1} ⊕ PUnit.{v + 1}

full_name: Equiv.sumComm_apply
code: /-- Sum of types is commutative up to an equivalence. This is `Sum.swap` as an equivalence. -/
@[simps (config := .asFn) apply]
def sumComm (α β) : α ⊕ β ≃ β ⊕ α 
goal: ⇑(Equiv.sumComm α β) = Sum.swap

full_name: Equiv.sumComm
code: /-- Sum of types is commutative up to an equivalence. This is `Sum.swap` as an equivalence. -/
@[simps (config := .asFn) apply]
def sumComm (α β) : α ⊕ β ≃ β ⊕ α 
goal: α ⊕ β ≃ β ⊕ α

full_name: Equiv.sumComm_symm
code: @[simp]
theorem sumComm_symm (α β) : (sumComm α β).symm = sumComm β α 
goal: (Equiv.sumComm α β).symm = Equiv.sumComm β α

full_name: Equiv.sumAssoc
code: /-- Sum of types is associative up to an equivalence. -/
def sumAssoc (α β γ) : (α ⊕ β) ⊕ γ ≃ α ⊕ (β ⊕ γ) 
goal: (α ⊕ β) ⊕ γ ≃ α ⊕ β ⊕ γ

full_name: Equiv.sumAssoc_apply_inl_inl
code: @[simp]
theorem sumAssoc_apply_inl_inl (a) : sumAssoc α β γ (inl (inl a)) = inl a 
goal: (Equiv.sumAssoc α β γ) (Sum.inl (Sum.inl a)) = Sum.inl a

full_name: Equiv.sumAssoc_apply_inl_inr
code: @[simp]
theorem sumAssoc_apply_inl_inr (b) : sumAssoc α β γ (inl (inr b)) = inr (inl b) 
goal: (Equiv.sumAssoc α β γ) (Sum.inl (Sum.inr b)) = Sum.inr (Sum.inl b)

full_name: Equiv.sumAssoc_apply_inr
code: @[simp]
theorem sumAssoc_apply_inr (c) : sumAssoc α β γ (inr c) = inr (inr c) 
goal: (Equiv.sumAssoc α β γ) (Sum.inr c) = Sum.inr (Sum.inr c)

full_name: Equiv.sumAssoc_symm_apply_inl
code: @[simp]
theorem sumAssoc_symm_apply_inl {α β γ} (a) : (sumAssoc α β γ).symm (inl a) = inl (inl a) 
goal: (Equiv.sumAssoc α β γ).symm (Sum.inl a) = Sum.inl (Sum.inl a)

full_name: Equiv.sumAssoc_symm_apply_inr_inl
code: @[simp]
theorem sumAssoc_symm_apply_inr_inl {α β γ} (b) :
    (sumAssoc α β γ).symm (inr (inl b)) = inl (inr b) 
goal: (Equiv.sumAssoc α β γ).symm (Sum.inr (Sum.inl b)) = Sum.inl (Sum.inr b)

full_name: Equiv.sumAssoc_symm_apply_inr_inr
code: @[simp]
theorem sumAssoc_symm_apply_inr_inr {α β γ} (c) : (sumAssoc α β γ).symm (inr (inr c)) = inr c 
goal: (Equiv.sumAssoc α β γ).symm (Sum.inr (Sum.inr c)) = Sum.inr c

full_name: Equiv.sumEmpty_symm_apply
code: /-- Sum with `IsEmpty` is equivalent to the original type. -/
@[simps symm_apply]
def sumEmpty (α β) [IsEmpty β] : α ⊕ β ≃ α 
goal: (Equiv.sumEmpty α β).symm val = Sum.inl val

full_name: Equiv.sumEmpty
code: /-- Sum with `IsEmpty` is equivalent to the original type. -/
@[simps symm_apply]
def sumEmpty (α β) [IsEmpty β] : α ⊕ β ≃ α 
goal: α ⊕ β ≃ α

full_name: Equiv.sumEmpty_apply_inl
code: @[simp]
theorem sumEmpty_apply_inl [IsEmpty β] (a : α) : sumEmpty α β (Sum.inl a) = a 
goal: (Equiv.sumEmpty α β) (Sum.inl a) = a

full_name: Equiv.emptySum_symm_apply
code: /-- The sum of `IsEmpty` with any type is equivalent to that type. -/
@[simps! symm_apply]
def emptySum (α β) [IsEmpty α] : α ⊕ β ≃ β 
goal: ∀ (a : β), (Equiv.emptySum α β).symm a = Sum.inr a

full_name: Equiv.emptySum
code: /-- The sum of `IsEmpty` with any type is equivalent to that type. -/
@[simps! symm_apply]
def emptySum (α β) [IsEmpty α] : α ⊕ β ≃ β 
goal: α ⊕ β ≃ β

full_name: Equiv.emptySum_apply_inr
code: @[simp]
theorem emptySum_apply_inr [IsEmpty α] (b : β) : emptySum α β (Sum.inr b) = b 
goal: (Equiv.emptySum α β) (Sum.inr b) = b

full_name: Equiv.optionEquivSumPUnit
code: /-- `Option α` is equivalent to `α ⊕ PUnit` -/
def optionEquivSumPUnit (α) : Option α ≃ α ⊕ PUnit 
goal: Option α ≃ α ⊕ PUnit.{u_2 + 1}

full_name: Equiv.optionEquivSumPUnit_none
code: @[simp]
theorem optionEquivSumPUnit_none : optionEquivSumPUnit α none = Sum.inr PUnit.unit 
goal: (Equiv.optionEquivSumPUnit α) none = Sum.inr PUnit.unit

full_name: Equiv.optionEquivSumPUnit_some
code: @[simp]
theorem optionEquivSumPUnit_some (a) : optionEquivSumPUnit α (some a) = Sum.inl a 
goal: (Equiv.optionEquivSumPUnit α) (some a) = Sum.inl a

full_name: Equiv.optionEquivSumPUnit_coe
code: @[simp]
theorem optionEquivSumPUnit_coe (a : α) : optionEquivSumPUnit α a = Sum.inl a 
goal: (Equiv.optionEquivSumPUnit α) (some a) = Sum.inl a

full_name: Equiv.optionEquivSumPUnit_symm_inl
code: @[simp]
theorem optionEquivSumPUnit_symm_inl (a) : (optionEquivSumPUnit α).symm (Sum.inl a) = a 
goal: (Equiv.optionEquivSumPUnit α).symm (Sum.inl a) = some a

full_name: Equiv.optionEquivSumPUnit_symm_inr
code: @[simp]
theorem optionEquivSumPUnit_symm_inr (a) : (optionEquivSumPUnit α).symm (Sum.inr a) = none 
goal: (Equiv.optionEquivSumPUnit α).symm (Sum.inr a) = none

full_name: Equiv.optionIsSomeEquiv
code: /-- The set of `x : Option α` such that `isSome x` is equivalent to `α`. -/
@[simps]
def optionIsSomeEquiv (α) : { x : Option α // x.isSome } ≃ α 
goal: { x // x.isSome = true } ≃ α

full_name: Equiv.optionIsSomeEquiv_apply
code: /-- The set of `x : Option α` such that `isSome x` is equivalent to `α`. -/
@[simps]
def optionIsSomeEquiv (α) : { x : Option α // x.isSome } ≃ α 
goal: (Equiv.optionIsSomeEquiv α) o = (↑o).get ⋯

full_name: Equiv.optionIsSomeEquiv_symm_apply_coe
code: /-- The set of `x : Option α` such that `isSome x` is equivalent to `α`. -/
@[simps]
def optionIsSomeEquiv (α) : { x : Option α // x.isSome } ≃ α 
goal: ↑((Equiv.optionIsSomeEquiv α).symm x) = some x

full_name: Equiv.piOptionEquivProd_apply
code: /-- The product over `Option α` of `β a` is the binary product of the
product over `α` of `β (some α)` and `β none` -/
@[simps]
def piOptionEquivProd {β : Option α → Type*} :
    (∀ a : Option α, β a) ≃ β none × ∀ a : α, β (some a) 
goal: Equiv.piOptionEquivProd f = (f none, fun a => f (some a))

full_name: Equiv.piOptionEquivProd
code: /-- The product over `Option α` of `β a` is the binary product of the
product over `α` of `β (some α)` and `β none` -/
@[simps]
def piOptionEquivProd {β : Option α → Type*} :
    (∀ a : Option α, β a) ≃ β none × ∀ a : α, β (some a) 
goal: ((a : Option α) → β a) ≃ β none × ((a : α) → β (some a))

full_name: Equiv.piOptionEquivProd_symm_apply
code: /-- The product over `Option α` of `β a` is the binary product of the
product over `α` of `β (some α)` and `β none` -/
@[simps]
def piOptionEquivProd {β : Option α → Type*} :
    (∀ a : Option α, β a) ≃ β none × ∀ a : α, β (some a) 
goal: Equiv.piOptionEquivProd.symm x a = Option.casesOn a x.1 x.2

full_name: Equiv.sumEquivSigmaBool
code: /-- `α ⊕ β` is equivalent to a `Sigma`-type over `Bool`. Note that this definition assumes `α` and
`β` to be types from the same universe, so it cannot be used directly to transfer theorems about
sigma types to theorems about sum types. In many cases one can use `ULift` to work around this
difficulty. -/
def sumEquivSigmaBool (α β : Type u) : α ⊕ β ≃ Σ b : Bool, b.casesOn α β 
goal: α ⊕ β ≃ (b : Bool) × Bool.casesOn b α β

full_name: Equiv.sigmaFiberEquiv
code: /-- `sigmaFiberEquiv f` for `f : α → β` is the natural equivalence between
the type of all fibres of `f` and the total space `α`. -/
@[simps]
def sigmaFiberEquiv {α β : Type*} (f : α → β) : (Σ y : β, { x // f x = y }) ≃ α 
goal: (y : β) × { x // f x = y } ≃ α

full_name: Equiv.sigmaFiberEquiv_symm_apply_snd_coe
code: /-- `sigmaFiberEquiv f` for `f : α → β` is the natural equivalence between
the type of all fibres of `f` and the total space `α`. -/
@[simps]
def sigmaFiberEquiv {α β : Type*} (f : α → β) : (Σ y : β, { x // f x = y }) ≃ α 
goal: ↑((Equiv.sigmaFiberEquiv f).symm x).snd = x

full_name: Equiv.sigmaFiberEquiv_apply
code: /-- `sigmaFiberEquiv f` for `f : α → β` is the natural equivalence between
the type of all fibres of `f` and the total space `α`. -/
@[simps]
def sigmaFiberEquiv {α β : Type*} (f : α → β) : (Σ y : β, { x // f x = y }) ≃ α 
goal: (Equiv.sigmaFiberEquiv f) x = ↑x.snd

full_name: Equiv.sigmaFiberEquiv_symm_apply_fst
code: /-- `sigmaFiberEquiv f` for `f : α → β` is the natural equivalence between
the type of all fibres of `f` and the total space `α`. -/
@[simps]
def sigmaFiberEquiv {α β : Type*} (f : α → β) : (Σ y : β, { x // f x = y }) ≃ α 
goal: ((Equiv.sigmaFiberEquiv f).symm x).fst = f x

full_name: Equiv.sigmaEquivOptionOfInhabited
code: /-- Inhabited types are equivalent to `Option β` for some `β` by identifying `default` with `none`.
-/
def sigmaEquivOptionOfInhabited (α : Type u) [Inhabited α] [DecidableEq α] :
    Σ β : Type u, α ≃ Option β 
goal: (β : Type u) × (α ≃ Option β)

full_name: Equiv.sumCompl
code: /-- For any predicate `p` on `α`,
the sum of the two subtypes `{a // p a}` and its complement `{a // ¬ p a}`
is naturally equivalent to `α`.

See `subtypeOrEquiv` for sum types over subtypes `{x // p x}` and `{x // q x}`
that are not necessarily `IsCompl p q`.  -/
def sumCompl {α : Type*} (p : α → Prop) [DecidablePred p] :
    { a // p a } ⊕ { a // ¬p a } ≃ α 
goal: { a // p a } ⊕ { a // ¬p a } ≃ α

full_name: Equiv.sumCompl_apply_inl
code: @[simp]
theorem sumCompl_apply_inl (p : α → Prop) [DecidablePred p] (x : { a // p a }) :
    sumCompl p (Sum.inl x) = x 
goal: (Equiv.sumCompl p) (Sum.inl x) = ↑x

full_name: Equiv.sumCompl_apply_inr
code: @[simp]
theorem sumCompl_apply_inr (p : α → Prop) [DecidablePred p] (x : { a // ¬p a }) :
    sumCompl p (Sum.inr x) = x 
goal: (Equiv.sumCompl p) (Sum.inr x) = ↑x

full_name: Equiv.sumCompl_apply_symm_of_pos
code: @[simp]
theorem sumCompl_apply_symm_of_pos (p : α → Prop) [DecidablePred p] (a : α) (h : p a) :
    (sumCompl p).symm a = Sum.inl ⟨a, h⟩ 
goal: (Equiv.sumCompl p).symm a = Sum.inl ⟨a, h⟩

full_name: Equiv.sumCompl_apply_symm_of_neg
code: @[simp]
theorem sumCompl_apply_symm_of_neg (p : α → Prop) [DecidablePred p] (a : α) (h : ¬p a) :
    (sumCompl p).symm a = Sum.inr ⟨a, h⟩ 
goal: (Equiv.sumCompl p).symm a = Sum.inr ⟨a, h⟩

full_name: Equiv.subtypeCongr
code: /-- Combines an `Equiv` between two subtypes with an `Equiv` between their complements to form a
  permutation. -/
def subtypeCongr {p q : α → Prop} [DecidablePred p] [DecidablePred q]
    (e : { x // p x } ≃ { x // q x }) (f : { x // ¬p x } ≃ { x // ¬q x }) : Perm α 
goal: Equiv.Perm α

full_name: Equiv.Perm.subtypeCongr
code: /-- Combining permutations on `ε` that permute only inside or outside the subtype
split induced by `p : ε → Prop` constructs a permutation on `ε`. -/
def Perm.subtypeCongr : Equiv.Perm ε 
goal: Equiv.Perm ε

full_name: Equiv.Perm.subtypeCongr.apply
code: theorem Perm.subtypeCongr.apply (a : ε) : ep.subtypeCongr en a =
    if h : p a then (ep ⟨a, h⟩ : ε) else en ⟨a, h⟩ 
goal: (ep.subtypeCongr en) a = if h : p a then ↑(ep ⟨a, h⟩) else ↑(en ⟨a, h⟩)

full_name: Equiv.Perm.subtypeCongr.left_apply
code: @[simp]
theorem Perm.subtypeCongr.left_apply {a : ε} (h : p a) : ep.subtypeCongr en a = ep ⟨a, h⟩ 
goal: (ep.subtypeCongr en) a = ↑(ep ⟨a, h⟩)

full_name: Equiv.Perm.subtypeCongr.left_apply_subtype
code: @[simp]
theorem Perm.subtypeCongr.left_apply_subtype (a : { a // p a }) : ep.subtypeCongr en a = ep a 
goal: (ep.subtypeCongr en) ↑a = ↑(ep a)

full_name: Equiv.Perm.subtypeCongr.right_apply
code: @[simp]
theorem Perm.subtypeCongr.right_apply {a : ε} (h : ¬p a) : ep.subtypeCongr en a = en ⟨a, h⟩ 
goal: (ep.subtypeCongr en) a = ↑(en ⟨a, h⟩)

full_name: Equiv.Perm.subtypeCongr.right_apply_subtype
code: @[simp]
theorem Perm.subtypeCongr.right_apply_subtype (a : { a // ¬p a }) : ep.subtypeCongr en a = en a 
goal: (ep.subtypeCongr en) ↑a = ↑(en a)

full_name: Equiv.Perm.subtypeCongr.refl
code: @[simp]
theorem Perm.subtypeCongr.refl :
    Perm.subtypeCongr (Equiv.refl { a // p a }) (Equiv.refl { a // ¬p a }) = Equiv.refl ε 
goal: Equiv.Perm.subtypeCongr (Equiv.refl { a // p a }) (Equiv.refl { a // ¬p a }) = Equiv.refl ε

full_name: Equiv.Perm.subtypeCongr.symm
code: @[simp]
theorem Perm.subtypeCongr.symm : (ep.subtypeCongr en).symm = Perm.subtypeCongr ep.symm en.symm 
goal: Equiv.symm (ep.subtypeCongr en) = Equiv.Perm.subtypeCongr (Equiv.symm ep) (Equiv.symm en)

full_name: Equiv.Perm.subtypeCongr.trans
code: @[simp]
theorem Perm.subtypeCongr.trans :
    (ep.subtypeCongr en).trans (ep'.subtypeCongr en')
    = Perm.subtypeCongr (ep.trans ep') (en.trans en') 
goal: Equiv.trans (ep.subtypeCongr en) (ep'.subtypeCongr en') =
  Equiv.Perm.subtypeCongr (Equiv.trans ep ep') (Equiv.trans en en')

full_name: Equiv.subtypePreimage_apply
code: /-- For a fixed function `x₀ : {a // p a} → β` defined on a subtype of `α`,
the subtype of functions `x : α → β` that agree with `x₀` on the subtype `{a // p a}`
is naturally equivalent to the type of functions `{a // ¬ p a} → β`. -/
@[simps]
def subtypePreimage : { x : α → β // x ∘ Subtype.val = x₀ } ≃ ({ a // ¬p a } → β) 
goal: (Equiv.subtypePreimage p x₀) x a = ↑x ↑a

full_name: Equiv.subtypePreimage_symm_apply_coe
code: /-- For a fixed function `x₀ : {a // p a} → β` defined on a subtype of `α`,
the subtype of functions `x : α → β` that agree with `x₀` on the subtype `{a // p a}`
is naturally equivalent to the type of functions `{a // ¬ p a} → β`. -/
@[simps]
def subtypePreimage : { x : α → β // x ∘ Subtype.val = x₀ } ≃ ({ a // ¬p a } → β) 
goal: ↑((Equiv.subtypePreimage p x₀).symm x) a = if h : p a then x₀ ⟨a, h⟩ else x ⟨a, h⟩

full_name: Equiv.subtypePreimage
code: /-- For a fixed function `x₀ : {a // p a} → β` defined on a subtype of `α`,
the subtype of functions `x : α → β` that agree with `x₀` on the subtype `{a // p a}`
is naturally equivalent to the type of functions `{a // ¬ p a} → β`. -/
@[simps]
def subtypePreimage : { x : α → β // x ∘ Subtype.val = x₀ } ≃ ({ a // ¬p a } → β) 
goal: { x // x ∘ Subtype.val = x₀ } ≃ ({ a // ¬p a } → β)

full_name: Equiv.subtypePreimage_symm_apply_coe_pos
code: theorem subtypePreimage_symm_apply_coe_pos (x : { a // ¬p a } → β) (a : α) (h : p a) :
    ((subtypePreimage p x₀).symm x : α → β) a = x₀ ⟨a, h⟩ 
goal: ↑((Equiv.subtypePreimage p x₀).symm x) a = x₀ ⟨a, h⟩

full_name: Equiv.subtypePreimage_symm_apply_coe_neg
code: theorem subtypePreimage_symm_apply_coe_neg (x : { a // ¬p a } → β) (a : α) (h : ¬p a) :
    ((subtypePreimage p x₀).symm x : α → β) a = x ⟨a, h⟩ 
goal: ↑((Equiv.subtypePreimage p x₀).symm x) a = x ⟨a, h⟩

full_name: Equiv.piCongrRight
code: /-- A family of equivalences `∀ a, β₁ a ≃ β₂ a` generates an equivalence between `∀ a, β₁ a` and
`∀ a, β₂ a`. -/
def piCongrRight {β₁ β₂ : α → Sort*} (F : ∀ a, β₁ a ≃ β₂ a) : (∀ a, β₁ a) ≃ (∀ a, β₂ a) 
goal: ((a : α) → β₁ a) ≃ ((a : α) → β₂ a)

full_name: Equiv.piComm
code: /-- Given `φ : α → β → Sort*`, we have an equivalence between `∀ a b, φ a b` and `∀ b a, φ a b`.
This is `Function.swap` as an `Equiv`. -/
@[simps apply]
def piComm (φ : α → β → Sort*) : (∀ a b, φ a b) ≃ ∀ b a, φ a b 
goal: ((a : α) → (b : β) → φ a b) ≃ ((b : β) → (a : α) → φ a b)

full_name: Equiv.piComm_apply
code: /-- Given `φ : α → β → Sort*`, we have an equivalence between `∀ a b, φ a b` and `∀ b a, φ a b`.
This is `Function.swap` as an `Equiv`. -/
@[simps apply]
def piComm (φ : α → β → Sort*) : (∀ a b, φ a b) ≃ ∀ b a, φ a b 
goal: (Equiv.piComm φ) f y x = Function.swap f y x

full_name: Equiv.piComm_symm
code: @[simp]
theorem piComm_symm {φ : α → β → Sort*} : (piComm φ).symm = (piComm <| swap φ) 
goal: (Equiv.piComm φ).symm = Equiv.piComm (Function.swap φ)

full_name: Equiv.piCurry
code: /-- Dependent `curry` equivalence: the type of dependent functions on `Σ i, β i` is equivalent
to the type of dependent functions of two arguments (i.e., functions to the space of functions).

This is `Sigma.curry` and `Sigma.uncurry` together as an equiv. -/
def piCurry {β : α → Type*} (γ : ∀ a, β a → Type*) :
    (∀ x : Σ i, β i, γ x.1 x.2) ≃ ∀ a b, γ a b 
goal: ((x : (i : α) × β i) → γ x.fst x.snd) ≃ ((a : α) → (b : β a) → γ a b)

full_name: Equiv.piCurry_apply
code: @[simp] theorem piCurry_apply {β : α → Type*} (γ : ∀ a, β a → Type*)
    (f : ∀ x : Σ i, β i, γ x.1 x.2) :
    piCurry γ f = Sigma.curry f 
goal: (Equiv.piCurry γ) f = Sigma.curry f

full_name: Equiv.piCurry_symm_apply
code: @[simp] theorem piCurry_symm_apply {β : α → Type*} (γ : ∀ a, β a → Type*) (f : ∀ a b, γ a b) :
    (piCurry γ).symm f = Sigma.uncurry f 
goal: (Equiv.piCurry γ).symm f = Sigma.uncurry f

full_name: Equiv.prodCongrLeft
code: /-- A family of equivalences `∀ (a : α₁), β₁ ≃ β₂` generates an equivalence
between `β₁ × α₁` and `β₂ × α₁`. -/
def prodCongrLeft : β₁ × α₁ ≃ β₂ × α₁ 
goal: β₁ × α₁ ≃ β₂ × α₁

full_name: Equiv.prodCongrLeft_apply
code: @[simp]
theorem prodCongrLeft_apply (b : β₁) (a : α₁) : prodCongrLeft e (b, a) = (e a b, a) 
goal: (Equiv.prodCongrLeft e) (b, a) = ((e a) b, a)

full_name: Equiv.prodCongr_refl_right
code: theorem prodCongr_refl_right (e : β₁ ≃ β₂) :
    prodCongr e (Equiv.refl α₁) = prodCongrLeft fun _ => e 
goal: e.prodCongr (Equiv.refl α₁) = Equiv.prodCongrLeft fun x => e

full_name: Equiv.prodCongrRight
code: /-- A family of equivalences `∀ (a : α₁), β₁ ≃ β₂` generates an equivalence
between `α₁ × β₁` and `α₁ × β₂`. -/
def prodCongrRight : α₁ × β₁ ≃ α₁ × β₂ 
goal: α₁ × β₁ ≃ α₁ × β₂

full_name: Equiv.prodCongrRight_apply
code: @[simp]
theorem prodCongrRight_apply (a : α₁) (b : β₁) : prodCongrRight e (a, b) = (a, e a b) 
goal: (Equiv.prodCongrRight e) (a, b) = (a, (e a) b)

full_name: Equiv.prodCongr_refl_left
code: theorem prodCongr_refl_left (e : β₁ ≃ β₂) :
    prodCongr (Equiv.refl α₁) e = prodCongrRight fun _ => e 
goal: (Equiv.refl α₁).prodCongr e = Equiv.prodCongrRight fun x => e

full_name: Equiv.prodCongrLeft_trans_prodComm
code: @[simp]
theorem prodCongrLeft_trans_prodComm :
    (prodCongrLeft e).trans (prodComm _ _) = (prodComm _ _).trans (prodCongrRight e) 
goal: (Equiv.prodCongrLeft e).trans (Equiv.prodComm β₂ α₁) = (Equiv.prodComm β₁ α₁).trans (Equiv.prodCongrRight e)

full_name: Equiv.prodCongrRight_trans_prodComm
code: @[simp]
theorem prodCongrRight_trans_prodComm :
    (prodCongrRight e).trans (prodComm _ _) = (prodComm _ _).trans (prodCongrLeft e) 
goal: (Equiv.prodCongrRight e).trans (Equiv.prodComm α₁ β₂) = (Equiv.prodComm α₁ β₁).trans (Equiv.prodCongrLeft e)

full_name: Equiv.sigmaCongrRight_sigmaEquivProd
code: theorem sigmaCongrRight_sigmaEquivProd :
    (sigmaCongrRight e).trans (sigmaEquivProd α₁ β₂)
    = (sigmaEquivProd α₁ β₁).trans (prodCongrRight e) 
goal: (Equiv.sigmaCongrRight e).trans (Equiv.sigmaEquivProd α₁ β₂) =
  (Equiv.sigmaEquivProd α₁ β₁).trans (Equiv.prodCongrRight e)

full_name: Equiv.sigmaEquivProd_sigmaCongrRight
code: theorem sigmaEquivProd_sigmaCongrRight :
    (sigmaEquivProd α₁ β₁).symm.trans (sigmaCongrRight e)
    = (prodCongrRight e).trans (sigmaEquivProd α₁ β₂).symm 
goal: (Equiv.sigmaEquivProd α₁ β₁).symm.trans (Equiv.sigmaCongrRight e) =
  (Equiv.prodCongrRight e).trans (Equiv.sigmaEquivProd α₁ β₂).symm

full_name: Equiv.ofFiberEquiv_symm_apply
code: /-- A family of equivalences between fibers gives an equivalence between domains. -/
@[simps!]
def ofFiberEquiv {f : α → γ} {g : β → γ} (e : ∀ c, { a // f a = c } ≃ { b // g b = c }) : α ≃ β 
goal: ∀ (a : β), (Equiv.ofFiberEquiv e).symm a = ↑((Equiv.sigmaCongrRight e).symm ((Equiv.sigmaFiberEquiv g).symm a)).snd

full_name: Equiv.ofFiberEquiv_apply
code: /-- A family of equivalences between fibers gives an equivalence between domains. -/
@[simps!]
def ofFiberEquiv {f : α → γ} {g : β → γ} (e : ∀ c, { a // f a = c } ≃ { b // g b = c }) : α ≃ β 
goal: ∀ (a : α), (Equiv.ofFiberEquiv e) a = ↑((e (f a)) ((Equiv.sigmaFiberEquiv f).symm a).snd)

full_name: Equiv.ofFiberEquiv
code: /-- A family of equivalences between fibers gives an equivalence between domains. -/
@[simps!]
def ofFiberEquiv {f : α → γ} {g : β → γ} (e : ∀ c, { a // f a = c } ≃ { b // g b = c }) : α ≃ β 
goal: α ≃ β

full_name: Equiv.ofFiberEquiv_map
code: theorem ofFiberEquiv_map {α β γ} {f : α → γ} {g : β → γ}
    (e : ∀ c, { a // f a = c } ≃ { b // g b = c }) (a : α) : g (ofFiberEquiv e a) = f a 
goal: g ((Equiv.ofFiberEquiv e) a) = f a

full_name: Equiv.prodShear_symm_apply
code: /-- A variation on `Equiv.prodCongr` where the equivalence in the second component can depend
  on the first component. A typical example is a shear mapping, explaining the name of this
  declaration. -/
@[simps (config := .asFn)]
def prodShear (e₁ : α₁ ≃ α₂) (e₂ : α₁ → β₁ ≃ β₂) : α₁ × β₁ ≃ α₂ × β₂ 
goal: ⇑(e₁.prodShear e₂).symm = fun y => (e₁.symm y.1, (e₂ (e₁.symm y.1)).symm y.2)

full_name: Equiv.prodShear_apply
code: /-- A variation on `Equiv.prodCongr` where the equivalence in the second component can depend
  on the first component. A typical example is a shear mapping, explaining the name of this
  declaration. -/
@[simps (config := .asFn)]
def prodShear (e₁ : α₁ ≃ α₂) (e₂ : α₁ → β₁ ≃ β₂) : α₁ × β₁ ≃ α₂ × β₂ 
goal: ⇑(e₁.prodShear e₂) = fun x => (e₁ x.1, (e₂ x.1) x.2)

full_name: Equiv.prodShear
code: /-- A variation on `Equiv.prodCongr` where the equivalence in the second component can depend
  on the first component. A typical example is a shear mapping, explaining the name of this
  declaration. -/
@[simps (config := .asFn)]
def prodShear (e₁ : α₁ ≃ α₂) (e₂ : α₁ → β₁ ≃ β₂) : α₁ × β₁ ≃ α₂ × β₂ 
goal: α₁ × β₁ ≃ α₂ × β₂

full_name: Equiv.Perm.prodExtendRight
code: /-- `prodExtendRight a e` extends `e : Perm β` to `Perm (α × β)` by sending `(a, b)` to
`(a, e b)` and keeping the other `(a', b)` fixed. -/
def prodExtendRight : Perm (α₁ × β₁) 
goal: Equiv.Perm (α₁ × β₁)

full_name: Equiv.Perm.prodExtendRight_apply_eq
code: @[simp]
theorem prodExtendRight_apply_eq (b : β₁) : prodExtendRight a e (a, b) = (a, e b) 
goal: (Equiv.Perm.prodExtendRight a e) (a, b) = (a, e b)

full_name: Equiv.Perm.prodExtendRight_apply_ne
code: theorem prodExtendRight_apply_ne {a a' : α₁} (h : a' ≠ a) (b : β₁) :
    prodExtendRight a e (a', b) = (a', b) 
goal: (Equiv.Perm.prodExtendRight a e) (a', b) = (a', b)

full_name: Equiv.Perm.eq_of_prodExtendRight_ne
code: theorem eq_of_prodExtendRight_ne {e : Perm β₁} {a a' : α₁} {b : β₁}
    (h : prodExtendRight a e (a', b) ≠ (a', b)) : a' = a 
goal: a' = a

full_name: Equiv.Perm.fst_prodExtendRight
code: @[simp]
theorem fst_prodExtendRight (ab : α₁ × β₁) : (prodExtendRight a e ab).fst = ab.fst 
goal: ((Equiv.Perm.prodExtendRight a e) ab).1 = ab.1

full_name: Equiv.arrowProdEquivProdArrow
code: /-- The type of functions to a product `α × β` is equivalent to the type of pairs of functions
`γ → α` and `γ → β`. -/
def arrowProdEquivProdArrow (α β γ : Type*) : (γ → α × β) ≃ (γ → α) × (γ → β) 
goal: (γ → α × β) ≃ (γ → α) × (γ → β)

full_name: Equiv.sumPiEquivProdPi_symm_apply
code: /-- The type of dependent functions on a sum type `ι ⊕ ι'` is equivalent to the type of pairs of
functions on `ι` and on `ι'`. This is a dependent version of `Equiv.sumArrowEquivProdArrow`. -/
@[simps]
def sumPiEquivProdPi (π : ι ⊕ ι' → Type*) : (∀ i, π i) ≃ (∀ i, π (inl i)) × ∀ i', π (inr i') 
goal: (Equiv.sumPiEquivProdPi π).symm g t = Sum.rec g.1 g.2 t

full_name: Equiv.sumPiEquivProdPi_apply
code: /-- The type of dependent functions on a sum type `ι ⊕ ι'` is equivalent to the type of pairs of
functions on `ι` and on `ι'`. This is a dependent version of `Equiv.sumArrowEquivProdArrow`. -/
@[simps]
def sumPiEquivProdPi (π : ι ⊕ ι' → Type*) : (∀ i, π i) ≃ (∀ i, π (inl i)) × ∀ i', π (inr i') 
goal: (Equiv.sumPiEquivProdPi π) f = (fun i => f (Sum.inl i), fun i' => f (Sum.inr i'))

full_name: Equiv.sumPiEquivProdPi
code: /-- The type of dependent functions on a sum type `ι ⊕ ι'` is equivalent to the type of pairs of
functions on `ι` and on `ι'`. This is a dependent version of `Equiv.sumArrowEquivProdArrow`. -/
@[simps]
def sumPiEquivProdPi (π : ι ⊕ ι' → Type*) : (∀ i, π i) ≃ (∀ i, π (inl i)) × ∀ i', π (inr i') 
goal: ((i : ι ⊕ ι') → π i) ≃ ((i : ι) → π (Sum.inl i)) × ((i' : ι') → π (Sum.inr i'))

full_name: Equiv.prodPiEquivSumPi_apply
code: /-- The equivalence between a product of two dependent functions types and a single dependent
function type. Basically a symmetric version of `Equiv.sumPiEquivProdPi`. -/
@[simps!]
def prodPiEquivSumPi (π : ι → Type u) (π' : ι' → Type u) :
    ((∀ i, π i) × ∀ i', π' i') ≃ ∀ i, Sum.elim π π' i 
goal: ∀ (a : ((i : ι) → Sum.elim π π' (Sum.inl i)) × ((i' : ι') → Sum.elim π π' (Sum.inr i'))) (i : ι ⊕ ι'),
  (Equiv.prodPiEquivSumPi π π') a i = (Equiv.sumPiEquivProdPi (Sum.elim π π')).symm a i

full_name: Equiv.prodPiEquivSumPi_symm_apply
code: /-- The equivalence between a product of two dependent functions types and a single dependent
function type. Basically a symmetric version of `Equiv.sumPiEquivProdPi`. -/
@[simps!]
def prodPiEquivSumPi (π : ι → Type u) (π' : ι' → Type u) :
    ((∀ i, π i) × ∀ i', π' i') ≃ ∀ i, Sum.elim π π' i 
goal: ∀ (a : (i : ι ⊕ ι') → Sum.elim π π' i),
  (Equiv.prodPiEquivSumPi π π').symm a = (Equiv.sumPiEquivProdPi (Sum.elim π π')) a

full_name: Equiv.prodPiEquivSumPi
code: /-- The equivalence between a product of two dependent functions types and a single dependent
function type. Basically a symmetric version of `Equiv.sumPiEquivProdPi`. -/
@[simps!]
def prodPiEquivSumPi (π : ι → Type u) (π' : ι' → Type u) :
    ((∀ i, π i) × ∀ i', π' i') ≃ ∀ i, Sum.elim π π' i 
goal: ((i : ι) → π i) × ((i' : ι') → π' i') ≃ ((i : ι ⊕ ι') → Sum.elim π π' i)

full_name: Equiv.sumArrowEquivProdArrow
code: /-- The type of functions on a sum type `α ⊕ β` is equivalent to the type of pairs of functions
on `α` and on `β`. -/
def sumArrowEquivProdArrow (α β γ : Type*) : (α ⊕ β → γ) ≃ (α → γ) × (β → γ) 
goal: (α ⊕ β → γ) ≃ (α → γ) × (β → γ)

full_name: Equiv.sumArrowEquivProdArrow_apply_fst
code: @[simp]
theorem sumArrowEquivProdArrow_apply_fst (f : α ⊕ β → γ) (a : α) :
    (sumArrowEquivProdArrow α β γ f).1 a = f (inl a) 
goal: ((Equiv.sumArrowEquivProdArrow α β γ) f).1 a = f (Sum.inl a)

full_name: Equiv.sumArrowEquivProdArrow_apply_snd
code: @[simp]
theorem sumArrowEquivProdArrow_apply_snd (f : α ⊕ β → γ) (b : β) :
    (sumArrowEquivProdArrow α β γ f).2 b = f (inr b) 
goal: ((Equiv.sumArrowEquivProdArrow α β γ) f).2 b = f (Sum.inr b)

full_name: Equiv.sumArrowEquivProdArrow_symm_apply_inl
code: @[simp]
theorem sumArrowEquivProdArrow_symm_apply_inl (f : α → γ) (g : β → γ) (a : α) :
    ((sumArrowEquivProdArrow α β γ).symm (f, g)) (inl a) = f a 
goal: (Equiv.sumArrowEquivProdArrow α β γ).symm (f, g) (Sum.inl a) = f a

full_name: Equiv.sumArrowEquivProdArrow_symm_apply_inr
code: @[simp]
theorem sumArrowEquivProdArrow_symm_apply_inr (f : α → γ) (g : β → γ) (b : β) :
    ((sumArrowEquivProdArrow α β γ).symm (f, g)) (inr b) = g b 
goal: (Equiv.sumArrowEquivProdArrow α β γ).symm (f, g) (Sum.inr b) = g b

full_name: Equiv.sumProdDistrib
code: /-- Type product is right distributive with respect to type sum up to an equivalence. -/
def sumProdDistrib (α β γ) : (α ⊕ β) × γ ≃ α × γ ⊕ β × γ 
goal: (α ⊕ β) × γ ≃ α × γ ⊕ β × γ

full_name: Equiv.sumProdDistrib_apply_left
code: @[simp]
theorem sumProdDistrib_apply_left (a : α) (c : γ) :
    sumProdDistrib α β γ (Sum.inl a, c) = Sum.inl (a, c) 
goal: (Equiv.sumProdDistrib α β γ) (Sum.inl a, c) = Sum.inl (a, c)

full_name: Equiv.sumProdDistrib_apply_right
code: @[simp]
theorem sumProdDistrib_apply_right (b : β) (c : γ) :
    sumProdDistrib α β γ (Sum.inr b, c) = Sum.inr (b, c) 
goal: (Equiv.sumProdDistrib α β γ) (Sum.inr b, c) = Sum.inr (b, c)

full_name: Equiv.sumProdDistrib_symm_apply_left
code: @[simp]
theorem sumProdDistrib_symm_apply_left (a : α × γ) :
    (sumProdDistrib α β γ).symm (inl a) = (inl a.1, a.2) 
goal: (Equiv.sumProdDistrib α β γ).symm (Sum.inl a) = (Sum.inl a.1, a.2)

full_name: Equiv.sumProdDistrib_symm_apply_right
code: @[simp]
theorem sumProdDistrib_symm_apply_right (b : β × γ) :
    (sumProdDistrib α β γ).symm (inr b) = (inr b.1, b.2) 
goal: (Equiv.sumProdDistrib α β γ).symm (Sum.inr b) = (Sum.inr b.1, b.2)

full_name: Equiv.prodSumDistrib
code: /-- Type product is left distributive with respect to type sum up to an equivalence. -/
def prodSumDistrib (α β γ : Type*) : α × (β ⊕ γ) ≃ (α × β) ⊕ (α × γ) 
goal: α × (β ⊕ γ) ≃ α × β ⊕ α × γ

full_name: Equiv.prodSumDistrib_apply_left
code: @[simp]
theorem prodSumDistrib_apply_left (a : α) (b : β) :
    prodSumDistrib α β γ (a, Sum.inl b) = Sum.inl (a, b) 
goal: (Equiv.prodSumDistrib α β γ) (a, Sum.inl b) = Sum.inl (a, b)

full_name: Equiv.prodSumDistrib_apply_right
code: @[simp]
theorem prodSumDistrib_apply_right (a : α) (c : γ) :
    prodSumDistrib α β γ (a, Sum.inr c) = Sum.inr (a, c) 
goal: (Equiv.prodSumDistrib α β γ) (a, Sum.inr c) = Sum.inr (a, c)

full_name: Equiv.prodSumDistrib_symm_apply_left
code: @[simp]
theorem prodSumDistrib_symm_apply_left (a : α × β) :
    (prodSumDistrib α β γ).symm (inl a) = (a.1, inl a.2) 
goal: (Equiv.prodSumDistrib α β γ).symm (Sum.inl a) = (a.1, Sum.inl a.2)

full_name: Equiv.prodSumDistrib_symm_apply_right
code: @[simp]
theorem prodSumDistrib_symm_apply_right (a : α × γ) :
    (prodSumDistrib α β γ).symm (inr a) = (a.1, inr a.2) 
goal: (Equiv.prodSumDistrib α β γ).symm (Sum.inr a) = (a.1, Sum.inr a.2)

full_name: Equiv.sigmaSumDistrib_apply
code: /-- An indexed sum of disjoint sums of types is equivalent to the sum of the indexed sums. -/
@[simps]
def sigmaSumDistrib (α β : ι → Type*) :
    (Σ i, α i ⊕ β i) ≃ (Σ i, α i) ⊕ (Σ i, β i) 
goal: (Equiv.sigmaSumDistrib α β) p = Sum.map (Sigma.mk p.fst) (Sigma.mk p.fst) p.snd

full_name: Equiv.sigmaSumDistrib
code: /-- An indexed sum of disjoint sums of types is equivalent to the sum of the indexed sums. -/
@[simps]
def sigmaSumDistrib (α β : ι → Type*) :
    (Σ i, α i ⊕ β i) ≃ (Σ i, α i) ⊕ (Σ i, β i) 
goal: (i : ι) × (α i ⊕ β i) ≃ (i : ι) × α i ⊕ (i : ι) × β i

full_name: Equiv.sigmaSumDistrib_symm_apply
code: /-- An indexed sum of disjoint sums of types is equivalent to the sum of the indexed sums. -/
@[simps]
def sigmaSumDistrib (α β : ι → Type*) :
    (Σ i, α i ⊕ β i) ≃ (Σ i, α i) ⊕ (Σ i, β i) 
goal: ∀ (a : (i : ι) × α i ⊕ (i : ι) × β i),
  (Equiv.sigmaSumDistrib α β).symm a = Sum.elim (Sigma.map id fun x => Sum.inl) (Sigma.map id fun x => Sum.inr) a

full_name: Equiv.sigmaProdDistrib
code: /-- The product of an indexed sum of types (formally, a `Sigma`-type `Σ i, α i`) by a type `β` is
equivalent to the sum of products `Σ i, (α i × β)`. -/
def sigmaProdDistrib (α : ι → Type*) (β : Type*) : (Σ i, α i) × β ≃ Σ i, α i × β 
goal: ((i : ι) × α i) × β ≃ (i : ι) × α i × β

full_name: Equiv.sigmaNatSucc
code: /-- An equivalence that separates out the 0th fiber of `(Σ (n : ℕ), f n)`. -/
def sigmaNatSucc (f : ℕ → Type u) : (Σ n, f n) ≃ f 0 ⊕ Σ n, f (n + 1) 
goal: (n : ℕ) × f n ≃ f 0 ⊕ (n : ℕ) × f (n + 1)

full_name: Equiv.boolProdEquivSum
code: /-- The product `Bool × α` is equivalent to `α ⊕ α`. -/
@[simps]
def boolProdEquivSum (α) : Bool × α ≃ α ⊕ α 
goal: Bool × α ≃ α ⊕ α

full_name: Equiv.boolProdEquivSum_symm_apply
code: /-- The product `Bool × α` is equivalent to `α ⊕ α`. -/
@[simps]
def boolProdEquivSum (α) : Bool × α ≃ α ⊕ α 
goal: ∀ (a : α ⊕ α), (Equiv.boolProdEquivSum α).symm a = Sum.elim (Prod.mk false) (Prod.mk true) a

full_name: Equiv.boolProdEquivSum_apply
code: /-- The product `Bool × α` is equivalent to `α ⊕ α`. -/
@[simps]
def boolProdEquivSum (α) : Bool × α ≃ α ⊕ α 
goal: (Equiv.boolProdEquivSum α) p = Bool.casesOn p.1 (Sum.inl p.2) (Sum.inr p.2)

full_name: Equiv.boolArrowEquivProd
code: /-- The function type `Bool → α` is equivalent to `α × α`. -/
@[simps]
def boolArrowEquivProd (α) : (Bool → α) ≃ α × α 
goal: (Bool → α) ≃ α × α

full_name: Equiv.boolArrowEquivProd_apply
code: /-- The function type `Bool → α` is equivalent to `α × α`. -/
@[simps]
def boolArrowEquivProd (α) : (Bool → α) ≃ α × α 
goal: (Equiv.boolArrowEquivProd α) f = (f false, f true)

full_name: Equiv.boolArrowEquivProd_symm_apply
code: /-- The function type `Bool → α` is equivalent to `α × α`. -/
@[simps]
def boolArrowEquivProd (α) : (Bool → α) ≃ α × α 
goal: (Equiv.boolArrowEquivProd α).symm p b = Bool.casesOn b p.1 p.2

full_name: Equiv.natEquivNatSumPUnit
code: /-- The set of natural numbers is equivalent to `ℕ ⊕ PUnit`. -/
def natEquivNatSumPUnit : ℕ ≃ ℕ ⊕ PUnit 
goal: ℕ ≃ ℕ ⊕ PUnit.{u_1 + 1}

full_name: Equiv.natSumPUnitEquivNat
code: /-- `ℕ ⊕ PUnit` is equivalent to `ℕ`. -/
def natSumPUnitEquivNat : ℕ ⊕ PUnit ≃ ℕ 
goal: ℕ ⊕ PUnit.{u_1 + 1} ≃ ℕ

full_name: Equiv.intEquivNatSumNat
code: /-- The type of integer numbers is equivalent to `ℕ ⊕ ℕ`. -/
def intEquivNatSumNat : ℤ ≃ ℕ ⊕ ℕ 
goal: ℤ ≃ ℕ ⊕ ℕ

full_name: Equiv.listEquivOfEquiv
code: /-- An equivalence between `α` and `β` generates an equivalence between `List α` and `List β`. -/
def listEquivOfEquiv (e : α ≃ β) : List α ≃ List β 
goal: List α ≃ List β

full_name: Equiv.uniqueCongr
code: /-- If `α` is equivalent to `β`, then `Unique α` is equivalent to `Unique β`. -/
def uniqueCongr (e : α ≃ β) : Unique α ≃ Unique β 
goal: Unique α ≃ Unique β

full_name: Equiv.isEmpty_congr
code: /-- If `α` is equivalent to `β`, then `IsEmpty α` is equivalent to `IsEmpty β`. -/
theorem isEmpty_congr (e : α ≃ β) : IsEmpty α ↔ IsEmpty β 
goal: IsEmpty α ↔ IsEmpty β

full_name: Equiv.isEmpty
code: protected theorem isEmpty (e : α ≃ β) [IsEmpty β] : IsEmpty α 
goal: IsEmpty α

full_name: Equiv.subtypeEquiv
code: /-- If `α` is equivalent to `β` and the predicates `p : α → Prop` and `q : β → Prop` are equivalent
at corresponding points, then `{a // p a}` is equivalent to `{b // q b}`.
For the statement where `α = β`, that is, `e : perm α`, see `Perm.subtypePerm`. -/
def subtypeEquiv {p : α → Prop} {q : β → Prop} (e : α ≃ β) (h : ∀ a, p a ↔ q (e a)) :
    { a : α // p a } ≃ { b : β // q b } 
goal: { a // p a } ≃ { b // q b }

full_name: Equiv.coe_subtypeEquiv_eq_map
code: lemma coe_subtypeEquiv_eq_map {X Y : Type*} {p : X → Prop} {q : Y → Prop} (e : X ≃ Y)
    (h : ∀ x, p x ↔ q (e x)) : ⇑(e.subtypeEquiv h) = Subtype.map e (h · |>.mp) 
goal: ⇑(e.subtypeEquiv h) = Subtype.map ⇑e ⋯

full_name: Equiv.subtypeEquiv_refl
code: @[simp]
theorem subtypeEquiv_refl {p : α → Prop} (h : ∀ a, p a ↔ p (Equiv.refl _ a) := fun a => Iff.rfl) :
    (Equiv.refl α).subtypeEquiv h = Equiv.refl { a : α // p a } 
goal: (Equiv.refl α).subtypeEquiv h = Equiv.refl { a // p a }

full_name: Equiv.subtypeEquiv_symm
code: @[simp]
theorem subtypeEquiv_symm {p : α → Prop} {q : β → Prop} (e : α ≃ β) (h : ∀ a : α, p a ↔ q (e a)) :
    (e.subtypeEquiv h).symm =
      e.symm.subtypeEquiv fun a => by
        convert (h <| e.symm a).symm
        exact (e.apply_symm_apply a).symm 
goal: (e.subtypeEquiv h).symm = e.symm.subtypeEquiv ⋯

full_name: Equiv.subtypeEquiv_trans
code: @[simp]
theorem subtypeEquiv_trans {p : α → Prop} {q : β → Prop} {r : γ → Prop} (e : α ≃ β) (f : β ≃ γ)
    (h : ∀ a : α, p a ↔ q (e a)) (h' : ∀ b : β, q b ↔ r (f b)) :
    (e.subtypeEquiv h).trans (f.subtypeEquiv h')
    = (e.trans f).subtypeEquiv fun a => (h a).trans (h' <| e a) 
goal: (e.subtypeEquiv h).trans (f.subtypeEquiv h') = (e.trans f).subtypeEquiv ⋯

full_name: Equiv.subtypeEquiv_apply
code: @[simp]
theorem subtypeEquiv_apply {p : α → Prop} {q : β → Prop}
    (e : α ≃ β) (h : ∀ a : α, p a ↔ q (e a)) (x : { x // p x }) :
    e.subtypeEquiv h x = ⟨e x, (h _).1 x.2⟩ 
goal: (e.subtypeEquiv h) x = ⟨e ↑x, ⋯⟩

full_name: Equiv.subtypeEquivRight
code: /-- If two predicates `p` and `q` are pointwise equivalent, then `{x // p x}` is equivalent to
`{x // q x}`. -/
@[simps!]
def subtypeEquivRight {p q : α → Prop} (e : ∀ x, p x ↔ q x) : { x // p x } ≃ { x // q x } 
goal: { x // p x } ≃ { x // q x }

full_name: Equiv.subtypeEquivRight_symm_apply_coe
code: /-- If two predicates `p` and `q` are pointwise equivalent, then `{x // p x}` is equivalent to
`{x // q x}`. -/
@[simps!]
def subtypeEquivRight {p q : α → Prop} (e : ∀ x, p x ↔ q x) : { x // p x } ≃ { x // q x } 
goal: ↑((Equiv.subtypeEquivRight e).symm b) = ↑b

full_name: Equiv.subtypeEquivRight_apply_coe
code: /-- If two predicates `p` and `q` are pointwise equivalent, then `{x // p x}` is equivalent to
`{x // q x}`. -/
@[simps!]
def subtypeEquivRight {p q : α → Prop} (e : ∀ x, p x ↔ q x) : { x // p x } ≃ { x // q x } 
goal: ↑((Equiv.subtypeEquivRight e) a) = ↑a

full_name: Equiv.subtypeEquivRight_apply
code: lemma subtypeEquivRight_apply {p q : α → Prop} (e : ∀ x, p x ↔ q x)
    (z : { x // p x }) : subtypeEquivRight e z = ⟨z, (e z.1).mp z.2⟩ 
goal: (Equiv.subtypeEquivRight e) z = ⟨↑z, ⋯⟩

full_name: Equiv.subtypeEquivRight_symm_apply
code: lemma subtypeEquivRight_symm_apply {p q : α → Prop} (e : ∀ x, p x ↔ q x)
    (z : { x // q x }) : (subtypeEquivRight e).symm z = ⟨z, (e z.1).mpr z.2⟩ 
goal: (Equiv.subtypeEquivRight e).symm z = ⟨↑z, ⋯⟩

full_name: Equiv.subtypeEquivOfSubtype
code: /-- If `α ≃ β`, then for any predicate `p : β → Prop` the subtype `{a // p (e a)}` is equivalent
to the subtype `{b // p b}`. -/
def subtypeEquivOfSubtype {p : β → Prop} (e : α ≃ β) : { a : α // p (e a) } ≃ { b : β // p b } 
goal: { a // p (e a) } ≃ { b // p b }

full_name: Equiv.subtypeEquivOfSubtype'
code: /-- If `α ≃ β`, then for any predicate `p : α → Prop` the subtype `{a // p a}` is equivalent
to the subtype `{b // p (e.symm b)}`. This version is used by `equiv_rw`. -/
def subtypeEquivOfSubtype' {p : α → Prop} (e : α ≃ β) :
    { a : α // p a } ≃ { b : β // p (e.symm b) } 
goal: { a // p a } ≃ { b // p (e.symm b) }

full_name: Equiv.subtypeEquivProp
code: /-- If two predicates are equal, then the corresponding subtypes are equivalent. -/
def subtypeEquivProp {p q : α → Prop} (h : p = q) : Subtype p ≃ Subtype q 
goal: Subtype p ≃ Subtype q

full_name: Equiv.subtypeSubtypeEquivSubtypeExists
code: /-- A subtype of a subtype is equivalent to the subtype of elements satisfying both predicates. This
version allows the “inner” predicate to depend on `h : p a`. -/
@[simps]
def subtypeSubtypeEquivSubtypeExists (p : α → Prop) (q : Subtype p → Prop) :
    Subtype q ≃ { a : α // ∃ h : p a, q ⟨a, h⟩ } 
goal: Subtype q ≃ { a // ∃ h, q ⟨a, h⟩ }

full_name: Equiv.subtypeSubtypeEquivSubtypeExists_apply_coe
code: /-- A subtype of a subtype is equivalent to the subtype of elements satisfying both predicates. This
version allows the “inner” predicate to depend on `h : p a`. -/
@[simps]
def subtypeSubtypeEquivSubtypeExists (p : α → Prop) (q : Subtype p → Prop) :
    Subtype q ≃ { a : α // ∃ h : p a, q ⟨a, h⟩ } 
goal: ↑((Equiv.subtypeSubtypeEquivSubtypeExists p q) a) = ↑↑a

full_name: Equiv.subtypeSubtypeEquivSubtypeExists_symm_apply_coe_coe
code: /-- A subtype of a subtype is equivalent to the subtype of elements satisfying both predicates. This
version allows the “inner” predicate to depend on `h : p a`. -/
@[simps]
def subtypeSubtypeEquivSubtypeExists (p : α → Prop) (q : Subtype p → Prop) :
    Subtype q ≃ { a : α // ∃ h : p a, q ⟨a, h⟩ } 
goal: ↑↑((Equiv.subtypeSubtypeEquivSubtypeExists p q).symm a) = ↑a

full_name: Equiv.subtypeSubtypeEquivSubtypeInter_apply_coe
code: /-- A subtype of a subtype is equivalent to the subtype of elements satisfying both predicates. -/
@[simps!]
def subtypeSubtypeEquivSubtypeInter {α : Type u} (p q : α → Prop) :
    { x : Subtype p // q x.1 } ≃ Subtype fun x => p x ∧ q x 
goal: ∀ (a : { x // q ↑x }), ↑((Equiv.subtypeSubtypeEquivSubtypeInter p q) a) = ↑↑a

full_name: Equiv.subtypeSubtypeEquivSubtypeInter_symm_apply_coe_coe
code: /-- A subtype of a subtype is equivalent to the subtype of elements satisfying both predicates. -/
@[simps!]
def subtypeSubtypeEquivSubtypeInter {α : Type u} (p q : α → Prop) :
    { x : Subtype p // q x.1 } ≃ Subtype fun x => p x ∧ q x 
goal: ∀ (a : { x // p x ∧ q x }), ↑↑((Equiv.subtypeSubtypeEquivSubtypeInter p q).symm a) = ↑a

full_name: Equiv.subtypeSubtypeEquivSubtypeInter
code: /-- A subtype of a subtype is equivalent to the subtype of elements satisfying both predicates. -/
@[simps!]
def subtypeSubtypeEquivSubtypeInter {α : Type u} (p q : α → Prop) :
    { x : Subtype p // q x.1 } ≃ Subtype fun x => p x ∧ q x 
goal: { x // q ↑x } ≃ { x // p x ∧ q x }

full_name: Equiv.subtypeSubtypeEquivSubtype_symm_apply_coe_coe
code: /-- If the outer subtype has more restrictive predicate than the inner one,
then we can drop the latter. -/
@[simps!]
def subtypeSubtypeEquivSubtype {p q : α → Prop} (h : ∀ {x}, q x → p x) :
    { x : Subtype p // q x.1 } ≃ Subtype q 
goal: ∀ (a : Subtype q), ↑↑((Equiv.subtypeSubtypeEquivSubtype h).symm a) = ↑a

full_name: Equiv.subtypeSubtypeEquivSubtype
code: /-- If the outer subtype has more restrictive predicate than the inner one,
then we can drop the latter. -/
@[simps!]
def subtypeSubtypeEquivSubtype {p q : α → Prop} (h : ∀ {x}, q x → p x) :
    { x : Subtype p // q x.1 } ≃ Subtype q 
goal: { x // q ↑x } ≃ Subtype q

full_name: Equiv.subtypeSubtypeEquivSubtype_apply_coe
code: /-- If the outer subtype has more restrictive predicate than the inner one,
then we can drop the latter. -/
@[simps!]
def subtypeSubtypeEquivSubtype {p q : α → Prop} (h : ∀ {x}, q x → p x) :
    { x : Subtype p // q x.1 } ≃ Subtype q 
goal: ∀ (a : { x // q ↑x }), ↑((Equiv.subtypeSubtypeEquivSubtype h) a) = ↑↑a

full_name: Equiv.subtypeUnivEquiv
code: /-- If a proposition holds for all elements, then the subtype is
equivalent to the original type. -/
@[simps apply symm_apply]
def subtypeUnivEquiv {p : α → Prop} (h : ∀ x, p x) : Subtype p ≃ α 
goal: Subtype p ≃ α

full_name: Equiv.subtypeUnivEquiv_apply
code: /-- If a proposition holds for all elements, then the subtype is
equivalent to the original type. -/
@[simps apply symm_apply]
def subtypeUnivEquiv {p : α → Prop} (h : ∀ x, p x) : Subtype p ≃ α 
goal: (Equiv.subtypeUnivEquiv h) x = ↑x

full_name: Equiv.subtypeUnivEquiv_symm_apply
code: /-- If a proposition holds for all elements, then the subtype is
equivalent to the original type. -/
@[simps apply symm_apply]
def subtypeUnivEquiv {p : α → Prop} (h : ∀ x, p x) : Subtype p ≃ α 
goal: (Equiv.subtypeUnivEquiv h).symm x = ⟨x, ⋯⟩

full_name: Equiv.subtypeSigmaEquiv
code: /-- A subtype of a sigma-type is a sigma-type over a subtype. -/
def subtypeSigmaEquiv (p : α → Type v) (q : α → Prop) : { y : Sigma p // q y.1 } ≃ Σ x :
    Subtype q, p x.1 
goal: { y // q y.fst } ≃ (x : Subtype q) × p ↑x

full_name: Equiv.sigmaSubtypeEquivOfSubset
code: /-- A sigma type over a subtype is equivalent to the sigma set over the original type,
if the fiber is empty outside of the subset -/
def sigmaSubtypeEquivOfSubset (p : α → Type v) (q : α → Prop) (h : ∀ x, p x → q x) :
    (Σ x : Subtype q, p x) ≃ Σ x : α, p x 
goal: (x : Subtype q) × p ↑x ≃ (x : α) × p x

full_name: Equiv.sigmaSubtypeFiberEquiv
code: /-- If a predicate `p : β → Prop` is true on the range of a map `f : α → β`, then
`Σ y : {y // p y}, {x // f x = y}` is equivalent to `α`. -/
def sigmaSubtypeFiberEquiv {α β : Type*} (f : α → β) (p : β → Prop) (h : ∀ x, p (f x)) :
    (Σ y : Subtype p, { x : α // f x = y }) ≃ α 
goal: (y : Subtype p) × { x // f x = ↑y } ≃ α

full_name: Equiv.sigmaSubtypeFiberEquivSubtype
code: /-- If for each `x` we have `p x ↔ q (f x)`, then `Σ y : {y // q y}, f ⁻¹' {y}` is equivalent
to `{x // p x}`. -/
def sigmaSubtypeFiberEquivSubtype {α β : Type*} (f : α → β) {p : α → Prop} {q : β → Prop}
    (h : ∀ x, p x ↔ q (f x)) : (Σ y : Subtype q, { x : α // f x = y }) ≃ Subtype p 
goal: (y : Subtype q) × { x // f x = ↑y } ≃ Subtype p

full_name: Equiv.sigmaOptionEquivOfSome
code: /-- A sigma type over an `Option` is equivalent to the sigma set over the original type,
if the fiber is empty at none. -/
def sigmaOptionEquivOfSome (p : Option α → Type v) (h : p none → False) :
    (Σ x : Option α, p x) ≃ Σ x : α, p (some x) 
goal: (x : Option α) × p x ≃ (x : α) × p (some x)

full_name: Equiv.piEquivSubtypeSigma
code: /-- The `Pi`-type `∀ i, π i` is equivalent to the type of sections `f : ι → Σ i, π i` of the
`Sigma` type such that for all `i` we have `(f i).fst = i`. -/
def piEquivSubtypeSigma (ι) (π : ι → Type*) :
    (∀ i, π i) ≃ { f : ι → Σ i, π i // ∀ i, (f i).1 = i } 
goal: ((i : ι) → π i) ≃ { f // ∀ (i : ι), (f i).fst = i }

full_name: Equiv.subtypePiEquivPi
code: /-- The type of functions `f : ∀ a, β a` such that for all `a` we have `p a (f a)` is equivalent
to the type of functions `∀ a, {b : β a // p a b}`. -/
def subtypePiEquivPi {β : α → Sort v} {p : ∀ a, β a → Prop} :
    { f : ∀ a, β a // ∀ a, p a (f a) } ≃ ∀ a, { b : β a // p a b } 
goal: { f // ∀ (a : α), p a (f a) } ≃ ((a : α) → { b // p a b })

full_name: Equiv.subtypeProdEquivProd
code: /-- A subtype of a product defined by componentwise conditions
is equivalent to a product of subtypes. -/
def subtypeProdEquivProd {p : α → Prop} {q : β → Prop} :
    { c : α × β // p c.1 ∧ q c.2 } ≃ { a // p a } × { b // q b } 
goal: { c // p c.1 ∧ q c.2 } ≃ { a // p a } × { b // q b }

full_name: Equiv.prodSubtypeFstEquivSubtypeProd
code: /-- A subtype of a `Prod` that depends only on the first component is equivalent to the
corresponding subtype of the first type times the second type. -/
def prodSubtypeFstEquivSubtypeProd {p : α → Prop} : {s : α × β // p s.1} ≃ {a // p a} × β 
goal: { s // p s.1 } ≃ { a // p a } × β

full_name: Equiv.subtypeProdEquivSigmaSubtype
code: /-- A subtype of a `Prod` is equivalent to a sigma type whose fibers are subtypes. -/
def subtypeProdEquivSigmaSubtype (p : α → β → Prop) :
    { x : α × β // p x.1 x.2 } ≃ Σa, { b : β // p a b } 
goal: { x // p x.1 x.2 } ≃ (a : α) × { b // p a b }

full_name: Equiv.piEquivPiSubtypeProd_apply
code: /-- The type `∀ (i : α), β i` can be split as a product by separating the indices in `α`
depending on whether they satisfy a predicate `p` or not. -/
@[simps]
def piEquivPiSubtypeProd {α : Type*} (p : α → Prop) (β : α → Type*) [DecidablePred p] :
    (∀ i : α, β i) ≃ (∀ i : { x // p x }, β i) × ∀ i : { x // ¬p x }, β i 
goal: (Equiv.piEquivPiSubtypeProd p β) f = (fun x => f ↑x, fun x => f ↑x)

full_name: Equiv.piEquivPiSubtypeProd
code: /-- The type `∀ (i : α), β i` can be split as a product by separating the indices in `α`
depending on whether they satisfy a predicate `p` or not. -/
@[simps]
def piEquivPiSubtypeProd {α : Type*} (p : α → Prop) (β : α → Type*) [DecidablePred p] :
    (∀ i : α, β i) ≃ (∀ i : { x // p x }, β i) × ∀ i : { x // ¬p x }, β i 
goal: ((i : α) → β i) ≃ ((i : { x // p x }) → β ↑i) × ((i : { x // ¬p x }) → β ↑i)

full_name: Equiv.piEquivPiSubtypeProd_symm_apply
code: /-- The type `∀ (i : α), β i` can be split as a product by separating the indices in `α`
depending on whether they satisfy a predicate `p` or not. -/
@[simps]
def piEquivPiSubtypeProd {α : Type*} (p : α → Prop) (β : α → Type*) [DecidablePred p] :
    (∀ i : α, β i) ≃ (∀ i : { x // p x }, β i) × ∀ i : { x // ¬p x }, β i 
goal: (Equiv.piEquivPiSubtypeProd p β).symm f x = if h : p x then f.1 ⟨x, h⟩ else f.2 ⟨x, h⟩

full_name: Equiv.piSplitAt
code: /-- A product of types can be split as the binary product of one of the types and the product
  of all the remaining types. -/
@[simps]
def piSplitAt {α : Type*} [DecidableEq α] (i : α) (β : α → Type*) :
    (∀ j, β j) ≃ β i × ∀ j : { j // j ≠ i }, β j 
goal: ((j : α) → β j) ≃ β i × ((j : { j // j ≠ i }) → β ↑j)

full_name: Equiv.piSplitAt_symm_apply
code: /-- A product of types can be split as the binary product of one of the types and the product
  of all the remaining types. -/
@[simps]
def piSplitAt {α : Type*} [DecidableEq α] (i : α) (β : α → Type*) :
    (∀ j, β j) ≃ β i × ∀ j : { j // j ≠ i }, β j 
goal: (Equiv.piSplitAt i β).symm f j = if h : j = i then ⋯ ▸ f.1 else f.2 ⟨j, h⟩

full_name: Equiv.piSplitAt_apply
code: /-- A product of types can be split as the binary product of one of the types and the product
  of all the remaining types. -/
@[simps]
def piSplitAt {α : Type*} [DecidableEq α] (i : α) (β : α → Type*) :
    (∀ j, β j) ≃ β i × ∀ j : { j // j ≠ i }, β j 
goal: (Equiv.piSplitAt i β) f = (f i, fun j => f ↑j)

full_name: Equiv.funSplitAt
code: /-- A product of copies of a type can be split as the binary product of one copy and the product
  of all the remaining copies. -/
@[simps!]
def funSplitAt {α : Type*} [DecidableEq α] (i : α) (β : Type*) :
    (α → β) ≃ β × ({ j // j ≠ i } → β) 
goal: (α → β) ≃ β × ({ j // j ≠ i } → β)

full_name: Equiv.funSplitAt_apply
code: /-- A product of copies of a type can be split as the binary product of one copy and the product
  of all the remaining copies. -/
@[simps!]
def funSplitAt {α : Type*} [DecidableEq α] (i : α) (β : Type*) :
    (α → β) ≃ β × ({ j // j ≠ i } → β) 
goal: (Equiv.funSplitAt i β) f = (f i, fun j => f ↑j)

full_name: Equiv.funSplitAt_symm_apply
code: /-- A product of copies of a type can be split as the binary product of one copy and the product
  of all the remaining copies. -/
@[simps!]
def funSplitAt {α : Type*} [DecidableEq α] (i : α) (β : Type*) :
    (α → β) ≃ β × ({ j // j ≠ i } → β) 
goal: (Equiv.funSplitAt i β).symm f j = if h : j = i then f.1 else f.2 ⟨j, ⋯⟩

full_name: Equiv.subtypeEquivCodomain
code: /-- The type of all functions `X → Y` with prescribed values for all `x' ≠ x`
is equivalent to the codomain `Y`. -/
def subtypeEquivCodomain (f : { x' // x' ≠ x } → Y) :
    { g : X → Y // g ∘ (↑) = f } ≃ Y 
goal: { g // g ∘ Subtype.val = f } ≃ Y

full_name: Equiv.coe_subtypeEquivCodomain
code: @[simp]
theorem coe_subtypeEquivCodomain (f : { x' // x' ≠ x } → Y) :
    (subtypeEquivCodomain f : _ → Y) =
      fun g : { g : X → Y // g ∘ (↑) = f } => (g : X → Y) x 
goal: ⇑(Equiv.subtypeEquivCodomain f) = fun g => ↑g x

full_name: Equiv.subtypeEquivCodomain_apply
code: @[simp]
theorem subtypeEquivCodomain_apply (f : { x' // x' ≠ x } → Y) (g) :
    subtypeEquivCodomain f g = (g : X → Y) x 
goal: (Equiv.subtypeEquivCodomain f) g = ↑g x

full_name: Equiv.coe_subtypeEquivCodomain_symm
code: theorem coe_subtypeEquivCodomain_symm (f : { x' // x' ≠ x } → Y) :
    ((subtypeEquivCodomain f).symm : Y → _) = fun y =>
      ⟨fun x' => if h : x' ≠ x then f ⟨x', h⟩ else y, by
        funext x'
        simp only [ne_eq, dite_not, comp_apply, Subtype.coe_eta, dite_eq_ite, ite_eq_right_iff]
        intro w
        exfalso
        exact x'.property w⟩ 
goal: ⇑(Equiv.subtypeEquivCodomain f).symm = fun y => ⟨fun x' => if h : x' ≠ x then f ⟨x', h⟩ else y, ⋯⟩

full_name: Equiv.subtypeEquivCodomain_symm_apply
code: @[simp]
theorem subtypeEquivCodomain_symm_apply (f : { x' // x' ≠ x } → Y) (y : Y) (x' : X) :
    ((subtypeEquivCodomain f).symm y : X → Y) x' = if h : x' ≠ x then f ⟨x', h⟩ else y 
goal: ↑((Equiv.subtypeEquivCodomain f).symm y) x' = if h : x' ≠ x then f ⟨x', h⟩ else y

full_name: Equiv.subtypeEquivCodomain_symm_apply_eq
code: theorem subtypeEquivCodomain_symm_apply_eq (f : { x' // x' ≠ x } → Y) (y : Y) :
    ((subtypeEquivCodomain f).symm y : X → Y) x = y 
goal: ↑((Equiv.subtypeEquivCodomain f).symm y) x = y

full_name: Equiv.subtypeEquivCodomain_symm_apply_ne
code: theorem subtypeEquivCodomain_symm_apply_ne
    (f : { x' // x' ≠ x } → Y) (y : Y) (x' : X) (h : x' ≠ x) :
    ((subtypeEquivCodomain f).symm y : X → Y) x' = f ⟨x', h⟩ 
goal: ↑((Equiv.subtypeEquivCodomain f).symm y) x' = f ⟨x', h⟩

full_name: Equiv.instCanLiftForallCoeBijective
code: instance : CanLift (α → β) (α ≃ β) (↑) Bijective 
goal: CanLift (α → β) (α ≃ β) DFunLike.coe Function.Bijective

full_name: Equiv.Perm.extendDomain
code: /-- Extend the domain of `e : Equiv.Perm α` to one that is over `β` via `f : α → Subtype p`,
where `p : β → Prop`, permuting only the `b : β` that satisfy `p b`.
This can be used to extend the domain across a function `f : α → β`,
keeping everything outside of `Set.range f` fixed. For this use-case `Equiv` given by `f` can
be constructed by `Equiv.of_leftInverse'` or `Equiv.of_leftInverse` when there is a known
inverse, or `Equiv.ofInjective` in the general case.
-/
def Perm.extendDomain : Perm β' 
goal: Equiv.Perm β'

full_name: Equiv.Perm.extendDomain_apply_image
code: @[simp]
theorem Perm.extendDomain_apply_image (a : α') : e.extendDomain f (f a) = f (e a) 
goal: (e.extendDomain f) ↑(f a) = ↑(f (e a))

full_name: Equiv.Perm.extendDomain_apply_subtype
code: theorem Perm.extendDomain_apply_subtype {b : β'} (h : p b) :
    e.extendDomain f b = f (e (f.symm ⟨b, h⟩)) 
goal: (e.extendDomain f) b = ↑(f (e (f.symm ⟨b, h⟩)))

full_name: Equiv.Perm.extendDomain_apply_not_subtype
code: theorem Perm.extendDomain_apply_not_subtype {b : β'} (h : ¬p b) : e.extendDomain f b = b 
goal: (e.extendDomain f) b = b

full_name: Equiv.Perm.extendDomain_refl
code: @[simp]
theorem Perm.extendDomain_refl : Perm.extendDomain (Equiv.refl _) f = Equiv.refl _ 
goal: Equiv.Perm.extendDomain (Equiv.refl α') f = Equiv.refl β'

full_name: Equiv.Perm.extendDomain_symm
code: @[simp]
theorem Perm.extendDomain_symm : (e.extendDomain f).symm = Perm.extendDomain e.symm f 
goal: Equiv.symm (e.extendDomain f) = Equiv.Perm.extendDomain (Equiv.symm e) f

full_name: Equiv.Perm.extendDomain_trans
code: theorem Perm.extendDomain_trans (e e' : Perm α') :
    (e.extendDomain f).trans (e'.extendDomain f) = Perm.extendDomain (e.trans e') f 
goal: Equiv.trans (e.extendDomain f) (e'.extendDomain f) = Equiv.Perm.extendDomain (Equiv.trans e e') f

full_name: Equiv.subtypeQuotientEquivQuotientSubtype
code: /-- Subtype of the quotient is equivalent to the quotient of the subtype. Let `α` be a setoid with
equivalence relation `~`. Let `p₂` be a predicate on the quotient type `α/~`, and `p₁` be the lift
of this predicate to `α`: `p₁ a ↔ p₂ ⟦a⟧`. Let `~₂` be the restriction of `~` to `{x // p₁ x}`.
Then `{x // p₂ x}` is equivalent to the quotient of `{x // p₁ x}` by `~₂`. -/
def subtypeQuotientEquivQuotientSubtype (p₁ : α → Prop) {s₁ : Setoid α} {s₂ : Setoid (Subtype p₁)}
    (p₂ : Quotient s₁ → Prop) (hp₂ : ∀ a, p₁ a ↔ p₂ ⟦a⟧)
    (h : ∀ x y : Subtype p₁, s₂.r x y ↔ s₁.r x y) : {x // p₂ x} ≃ Quotient s₂ 
goal: { x // p₂ x } ≃ Quotient s₂

full_name: Equiv.subtypeQuotientEquivQuotientSubtype_mk
code: @[simp]
theorem subtypeQuotientEquivQuotientSubtype_mk (p₁ : α → Prop)
    [s₁ : Setoid α] [s₂ : Setoid (Subtype p₁)] (p₂ : Quotient s₁ → Prop) (hp₂ : ∀ a, p₁ a ↔ p₂ ⟦a⟧)
    (h : ∀ x y : Subtype p₁, @Setoid.r _ s₂ x y ↔ (x : α) ≈ y)
    (x hx) : subtypeQuotientEquivQuotientSubtype p₁ p₂ hp₂ h ⟨⟦x⟧, hx⟩ = ⟦⟨x, (hp₂ _).2 hx⟩⟧ 
goal: (Equiv.subtypeQuotientEquivQuotientSubtype p₁ p₂ hp₂ h) ⟨⟦x⟧, hx⟩ = ⟦⟨x, ⋯⟩⟧

full_name: Equiv.subtypeQuotientEquivQuotientSubtype_symm_mk
code: @[simp]
theorem subtypeQuotientEquivQuotientSubtype_symm_mk (p₁ : α → Prop)
    [s₁ : Setoid α] [s₂ : Setoid (Subtype p₁)] (p₂ : Quotient s₁ → Prop) (hp₂ : ∀ a, p₁ a ↔ p₂ ⟦a⟧)
    (h : ∀ x y : Subtype p₁, @Setoid.r _ s₂ x y ↔ (x : α) ≈ y) (x) :
    (subtypeQuotientEquivQuotientSubtype p₁ p₂ hp₂ h).symm ⟦x⟧ = ⟨⟦x⟧, (hp₂ _).1 x.property⟩ 
goal: (Equiv.subtypeQuotientEquivQuotientSubtype p₁ p₂ hp₂ h).symm ⟦x⟧ = ⟨⟦↑x⟧, ⋯⟩

full_name: Equiv.swapCore
code: /-- A helper function for `Equiv.swap`. -/
def swapCore (a b r : α) : α 
goal: α

full_name: Equiv.swapCore_self
code: theorem swapCore_self (r a : α) : swapCore a a r = r 
goal: Equiv.swapCore a a r = r

full_name: Equiv.swapCore_swapCore
code: theorem swapCore_swapCore (r a b : α) : swapCore a b (swapCore a b r) = r 
goal: Equiv.swapCore a b (Equiv.swapCore a b r) = r

full_name: Equiv.swapCore_comm
code: theorem swapCore_comm (r a b : α) : swapCore a b r = swapCore b a r 
goal: Equiv.swapCore a b r = Equiv.swapCore b a r

full_name: Equiv.swap
code: /-- `swap a b` is the permutation that swaps `a` and `b` and
  leaves other values as is. -/
def swap (a b : α) : Perm α 
goal: Equiv.Perm α

full_name: Equiv.swap_self
code: @[simp]
theorem swap_self (a : α) : swap a a = Equiv.refl _ 
goal: Equiv.swap a a = Equiv.refl α

full_name: Equiv.swap_comm
code: theorem swap_comm (a b : α) : swap a b = swap b a 
goal: Equiv.swap a b = Equiv.swap b a

full_name: Equiv.swap_apply_def
code: theorem swap_apply_def (a b x : α) : swap a b x = if x = a then b else if x = b then a else x 
goal: (Equiv.swap a b) x = if x = a then b else if x = b then a else x

full_name: Equiv.swap_apply_left
code: @[simp]
theorem swap_apply_left (a b : α) : swap a b a = b 
goal: (Equiv.swap a b) a = b

full_name: Equiv.swap_apply_right
code: @[simp]
theorem swap_apply_right (a b : α) : swap a b b = a 
goal: (Equiv.swap a b) b = a

full_name: Equiv.swap_apply_of_ne_of_ne
code: theorem swap_apply_of_ne_of_ne {a b x : α} : x ≠ a → x ≠ b → swap a b x = x 
goal: x ≠ a → x ≠ b → (Equiv.swap a b) x = x

full_name: Equiv.eq_or_eq_of_swap_apply_ne_self
code: theorem eq_or_eq_of_swap_apply_ne_self {a b x : α} (h : swap a b x ≠ x) : x = a ∨ x = b 
goal: x = a ∨ x = b

full_name: Equiv.swap_swap
code: @[simp]
theorem swap_swap (a b : α) : (swap a b).trans (swap a b) = Equiv.refl _ 
goal: Equiv.trans (Equiv.swap a b) (Equiv.swap a b) = Equiv.refl α

full_name: Equiv.symm_swap
code: @[simp]
theorem symm_swap (a b : α) : (swap a b).symm = swap a b 
goal: Equiv.symm (Equiv.swap a b) = Equiv.swap a b

full_name: Equiv.swap_eq_refl_iff
code: @[simp]
theorem swap_eq_refl_iff {x y : α} : swap x y = Equiv.refl _ ↔ x = y 
goal: Equiv.swap x y = Equiv.refl α ↔ x = y

full_name: Equiv.swap_comp_apply
code: theorem swap_comp_apply {a b x : α} (π : Perm α) :
    π.trans (swap a b) x = if π x = a then b else if π x = b then a else π x 
goal: (Equiv.trans π (Equiv.swap a b)) x = if π x = a then b else if π x = b then a else π x

full_name: Equiv.swap_eq_update
code: theorem swap_eq_update (i j : α) : (Equiv.swap i j : α → α) = update (update id j i) i j 
goal: ⇑(Equiv.swap i j) = Function.update (Function.update id j i) i j

full_name: Equiv.comp_swap_eq_update
code: theorem comp_swap_eq_update (i j : α) (f : α → β) :
    f ∘ Equiv.swap i j = update (update f j (f i)) i (f j) 
goal: f ∘ ⇑(Equiv.swap i j) = Function.update (Function.update f j (f i)) i (f j)

full_name: Equiv.symm_trans_swap_trans
code: @[simp]
theorem symm_trans_swap_trans [DecidableEq β] (a b : α) (e : α ≃ β) :
    (e.symm.trans (swap a b)).trans e = swap (e a) (e b) 
goal: (e.symm.trans (Equiv.swap a b)).trans e = Equiv.swap (e a) (e b)

full_name: Equiv.trans_swap_trans_symm
code: @[simp]
theorem trans_swap_trans_symm [DecidableEq β] (a b : β) (e : α ≃ β) :
    (e.trans (swap a b)).trans e.symm = swap (e.symm a) (e.symm b) 
goal: (e.trans (Equiv.swap a b)).trans e.symm = Equiv.swap (e.symm a) (e.symm b)

full_name: Equiv.swap_apply_self
code: @[simp]
theorem swap_apply_self (i j a : α) : swap i j (swap i j a) = a 
goal: (Equiv.swap i j) ((Equiv.swap i j) a) = a

full_name: Equiv.apply_swap_eq_self
code: /-- A function is invariant to a swap if it is equal at both elements -/
theorem apply_swap_eq_self {v : α → β} {i j : α} (hv : v i = v j) (k : α) :
    v (swap i j k) = v k 
goal: v ((Equiv.swap i j) k) = v k

full_name: Equiv.swap_apply_eq_iff
code: theorem swap_apply_eq_iff {x y z w : α} : swap x y z = w ↔ z = swap x y w 
goal: (Equiv.swap x y) z = w ↔ z = (Equiv.swap x y) w

full_name: Equiv.swap_apply_ne_self_iff
code: theorem swap_apply_ne_self_iff {a b x : α} : swap a b x ≠ x ↔ a ≠ b ∧ (x = a ∨ x = b) 
goal: (Equiv.swap a b) x ≠ x ↔ a ≠ b ∧ (x = a ∨ x = b)

full_name: Equiv.Perm.sumCongr_swap_refl
code: @[simp]
theorem sumCongr_swap_refl {α β : Sort _} [DecidableEq α] [DecidableEq β] (i j : α) :
    Equiv.Perm.sumCongr (Equiv.swap i j) (Equiv.refl β) = Equiv.swap (Sum.inl i) (Sum.inl j) 
goal: (Equiv.swap i j).sumCongr (Equiv.refl β) = Equiv.swap (Sum.inl i) (Sum.inl j)

full_name: Equiv.Perm.sumCongr_refl_swap
code: @[simp]
theorem sumCongr_refl_swap {α β : Sort _} [DecidableEq α] [DecidableEq β] (i j : β) :
    Equiv.Perm.sumCongr (Equiv.refl α) (Equiv.swap i j) = Equiv.swap (Sum.inr i) (Sum.inr j) 
goal: Equiv.Perm.sumCongr (Equiv.refl α) (Equiv.swap i j) = Equiv.swap (Sum.inr i) (Sum.inr j)

full_name: Equiv.setValue
code: /-- Augment an equivalence with a prescribed mapping `f a = b` -/
def setValue (f : α ≃ β) (a : α) (b : β) : α ≃ β 
goal: α ≃ β

full_name: Equiv.setValue_eq
code: @[simp]
theorem setValue_eq (f : α ≃ β) (a : α) (b : β) : setValue f a b a = b 
goal: (f.setValue a b) a = b

full_name: Function.Involutive.toPerm
code: /-- Convert an involutive function `f` to a permutation with `toFun = invFun = f`. -/
def toPerm (f : α → α) (h : Involutive f) : Equiv.Perm α 
goal: Equiv.Perm α

full_name: Function.Involutive.coe_toPerm
code: @[simp]
theorem coe_toPerm {f : α → α} (h : Involutive f) : (h.toPerm f : α → α) = f 
goal: ⇑(Function.Involutive.toPerm f h) = f

full_name: Function.Involutive.toPerm_symm
code: @[simp]
theorem toPerm_symm {f : α → α} (h : Involutive f) : (h.toPerm f).symm = h.toPerm f 
goal: Equiv.symm (Function.Involutive.toPerm f h) = Function.Involutive.toPerm f h

full_name: Function.Involutive.toPerm_involutive
code: theorem toPerm_involutive {f : α → α} (h : Involutive f) : Involutive (h.toPerm f) 
goal: Function.Involutive ⇑(Function.Involutive.toPerm f h)

full_name: PLift.eq_up_iff_down_eq
code: theorem PLift.eq_up_iff_down_eq {x : PLift α} {y : α} : x = PLift.up y ↔ x.down = y 
goal: x = { down := y } ↔ x.down = y

full_name: Function.Injective.map_swap
code: theorem Function.Injective.map_swap [DecidableEq α] [DecidableEq β] {f : α → β}
    (hf : Function.Injective f) (x y z : α) :
    f (Equiv.swap x y z) = Equiv.swap (f x) (f y) (f z) 
goal: f ((Equiv.swap x y) z) = (Equiv.swap (f x) (f y)) (f z)

full_name: Equiv.piCongrLeft'_symm_apply
code: /-- Transport dependent functions through an equivalence of the base space.
-/
@[simps]
def piCongrLeft' (P : α → Sort*) (e : α ≃ β) : (∀ a, P a) ≃ ∀ b, P (e.symm b) 
goal: (Equiv.piCongrLeft' P e).symm f x = ⋯ ▸ f (e x)

full_name: Equiv.piCongrLeft'_apply
code: /-- Transport dependent functions through an equivalence of the base space.
-/
@[simps]
def piCongrLeft' (P : α → Sort*) (e : α ≃ β) : (∀ a, P a) ≃ ∀ b, P (e.symm b) 
goal: (Equiv.piCongrLeft' P e) f x = f (e.symm x)

full_name: Equiv.piCongrLeft'
code: /-- Transport dependent functions through an equivalence of the base space.
-/
@[simps]
def piCongrLeft' (P : α → Sort*) (e : α ≃ β) : (∀ a, P a) ≃ ∀ b, P (e.symm b) 
goal: ((a : α) → P a) ≃ ((b : β) → P (e.symm b))

full_name: Equiv.piCongrLeft'_symm
code: /-- This lemma is impractical to state in the dependent case. -/
@[simp]
theorem piCongrLeft'_symm (P : Sort*) (e : α ≃ β) :
    (piCongrLeft' (fun _ => P) e).symm = piCongrLeft' _ e.symm 
goal: (Equiv.piCongrLeft' (fun x => P) e).symm = Equiv.piCongrLeft' (fun a => P) e.symm

full_name: Equiv.piCongrLeft'_symm_apply_apply
code: /-- Note: the "obvious" statement `(piCongrLeft' P e).symm g a = g (e a)` doesn't typecheck: the
LHS would have type `P a` while the RHS would have type `P (e.symm (e a))`. This lemma is a way
around it in the case where `a` is of the form `e.symm b`, so we can use `g b` instead of
`g (e (e.symm b))`. -/
lemma piCongrLeft'_symm_apply_apply (P : α → Sort*) (e : α ≃ β) (g : ∀ b, P (e.symm b)) (b : β) :
    (piCongrLeft' P e).symm g (e.symm b) = g b 
goal: (Equiv.piCongrLeft' P e).symm g (e.symm b) = g b

full_name: Equiv.piCongrLeft
code: /-- Transporting dependent functions through an equivalence of the base,
expressed as a "simplification".
-/
def piCongrLeft : (∀ a, P (e a)) ≃ ∀ b, P b 
goal: ((a : α) → P (e a)) ≃ ((b : β) → P b)

full_name: Equiv.piCongrLeft_apply
code: /-- Note: the "obvious" statement `(piCongrLeft P e) f b = f (e.symm b)` doesn't typecheck: the
LHS would have type `P b` while the RHS would have type `P (e (e.symm b))`. For that reason,
we have to explicitly substitute along `e (e.symm b) = b` in the statement of this lemma. -/
@[simp]
lemma piCongrLeft_apply (f : ∀ a, P (e a)) (b : β) :
    (piCongrLeft P e) f b = e.apply_symm_apply b ▸ f (e.symm b) 
goal: (Equiv.piCongrLeft P e) f b = ⋯ ▸ f (e.symm b)

full_name: Equiv.piCongrLeft_symm_apply
code: @[simp]
lemma piCongrLeft_symm_apply (g : ∀ b, P b) (a : α) :
    (piCongrLeft P e).symm g a = g (e a) 
goal: (Equiv.piCongrLeft P e).symm g a = g (e a)

full_name: Equiv.piCongrLeft_apply_apply
code: /-- Note: the "obvious" statement `(piCongrLeft P e) f b = f (e.symm b)` doesn't typecheck: the
LHS would have type `P b` while the RHS would have type `P (e (e.symm b))`. This lemma is a way
around it in the case where `b` is of the form `e a`, so we can use `f a` instead of
`f (e.symm (e a))`. -/
lemma piCongrLeft_apply_apply (f : ∀ a, P (e a)) (a : α) :
    (piCongrLeft P e) f (e a) = f a 
goal: (Equiv.piCongrLeft P e) f (e a) = f a

full_name: Equiv.piCongrLeft_apply_eq_cast
code: lemma piCongrLeft_apply_eq_cast {P : β → Sort v} {e : α ≃ β}
    (f : (a : α) → P (e a)) (b : β) :
    piCongrLeft P e f b = cast (congr_arg P (e.apply_symm_apply b)) (f (e.symm b)) 
goal: (Equiv.piCongrLeft P e) f b = cast ⋯ (f (e.symm b))

full_name: Equiv.piCongrLeft_sum_inl
code: theorem piCongrLeft_sum_inl (π : ι'' → Type*) (e : ι ⊕ ι' ≃ ι'') (f : ∀ i, π (e (inl i)))
    (g : ∀ i, π (e (inr i))) (i : ι) :
    piCongrLeft π e (sumPiEquivProdPi (fun x => π (e x)) |>.symm (f, g)) (e (inl i)) = f i 
goal: (Equiv.piCongrLeft π e) ((Equiv.sumPiEquivProdPi fun x => π (e x)).symm (f, g)) (e (Sum.inl i)) = f i

full_name: Equiv.piCongrLeft_sum_inr
code: theorem piCongrLeft_sum_inr (π : ι'' → Type*) (e : ι ⊕ ι' ≃ ι'') (f : ∀ i, π (e (inl i)))
    (g : ∀ i, π (e (inr i))) (j : ι') :
    piCongrLeft π e (sumPiEquivProdPi (fun x => π (e x)) |>.symm (f, g)) (e (inr j)) = g j 
goal: (Equiv.piCongrLeft π e) ((Equiv.sumPiEquivProdPi fun x => π (e x)).symm (f, g)) (e (Sum.inr j)) = g j

full_name: Equiv.piCongr
code: /-- Transport dependent functions through
an equivalence of the base spaces and a family
of equivalences of the matching fibers.
-/
def piCongr : (∀ a, W a) ≃ ∀ b, Z b 
goal: ((a : α) → W a) ≃ ((b : β) → Z b)

full_name: Equiv.coe_piCongr_symm
code: @[simp]
theorem coe_piCongr_symm : ((h₁.piCongr h₂).symm :
    (∀ b, Z b) → ∀ a, W a) = fun f a => (h₂ a).symm (f (h₁ a)) 
goal: ⇑(h₁.piCongr h₂).symm = fun f a => (h₂ a).symm (f (h₁ a))

full_name: Equiv.piCongr_symm_apply
code: theorem piCongr_symm_apply (f : ∀ b, Z b) :
    (h₁.piCongr h₂).symm f = fun a => (h₂ a).symm (f (h₁ a)) 
goal: (h₁.piCongr h₂).symm f = fun a => (h₂ a).symm (f (h₁ a))

full_name: Equiv.piCongr_apply_apply
code: @[simp]
theorem piCongr_apply_apply (f : ∀ a, W a) (a : α) : h₁.piCongr h₂ f (h₁ a) = h₂ a (f a) 
goal: (h₁.piCongr h₂) f (h₁ a) = (h₂ a) (f a)

full_name: Equiv.piCongr'
code: /-- Transport dependent functions through
an equivalence of the base spaces and a family
of equivalences of the matching fibres.
-/
def piCongr' : (∀ a, W a) ≃ ∀ b, Z b 
goal: ((a : α) → W a) ≃ ((b : β) → Z b)

full_name: Equiv.coe_piCongr'
code: @[simp]
theorem coe_piCongr' :
    (h₁.piCongr' h₂ : (∀ a, W a) → ∀ b, Z b) = fun f b => h₂ b <| f <| h₁.symm b 
goal: ⇑(h₁.piCongr' h₂) = fun f b => (h₂ b) (f (h₁.symm b))

full_name: Equiv.piCongr'_apply
code: theorem piCongr'_apply (f : ∀ a, W a) : h₁.piCongr' h₂ f = fun b => h₂ b <| f <| h₁.symm b 
goal: (h₁.piCongr' h₂) f = fun b => (h₂ b) (f (h₁.symm b))

full_name: Equiv.piCongr'_symm_apply_symm_apply
code: @[simp]
theorem piCongr'_symm_apply_symm_apply (f : ∀ b, Z b) (b : β) :
    (h₁.piCongr' h₂).symm f (h₁.symm b) = (h₂ b).symm (f b) 
goal: (h₁.piCongr' h₂).symm f (h₁.symm b) = (h₂ b).symm (f b)

full_name: Equiv.semiconj_conj
code: theorem semiconj_conj (f : α₁ → α₁) : Semiconj e f (e.conj f) 
goal: Function.Semiconj (⇑e) f (e.conj f)

full_name: Equiv.semiconj₂_conj
code: theorem semiconj₂_conj : Semiconj₂ e f (e.arrowCongr e.conj f) 
goal: Function.Semiconj₂ (⇑e) f ((e.arrowCongr e.conj) f)

full_name: Equiv.instAssociativeCoeForallForallArrowCongr
code: instance [Std.Associative f] : Std.Associative (e.arrowCongr (e.arrowCongr e) f) 
goal: Std.Associative ((e.arrowCongr (e.arrowCongr e)) f)

full_name: Equiv.instIdempotentOpCoeForallForallArrowCongr
code: instance [Std.IdempotentOp f] : Std.IdempotentOp (e.arrowCongr (e.arrowCongr e) f) 
goal: Std.IdempotentOp ((e.arrowCongr (e.arrowCongr e)) f)

full_name: Equiv.instIsLeftCancelCoeForallForallArrowCongr
code: instance [IsLeftCancel α₁ f] : IsLeftCancel β₁ (e.arrowCongr (e.arrowCongr e) f) 
goal: IsLeftCancel β₁ ((e.arrowCongr (e.arrowCongr e)) f)

full_name: Equiv.instIsRightCancelCoeForallForallArrowCongr
code: instance [IsRightCancel α₁ f] : IsRightCancel β₁ (e.arrowCongr (e.arrowCongr e) f) 
goal: IsRightCancel β₁ ((e.arrowCongr (e.arrowCongr e)) f)

full_name: Equiv.ulift_symm_down
code: @[simp]
theorem ulift_symm_down (x : α) : (Equiv.ulift.{u, v}.symm x).down = x 
goal: (Equiv.ulift.symm x).down = x

full_name: Function.Injective.swap_apply
code: theorem Function.Injective.swap_apply
    [DecidableEq α] [DecidableEq β] {f : α → β} (hf : Function.Injective f) (x y z : α) :
    Equiv.swap (f x) (f y) (f z) = f (Equiv.swap x y z) 
goal: (Equiv.swap (f x) (f y)) (f z) = f ((Equiv.swap x y) z)

full_name: Function.Injective.swap_comp
code: theorem Function.Injective.swap_comp
    [DecidableEq α] [DecidableEq β] {f : α → β} (hf : Function.Injective f) (x y : α) :
    Equiv.swap (f x) (f y) ∘ f = f ∘ Equiv.swap x y 
goal: ⇑(Equiv.swap (f x) (f y)) ∘ f = f ∘ ⇑(Equiv.swap x y)

full_name: subsingletonProdSelfEquiv
code: /-- If `α` is a subsingleton, then it is equivalent to `α × α`. -/
def subsingletonProdSelfEquiv [Subsingleton α] : α × α ≃ α 
goal: α × α ≃ α

full_name: equivOfSubsingletonOfSubsingleton
code: /-- To give an equivalence between two subsingleton types, it is sufficient to give any two
    functions between them. -/
def equivOfSubsingletonOfSubsingleton [Subsingleton α] [Subsingleton β] (f : α → β) (g : β → α) :
    α ≃ β 
goal: α ≃ β

full_name: Equiv.punitOfNonemptyOfSubsingleton
code: /-- A nonempty subsingleton type is (noncomputably) equivalent to `PUnit`. -/
noncomputable def Equiv.punitOfNonemptyOfSubsingleton [h : Nonempty α] [Subsingleton α] :
    α ≃ PUnit 
goal: α ≃ PUnit.{u_2}

full_name: uniqueUniqueEquiv
code: /-- `Unique (Unique α)` is equivalent to `Unique α`. -/
def uniqueUniqueEquiv : Unique (Unique α) ≃ Unique α 
goal: Unique (Unique α) ≃ Unique α

full_name: uniqueEquivEquivUnique
code: /-- If `Unique β`, then `Unique α` is equivalent to `α ≃ β`. -/
def uniqueEquivEquivUnique (α : Sort u) (β : Sort v) [Unique β] : Unique α ≃ (α ≃ β) 
goal: Unique α ≃ (α ≃ β)

full_name: Function.update_comp_equiv
code: theorem update_comp_equiv [DecidableEq α'] [DecidableEq α] (f : α → β)
    (g : α' ≃ α) (a : α) (v : β) :
    update f a v ∘ g = update (f ∘ g) (g.symm a) v 
goal: Function.update f a v ∘ ⇑g = Function.update (f ∘ ⇑g) (g.symm a) v

full_name: Function.update_apply_equiv_apply
code: theorem update_apply_equiv_apply [DecidableEq α'] [DecidableEq α] (f : α → β)
    (g : α' ≃ α) (a : α) (v : β) (a' : α') : update f a v (g a') = update (f ∘ g) (g.symm a) v a' 
goal: Function.update f a v (g a') = Function.update (f ∘ ⇑g) (g.symm a) v a'

full_name: Function.piCongrLeft'_update
code: theorem piCongrLeft'_update [DecidableEq α] [DecidableEq β] (P : α → Sort*) (e : α ≃ β)
    (f : ∀ a, P a) (b : β) (x : P (e.symm b)) :
    e.piCongrLeft' P (update f (e.symm b) x) = update (e.piCongrLeft' P f) b x 
goal: (Equiv.piCongrLeft' P e) (Function.update f (e.symm b) x) = Function.update ((Equiv.piCongrLeft' P e) f) b x

full_name: Function.piCongrLeft'_symm_update
code: theorem piCongrLeft'_symm_update [DecidableEq α] [DecidableEq β] (P : α → Sort*) (e : α ≃ β)
    (f : ∀ b, P (e.symm b)) (b : β) (x : P (e.symm b)) :
    (e.piCongrLeft' P).symm (update f b x) = update ((e.piCongrLeft' P).symm f) (e.symm b) x 
goal: (Equiv.piCongrLeft' P e).symm (Function.update f b x) = Function.update ((Equiv.piCongrLeft' P e).symm f) (e.symm b) x