l3lab/ntp-mathlib huggingface dataset:
/-- `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 (α₁ × β₁) where
  toFun ab := if ab.fst = a then (a, e ab.snd) else ab
  invFun ab := if ab.fst = a then (a, e.symm ab.snd) else ab
  left_inv := by
    rintro ⟨k', x⟩
    dsimp only
    split_ifs with h₁ h₂
    · simp [h₁]
    · 

Proof state:
case neg
α₁ : Type ?u.51937
β₁ : Type ?u.51936
inst✝ : DecidableEq α₁
a : α₁
e : Perm β₁
k' : α₁
x : β₁
h₁ : k' = a
h₂ : ¬(a, e x).1 = a
⊢ (a, e x) = (k', x)

Next tactic:
simp at h₂
/-- `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 (α₁ × β₁) where
  toFun ab := if ab.fst = a then (a, e ab.snd) else ab
  invFun ab := if ab.fst = a then (a, e.symm ab.snd) else ab
  left_inv := by
    rintro ⟨k', x⟩
    dsimp only
    split_ifs with h₁ h₂
    · simp [h₁]
    · simp at h₂
    · 

Proof state:
case neg
α₁ : Type ?u.51937
β₁ : Type ?u.51936
inst✝ : DecidableEq α₁
a : α₁
e : Perm β₁
k' : α₁
x : β₁
h₁ : ¬k' = a
⊢ (k', x) = (k', x)

Next tactic:
simp
/-- `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 (α₁ × β₁) where
  toFun ab := if ab.fst = a then (a, e ab.snd) else ab
  invFun ab := if ab.fst = a then (a, e.symm ab.snd) else ab
  left_inv := by
    rintro ⟨k', x⟩
    dsimp only
    split_ifs with h₁ h₂
    · simp [h₁]
    · simp at h₂
    · simp
  right_inv := by
    

Proof state:
α₁ : Type ?u.51937
β₁ : Type ?u.51936
inst✝ : DecidableEq α₁
a : α₁
e : Perm β₁
⊢ Function.RightInverse (fun ab => if ab.1 = a then (a, e.symm ab.2) else ab) fun ab =>
    if ab.1 = a then (a, e ab.2) else ab

Next tactic:
rintro ⟨k', x⟩
/-- `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 (α₁ × β₁) where
  toFun ab := if ab.fst = a then (a, e ab.snd) else ab
  invFun ab := if ab.fst = a then (a, e.symm ab.snd) else ab
  left_inv := by
    rintro ⟨k', x⟩
    dsimp only
    split_ifs with h₁ h₂
    · simp [h₁]
    · simp at h₂
    · simp
  right_inv := by
    rintro ⟨k', x⟩
    

Proof state:
case mk
α₁ : Type ?u.51937
β₁ : Type ?u.51936
inst✝ : DecidableEq α₁
a : α₁
e : Perm β₁
k' : α₁
x : β₁
⊢ (fun ab => if ab.1 = a then (a, e ab.2) else ab) ((fun ab => if ab.1 = a then (a, e.symm ab.2) else ab) (k', x)) =
    (k', x)

Next tactic:
dsimp only
/-- `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 (α₁ × β₁) where
  toFun ab := if ab.fst = a then (a, e ab.snd) else ab
  invFun ab := if ab.fst = a then (a, e.symm ab.snd) else ab
  left_inv := by
    rintro ⟨k', x⟩
    dsimp only
    split_ifs with h₁ h₂
    · simp [h₁]
    · simp at h₂
    · simp
  right_inv := by
    rintro ⟨k', x⟩
    dsimp only
    

Proof state:
case mk
α₁ : Type ?u.51937
β₁ : Type ?u.51936
inst✝ : DecidableEq α₁
a : α₁
e : Perm β₁
k' : α₁
x : β₁
⊢ (if (if k' = a then (a, e.symm x) else (k', x)).1 = a then (a, e (if k' = a then (a, e.symm x) else (k', x)).2)
    else if k' = a then (a, e.symm x) else (k', x)) =
    (k', x)

Next tactic:
split_ifs with h₁ h₂
/-- `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 (α₁ × β₁) where
  toFun ab := if ab.fst = a then (a, e ab.snd) else ab
  invFun ab := if ab.fst = a then (a, e.symm ab.snd) else ab
  left_inv := by
    rintro ⟨k', x⟩
    dsimp only
    split_ifs with h₁ h₂
    · simp [h₁]
    · simp at h₂
    · simp
  right_inv := by
    rintro ⟨k', x⟩
    dsimp only
    split_ifs with h₁ h₂
    · 

Proof state:
case pos
α₁ : Type ?u.51937
β₁ : Type ?u.51936
inst✝ : DecidableEq α₁
a : α₁
e : Perm β₁
k' : α₁
x : β₁
h₁ : k' = a
h₂ : (a, e.symm x).1 = a
⊢ (a, e (a, e.symm x).2) = (k', x)

Next tactic:
simp [h₁]
/-- `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 (α₁ × β₁) where
  toFun ab := if ab.fst = a then (a, e ab.snd) else ab
  invFun ab := if ab.fst = a then (a, e.symm ab.snd) else ab
  left_inv := by
    rintro ⟨k', x⟩
    dsimp only
    split_ifs with h₁ h₂
    · simp [h₁]
    · simp at h₂
    · simp
  right_inv := by
    rintro ⟨k', x⟩
    dsimp only
    split_ifs with h₁ h₂
    · simp [h₁]
    · 

Proof state:
case neg
α₁ : Type ?u.51937
β₁ : Type ?u.51936
inst✝ : DecidableEq α₁
a : α₁
e : Perm β₁
k' : α₁
x : β₁
h₁ : k' = a
h₂ : ¬(a, e.symm x).1 = a
⊢ (a, e.symm x) = (k', x)

Next tactic:
simp at h₂
/-- `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 (α₁ × β₁) where
  toFun ab := if ab.fst = a then (a, e ab.snd) else ab
  invFun ab := if ab.fst = a then (a, e.symm ab.snd) else ab
  left_inv := by
    rintro ⟨k', x⟩
    dsimp only
    split_ifs with h₁ h₂
    · simp [h₁]
    · simp at h₂
    · simp
  right_inv := by
    rintro ⟨k', x⟩
    dsimp only
    split_ifs with h₁ h₂
    · simp [h₁]
    · simp at h₂
    · 

Proof state:
case neg
α₁ : Type ?u.51937
β₁ : Type ?u.51936
inst✝ : DecidableEq α₁
a : α₁
e : Perm β₁
k' : α₁
x : β₁
h₁ : ¬k' = a
⊢ (k', x) = (k', x)

Next tactic:
simp
theorem eq_of_prodExtendRight_ne {e : Perm β₁} {a a' : α₁} {b : β₁}
    (h : prodExtendRight a e (a', b) ≠ (a', b)) : a' = a := by
  

Proof state:
α₁ : Type u_2
β₁ : Type u_1
inst✝ : DecidableEq α₁
a✝ : α₁
e✝ e : Perm β₁
a a' : α₁
b : β₁
h : (prodExtendRight a e) (a', b) ≠ (a', b)
⊢ a' = a

Next tactic:
contrapose! h
theorem eq_of_prodExtendRight_ne {e : Perm β₁} {a a' : α₁} {b : β₁}
    (h : prodExtendRight a e (a', b) ≠ (a', b)) : a' = a := by
  contrapose! h
  

Proof state:
α₁ : Type u_2
β₁ : Type u_1
inst✝ : DecidableEq α₁
a✝ : α₁
e✝ e : Perm β₁
a a' : α₁
b : β₁
h : a' ≠ a
⊢ (prodExtendRight a e) (a', b) = (a', b)

Next tactic:
exact prodExtendRight_apply_ne _ h _
@[simp]
theorem fst_prodExtendRight (ab : α₁ × β₁) : (prodExtendRight a e ab).fst = ab.fst := by
  

Proof state:
α₁ : Type u_1
β₁ : Type u_2
inst✝ : DecidableEq α₁
a : α₁
e : Perm β₁
ab : α₁ × β₁
⊢ ((prodExtendRight a e) ab).1 = ab.1

Next tactic:
rw [prodExtendRight]
@[simp]
theorem fst_prodExtendRight (ab : α₁ × β₁) : (prodExtendRight a e ab).fst = ab.fst := by
  rw [prodExtendRight]
  

Proof state:
α₁ : Type u_1
β₁ : Type u_2
inst✝ : DecidableEq α₁
a : α₁
e : Perm β₁
ab : α₁ × β₁
⊢ ({ toFun := fun ab => if ab.1 = a then (a, e ab.2) else ab,
          invFun := fun ab => if ab.1 = a then (a, e.symm ab.2) else ab,
          left_inv :=
            (_ :
              ∀ (x : α₁ × β₁),
                (fun ab => if ab.1 = a then (a, e.symm ab.2) else ab)
                    ((fun ab => if ab.1 = a then (a, e ab.2) else ab) x) =
                  x),
          right_inv :=
            (_ :
              ∀ (x : α₁ × β₁),
                (fun ab => if ab.1 = a then (a, e ab.2) else ab)
                    ((fun ab => if ab.1 = a then (a, e.symm ab.2) else ab) x) =
                  x) }
        ab).1 =
    ab.1

Next tactic:
dsimp
@[simp]
theorem fst_prodExtendRight (ab : α₁ × β₁) : (prodExtendRight a e ab).fst = ab.fst := by
  rw [prodExtendRight]
  dsimp
  

Proof state:
α₁ : Type u_1
β₁ : Type u_2
inst✝ : DecidableEq α₁
a : α₁
e : Perm β₁
ab : α₁ × β₁
⊢ (if ab.1 = a then (a, e ab.2) else ab).1 = ab.1

Next tactic:
split_ifs with h
@[simp]
theorem fst_prodExtendRight (ab : α₁ × β₁) : (prodExtendRight a e ab).fst = ab.fst := by
  rw [prodExtendRight]
  dsimp
  split_ifs with h
  · 

Proof state:
case pos
α₁ : Type u_1
β₁ : Type u_2
inst✝ : DecidableEq α₁
a : α₁
e : Perm β₁
ab : α₁ × β₁
h : ab.1 = a
⊢ (a, e ab.2).1 = ab.1

Next tactic:
rw [h]
@[simp]
theorem fst_prodExtendRight (ab : α₁ × β₁) : (prodExtendRight a e ab).fst = ab.fst := by
  rw [prodExtendRight]
  dsimp
  split_ifs with h
  · rw [h]
  · 

Proof state:
case neg
α₁ : Type u_1
β₁ : Type u_2
inst✝ : DecidableEq α₁
a : α₁
e : Perm β₁
ab : α₁ × β₁
h : ¬ab.1 = a
⊢ ab.1 = ab.1

Next tactic:
rfl
/-- The type of functions to a product `α × β` is equivalent to the type of pairs of functions
`γ → α` and `γ → β`. -/
def arrowProdEquivProdArrow (α β γ : Type*) : (γ → α × β) ≃ (γ → α) × (γ → β) where
  toFun := fun f => (fun c => (f c).1, fun c => (f c).2)
  invFun := fun p c => (p.1 c, p.2 c)
  left_inv := fun f => rfl
  right_inv := fun p => by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
p : (γ → α) × (γ → β)
⊢ (fun f => (fun c => (f c).1, fun c => (f c).2)) ((fun p c => (p.1 c, p.2 c)) p) = p

Next tactic:
cases p
/-- The type of functions to a product `α × β` is equivalent to the type of pairs of functions
`γ → α` and `γ → β`. -/
def arrowProdEquivProdArrow (α β γ : Type*) : (γ → α × β) ≃ (γ → α) × (γ → β) where
  toFun := fun f => (fun c => (f c).1, fun c => (f c).2)
  invFun := fun p c => (p.1 c, p.2 c)
  left_inv := fun f => rfl
  right_inv := fun p => by cases p; 

Proof state:
case mk
α : Type u_1
β : Type u_2
γ : Type u_3
fst✝ : γ → α
snd✝ : γ → β
⊢ (fun f => (fun c => (f c).1, fun c => (f c).2)) ((fun p c => (p.1 c, p.2 c)) (fst✝, snd✝)) = (fst✝, snd✝)

Next tactic:
rfl
/-- 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')
    where
  toFun f := ⟨fun i => f (inl i), fun i' => f (inr i')⟩
  invFun g := Sum.rec g.1 g.2
  left_inv f := by 

Proof state:
ι : Type ?u.56717
ι' : Type ?u.56716
π : ι ⊕ ι' → Type u_1
f : (i : ι ⊕ ι') → π i
⊢ (fun g t => Sum.rec g.1 g.2 t) ((fun f => (fun i => f (inl i), fun i' => f (inr i'))) f) = f

Next tactic:
ext (i | i)
/-- 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')
    where
  toFun f := ⟨fun i => f (inl i), fun i' => f (inr i')⟩
  invFun g := Sum.rec g.1 g.2
  left_inv f := by ext (i | i) <;> 

Proof state:
case h.inl
ι : Type ?u.56717
ι' : Type ?u.56716
π : ι ⊕ ι' → Type u_1
f : (i : ι ⊕ ι') → π i
i : ι
⊢ (fun g t => Sum.rec g.1 g.2 t) ((fun f => (fun i => f (inl i), fun i' => f (inr i'))) f) (inl i) = f (inl i)

Next tactic:
rfl
/-- 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')
    where
  toFun f := ⟨fun i => f (inl i), fun i' => f (inr i')⟩
  invFun g := Sum.rec g.1 g.2
  left_inv f := by ext (i | i) <;> 

Proof state:
case h.inr
ι : Type ?u.56717
ι' : Type ?u.56716
π : ι ⊕ ι' → Type u_1
f : (i : ι ⊕ ι') → π i
i : ι'
⊢ (fun g t => Sum.rec g.1 g.2 t) ((fun f => (fun i => f (inl i), fun i' => f (inr i'))) f) (inr i) = f (inr i)

Next tactic:
rfl
/-- The type of functions on a sum type `α ⊕ β` is equivalent to the type of pairs of functions
on `α` and on `β`. -/
def sumArrowEquivProdArrow (α β γ : Type*) : (Sum α β → γ) ≃ (α → γ) × (β → γ) :=
  ⟨fun f => (f ∘ inl, f ∘ inr), fun p => Sum.elim p.1 p.2, fun f => by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
f : α ⊕ β → γ
⊢ (fun p => Sum.elim p.1 p.2) ((fun f => (f ∘ inl, f ∘ inr)) f) = f

Next tactic:
ext ⟨⟩
/-- The type of functions on a sum type `α ⊕ β` is equivalent to the type of pairs of functions
on `α` and on `β`. -/
def sumArrowEquivProdArrow (α β γ : Type*) : (Sum α β → γ) ≃ (α → γ) × (β → γ) :=
  ⟨fun f => (f ∘ inl, f ∘ inr), fun p => Sum.elim p.1 p.2, fun f => by ext ⟨⟩ <;> 

Proof state:
case h.inl
α : Type u_1
β : Type u_2
γ : Type u_3
f : α ⊕ β → γ
val✝ : α
⊢ (fun p => Sum.elim p.1 p.2) ((fun f => (f ∘ inl, f ∘ inr)) f) (inl val✝) = f (inl val✝)

Next tactic:
rfl
/-- The type of functions on a sum type `α ⊕ β` is equivalent to the type of pairs of functions
on `α` and on `β`. -/
def sumArrowEquivProdArrow (α β γ : Type*) : (Sum α β → γ) ≃ (α → γ) × (β → γ) :=
  ⟨fun f => (f ∘ inl, f ∘ inr), fun p => Sum.elim p.1 p.2, fun f => by ext ⟨⟩ <;> 

Proof state:
case h.inr
α : Type u_1
β : Type u_2
γ : Type u_3
f : α ⊕ β → γ
val✝ : β
⊢ (fun p => Sum.elim p.1 p.2) ((fun f => (f ∘ inl, f ∘ inr)) f) (inr val✝) = f (inr val✝)

Next tactic:
rfl
/-- The type of functions on a sum type `α ⊕ β` is equivalent to the type of pairs of functions
on `α` and on `β`. -/
def sumArrowEquivProdArrow (α β γ : Type*) : (Sum α β → γ) ≃ (α → γ) × (β → γ) :=
  ⟨fun f => (f ∘ inl, f ∘ inr), fun p => Sum.elim p.1 p.2, fun f => by ext ⟨⟩ <;> rfl, fun p => by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
p : (α → γ) × (β → γ)
⊢ (fun f => (f ∘ inl, f ∘ inr)) ((fun p => Sum.elim p.1 p.2) p) = p

Next tactic:
cases p
/-- The type of functions on a sum type `α ⊕ β` is equivalent to the type of pairs of functions
on `α` and on `β`. -/
def sumArrowEquivProdArrow (α β γ : Type*) : (Sum α β → γ) ≃ (α → γ) × (β → γ) :=
  ⟨fun f => (f ∘ inl, f ∘ inr), fun p => Sum.elim p.1 p.2, fun f => by ext ⟨⟩ <;> rfl, fun p => by
    cases p
    

Proof state:
case mk
α : Type u_1
β : Type u_2
γ : Type u_3
fst✝ : α → γ
snd✝ : β → γ
⊢ (fun f => (f ∘ inl, f ∘ inr)) ((fun p => Sum.elim p.1 p.2) (fst✝, snd✝)) = (fst✝, snd✝)

Next tactic:
rfl
/-- Type product is right distributive with respect to type sum up to an equivalence. -/
def sumProdDistrib (α β γ) : Sum α β × γ ≃ Sum (α × γ) (β × γ) :=
  ⟨fun p => p.1.map (fun x => (x, p.2)) fun x => (x, p.2),
    fun s => s.elim (Prod.map inl id) (Prod.map inr id), by
      

Proof state:
α : Type ?u.59315
β : Type ?u.59314
γ : Type ?u.59312
⊢ LeftInverse (fun s => Sum.elim (Prod.map inl id) (Prod.map inr id) s) fun p =>
    Sum.map (fun x => (x, p.2)) (fun x => (x, p.2)) p.1

Next tactic:
rintro ⟨_ | _, _⟩
/-- Type product is right distributive with respect to type sum up to an equivalence. -/
def sumProdDistrib (α β γ) : Sum α β × γ ≃ Sum (α × γ) (β × γ) :=
  ⟨fun p => p.1.map (fun x => (x, p.2)) fun x => (x, p.2),
    fun s => s.elim (Prod.map inl id) (Prod.map inr id), by
      rintro ⟨_ | _, _⟩ <;> 

Proof state:
case mk.inl
α : Type ?u.59315
β : Type ?u.59314
γ : Type ?u.59312
snd✝ : γ
val✝ : α
⊢ (fun s => Sum.elim (Prod.map inl id) (Prod.map inr id) s)
      ((fun p => Sum.map (fun x => (x, p.2)) (fun x => (x, p.2)) p.1) (inl val✝, snd✝)) =
    (inl val✝, snd✝)

Next tactic:
rfl
/-- Type product is right distributive with respect to type sum up to an equivalence. -/
def sumProdDistrib (α β γ) : Sum α β × γ ≃ Sum (α × γ) (β × γ) :=
  ⟨fun p => p.1.map (fun x => (x, p.2)) fun x => (x, p.2),
    fun s => s.elim (Prod.map inl id) (Prod.map inr id), by
      rintro ⟨_ | _, _⟩ <;> 

Proof state:
case mk.inr
α : Type ?u.59315
β : Type ?u.59314
γ : Type ?u.59312
snd✝ : γ
val✝ : β
⊢ (fun s => Sum.elim (Prod.map inl id) (Prod.map inr id) s)
      ((fun p => Sum.map (fun x => (x, p.2)) (fun x => (x, p.2)) p.1) (inr val✝, snd✝)) =
    (inr val✝, snd✝)

Next tactic:
rfl
/-- Type product is right distributive with respect to type sum up to an equivalence. -/
def sumProdDistrib (α β γ) : Sum α β × γ ≃ Sum (α × γ) (β × γ) :=
  ⟨fun p => p.1.map (fun x => (x, p.2)) fun x => (x, p.2),
    fun s => s.elim (Prod.map inl id) (Prod.map inr id), by
      rintro ⟨_ | _, _⟩ <;> rfl, by 

Proof state:
α : Type ?u.59315
β : Type ?u.59314
γ : Type ?u.59312
⊢ Function.RightInverse (fun s => Sum.elim (Prod.map inl id) (Prod.map inr id) s) fun p =>
    Sum.map (fun x => (x, p.2)) (fun x => (x, p.2)) p.1

Next tactic:
rintro (⟨_, _⟩ | ⟨_, _⟩)
/-- Type product is right distributive with respect to type sum up to an equivalence. -/
def sumProdDistrib (α β γ) : Sum α β × γ ≃ Sum (α × γ) (β × γ) :=
  ⟨fun p => p.1.map (fun x => (x, p.2)) fun x => (x, p.2),
    fun s => s.elim (Prod.map inl id) (Prod.map inr id), by
      rintro ⟨_ | _, _⟩ <;> rfl, by rintro (⟨_, _⟩ | ⟨_, _⟩) <;> 

Proof state:
case inl.mk
α : Type ?u.59315
β : Type ?u.59314
γ : Type ?u.59312
fst✝ : α
snd✝ : γ
⊢ (fun p => Sum.map (fun x => (x, p.2)) (fun x => (x, p.2)) p.1)
      ((fun s => Sum.elim (Prod.map inl id) (Prod.map inr id) s) (inl (fst✝, snd✝))) =
    inl (fst✝, snd✝)

Next tactic:
rfl
/-- Type product is right distributive with respect to type sum up to an equivalence. -/
def sumProdDistrib (α β γ) : Sum α β × γ ≃ Sum (α × γ) (β × γ) :=
  ⟨fun p => p.1.map (fun x => (x, p.2)) fun x => (x, p.2),
    fun s => s.elim (Prod.map inl id) (Prod.map inr id), by
      rintro ⟨_ | _, _⟩ <;> rfl, by rintro (⟨_, _⟩ | ⟨_, _⟩) <;> 

Proof state:
case inr.mk
α : Type ?u.59315
β : Type ?u.59314
γ : Type ?u.59312
fst✝ : β
snd✝ : γ
⊢ (fun p => Sum.map (fun x => (x, p.2)) (fun x => (x, p.2)) p.1)
      ((fun s => Sum.elim (Prod.map inl id) (Prod.map inr id) s) (inr (fst✝, snd✝))) =
    inr (fst✝, snd✝)

Next tactic:
rfl
/-- An indexed sum of disjoint sums of types is equivalent to the sum of the indexed sums. -/
@[simps]
def sigmaSumDistrib (α β : ι → Type*) :
    (Σ i, Sum (α i) (β i)) ≃ Sum (Σ i, α i) (Σ i, β i) :=
  ⟨fun p => p.2.map (Sigma.mk p.1) (Sigma.mk p.1),
    Sum.elim (Sigma.map id fun _ => Sum.inl) (Sigma.map id fun _ => Sum.inr), fun p => by
    

Proof state:
ι : Type ?u.62198
α : ι → Type u_1
β : ι → Type u_2
p : (i : ι) × (α i ⊕ β i)
⊢ Sum.elim (Sigma.map id fun x => inl) (Sigma.map id fun x => inr)
      ((fun p => Sum.map (Sigma.mk p.fst) (Sigma.mk p.fst) p.snd) p) =
    p

Next tactic:
rcases p with ⟨i, a | b⟩
/-- An indexed sum of disjoint sums of types is equivalent to the sum of the indexed sums. -/
@[simps]
def sigmaSumDistrib (α β : ι → Type*) :
    (Σ i, Sum (α i) (β i)) ≃ Sum (Σ i, α i) (Σ i, β i) :=
  ⟨fun p => p.2.map (Sigma.mk p.1) (Sigma.mk p.1),
    Sum.elim (Sigma.map id fun _ => Sum.inl) (Sigma.map id fun _ => Sum.inr), fun p => by
    rcases p with ⟨i, a | b⟩ <;> 

Proof state:
case mk.inl
ι : Type ?u.62198
α : ι → Type u_1
β : ι → Type u_2
i : ι
a : α i
⊢ Sum.elim (Sigma.map id fun x => inl) (Sigma.map id fun x => inr)
      ((fun p => Sum.map (Sigma.mk p.fst) (Sigma.mk p.fst) p.snd) { fst := i, snd := inl a }) =
    { fst := i, snd := inl a }

Next tactic:
rfl
/-- An indexed sum of disjoint sums of types is equivalent to the sum of the indexed sums. -/
@[simps]
def sigmaSumDistrib (α β : ι → Type*) :
    (Σ i, Sum (α i) (β i)) ≃ Sum (Σ i, α i) (Σ i, β i) :=
  ⟨fun p => p.2.map (Sigma.mk p.1) (Sigma.mk p.1),
    Sum.elim (Sigma.map id fun _ => Sum.inl) (Sigma.map id fun _ => Sum.inr), fun p => by
    rcases p with ⟨i, a | b⟩ <;> 

Proof state:
case mk.inr
ι : Type ?u.62198
α : ι → Type u_1
β : ι → Type u_2
i : ι
b : β i
⊢ Sum.elim (Sigma.map id fun x => inl) (Sigma.map id fun x => inr)
      ((fun p => Sum.map (Sigma.mk p.fst) (Sigma.mk p.fst) p.snd) { fst := i, snd := inr b }) =
    { fst := i, snd := inr b }

Next tactic:
rfl
/-- An indexed sum of disjoint sums of types is equivalent to the sum of the indexed sums. -/
@[simps]
def sigmaSumDistrib (α β : ι → Type*) :
    (Σ i, Sum (α i) (β i)) ≃ Sum (Σ i, α i) (Σ i, β i) :=
  ⟨fun p => p.2.map (Sigma.mk p.1) (Sigma.mk p.1),
    Sum.elim (Sigma.map id fun _ => Sum.inl) (Sigma.map id fun _ => Sum.inr), fun p => by
    rcases p with ⟨i, a | b⟩ <;> rfl, fun p => by 

Proof state:
ι : Type ?u.62198
α : ι → Type u_1
β : ι → Type u_2
p : (i : ι) × α i ⊕ (i : ι) × β i
⊢ (fun p => Sum.map (Sigma.mk p.fst) (Sigma.mk p.fst) p.snd)
      (Sum.elim (Sigma.map id fun x => inl) (Sigma.map id fun x => inr) p) =
    p

Next tactic:
rcases p with (⟨i, a⟩ | ⟨i, b⟩)
/-- An indexed sum of disjoint sums of types is equivalent to the sum of the indexed sums. -/
@[simps]
def sigmaSumDistrib (α β : ι → Type*) :
    (Σ i, Sum (α i) (β i)) ≃ Sum (Σ i, α i) (Σ i, β i) :=
  ⟨fun p => p.2.map (Sigma.mk p.1) (Sigma.mk p.1),
    Sum.elim (Sigma.map id fun _ => Sum.inl) (Sigma.map id fun _ => Sum.inr), fun p => by
    rcases p with ⟨i, a | b⟩ <;> rfl, fun p => by rcases p with (⟨i, a⟩ | ⟨i, b⟩) <;> 

Proof state:
case inl.mk
ι : Type ?u.62198
α : ι → Type u_1
β : ι → Type u_2
i : ι
a : α i
⊢ (fun p => Sum.map (Sigma.mk p.fst) (Sigma.mk p.fst) p.snd)
      (Sum.elim (Sigma.map id fun x => inl) (Sigma.map id fun x => inr) (inl { fst := i, snd := a })) =
    inl { fst := i, snd := a }

Next tactic:
rfl
/-- An indexed sum of disjoint sums of types is equivalent to the sum of the indexed sums. -/
@[simps]
def sigmaSumDistrib (α β : ι → Type*) :
    (Σ i, Sum (α i) (β i)) ≃ Sum (Σ i, α i) (Σ i, β i) :=
  ⟨fun p => p.2.map (Sigma.mk p.1) (Sigma.mk p.1),
    Sum.elim (Sigma.map id fun _ => Sum.inl) (Sigma.map id fun _ => Sum.inr), fun p => by
    rcases p with ⟨i, a | b⟩ <;> rfl, fun p => by rcases p with (⟨i, a⟩ | ⟨i, b⟩) <;> 

Proof state:
case inr.mk
ι : Type ?u.62198
α : ι → Type u_1
β : ι → Type u_2
i : ι
b : β i
⊢ (fun p => Sum.map (Sigma.mk p.fst) (Sigma.mk p.fst) p.snd)
      (Sum.elim (Sigma.map id fun x => inl) (Sigma.map id fun x => inr) (inr { fst := i, snd := b })) =
    inr { fst := i, snd := b }

Next tactic:
rfl
/-- 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 × β :=
  ⟨fun p => ⟨p.1.1, (p.1.2, p.2)⟩, fun p => (⟨p.1, p.2.1⟩, p.2.2), fun p => by
    

Proof state:
ι : Type ?u.63006
α : ι → Type u_1
β : Type u_2
p : ((i : ι) × α i) × β
⊢ (fun p => ({ fst := p.fst, snd := p.snd.1 }, p.snd.2)) ((fun p => { fst := p.1.fst, snd := (p.1.snd, p.2) }) p) = p

Next tactic:
rcases p with ⟨⟨_, _⟩, _⟩
/-- 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 × β :=
  ⟨fun p => ⟨p.1.1, (p.1.2, p.2)⟩, fun p => (⟨p.1, p.2.1⟩, p.2.2), fun p => by
    rcases p with ⟨⟨_, _⟩, _⟩
    

Proof state:
case mk.mk
ι : Type ?u.63006
α : ι → Type u_1
β : Type u_2
snd✝¹ : β
fst✝ : ι
snd✝ : α fst✝
⊢ (fun p => ({ fst := p.fst, snd := p.snd.1 }, p.snd.2))
      ((fun p => { fst := p.1.fst, snd := (p.1.snd, p.2) }) ({ fst := fst✝, snd := snd✝ }, snd✝¹)) =
    ({ fst := fst✝, snd := snd✝ }, snd✝¹)

Next tactic:
rfl
/-- 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 × β :=
  ⟨fun p => ⟨p.1.1, (p.1.2, p.2)⟩, fun p => (⟨p.1, p.2.1⟩, p.2.2), fun p => by
    rcases p with ⟨⟨_, _⟩, _⟩
    rfl, fun p => by
    

Proof state:
ι : Type ?u.63006
α : ι → Type u_1
β : Type u_2
p : (i : ι) × α i × β
⊢ (fun p => { fst := p.1.fst, snd := (p.1.snd, p.2) }) ((fun p => ({ fst := p.fst, snd := p.snd.1 }, p.snd.2)) p) = p

Next tactic:
rcases p with ⟨_, ⟨_, _⟩⟩
/-- 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 × β :=
  ⟨fun p => ⟨p.1.1, (p.1.2, p.2)⟩, fun p => (⟨p.1, p.2.1⟩, p.2.2), fun p => by
    rcases p with ⟨⟨_, _⟩, _⟩
    rfl, fun p => by
    rcases p with ⟨_, ⟨_, _⟩⟩
    

Proof state:
case mk.mk
ι : Type ?u.63006
α : ι → Type u_1
β : Type u_2
fst✝¹ : ι
fst✝ : α fst✝¹
snd✝ : β
⊢ (fun p => { fst := p.1.fst, snd := (p.1.snd, p.2) })
      ((fun p => ({ fst := p.fst, snd := p.snd.1 }, p.snd.2)) { fst := fst✝¹, snd := (fst✝, snd✝) }) =
    { fst := fst✝¹, snd := (fst✝, snd✝) }

Next tactic:
rfl