l3lab/ntp-mathlib huggingface dataset:
theorem int_cast (n : ℤ) : mapFun f (n : 𝕎 R) = n :=
  show mapFun f n.castDef = (n : WittVector p S) by
    cases n <;> simp [*, Int.castDef, add, one, neg, zero, nat_cast] <;> 

Proof state:
case negSucc
p : ℕ
R : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝² : CommRing R
inst✝¹ : CommRing S
inst✝ : CommRing T
α : Type u_4
β : Type u_5
f : R →+* S
x y : 𝕎 R
a✝ : ℕ
⊢ -↑(a✝ + 1) = ↑(Int.negSucc a✝)

Next tactic:
rfl
@[local simp]
theorem matrix_vecEmpty_coeff {R} (i j) :
    @coeff p R (Matrix.vecEmpty i) j = (Matrix.vecEmpty i : ℕ → R) j := by
  

Proof state:
p : ℕ
R✝ : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝² : CommRing R✝
inst✝¹ : CommRing S
inst✝ : CommRing T
α : Type u_4
β : Type u_5
x y : 𝕎 R✝
R : Type u_6
i : Fin 0
j : ℕ
⊢ coeff ![] j = ![]

Next tactic:
rcases i with ⟨_ | _ | _ | _ | i_val, ⟨⟩⟩
private theorem ghostFun_zero : ghostFun (0 : 𝕎 R) = 0 := by
  

Proof state:
p : ℕ
R : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝² : CommRing R
inst✝¹ : CommRing S
inst✝ : CommRing T
α : Type u_4
β : Type u_5
x y : 𝕎 R
⊢ WittVector.ghostFun 0 = 0

Next tactic:
ghost_fun_tac 0, ![]
private theorem ghostFun_one : ghostFun (1 : 𝕎 R) = 1 := by
  

Proof state:
p : ℕ
R : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝² : CommRing R
inst✝¹ : CommRing S
inst✝ : CommRing T
α : Type u_4
β : Type u_5
x y : 𝕎 R
⊢ WittVector.ghostFun 1 = 1

Next tactic:
ghost_fun_tac 1, ![]
private theorem ghostFun_add : ghostFun (x + y) = ghostFun x + ghostFun y := by
  

Proof state:
p : ℕ
R : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝² : CommRing R
inst✝¹ : CommRing S
inst✝ : CommRing T
α : Type u_4
β : Type u_5
x y : 𝕎 R
⊢ WittVector.ghostFun (x + y) = WittVector.ghostFun x + WittVector.ghostFun y

Next tactic:
ghost_fun_tac X 0 + X 1, ![x.coeff, y.coeff]
private theorem ghostFun_nat_cast (i : ℕ) : ghostFun (i : 𝕎 R) = i :=
  show ghostFun i.unaryCast = _ by
    

Proof state:
p : ℕ
R : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝² : CommRing R
inst✝¹ : CommRing S
inst✝ : CommRing T
α : Type u_4
β : Type u_5
x y : 𝕎 R
i : ℕ
⊢ WittVector.ghostFun (Nat.unaryCast i) = ↑i

Next tactic:
induction i
private theorem ghostFun_nat_cast (i : ℕ) : ghostFun (i : 𝕎 R) = i :=
  show ghostFun i.unaryCast = _ by
    induction i <;>
      

Proof state:
case zero
p : ℕ
R : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝² : CommRing R
inst✝¹ : CommRing S
inst✝ : CommRing T
α : Type u_4
β : Type u_5
x y : 𝕎 R
⊢ WittVector.ghostFun (Nat.unaryCast Nat.zero) = ↑Nat.zero

Next tactic:
simp [*, Nat.unaryCast, ghostFun_zero, ghostFun_one, ghostFun_add, -Pi.coe_nat]
private theorem ghostFun_nat_cast (i : ℕ) : ghostFun (i : 𝕎 R) = i :=
  show ghostFun i.unaryCast = _ by
    induction i <;>
      

Proof state:
case succ
p : ℕ
R : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝² : CommRing R
inst✝¹ : CommRing S
inst✝ : CommRing T
α : Type u_4
β : Type u_5
x y : 𝕎 R
n✝ : ℕ
n_ih✝ : WittVector.ghostFun (Nat.unaryCast n✝) = ↑n✝
⊢ WittVector.ghostFun (Nat.unaryCast (Nat.succ n✝)) = ↑(Nat.succ n✝)

Next tactic:
simp [*, Nat.unaryCast, ghostFun_zero, ghostFun_one, ghostFun_add, -Pi.coe_nat]
private theorem ghostFun_sub : ghostFun (x - y) = ghostFun x - ghostFun y := by
  

Proof state:
p : ℕ
R : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝² : CommRing R
inst✝¹ : CommRing S
inst✝ : CommRing T
α : Type u_4
β : Type u_5
x y : 𝕎 R
⊢ WittVector.ghostFun (x - y) = WittVector.ghostFun x - WittVector.ghostFun y

Next tactic:
ghost_fun_tac X 0 - X 1, ![x.coeff, y.coeff]
private theorem ghostFun_mul : ghostFun (x * y) = ghostFun x * ghostFun y := by
  

Proof state:
p : ℕ
R : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝² : CommRing R
inst✝¹ : CommRing S
inst✝ : CommRing T
α : Type u_4
β : Type u_5
x y : 𝕎 R
⊢ WittVector.ghostFun (x * y) = WittVector.ghostFun x * WittVector.ghostFun y

Next tactic:
ghost_fun_tac X 0 * X 1, ![x.coeff, y.coeff]
private theorem ghostFun_neg : ghostFun (-x) = -ghostFun x := by 

Proof state:
p : ℕ
R : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝² : CommRing R
inst✝¹ : CommRing S
inst✝ : CommRing T
α : Type u_4
β : Type u_5
x y : 𝕎 R
⊢ WittVector.ghostFun (-x) = -WittVector.ghostFun x

Next tactic:
ghost_fun_tac -X 0, ![x.coeff]
private theorem ghostFun_int_cast (i : ℤ) : ghostFun (i : 𝕎 R) = i :=
  show ghostFun i.castDef = _ by
    

Proof state:
p : ℕ
R : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝² : CommRing R
inst✝¹ : CommRing S
inst✝ : CommRing T
α : Type u_4
β : Type u_5
x y : 𝕎 R
i : ℤ
⊢ WittVector.ghostFun (Int.castDef i) = ↑i

Next tactic:
cases i
private theorem ghostFun_int_cast (i : ℤ) : ghostFun (i : 𝕎 R) = i :=
  show ghostFun i.castDef = _ by
    cases i <;> 

Proof state:
case ofNat
p : ℕ
R : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝² : CommRing R
inst✝¹ : CommRing S
inst✝ : CommRing T
α : Type u_4
β : Type u_5
x y : 𝕎 R
a✝ : ℕ
⊢ WittVector.ghostFun (Int.castDef (Int.ofNat a✝)) = ↑(Int.ofNat a✝)

Next tactic:
simp [*, Int.castDef, ghostFun_nat_cast, ghostFun_neg, -Pi.coe_nat, -Pi.coe_int]
private theorem ghostFun_int_cast (i : ℤ) : ghostFun (i : 𝕎 R) = i :=
  show ghostFun i.castDef = _ by
    cases i <;> 

Proof state:
case negSucc
p : ℕ
R : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝² : CommRing R
inst✝¹ : CommRing S
inst✝ : CommRing T
α : Type u_4
β : Type u_5
x y : 𝕎 R
a✝ : ℕ
⊢ WittVector.ghostFun (Int.castDef (Int.negSucc a✝)) = ↑(Int.negSucc a✝)

Next tactic:
simp [*, Int.castDef, ghostFun_nat_cast, ghostFun_neg, -Pi.coe_nat, -Pi.coe_int]
private theorem ghostFun_nsmul (m : ℕ) : ghostFun (m • x) = m • ghostFun x := by
  --  porting note: I had to add the explicit type ascription.
  --  This could very well be due to my poor tactic writing!
  

Proof state:
p : ℕ
R : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝² : CommRing R
inst✝¹ : CommRing S
inst✝ : CommRing T
α : Type u_4
β : Type u_5
x y : 𝕎 R
m : ℕ
⊢ WittVector.ghostFun (m • x) = m • WittVector.ghostFun x

Next tactic:
ghost_fun_tac m • (X 0 : MvPolynomial _ ℤ), ![x.coeff]
private theorem ghostFun_zsmul (m : ℤ) : ghostFun (m • x) = m • ghostFun x := by
  --  porting note: I had to add the explicit type ascription.
  --  This could very well be due to my poor tactic writing!
  

Proof state:
p : ℕ
R : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝² : CommRing R
inst✝¹ : CommRing S
inst✝ : CommRing T
α : Type u_4
β : Type u_5
x y : 𝕎 R
m : ℤ
⊢ WittVector.ghostFun (m • x) = m • WittVector.ghostFun x

Next tactic:
ghost_fun_tac m • (X 0 : MvPolynomial _ ℤ), ![x.coeff]
private theorem ghostFun_pow (m : ℕ) : ghostFun (x ^ m) = ghostFun x ^ m := by
  

Proof state:
p : ℕ
R : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝² : CommRing R
inst✝¹ : CommRing S
inst✝ : CommRing T
α : Type u_4
β : Type u_5
x y : 𝕎 R
m : ℕ
⊢ WittVector.ghostFun (x ^ m) = WittVector.ghostFun x ^ m

Next tactic:
ghost_fun_tac X 0 ^ m, ![x.coeff]
/-- The bijection between `𝕎 R` and `ℕ → R`, under the assumption that `p` is invertible in `R`.
In `WittVector.ghostEquiv` we upgrade this to an isomorphism of rings. -/
private def ghostEquiv' [Invertible (p : R)] : 𝕎 R ≃ (ℕ → R) where
  toFun := ghostFun
  invFun x := mk p fun n => aeval x (xInTermsOfW p R n)
  left_inv := by
    

Proof state:
p : ℕ
R : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝³ : CommRing R
inst✝² : CommRing S
inst✝¹ : CommRing T
α : Type u_4
β : Type u_5
inst✝ : Invertible ↑p
⊢ LeftInverse (fun x => mk p fun n => (aeval x) (xInTermsOfW p R n)) WittVector.ghostFun

Next tactic:
intro x
/-- The bijection between `𝕎 R` and `ℕ → R`, under the assumption that `p` is invertible in `R`.
In `WittVector.ghostEquiv` we upgrade this to an isomorphism of rings. -/
private def ghostEquiv' [Invertible (p : R)] : 𝕎 R ≃ (ℕ → R) where
  toFun := ghostFun
  invFun x := mk p fun n => aeval x (xInTermsOfW p R n)
  left_inv := by
    intro x
    

Proof state:
p : ℕ
R : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝³ : CommRing R
inst✝² : CommRing S
inst✝¹ : CommRing T
α : Type u_4
β : Type u_5
inst✝ : Invertible ↑p
x : 𝕎 R
⊢ (fun x => mk p fun n => (aeval x) (xInTermsOfW p R n)) (WittVector.ghostFun x) = x

Next tactic:
ext n
/-- The bijection between `𝕎 R` and `ℕ → R`, under the assumption that `p` is invertible in `R`.
In `WittVector.ghostEquiv` we upgrade this to an isomorphism of rings. -/
private def ghostEquiv' [Invertible (p : R)] : 𝕎 R ≃ (ℕ → R) where
  toFun := ghostFun
  invFun x := mk p fun n => aeval x (xInTermsOfW p R n)
  left_inv := by
    intro x
    ext n
    

Proof state:
case h
p : ℕ
R : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝³ : CommRing R
inst✝² : CommRing S
inst✝¹ : CommRing T
α : Type u_4
β : Type u_5
inst✝ : Invertible ↑p
x : 𝕎 R
n : ℕ
⊢ coeff ((fun x => mk p fun n => (aeval x) (xInTermsOfW p R n)) (WittVector.ghostFun x)) n = coeff x n

Next tactic:
have := bind₁_wittPolynomial_xInTermsOfW p R n
/-- The bijection between `𝕎 R` and `ℕ → R`, under the assumption that `p` is invertible in `R`.
In `WittVector.ghostEquiv` we upgrade this to an isomorphism of rings. -/
private def ghostEquiv' [Invertible (p : R)] : 𝕎 R ≃ (ℕ → R) where
  toFun := ghostFun
  invFun x := mk p fun n => aeval x (xInTermsOfW p R n)
  left_inv := by
    intro x
    ext n
    have := bind₁_wittPolynomial_xInTermsOfW p R n
    

Proof state:
case h
p : ℕ
R : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝³ : CommRing R
inst✝² : CommRing S
inst✝¹ : CommRing T
α : Type u_4
β : Type u_5
inst✝ : Invertible ↑p
x : 𝕎 R
n : ℕ
this : (bind₁ (W_ R)) (xInTermsOfW p R n) = X n
⊢ coeff ((fun x => mk p fun n => (aeval x) (xInTermsOfW p R n)) (WittVector.ghostFun x)) n = coeff x n

Next tactic:
apply_fun aeval x.coeff at this
/-- The bijection between `𝕎 R` and `ℕ → R`, under the assumption that `p` is invertible in `R`.
In `WittVector.ghostEquiv` we upgrade this to an isomorphism of rings. -/
private def ghostEquiv' [Invertible (p : R)] : 𝕎 R ≃ (ℕ → R) where
  toFun := ghostFun
  invFun x := mk p fun n => aeval x (xInTermsOfW p R n)
  left_inv := by
    intro x
    ext n
    have := bind₁_wittPolynomial_xInTermsOfW p R n
    apply_fun aeval x.coeff at this
    

Proof state:
case h
p : ℕ
R : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝³ : CommRing R
inst✝² : CommRing S
inst✝¹ : CommRing T
α : Type u_4
β : Type u_5
inst✝ : Invertible ↑p
x : 𝕎 R
n : ℕ
this : (aeval x.coeff) ((bind₁ (W_ R)) (xInTermsOfW p R n)) = (aeval x.coeff) (X n)
⊢ coeff ((fun x => mk p fun n => (aeval x) (xInTermsOfW p R n)) (WittVector.ghostFun x)) n = coeff x n

Next tactic:
simpa (config := { unfoldPartialApp := true }) only [aeval_bind₁, aeval_X, ghostFun,
      aeval_wittPolynomial]
/-- The bijection between `𝕎 R` and `ℕ → R`, under the assumption that `p` is invertible in `R`.
In `WittVector.ghostEquiv` we upgrade this to an isomorphism of rings. -/
private def ghostEquiv' [Invertible (p : R)] : 𝕎 R ≃ (ℕ → R) where
  toFun := ghostFun
  invFun x := mk p fun n => aeval x (xInTermsOfW p R n)
  left_inv := by
    intro x
    ext n
    have := bind₁_wittPolynomial_xInTermsOfW p R n
    apply_fun aeval x.coeff at this
    simpa (config := { unfoldPartialApp := true }) only [aeval_bind₁, aeval_X, ghostFun,
      aeval_wittPolynomial]
  right_inv := by
    

Proof state:
p : ℕ
R : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝³ : CommRing R
inst✝² : CommRing S
inst✝¹ : CommRing T
α : Type u_4
β : Type u_5
inst✝ : Invertible ↑p
⊢ Function.RightInverse (fun x => mk p fun n => (aeval x) (xInTermsOfW p R n)) WittVector.ghostFun

Next tactic:
intro x
/-- The bijection between `𝕎 R` and `ℕ → R`, under the assumption that `p` is invertible in `R`.
In `WittVector.ghostEquiv` we upgrade this to an isomorphism of rings. -/
private def ghostEquiv' [Invertible (p : R)] : 𝕎 R ≃ (ℕ → R) where
  toFun := ghostFun
  invFun x := mk p fun n => aeval x (xInTermsOfW p R n)
  left_inv := by
    intro x
    ext n
    have := bind₁_wittPolynomial_xInTermsOfW p R n
    apply_fun aeval x.coeff at this
    simpa (config := { unfoldPartialApp := true }) only [aeval_bind₁, aeval_X, ghostFun,
      aeval_wittPolynomial]
  right_inv := by
    intro x
    

Proof state:
p : ℕ
R : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝³ : CommRing R
inst✝² : CommRing S
inst✝¹ : CommRing T
α : Type u_4
β : Type u_5
inst✝ : Invertible ↑p
x : ℕ → R
⊢ WittVector.ghostFun ((fun x => mk p fun n => (aeval x) (xInTermsOfW p R n)) x) = x

Next tactic:
ext n
/-- The bijection between `𝕎 R` and `ℕ → R`, under the assumption that `p` is invertible in `R`.
In `WittVector.ghostEquiv` we upgrade this to an isomorphism of rings. -/
private def ghostEquiv' [Invertible (p : R)] : 𝕎 R ≃ (ℕ → R) where
  toFun := ghostFun
  invFun x := mk p fun n => aeval x (xInTermsOfW p R n)
  left_inv := by
    intro x
    ext n
    have := bind₁_wittPolynomial_xInTermsOfW p R n
    apply_fun aeval x.coeff at this
    simpa (config := { unfoldPartialApp := true }) only [aeval_bind₁, aeval_X, ghostFun,
      aeval_wittPolynomial]
  right_inv := by
    intro x
    ext n
    

Proof state:
case h
p : ℕ
R : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝³ : CommRing R
inst✝² : CommRing S
inst✝¹ : CommRing T
α : Type u_4
β : Type u_5
inst✝ : Invertible ↑p
x : ℕ → R
n : ℕ
⊢ WittVector.ghostFun ((fun x => mk p fun n => (aeval x) (xInTermsOfW p R n)) x) n = x n

Next tactic:
have := bind₁_xInTermsOfW_wittPolynomial p R n
/-- The bijection between `𝕎 R` and `ℕ → R`, under the assumption that `p` is invertible in `R`.
In `WittVector.ghostEquiv` we upgrade this to an isomorphism of rings. -/
private def ghostEquiv' [Invertible (p : R)] : 𝕎 R ≃ (ℕ → R) where
  toFun := ghostFun
  invFun x := mk p fun n => aeval x (xInTermsOfW p R n)
  left_inv := by
    intro x
    ext n
    have := bind₁_wittPolynomial_xInTermsOfW p R n
    apply_fun aeval x.coeff at this
    simpa (config := { unfoldPartialApp := true }) only [aeval_bind₁, aeval_X, ghostFun,
      aeval_wittPolynomial]
  right_inv := by
    intro x
    ext n
    have := bind₁_xInTermsOfW_wittPolynomial p R n
    

Proof state:
case h
p : ℕ
R : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝³ : CommRing R
inst✝² : CommRing S
inst✝¹ : CommRing T
α : Type u_4
β : Type u_5
inst✝ : Invertible ↑p
x : ℕ → R
n : ℕ
this : (bind₁ (xInTermsOfW p R)) (W_ R n) = X n
⊢ WittVector.ghostFun ((fun x => mk p fun n => (aeval x) (xInTermsOfW p R n)) x) n = x n

Next tactic:
apply_fun aeval x at this
/-- The bijection between `𝕎 R` and `ℕ → R`, under the assumption that `p` is invertible in `R`.
In `WittVector.ghostEquiv` we upgrade this to an isomorphism of rings. -/
private def ghostEquiv' [Invertible (p : R)] : 𝕎 R ≃ (ℕ → R) where
  toFun := ghostFun
  invFun x := mk p fun n => aeval x (xInTermsOfW p R n)
  left_inv := by
    intro x
    ext n
    have := bind₁_wittPolynomial_xInTermsOfW p R n
    apply_fun aeval x.coeff at this
    simpa (config := { unfoldPartialApp := true }) only [aeval_bind₁, aeval_X, ghostFun,
      aeval_wittPolynomial]
  right_inv := by
    intro x
    ext n
    have := bind₁_xInTermsOfW_wittPolynomial p R n
    apply_fun aeval x at this
    

Proof state:
case h
p : ℕ
R : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝³ : CommRing R
inst✝² : CommRing S
inst✝¹ : CommRing T
α : Type u_4
β : Type u_5
inst✝ : Invertible ↑p
x : ℕ → R
n : ℕ
this : (aeval x) ((bind₁ (xInTermsOfW p R)) (W_ R n)) = (aeval x) (X n)
⊢ WittVector.ghostFun ((fun x => mk p fun n => (aeval x) (xInTermsOfW p R n)) x) n = x n

Next tactic:
simpa only [aeval_bind₁, aeval_X, ghostFun, aeval_wittPolynomial]
/-- `WittVector.coeff x 0` as a `RingHom` -/
@[simps]
noncomputable def constantCoeff : 𝕎 R →+* R where
  toFun x := x.coeff 0
  map_zero' := by simp
  map_one' := by 

Proof state:
p : ℕ
R : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝² : CommRing R
inst✝¹ : CommRing S
inst✝ : CommRing T
α : Type u_4
β : Type u_5
⊢ (fun x => coeff x 0) 1 = 1

Next tactic:
simp
/-- `WittVector.coeff x 0` as a `RingHom` -/
@[simps]
noncomputable def constantCoeff : 𝕎 R →+* R where
  toFun x := x.coeff 0
  map_zero' := by 

Proof state:
p : ℕ
R : Type u_1
S : Type u_2
T : Type u_3
hp : Fact (Nat.Prime p)
inst✝² : CommRing R
inst✝¹ : CommRing S
inst✝ : CommRing T
α : Type u_4
β : Type u_5
⊢ OneHom.toFun
      (↑{ toOneHom := { toFun := fun x => coeff x 0, map_one' := (_ : coeff 1 0 = 1) },
          map_mul' := (_ : ∀ (x y : 𝕎 R), coeff (x * y) 0 = coeff x 0 * coeff y 0) })
      0 =
    0

Next tactic:
simp
/-- If a cartesian closed category has a zero object, each homset has exactly one element. -/
def uniqueHomsetOfZero [HasZeroObject C] (X Y : C) : Unique (X ⟶ Y) := by
  

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : HasFiniteProducts C
inst✝¹ : CartesianClosed C
inst✝ : HasZeroObject C
X Y : C
⊢ Unique (X ⟶ Y)

Next tactic:
haveI : HasInitial C := HasZeroObject.hasInitial
/-- If a cartesian closed category has a zero object, each homset has exactly one element. -/
def uniqueHomsetOfZero [HasZeroObject C] (X Y : C) : Unique (X ⟶ Y) := by
  haveI : HasInitial C := HasZeroObject.hasInitial
  

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : HasFiniteProducts C
inst✝¹ : CartesianClosed C
inst✝ : HasZeroObject C
X Y : C
this : HasInitial C
⊢ Unique (X ⟶ Y)

Next tactic:
apply uniqueHomsetOfInitialIsoTerminal _ X Y
/-- If a cartesian closed category has a zero object, each homset has exactly one element. -/
def uniqueHomsetOfZero [HasZeroObject C] (X Y : C) : Unique (X ⟶ Y) := by
  haveI : HasInitial C := HasZeroObject.hasInitial
  apply uniqueHomsetOfInitialIsoTerminal _ X Y
  

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : HasFiniteProducts C
inst✝¹ : CartesianClosed C
inst✝ : HasZeroObject C
X Y : C
this : HasInitial C
⊢ ⊥_ C ≅ ⊤_ C

Next tactic:
refine' ⟨default, (default : ⊤_ C ⟶ 0) ≫ default, _, _⟩
/-- If a cartesian closed category has a zero object, each homset has exactly one element. -/
def uniqueHomsetOfZero [HasZeroObject C] (X Y : C) : Unique (X ⟶ Y) := by
  haveI : HasInitial C := HasZeroObject.hasInitial
  apply uniqueHomsetOfInitialIsoTerminal _ X Y
  refine' ⟨default, (default : ⊤_ C ⟶ 0) ≫ default, _, _⟩ <;> 

Proof state:
case refine'_1
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : HasFiniteProducts C
inst✝¹ : CartesianClosed C
inst✝ : HasZeroObject C
X Y : C
this : HasInitial C
⊢ default ≫ default ≫ default = 𝟙 (⊥_ C)

Next tactic:
simp [eq_iff_true_of_subsingleton]
/-- If a cartesian closed category has a zero object, each homset has exactly one element. -/
def uniqueHomsetOfZero [HasZeroObject C] (X Y : C) : Unique (X ⟶ Y) := by
  haveI : HasInitial C := HasZeroObject.hasInitial
  apply uniqueHomsetOfInitialIsoTerminal _ X Y
  refine' ⟨default, (default : ⊤_ C ⟶ 0) ≫ default, _, _⟩ <;> 

Proof state:
case refine'_2
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : HasFiniteProducts C
inst✝¹ : CartesianClosed C
inst✝ : HasZeroObject C
X Y : C
this : HasInitial C
⊢ (default ≫ default) ≫ default = 𝟙 (⊤_ C)

Next tactic:
simp [eq_iff_true_of_subsingleton]
instance instStarRing : StarRing (CliffordAlgebra Q) where
  star x := reverse (involute x)
  star_involutive x := by
    

Proof state:
R : Type u_1
inst✝² : CommRing R
M : Type u_2
inst✝¹ : AddCommGroup M
inst✝ : Module R M
Q : QuadraticForm R M
x : CliffordAlgebra Q
⊢ star (star x) = x

Next tactic:
simp only [reverse_involute_commute.eq, reverse_reverse, involute_involute]
instance instStarRing : StarRing (CliffordAlgebra Q) where
  star x := reverse (involute x)
  star_involutive x := by
    simp only [reverse_involute_commute.eq, reverse_reverse, involute_involute]
  star_mul x y := by 

Proof state:
R : Type u_1
inst✝² : CommRing R
M : Type u_2
inst✝¹ : AddCommGroup M
inst✝ : Module R M
Q : QuadraticForm R M
x y : CliffordAlgebra Q
⊢ star (x * y) = star y * star x

Next tactic:
simp only [map_mul, reverse.map_mul]
instance instStarRing : StarRing (CliffordAlgebra Q) where
  star x := reverse (involute x)
  star_involutive x := by
    simp only [reverse_involute_commute.eq, reverse_reverse, involute_involute]
  star_mul x y := by simp only [map_mul, reverse.map_mul]
  star_add x y := by 

Proof state:
R : Type u_1
inst✝² : CommRing R
M : Type u_2
inst✝¹ : AddCommGroup M
inst✝ : Module R M
Q : QuadraticForm R M
x y : CliffordAlgebra Q
⊢ star (x + y) = star x + star y

Next tactic:
simp only [map_add]
@[simp]
theorem star_ι (m : M) : star (ι Q m) = -ι Q m := by 

Proof state:
R : Type u_1
inst✝² : CommRing R
M : Type u_2
inst✝¹ : AddCommGroup M
inst✝ : Module R M
Q : QuadraticForm R M
m : M
⊢ star ((ι Q) m) = -(ι Q) m

Next tactic:
rw [star_def, involute_ι, map_neg, reverse_ι]
/-- Note that this not match the `star_smul` implied by `StarModule`; it certainly could if we
also conjugated all the scalars, but there appears to be nothing in the literature that advocates
doing this. -/
@[simp]
theorem star_smul (r : R) (x : CliffordAlgebra Q) : star (r • x) = r • star x := by
  

Proof state:
R : Type u_1
inst✝² : CommRing R
M : Type u_2
inst✝¹ : AddCommGroup M
inst✝ : Module R M
Q : QuadraticForm R M
r : R
x : CliffordAlgebra Q
⊢ star (r • x) = r • star x

Next tactic:
rw [star_def, star_def, map_smul, map_smul]
@[simp]
theorem star_algebraMap (r : R) :
    star (algebraMap R (CliffordAlgebra Q) r) = algebraMap R (CliffordAlgebra Q) r := by
  

Proof state:
R : Type u_1
inst✝² : CommRing R
M : Type u_2
inst✝¹ : AddCommGroup M
inst✝ : Module R M
Q : QuadraticForm R M
r : R
⊢ star ((algebraMap R (CliffordAlgebra Q)) r) = (algebraMap R (CliffordAlgebra Q)) r

Next tactic:
rw [star_def, involute.commutes, reverse.commutes]
/-- Translating a function by left-multiplication does not change its Lebesgue integral
with respect to a left-invariant measure. -/
@[to_additive
      "Translating a function by left-addition does not change its Lebesgue integral with
      respect to a left-invariant measure."]
theorem lintegral_mul_left_eq_self [IsMulLeftInvariant μ] (f : G → ℝ≥0∞) (g : G) :
    (∫⁻ x, f (g * x) ∂μ) = ∫⁻ x, f x ∂μ := by
  

Proof state:
G : Type u_1
inst✝³ : MeasurableSpace G
μ : Measure G
g✝ : G
inst✝² : Group G
inst✝¹ : MeasurableMul G
inst✝ : IsMulLeftInvariant μ
f : G → ℝ≥0∞
g : G
⊢ ∫⁻ (x : G), f (g * x) ∂μ = ∫⁻ (x : G), f x ∂μ

Next tactic:
convert (lintegral_map_equiv f <| MeasurableEquiv.mulLeft g).symm
/-- Translating a function by left-multiplication does not change its Lebesgue integral
with respect to a left-invariant measure. -/
@[to_additive
      "Translating a function by left-addition does not change its Lebesgue integral with
      respect to a left-invariant measure."]
theorem lintegral_mul_left_eq_self [IsMulLeftInvariant μ] (f : G → ℝ≥0∞) (g : G) :
    (∫⁻ x, f (g * x) ∂μ) = ∫⁻ x, f x ∂μ := by
  convert (lintegral_map_equiv f <| MeasurableEquiv.mulLeft g).symm
  

Proof state:
case h.e'_3.h.e'_3
G : Type u_1
inst✝³ : MeasurableSpace G
μ : Measure G
g✝ : G
inst✝² : Group G
inst✝¹ : MeasurableMul G
inst✝ : IsMulLeftInvariant μ
f : G → ℝ≥0∞
g : G
⊢ μ = map (⇑(MeasurableEquiv.mulLeft g)) μ

Next tactic:
simp [map_mul_left_eq_self μ g]
/-- Translating a function by right-multiplication does not change its Lebesgue integral
with respect to a right-invariant measure. -/
@[to_additive
      "Translating a function by right-addition does not change its Lebesgue integral with
      respect to a right-invariant measure."]
theorem lintegral_mul_right_eq_self [IsMulRightInvariant μ] (f : G → ℝ≥0∞) (g : G) :
    (∫⁻ x, f (x * g) ∂μ) = ∫⁻ x, f x ∂μ := by
  

Proof state:
G : Type u_1
inst✝³ : MeasurableSpace G
μ : Measure G
g✝ : G
inst✝² : Group G
inst✝¹ : MeasurableMul G
inst✝ : IsMulRightInvariant μ
f : G → ℝ≥0∞
g : G
⊢ ∫⁻ (x : G), f (x * g) ∂μ = ∫⁻ (x : G), f x ∂μ

Next tactic:
convert (lintegral_map_equiv f <| MeasurableEquiv.mulRight g).symm using 1