l3lab/ntp-mathlib huggingface dataset:
instance [CommMonoid α] : CommRing (FreeAbelianGroup α) :=
  { FreeAbelianGroup.ring α with
    mul_comm := fun x y ↦ by
      refine' FreeAbelianGroup.induction_on x (zero_mul y) _ _ _
      · intro s
        

Proof state:
case refine'_1
α : Type u
β : Type v
γ : Type w
inst✝ : CommMonoid α
src✝ : Ring (FreeAbelianGroup α) := ring α
x y : FreeAbelianGroup α
s : α
⊢ of s * y = y * of s

Next tactic:
refine' FreeAbelianGroup.induction_on y (zero_mul _).symm _ _ _
instance [CommMonoid α] : CommRing (FreeAbelianGroup α) :=
  { FreeAbelianGroup.ring α with
    mul_comm := fun x y ↦ by
      refine' FreeAbelianGroup.induction_on x (zero_mul y) _ _ _
      · intro s
        refine' FreeAbelianGroup.induction_on y (zero_mul _).symm _ _ _
        · 

Proof state:
case refine'_1.refine'_1
α : Type u
β : Type v
γ : Type w
inst✝ : CommMonoid α
src✝ : Ring (FreeAbelianGroup α) := ring α
x y : FreeAbelianGroup α
s : α
⊢ ∀ (x : α), of s * of x = of x * of s

Next tactic:
intro t
instance [CommMonoid α] : CommRing (FreeAbelianGroup α) :=
  { FreeAbelianGroup.ring α with
    mul_comm := fun x y ↦ by
      refine' FreeAbelianGroup.induction_on x (zero_mul y) _ _ _
      · intro s
        refine' FreeAbelianGroup.induction_on y (zero_mul _).symm _ _ _
        · intro t
          

Proof state:
case refine'_1.refine'_1
α : Type u
β : Type v
γ : Type w
inst✝ : CommMonoid α
src✝ : Ring (FreeAbelianGroup α) := ring α
x y : FreeAbelianGroup α
s t : α
⊢ of s * of t = of t * of s

Next tactic:
dsimp only [(· * ·), Mul.mul]
instance [CommMonoid α] : CommRing (FreeAbelianGroup α) :=
  { FreeAbelianGroup.ring α with
    mul_comm := fun x y ↦ by
      refine' FreeAbelianGroup.induction_on x (zero_mul y) _ _ _
      · intro s
        refine' FreeAbelianGroup.induction_on y (zero_mul _).symm _ _ _
        · intro t
          dsimp only [(· * ·), Mul.mul]
          

Proof state:
case refine'_1.refine'_1
α : Type u
β : Type v
γ : Type w
inst✝ : CommMonoid α
src✝ : Ring (FreeAbelianGroup α) := ring α
x y : FreeAbelianGroup α
s t : α
⊢ (lift fun x₂ => (lift fun x₁ => of (Mul.mul x₁ x₂)) (of s)) (of t) =
    (lift fun x₂ => (lift fun x₁ => of (Mul.mul x₁ x₂)) (of t)) (of s)

Next tactic:
iterate 4 rw [lift.of]
instance [CommMonoid α] : CommRing (FreeAbelianGroup α) :=
  { FreeAbelianGroup.ring α with
    mul_comm := fun x y ↦ by
      refine' FreeAbelianGroup.induction_on x (zero_mul y) _ _ _
      · intro s
        refine' FreeAbelianGroup.induction_on y (zero_mul _).symm _ _ _
        · intro t
          dsimp only [(· * ·), Mul.mul]
          iterate 4 

Proof state:
case refine'_1.refine'_1
α : Type u
β : Type v
γ : Type w
inst✝ : CommMonoid α
src✝ : Ring (FreeAbelianGroup α) := ring α
x y : FreeAbelianGroup α
s t : α
⊢ (lift fun x₂ => (lift fun x₁ => of (Mul.mul x₁ x₂)) (of s)) (of t) =
    (lift fun x₂ => (lift fun x₁ => of (Mul.mul x₁ x₂)) (of t)) (of s)

Next tactic:
rw [lift.of]
instance [CommMonoid α] : CommRing (FreeAbelianGroup α) :=
  { FreeAbelianGroup.ring α with
    mul_comm := fun x y ↦ by
      refine' FreeAbelianGroup.induction_on x (zero_mul y) _ _ _
      · intro s
        refine' FreeAbelianGroup.induction_on y (zero_mul _).symm _ _ _
        · intro t
          dsimp only [(· * ·), Mul.mul]
          iterate 4 

Proof state:
case refine'_1.refine'_1
α : Type u
β : Type v
γ : Type w
inst✝ : CommMonoid α
src✝ : Ring (FreeAbelianGroup α) := ring α
x y : FreeAbelianGroup α
s t : α
⊢ (lift fun x₁ => of (Mul.mul x₁ t)) (of s) = (lift fun x₂ => (lift fun x₁ => of (Mul.mul x₁ x₂)) (of t)) (of s)

Next tactic:
rw [lift.of]
instance [CommMonoid α] : CommRing (FreeAbelianGroup α) :=
  { FreeAbelianGroup.ring α with
    mul_comm := fun x y ↦ by
      refine' FreeAbelianGroup.induction_on x (zero_mul y) _ _ _
      · intro s
        refine' FreeAbelianGroup.induction_on y (zero_mul _).symm _ _ _
        · intro t
          dsimp only [(· * ·), Mul.mul]
          iterate 4 

Proof state:
case refine'_1.refine'_1
α : Type u
β : Type v
γ : Type w
inst✝ : CommMonoid α
src✝ : Ring (FreeAbelianGroup α) := ring α
x y : FreeAbelianGroup α
s t : α
⊢ of (Mul.mul s t) = (lift fun x₂ => (lift fun x₁ => of (Mul.mul x₁ x₂)) (of t)) (of s)

Next tactic:
rw [lift.of]
instance [CommMonoid α] : CommRing (FreeAbelianGroup α) :=
  { FreeAbelianGroup.ring α with
    mul_comm := fun x y ↦ by
      refine' FreeAbelianGroup.induction_on x (zero_mul y) _ _ _
      · intro s
        refine' FreeAbelianGroup.induction_on y (zero_mul _).symm _ _ _
        · intro t
          dsimp only [(· * ·), Mul.mul]
          iterate 4 

Proof state:
case refine'_1.refine'_1
α : Type u
β : Type v
γ : Type w
inst✝ : CommMonoid α
src✝ : Ring (FreeAbelianGroup α) := ring α
x y : FreeAbelianGroup α
s t : α
⊢ of (Mul.mul s t) = (lift fun x₁ => of (Mul.mul x₁ s)) (of t)

Next tactic:
rw [lift.of]
instance [CommMonoid α] : CommRing (FreeAbelianGroup α) :=
  { FreeAbelianGroup.ring α with
    mul_comm := fun x y ↦ by
      refine' FreeAbelianGroup.induction_on x (zero_mul y) _ _ _
      · intro s
        refine' FreeAbelianGroup.induction_on y (zero_mul _).symm _ _ _
        · intro t
          dsimp only [(· * ·), Mul.mul]
          iterate 4 rw [lift.of]
          

Proof state:
case refine'_1.refine'_1
α : Type u
β : Type v
γ : Type w
inst✝ : CommMonoid α
src✝ : Ring (FreeAbelianGroup α) := ring α
x y : FreeAbelianGroup α
s t : α
⊢ of (Mul.mul s t) = of (Mul.mul t s)

Next tactic:
congr 1
instance [CommMonoid α] : CommRing (FreeAbelianGroup α) :=
  { FreeAbelianGroup.ring α with
    mul_comm := fun x y ↦ by
      refine' FreeAbelianGroup.induction_on x (zero_mul y) _ _ _
      · intro s
        refine' FreeAbelianGroup.induction_on y (zero_mul _).symm _ _ _
        · intro t
          dsimp only [(· * ·), Mul.mul]
          iterate 4 rw [lift.of]
          congr 1
          

Proof state:
case refine'_1.refine'_1.e_x
α : Type u
β : Type v
γ : Type w
inst✝ : CommMonoid α
src✝ : Ring (FreeAbelianGroup α) := ring α
x y : FreeAbelianGroup α
s t : α
⊢ Mul.mul s t = Mul.mul t s

Next tactic:
exact mul_comm _ _
instance [CommMonoid α] : CommRing (FreeAbelianGroup α) :=
  { FreeAbelianGroup.ring α with
    mul_comm := fun x y ↦ by
      refine' FreeAbelianGroup.induction_on x (zero_mul y) _ _ _
      · intro s
        refine' FreeAbelianGroup.induction_on y (zero_mul _).symm _ _ _
        · intro t
          dsimp only [(· * ·), Mul.mul]
          iterate 4 rw [lift.of]
          congr 1
          exact mul_comm _ _
        · 

Proof state:
case refine'_1.refine'_2
α : Type u
β : Type v
γ : Type w
inst✝ : CommMonoid α
src✝ : Ring (FreeAbelianGroup α) := ring α
x y : FreeAbelianGroup α
s : α
⊢ ∀ (x : α), of s * of x = of x * of s → of s * -of x = -of x * of s

Next tactic:
intro t ih
instance [CommMonoid α] : CommRing (FreeAbelianGroup α) :=
  { FreeAbelianGroup.ring α with
    mul_comm := fun x y ↦ by
      refine' FreeAbelianGroup.induction_on x (zero_mul y) _ _ _
      · intro s
        refine' FreeAbelianGroup.induction_on y (zero_mul _).symm _ _ _
        · intro t
          dsimp only [(· * ·), Mul.mul]
          iterate 4 rw [lift.of]
          congr 1
          exact mul_comm _ _
        · intro t ih
          

Proof state:
case refine'_1.refine'_2
α : Type u
β : Type v
γ : Type w
inst✝ : CommMonoid α
src✝ : Ring (FreeAbelianGroup α) := ring α
x y : FreeAbelianGroup α
s t : α
ih : of s * of t = of t * of s
⊢ of s * -of t = -of t * of s

Next tactic:
rw [mul_neg, ih, neg_mul_eq_neg_mul]
instance [CommMonoid α] : CommRing (FreeAbelianGroup α) :=
  { FreeAbelianGroup.ring α with
    mul_comm := fun x y ↦ by
      refine' FreeAbelianGroup.induction_on x (zero_mul y) _ _ _
      · intro s
        refine' FreeAbelianGroup.induction_on y (zero_mul _).symm _ _ _
        · intro t
          dsimp only [(· * ·), Mul.mul]
          iterate 4 rw [lift.of]
          congr 1
          exact mul_comm _ _
        · intro t ih
          rw [mul_neg, ih, neg_mul_eq_neg_mul]
        · 

Proof state:
case refine'_1.refine'_3
α : Type u
β : Type v
γ : Type w
inst✝ : CommMonoid α
src✝ : Ring (FreeAbelianGroup α) := ring α
x y : FreeAbelianGroup α
s : α
⊢ ∀ (x y : FreeAbelianGroup α), of s * x = x * of s → of s * y = y * of s → of s * (x + y) = (x + y) * of s

Next tactic:
intro y1 y2 ih1 ih2
instance [CommMonoid α] : CommRing (FreeAbelianGroup α) :=
  { FreeAbelianGroup.ring α with
    mul_comm := fun x y ↦ by
      refine' FreeAbelianGroup.induction_on x (zero_mul y) _ _ _
      · intro s
        refine' FreeAbelianGroup.induction_on y (zero_mul _).symm _ _ _
        · intro t
          dsimp only [(· * ·), Mul.mul]
          iterate 4 rw [lift.of]
          congr 1
          exact mul_comm _ _
        · intro t ih
          rw [mul_neg, ih, neg_mul_eq_neg_mul]
        · intro y1 y2 ih1 ih2
          

Proof state:
case refine'_1.refine'_3
α : Type u
β : Type v
γ : Type w
inst✝ : CommMonoid α
src✝ : Ring (FreeAbelianGroup α) := ring α
x y : FreeAbelianGroup α
s : α
y1 y2 : FreeAbelianGroup α
ih1 : of s * y1 = y1 * of s
ih2 : of s * y2 = y2 * of s
⊢ of s * (y1 + y2) = (y1 + y2) * of s

Next tactic:
rw [mul_add, add_mul, ih1, ih2]
instance [CommMonoid α] : CommRing (FreeAbelianGroup α) :=
  { FreeAbelianGroup.ring α with
    mul_comm := fun x y ↦ by
      refine' FreeAbelianGroup.induction_on x (zero_mul y) _ _ _
      · intro s
        refine' FreeAbelianGroup.induction_on y (zero_mul _).symm _ _ _
        · intro t
          dsimp only [(· * ·), Mul.mul]
          iterate 4 rw [lift.of]
          congr 1
          exact mul_comm _ _
        · intro t ih
          rw [mul_neg, ih, neg_mul_eq_neg_mul]
        · intro y1 y2 ih1 ih2
          rw [mul_add, add_mul, ih1, ih2]
      · 

Proof state:
case refine'_2
α : Type u
β : Type v
γ : Type w
inst✝ : CommMonoid α
src✝ : Ring (FreeAbelianGroup α) := ring α
x y : FreeAbelianGroup α
⊢ ∀ (x : α), of x * y = y * of x → -of x * y = y * -of x

Next tactic:
intro s ih
instance [CommMonoid α] : CommRing (FreeAbelianGroup α) :=
  { FreeAbelianGroup.ring α with
    mul_comm := fun x y ↦ by
      refine' FreeAbelianGroup.induction_on x (zero_mul y) _ _ _
      · intro s
        refine' FreeAbelianGroup.induction_on y (zero_mul _).symm _ _ _
        · intro t
          dsimp only [(· * ·), Mul.mul]
          iterate 4 rw [lift.of]
          congr 1
          exact mul_comm _ _
        · intro t ih
          rw [mul_neg, ih, neg_mul_eq_neg_mul]
        · intro y1 y2 ih1 ih2
          rw [mul_add, add_mul, ih1, ih2]
      · intro s ih
        

Proof state:
case refine'_2
α : Type u
β : Type v
γ : Type w
inst✝ : CommMonoid α
src✝ : Ring (FreeAbelianGroup α) := ring α
x y : FreeAbelianGroup α
s : α
ih : of s * y = y * of s
⊢ -of s * y = y * -of s

Next tactic:
rw [neg_mul, ih, neg_mul_eq_mul_neg]
instance [CommMonoid α] : CommRing (FreeAbelianGroup α) :=
  { FreeAbelianGroup.ring α with
    mul_comm := fun x y ↦ by
      refine' FreeAbelianGroup.induction_on x (zero_mul y) _ _ _
      · intro s
        refine' FreeAbelianGroup.induction_on y (zero_mul _).symm _ _ _
        · intro t
          dsimp only [(· * ·), Mul.mul]
          iterate 4 rw [lift.of]
          congr 1
          exact mul_comm _ _
        · intro t ih
          rw [mul_neg, ih, neg_mul_eq_neg_mul]
        · intro y1 y2 ih1 ih2
          rw [mul_add, add_mul, ih1, ih2]
      · intro s ih
        rw [neg_mul, ih, neg_mul_eq_mul_neg]
      · 

Proof state:
case refine'_3
α : Type u
β : Type v
γ : Type w
inst✝ : CommMonoid α
src✝ : Ring (FreeAbelianGroup α) := ring α
x y : FreeAbelianGroup α
⊢ ∀ (x y_1 : FreeAbelianGroup α), x * y = y * x → y_1 * y = y * y_1 → (x + y_1) * y = y * (x + y_1)

Next tactic:
intro x1 x2 ih1 ih2
instance [CommMonoid α] : CommRing (FreeAbelianGroup α) :=
  { FreeAbelianGroup.ring α with
    mul_comm := fun x y ↦ by
      refine' FreeAbelianGroup.induction_on x (zero_mul y) _ _ _
      · intro s
        refine' FreeAbelianGroup.induction_on y (zero_mul _).symm _ _ _
        · intro t
          dsimp only [(· * ·), Mul.mul]
          iterate 4 rw [lift.of]
          congr 1
          exact mul_comm _ _
        · intro t ih
          rw [mul_neg, ih, neg_mul_eq_neg_mul]
        · intro y1 y2 ih1 ih2
          rw [mul_add, add_mul, ih1, ih2]
      · intro s ih
        rw [neg_mul, ih, neg_mul_eq_mul_neg]
      · intro x1 x2 ih1 ih2
        

Proof state:
case refine'_3
α : Type u
β : Type v
γ : Type w
inst✝ : CommMonoid α
src✝ : Ring (FreeAbelianGroup α) := ring α
x y x1 x2 : FreeAbelianGroup α
ih1 : x1 * y = y * x1
ih2 : x2 * y = y * x2
⊢ (x1 + x2) * y = y * (x1 + x2)

Next tactic:
rw [add_mul, mul_add, ih1, ih2]
instance pemptyUnique : Unique (FreeAbelianGroup PEmpty) where
  default := 0
  uniq x := FreeAbelianGroup.induction_on x rfl (PEmpty.elim ·) (PEmpty.elim ·) (by
    

Proof state:
α : Type u
β : Type v
γ : Type w
x : FreeAbelianGroup PEmpty.{?u.625800 + 1}
⊢ ∀ (x y : FreeAbelianGroup PEmpty.{?u.625800 + 1}), x = default → y = default → x + y = default

Next tactic:
rintro - - rfl rfl
instance pemptyUnique : Unique (FreeAbelianGroup PEmpty) where
  default := 0
  uniq x := FreeAbelianGroup.induction_on x rfl (PEmpty.elim ·) (PEmpty.elim ·) (by
    rintro - - rfl rfl
    

Proof state:
α : Type u
β : Type v
γ : Type w
x : FreeAbelianGroup PEmpty.{?u.625800 + 1}
⊢ default + default = default

Next tactic:
rfl
/-- The free abelian group on a type with one term is isomorphic to `ℤ`. -/
def punitEquiv (T : Type*) [Unique T] : FreeAbelianGroup T ≃+ ℤ where
  toFun := FreeAbelianGroup.lift fun _ ↦ (1 : ℤ)
  invFun n := n • of Inhabited.default
  left_inv z := FreeAbelianGroup.induction_on z
    (by 

Proof state:
α : Type u
β : Type v
γ : Type w
T : Type u_1
inst✝ : Unique T
z : FreeAbelianGroup T
⊢ (fun n => n • of default) ((lift fun x => 1) 0) = 0

Next tactic:
simp only [zero_smul, AddMonoidHom.map_zero]
/-- The free abelian group on a type with one term is isomorphic to `ℤ`. -/
def punitEquiv (T : Type*) [Unique T] : FreeAbelianGroup T ≃+ ℤ where
  toFun := FreeAbelianGroup.lift fun _ ↦ (1 : ℤ)
  invFun n := n • of Inhabited.default
  left_inv z := FreeAbelianGroup.induction_on z
    (by simp only [zero_smul, AddMonoidHom.map_zero])
    (Unique.forall_iff.2 <| by 

Proof state:
α : Type u
β : Type v
γ : Type w
T : Type u_1
inst✝ : Unique T
z : FreeAbelianGroup T
⊢ (fun n => n • of default) ((lift fun x => 1) (of default)) = of default

Next tactic:
simp only [one_smul, lift.of]
/-- The free abelian group on a type with one term is isomorphic to `ℤ`. -/
def punitEquiv (T : Type*) [Unique T] : FreeAbelianGroup T ≃+ ℤ where
  toFun := FreeAbelianGroup.lift fun _ ↦ (1 : ℤ)
  invFun n := n • of Inhabited.default
  left_inv z := FreeAbelianGroup.induction_on z
    (by simp only [zero_smul, AddMonoidHom.map_zero])
    (Unique.forall_iff.2 <| by simp only [one_smul, lift.of]) (Unique.forall_iff.2 <| by 

Proof state:
α : Type u
β : Type v
γ : Type w
T : Type u_1
inst✝ : Unique T
z : FreeAbelianGroup T
⊢ (fun n => n • of default) ((lift fun x => 1) (of default)) = of default →
    (fun n => n • of default) ((lift fun x => 1) (-of default)) = -of default

Next tactic:
simp
/-- The free abelian group on a type with one term is isomorphic to `ℤ`. -/
def punitEquiv (T : Type*) [Unique T] : FreeAbelianGroup T ≃+ ℤ where
  toFun := FreeAbelianGroup.lift fun _ ↦ (1 : ℤ)
  invFun n := n • of Inhabited.default
  left_inv z := FreeAbelianGroup.induction_on z
    (by simp only [zero_smul, AddMonoidHom.map_zero])
    (Unique.forall_iff.2 <| by simp only [one_smul, lift.of]) (Unique.forall_iff.2 <| by simp)
    fun x y hx hy ↦ by
      

Proof state:
α : Type u
β : Type v
γ : Type w
T : Type u_1
inst✝ : Unique T
z x y : FreeAbelianGroup T
hx : (fun n => n • of default) ((lift fun x => 1) x) = x
hy : (fun n => n • of default) ((lift fun x => 1) y) = y
⊢ (fun n => n • of default) ((lift fun x => 1) (x + y)) = x + y

Next tactic:
simp only [AddMonoidHom.map_add, add_smul] at *
/-- The free abelian group on a type with one term is isomorphic to `ℤ`. -/
def punitEquiv (T : Type*) [Unique T] : FreeAbelianGroup T ≃+ ℤ where
  toFun := FreeAbelianGroup.lift fun _ ↦ (1 : ℤ)
  invFun n := n • of Inhabited.default
  left_inv z := FreeAbelianGroup.induction_on z
    (by simp only [zero_smul, AddMonoidHom.map_zero])
    (Unique.forall_iff.2 <| by simp only [one_smul, lift.of]) (Unique.forall_iff.2 <| by simp)
    fun x y hx hy ↦ by
      simp only [AddMonoidHom.map_add, add_smul] at *
      

Proof state:
α : Type u
β : Type v
γ : Type w
T : Type u_1
inst✝ : Unique T
z x y : FreeAbelianGroup T
hx : (lift fun x => 1) x • of default = x
hy : (lift fun x => 1) y • of default = y
⊢ (lift fun x => 1) x • of default + (lift fun x => 1) y • of default = x + y

Next tactic:
rw [hx, hy]
/-- The free abelian group on a type with one term is isomorphic to `ℤ`. -/
def punitEquiv (T : Type*) [Unique T] : FreeAbelianGroup T ≃+ ℤ where
  toFun := FreeAbelianGroup.lift fun _ ↦ (1 : ℤ)
  invFun n := n • of Inhabited.default
  left_inv z := FreeAbelianGroup.induction_on z
    (by simp only [zero_smul, AddMonoidHom.map_zero])
    (Unique.forall_iff.2 <| by simp only [one_smul, lift.of]) (Unique.forall_iff.2 <| by simp)
    fun x y hx hy ↦ by
      simp only [AddMonoidHom.map_add, add_smul] at *
      rw [hx, hy]
  right_inv n := by
    

Proof state:
α : Type u
β : Type v
γ : Type w
T : Type u_1
inst✝ : Unique T
n : ℤ
⊢ (lift fun x => 1) ((fun n => n • of default) n) = n

Next tactic:
rw [AddMonoidHom.map_zsmul, lift.of]
/-- The free abelian group on a type with one term is isomorphic to `ℤ`. -/
def punitEquiv (T : Type*) [Unique T] : FreeAbelianGroup T ≃+ ℤ where
  toFun := FreeAbelianGroup.lift fun _ ↦ (1 : ℤ)
  invFun n := n • of Inhabited.default
  left_inv z := FreeAbelianGroup.induction_on z
    (by simp only [zero_smul, AddMonoidHom.map_zero])
    (Unique.forall_iff.2 <| by simp only [one_smul, lift.of]) (Unique.forall_iff.2 <| by simp)
    fun x y hx hy ↦ by
      simp only [AddMonoidHom.map_add, add_smul] at *
      rw [hx, hy]
  right_inv n := by
    rw [AddMonoidHom.map_zsmul, lift.of]
    

Proof state:
α : Type u
β : Type v
γ : Type w
T : Type u_1
inst✝ : Unique T
n : ℤ
⊢ n • 1 = n

Next tactic:
exact zsmul_int_one n
/-- Isomorphic types have isomorphic free abelian groups. -/
def equivOfEquiv {α β : Type*} (f : α ≃ β) : FreeAbelianGroup α ≃+ FreeAbelianGroup β where
  toFun := map f
  invFun := map f.symm
  left_inv := by
    

Proof state:
α✝ : Type u
β✝ : Type v
γ : Type w
α : Type u_1
β : Type u_2
f : α ≃ β
⊢ Function.LeftInverse ⇑(map ⇑f.symm) ⇑(map ⇑f)

Next tactic:
intro x
/-- Isomorphic types have isomorphic free abelian groups. -/
def equivOfEquiv {α β : Type*} (f : α ≃ β) : FreeAbelianGroup α ≃+ FreeAbelianGroup β where
  toFun := map f
  invFun := map f.symm
  left_inv := by
    intro x
    

Proof state:
α✝ : Type u
β✝ : Type v
γ : Type w
α : Type u_1
β : Type u_2
f : α ≃ β
x : FreeAbelianGroup α
⊢ (map ⇑f.symm) ((map ⇑f) x) = x

Next tactic:
rw [← map_comp_apply, Equiv.symm_comp_self, map_id]
/-- Isomorphic types have isomorphic free abelian groups. -/
def equivOfEquiv {α β : Type*} (f : α ≃ β) : FreeAbelianGroup α ≃+ FreeAbelianGroup β where
  toFun := map f
  invFun := map f.symm
  left_inv := by
    intro x
    rw [← map_comp_apply, Equiv.symm_comp_self, map_id]
    

Proof state:
α✝ : Type u
β✝ : Type v
γ : Type w
α : Type u_1
β : Type u_2
f : α ≃ β
x : FreeAbelianGroup α
⊢ (AddMonoidHom.id (FreeAbelianGroup α)) x = x

Next tactic:
rfl
/-- Isomorphic types have isomorphic free abelian groups. -/
def equivOfEquiv {α β : Type*} (f : α ≃ β) : FreeAbelianGroup α ≃+ FreeAbelianGroup β where
  toFun := map f
  invFun := map f.symm
  left_inv := by
    intro x
    rw [← map_comp_apply, Equiv.symm_comp_self, map_id]
    rfl
  right_inv := by
    

Proof state:
α✝ : Type u
β✝ : Type v
γ : Type w
α : Type u_1
β : Type u_2
f : α ≃ β
⊢ Function.RightInverse ⇑(map ⇑f.symm) ⇑(map ⇑f)

Next tactic:
intro x
/-- Isomorphic types have isomorphic free abelian groups. -/
def equivOfEquiv {α β : Type*} (f : α ≃ β) : FreeAbelianGroup α ≃+ FreeAbelianGroup β where
  toFun := map f
  invFun := map f.symm
  left_inv := by
    intro x
    rw [← map_comp_apply, Equiv.symm_comp_self, map_id]
    rfl
  right_inv := by
    intro x
    

Proof state:
α✝ : Type u
β✝ : Type v
γ : Type w
α : Type u_1
β : Type u_2
f : α ≃ β
x : FreeAbelianGroup β
⊢ (map ⇑f) ((map ⇑f.symm) x) = x

Next tactic:
rw [← map_comp_apply, Equiv.self_comp_symm, map_id]
/-- Isomorphic types have isomorphic free abelian groups. -/
def equivOfEquiv {α β : Type*} (f : α ≃ β) : FreeAbelianGroup α ≃+ FreeAbelianGroup β where
  toFun := map f
  invFun := map f.symm
  left_inv := by
    intro x
    rw [← map_comp_apply, Equiv.symm_comp_self, map_id]
    rfl
  right_inv := by
    intro x
    rw [← map_comp_apply, Equiv.self_comp_symm, map_id]
    

Proof state:
α✝ : Type u
β✝ : Type v
γ : Type w
α : Type u_1
β : Type u_2
f : α ≃ β
x : FreeAbelianGroup β
⊢ (AddMonoidHom.id (FreeAbelianGroup β)) x = x

Next tactic:
rfl
/-- `Part.bind` as a monotone function -/
@[simps]
def bind {β γ} (f : α →o Part β) (g : α →o β → Part γ) : α →o Part γ where
  toFun x := f x >>= g x
  monotone' := by
    

Proof state:
α : Type u_1
β✝ : Type u_2
γ✝ : Type u_3
inst✝² : Preorder α
inst✝¹ : Preorder β✝
inst✝ : Preorder γ✝
β γ : Type ?u.55
f : α →o Part β
g : α →o β → Part γ
⊢ Monotone fun x => f x >>= g x

Next tactic:
intro x y h a
/-- `Part.bind` as a monotone function -/
@[simps]
def bind {β γ} (f : α →o Part β) (g : α →o β → Part γ) : α →o Part γ where
  toFun x := f x >>= g x
  monotone' := by
    intro x y h a
    

Proof state:
α : Type u_1
β✝ : Type u_2
γ✝ : Type u_3
inst✝² : Preorder α
inst✝¹ : Preorder β✝
inst✝ : Preorder γ✝
β γ : Type ?u.55
f : α →o Part β
g : α →o β → Part γ
x y : α
h : x ≤ y
a : γ
⊢ a ∈ (fun x => f x >>= g x) x → a ∈ (fun x => f x >>= g x) y

Next tactic:
simp only [and_imp, exists_prop, Part.bind_eq_bind, Part.mem_bind_iff, exists_imp]
/-- `Part.bind` as a monotone function -/
@[simps]
def bind {β γ} (f : α →o Part β) (g : α →o β → Part γ) : α →o Part γ where
  toFun x := f x >>= g x
  monotone' := by
    intro x y h a
    simp only [and_imp, exists_prop, Part.bind_eq_bind, Part.mem_bind_iff, exists_imp]
    

Proof state:
α : Type u_1
β✝ : Type u_2
γ✝ : Type u_3
inst✝² : Preorder α
inst✝¹ : Preorder β✝
inst✝ : Preorder γ✝
β γ : Type ?u.55
f : α →o Part β
g : α →o β → Part γ
x y : α
h : x ≤ y
a : γ
⊢ ∀ x_1 ∈ f x, a ∈ g x x_1 → ∃ a_3 ∈ f y, a ∈ g y a_3

Next tactic:
intro b hb ha
/-- `Part.bind` as a monotone function -/
@[simps]
def bind {β γ} (f : α →o Part β) (g : α →o β → Part γ) : α →o Part γ where
  toFun x := f x >>= g x
  monotone' := by
    intro x y h a
    simp only [and_imp, exists_prop, Part.bind_eq_bind, Part.mem_bind_iff, exists_imp]
    intro b hb ha
    

Proof state:
α : Type u_1
β✝ : Type u_2
γ✝ : Type u_3
inst✝² : Preorder α
inst✝¹ : Preorder β✝
inst✝ : Preorder γ✝
β γ : Type ?u.55
f : α →o Part β
g : α →o β → Part γ
x y : α
h : x ≤ y
a : γ
b : β
hb : b ∈ f x
ha : a ∈ g x b
⊢ ∃ a_1 ∈ f y, a ∈ g y a_1

Next tactic:
refine' ⟨b, f.monotone h _ hb, g.monotone h _ _ ha⟩
@[simp]
theorem mem_map_iff {b : β} : b ∈ c.map f ↔ ∃ a, a ∈ c ∧ f a = b :=
  ⟨exists_of_mem_map _, fun h => by
    

Proof state:
α : Type u
β : Type v
γ : Type u_1
inst✝² : Preorder α
inst✝¹ : Preorder β
inst✝ : Preorder γ
c c' : Chain α
f : α →o β
g : β →o γ
b : β
h : ∃ a ∈ c, f a = b
⊢ b ∈ map c f

Next tactic:
rcases h with ⟨w, h, h'⟩
@[simp]
theorem mem_map_iff {b : β} : b ∈ c.map f ↔ ∃ a, a ∈ c ∧ f a = b :=
  ⟨exists_of_mem_map _, fun h => by
    rcases h with ⟨w, h, h'⟩
    

Proof state:
case intro.intro
α : Type u
β : Type v
γ : Type u_1
inst✝² : Preorder α
inst✝¹ : Preorder β
inst✝ : Preorder γ
c c' : Chain α
f : α →o β
g : β →o γ
b : β
w : α
h : w ∈ c
h' : f w = b
⊢ b ∈ map c f

Next tactic:
subst b
@[simp]
theorem mem_map_iff {b : β} : b ∈ c.map f ↔ ∃ a, a ∈ c ∧ f a = b :=
  ⟨exists_of_mem_map _, fun h => by
    rcases h with ⟨w, h, h'⟩
    subst b
    

Proof state:
case intro.intro
α : Type u
β : Type v
γ : Type u_1
inst✝² : Preorder α
inst✝¹ : Preorder β
inst✝ : Preorder γ
c c' : Chain α
f : α →o β
g : β →o γ
w : α
h : w ∈ c
⊢ f w ∈ map c f

Next tactic:
apply mem_map c _ h