l3lab/ntp-mathlib huggingface dataset:
/-- The converse: if the additive character takes the value `1` only at `0`,
then it is primitive. -/
theorem zmod_char_primitive_of_eq_one_only_at_zero (n : ℕ) (ψ : AddChar (ZMod n) C)
    (hψ : ∀ a, ψ a = 1 → a = 0) : IsPrimitive ψ := by
  refine' fun a ha => (isNontrivial_iff_ne_trivial _).mpr fun hf => _
  have h : mulShift ψ a 1 = (1 : AddChar (ZMod n) C) (1 : ZMod n) :=
    congr_fun (congr_arg (↑) hf) 1
  rw [mulShift_apply, mul_one] at h; 

Proof state:
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
C : Type v
inst✝ : CommRing C
n : ℕ
ψ : AddChar (ZMod n) C
hψ : ∀ (a : ZMod n), ψ a = 1 → a = 0
a : ZMod n
ha : a ≠ 0
hf : mulShift ψ a = 1
h : ψ a = 1 1
⊢ False

Next tactic:
norm_cast at h
/-- The converse: if the additive character takes the value `1` only at `0`,
then it is primitive. -/
theorem zmod_char_primitive_of_eq_one_only_at_zero (n : ℕ) (ψ : AddChar (ZMod n) C)
    (hψ : ∀ a, ψ a = 1 → a = 0) : IsPrimitive ψ := by
  refine' fun a ha => (isNontrivial_iff_ne_trivial _).mpr fun hf => _
  have h : mulShift ψ a 1 = (1 : AddChar (ZMod n) C) (1 : ZMod n) :=
    congr_fun (congr_arg (↑) hf) 1
  rw [mulShift_apply, mul_one] at h; norm_cast at h
  

Proof state:
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
C : Type v
inst✝ : CommRing C
n : ℕ
ψ : AddChar (ZMod n) C
hψ : ∀ (a : ZMod n), ψ a = 1 → a = 0
a : ZMod n
ha : a ≠ 0
hf : mulShift ψ a = 1
h : ψ a = 1 1
⊢ False

Next tactic:
exact ha (hψ a h)
/-- The additive character on `ZMod n` associated to a primitive `n`th root of unity
is primitive -/
theorem zmodChar_primitive_of_primitive_root (n : ℕ+) {ζ : C} (h : IsPrimitiveRoot ζ n) :
    IsPrimitive (zmodChar n ((IsPrimitiveRoot.iff_def ζ n).mp h).left) := by
  

Proof state:
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
C : Type v
inst✝ : CommRing C
n : ℕ+
ζ : C
h : IsPrimitiveRoot ζ ↑n
⊢ IsPrimitive (zmodChar n (_ : ζ ^ ↑n = 1))

Next tactic:
apply zmod_char_primitive_of_eq_one_only_at_zero
/-- The additive character on `ZMod n` associated to a primitive `n`th root of unity
is primitive -/
theorem zmodChar_primitive_of_primitive_root (n : ℕ+) {ζ : C} (h : IsPrimitiveRoot ζ n) :
    IsPrimitive (zmodChar n ((IsPrimitiveRoot.iff_def ζ n).mp h).left) := by
  apply zmod_char_primitive_of_eq_one_only_at_zero
  

Proof state:
case hψ
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
C : Type v
inst✝ : CommRing C
n : ℕ+
ζ : C
h : IsPrimitiveRoot ζ ↑n
⊢ ∀ (a : ZMod ↑n), (zmodChar n (_ : ζ ^ ↑n = 1)) a = 1 → a = 0

Next tactic:
intro a ha
/-- The additive character on `ZMod n` associated to a primitive `n`th root of unity
is primitive -/
theorem zmodChar_primitive_of_primitive_root (n : ℕ+) {ζ : C} (h : IsPrimitiveRoot ζ n) :
    IsPrimitive (zmodChar n ((IsPrimitiveRoot.iff_def ζ n).mp h).left) := by
  apply zmod_char_primitive_of_eq_one_only_at_zero
  intro a ha
  

Proof state:
case hψ
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
C : Type v
inst✝ : CommRing C
n : ℕ+
ζ : C
h : IsPrimitiveRoot ζ ↑n
a : ZMod ↑n
ha : (zmodChar n (_ : ζ ^ ↑n = 1)) a = 1
⊢ a = 0

Next tactic:
rw [zmodChar_apply, ← pow_zero ζ] at ha
/-- The additive character on `ZMod n` associated to a primitive `n`th root of unity
is primitive -/
theorem zmodChar_primitive_of_primitive_root (n : ℕ+) {ζ : C} (h : IsPrimitiveRoot ζ n) :
    IsPrimitive (zmodChar n ((IsPrimitiveRoot.iff_def ζ n).mp h).left) := by
  apply zmod_char_primitive_of_eq_one_only_at_zero
  intro a ha
  rw [zmodChar_apply, ← pow_zero ζ] at ha
  

Proof state:
case hψ
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
C : Type v
inst✝ : CommRing C
n : ℕ+
ζ : C
h : IsPrimitiveRoot ζ ↑n
a : ZMod ↑n
ha : ζ ^ ZMod.val a = ζ ^ 0
⊢ a = 0

Next tactic:
exact (ZMod.val_eq_zero a).mp (IsPrimitiveRoot.pow_inj h (ZMod.val_lt a) n.pos ha)
/-- There is a primitive additive character on the finite field `F` if the characteristic
of the target is different from that of `F`.
We obtain it as the composition of the trace from `F` to `ZMod p` with a primitive
additive character on `ZMod p`, where `p` is the characteristic of `F`. -/
noncomputable def primitiveCharFiniteField (F F' : Type*) [Field F] [Fintype F] [Field F']
    (h : ringChar F' ≠ ringChar F) : PrimitiveAddChar F F' := by
  

Proof state:
R : Type u
inst✝⁵ : CommRing R
R' : Type v
inst✝⁴ : CommRing R'
C : Type v
inst✝³ : CommRing C
F : Type u_1
F' : Type u_2
inst✝² : Field F
inst✝¹ : Fintype F
inst✝ : Field F'
h : ringChar F' ≠ ringChar F
⊢ PrimitiveAddChar F F'

Next tactic:
let p := ringChar F
/-- There is a primitive additive character on the finite field `F` if the characteristic
of the target is different from that of `F`.
We obtain it as the composition of the trace from `F` to `ZMod p` with a primitive
additive character on `ZMod p`, where `p` is the characteristic of `F`. -/
noncomputable def primitiveCharFiniteField (F F' : Type*) [Field F] [Fintype F] [Field F']
    (h : ringChar F' ≠ ringChar F) : PrimitiveAddChar F F' := by
  let p := ringChar F
  

Proof state:
R : Type u
inst✝⁵ : CommRing R
R' : Type v
inst✝⁴ : CommRing R'
C : Type v
inst✝³ : CommRing C
F : Type u_1
F' : Type u_2
inst✝² : Field F
inst✝¹ : Fintype F
inst✝ : Field F'
h : ringChar F' ≠ ringChar F
p : ℕ := ringChar F
⊢ PrimitiveAddChar F F'

Next tactic:
haveI hp : Fact p.Prime := ⟨CharP.char_is_prime F _⟩
/-- There is a primitive additive character on the finite field `F` if the characteristic
of the target is different from that of `F`.
We obtain it as the composition of the trace from `F` to `ZMod p` with a primitive
additive character on `ZMod p`, where `p` is the characteristic of `F`. -/
noncomputable def primitiveCharFiniteField (F F' : Type*) [Field F] [Fintype F] [Field F']
    (h : ringChar F' ≠ ringChar F) : PrimitiveAddChar F F' := by
  let p := ringChar F
  haveI hp : Fact p.Prime := ⟨CharP.char_is_prime F _⟩
  

Proof state:
R : Type u
inst✝⁵ : CommRing R
R' : Type v
inst✝⁴ : CommRing R'
C : Type v
inst✝³ : CommRing C
F : Type u_1
F' : Type u_2
inst✝² : Field F
inst✝¹ : Fintype F
inst✝ : Field F'
h : ringChar F' ≠ ringChar F
p : ℕ := ringChar F
hp : Fact (Nat.Prime p)
⊢ PrimitiveAddChar F F'

Next tactic:
let pp := p.toPNat hp.1.pos
/-- There is a primitive additive character on the finite field `F` if the characteristic
of the target is different from that of `F`.
We obtain it as the composition of the trace from `F` to `ZMod p` with a primitive
additive character on `ZMod p`, where `p` is the characteristic of `F`. -/
noncomputable def primitiveCharFiniteField (F F' : Type*) [Field F] [Fintype F] [Field F']
    (h : ringChar F' ≠ ringChar F) : PrimitiveAddChar F F' := by
  let p := ringChar F
  haveI hp : Fact p.Prime := ⟨CharP.char_is_prime F _⟩
  let pp := p.toPNat hp.1.pos
  

Proof state:
R : Type u
inst✝⁵ : CommRing R
R' : Type v
inst✝⁴ : CommRing R'
C : Type v
inst✝³ : CommRing C
F : Type u_1
F' : Type u_2
inst✝² : Field F
inst✝¹ : Fintype F
inst✝ : Field F'
h : ringChar F' ≠ ringChar F
p : ℕ := ringChar F
hp : Fact (Nat.Prime p)
pp : ℕ+ := Nat.toPNat p
⊢ PrimitiveAddChar F F'

Next tactic:
have hp₂ : ¬ringChar F' ∣ p := by
    cases' CharP.char_is_prime_or_zero F' (ringChar F') with hq hq
    · exact mt (Nat.Prime.dvd_iff_eq hp.1 (Nat.Prime.ne_one hq)).mp h.symm
    · rw [hq]
      exact fun hf => Nat.Prime.ne_zero hp.1 (zero_dvd_iff.mp hf)
/-- There is a primitive additive character on the finite field `F` if the characteristic
of the target is different from that of `F`.
We obtain it as the composition of the trace from `F` to `ZMod p` with a primitive
additive character on `ZMod p`, where `p` is the characteristic of `F`. -/
noncomputable def primitiveCharFiniteField (F F' : Type*) [Field F] [Fintype F] [Field F']
    (h : ringChar F' ≠ ringChar F) : PrimitiveAddChar F F' := by
  let p := ringChar F
  haveI hp : Fact p.Prime := ⟨CharP.char_is_prime F _⟩
  let pp := p.toPNat hp.1.pos
  have hp₂ : ¬ringChar F' ∣ p := by
    

Proof state:
R : Type u
inst✝⁵ : CommRing R
R' : Type v
inst✝⁴ : CommRing R'
C : Type v
inst✝³ : CommRing C
F : Type u_1
F' : Type u_2
inst✝² : Field F
inst✝¹ : Fintype F
inst✝ : Field F'
h : ringChar F' ≠ ringChar F
p : ℕ := ringChar F
hp : Fact (Nat.Prime p)
pp : ℕ+ := Nat.toPNat p
⊢ ¬ringChar F' ∣ p

Next tactic:
cases' CharP.char_is_prime_or_zero F' (ringChar F') with hq hq
/-- There is a primitive additive character on the finite field `F` if the characteristic
of the target is different from that of `F`.
We obtain it as the composition of the trace from `F` to `ZMod p` with a primitive
additive character on `ZMod p`, where `p` is the characteristic of `F`. -/
noncomputable def primitiveCharFiniteField (F F' : Type*) [Field F] [Fintype F] [Field F']
    (h : ringChar F' ≠ ringChar F) : PrimitiveAddChar F F' := by
  let p := ringChar F
  haveI hp : Fact p.Prime := ⟨CharP.char_is_prime F _⟩
  let pp := p.toPNat hp.1.pos
  have hp₂ : ¬ringChar F' ∣ p := by
    cases' CharP.char_is_prime_or_zero F' (ringChar F') with hq hq
    · 

Proof state:
case inl
R : Type u
inst✝⁵ : CommRing R
R' : Type v
inst✝⁴ : CommRing R'
C : Type v
inst✝³ : CommRing C
F : Type u_1
F' : Type u_2
inst✝² : Field F
inst✝¹ : Fintype F
inst✝ : Field F'
h : ringChar F' ≠ ringChar F
p : ℕ := ringChar F
hp : Fact (Nat.Prime p)
pp : ℕ+ := Nat.toPNat p
hq : Nat.Prime (ringChar F')
⊢ ¬ringChar F' ∣ p

Next tactic:
exact mt (Nat.Prime.dvd_iff_eq hp.1 (Nat.Prime.ne_one hq)).mp h.symm
/-- There is a primitive additive character on the finite field `F` if the characteristic
of the target is different from that of `F`.
We obtain it as the composition of the trace from `F` to `ZMod p` with a primitive
additive character on `ZMod p`, where `p` is the characteristic of `F`. -/
noncomputable def primitiveCharFiniteField (F F' : Type*) [Field F] [Fintype F] [Field F']
    (h : ringChar F' ≠ ringChar F) : PrimitiveAddChar F F' := by
  let p := ringChar F
  haveI hp : Fact p.Prime := ⟨CharP.char_is_prime F _⟩
  let pp := p.toPNat hp.1.pos
  have hp₂ : ¬ringChar F' ∣ p := by
    cases' CharP.char_is_prime_or_zero F' (ringChar F') with hq hq
    · exact mt (Nat.Prime.dvd_iff_eq hp.1 (Nat.Prime.ne_one hq)).mp h.symm
    · 

Proof state:
case inr
R : Type u
inst✝⁵ : CommRing R
R' : Type v
inst✝⁴ : CommRing R'
C : Type v
inst✝³ : CommRing C
F : Type u_1
F' : Type u_2
inst✝² : Field F
inst✝¹ : Fintype F
inst✝ : Field F'
h : ringChar F' ≠ ringChar F
p : ℕ := ringChar F
hp : Fact (Nat.Prime p)
pp : ℕ+ := Nat.toPNat p
hq : ringChar F' = 0
⊢ ¬ringChar F' ∣ p

Next tactic:
rw [hq]
/-- There is a primitive additive character on the finite field `F` if the characteristic
of the target is different from that of `F`.
We obtain it as the composition of the trace from `F` to `ZMod p` with a primitive
additive character on `ZMod p`, where `p` is the characteristic of `F`. -/
noncomputable def primitiveCharFiniteField (F F' : Type*) [Field F] [Fintype F] [Field F']
    (h : ringChar F' ≠ ringChar F) : PrimitiveAddChar F F' := by
  let p := ringChar F
  haveI hp : Fact p.Prime := ⟨CharP.char_is_prime F _⟩
  let pp := p.toPNat hp.1.pos
  have hp₂ : ¬ringChar F' ∣ p := by
    cases' CharP.char_is_prime_or_zero F' (ringChar F') with hq hq
    · exact mt (Nat.Prime.dvd_iff_eq hp.1 (Nat.Prime.ne_one hq)).mp h.symm
    · rw [hq]
      

Proof state:
case inr
R : Type u
inst✝⁵ : CommRing R
R' : Type v
inst✝⁴ : CommRing R'
C : Type v
inst✝³ : CommRing C
F : Type u_1
F' : Type u_2
inst✝² : Field F
inst✝¹ : Fintype F
inst✝ : Field F'
h : ringChar F' ≠ ringChar F
p : ℕ := ringChar F
hp : Fact (Nat.Prime p)
pp : ℕ+ := Nat.toPNat p
hq : ringChar F' = 0
⊢ ¬0 ∣ p

Next tactic:
exact fun hf => Nat.Prime.ne_zero hp.1 (zero_dvd_iff.mp hf)
/-- There is a primitive additive character on the finite field `F` if the characteristic
of the target is different from that of `F`.
We obtain it as the composition of the trace from `F` to `ZMod p` with a primitive
additive character on `ZMod p`, where `p` is the characteristic of `F`. -/
noncomputable def primitiveCharFiniteField (F F' : Type*) [Field F] [Fintype F] [Field F']
    (h : ringChar F' ≠ ringChar F) : PrimitiveAddChar F F' := by
  let p := ringChar F
  haveI hp : Fact p.Prime := ⟨CharP.char_is_prime F _⟩
  let pp := p.toPNat hp.1.pos
  have hp₂ : ¬ringChar F' ∣ p := by
    cases' CharP.char_is_prime_or_zero F' (ringChar F') with hq hq
    · exact mt (Nat.Prime.dvd_iff_eq hp.1 (Nat.Prime.ne_one hq)).mp h.symm
    · rw [hq]
      exact fun hf => Nat.Prime.ne_zero hp.1 (zero_dvd_iff.mp hf)
  

Proof state:
R : Type u
inst✝⁵ : CommRing R
R' : Type v
inst✝⁴ : CommRing R'
C : Type v
inst✝³ : CommRing C
F : Type u_1
F' : Type u_2
inst✝² : Field F
inst✝¹ : Fintype F
inst✝ : Field F'
h : ringChar F' ≠ ringChar F
p : ℕ := ringChar F
hp : Fact (Nat.Prime p)
pp : ℕ+ := Nat.toPNat p
hp₂ : ¬ringChar F' ∣ p
⊢ PrimitiveAddChar F F'

Next tactic:
let ψ := primitiveZModChar pp F' (neZero_iff.mp (NeZero.of_not_dvd F' hp₂))
/-- There is a primitive additive character on the finite field `F` if the characteristic
of the target is different from that of `F`.
We obtain it as the composition of the trace from `F` to `ZMod p` with a primitive
additive character on `ZMod p`, where `p` is the characteristic of `F`. -/
noncomputable def primitiveCharFiniteField (F F' : Type*) [Field F] [Fintype F] [Field F']
    (h : ringChar F' ≠ ringChar F) : PrimitiveAddChar F F' := by
  let p := ringChar F
  haveI hp : Fact p.Prime := ⟨CharP.char_is_prime F _⟩
  let pp := p.toPNat hp.1.pos
  have hp₂ : ¬ringChar F' ∣ p := by
    cases' CharP.char_is_prime_or_zero F' (ringChar F') with hq hq
    · exact mt (Nat.Prime.dvd_iff_eq hp.1 (Nat.Prime.ne_one hq)).mp h.symm
    · rw [hq]
      exact fun hf => Nat.Prime.ne_zero hp.1 (zero_dvd_iff.mp hf)
  let ψ := primitiveZModChar pp F' (neZero_iff.mp (NeZero.of_not_dvd F' hp₂))
  

Proof state:
R : Type u
inst✝⁵ : CommRing R
R' : Type v
inst✝⁴ : CommRing R'
C : Type v
inst✝³ : CommRing C
F : Type u_1
F' : Type u_2
inst✝² : Field F
inst✝¹ : Fintype F
inst✝ : Field F'
h : ringChar F' ≠ ringChar F
p : ℕ := ringChar F
hp : Fact (Nat.Prime p)
pp : ℕ+ := Nat.toPNat p
hp₂ : ¬ringChar F' ∣ p
ψ : PrimitiveAddChar (ZMod ↑pp) F' := primitiveZModChar pp F' (_ : ↑↑pp ≠ 0)
⊢ PrimitiveAddChar F F'

Next tactic:
letI : Algebra (ZMod p) F := ZMod.algebra _ _
/-- There is a primitive additive character on the finite field `F` if the characteristic
of the target is different from that of `F`.
We obtain it as the composition of the trace from `F` to `ZMod p` with a primitive
additive character on `ZMod p`, where `p` is the characteristic of `F`. -/
noncomputable def primitiveCharFiniteField (F F' : Type*) [Field F] [Fintype F] [Field F']
    (h : ringChar F' ≠ ringChar F) : PrimitiveAddChar F F' := by
  let p := ringChar F
  haveI hp : Fact p.Prime := ⟨CharP.char_is_prime F _⟩
  let pp := p.toPNat hp.1.pos
  have hp₂ : ¬ringChar F' ∣ p := by
    cases' CharP.char_is_prime_or_zero F' (ringChar F') with hq hq
    · exact mt (Nat.Prime.dvd_iff_eq hp.1 (Nat.Prime.ne_one hq)).mp h.symm
    · rw [hq]
      exact fun hf => Nat.Prime.ne_zero hp.1 (zero_dvd_iff.mp hf)
  let ψ := primitiveZModChar pp F' (neZero_iff.mp (NeZero.of_not_dvd F' hp₂))
  letI : Algebra (ZMod p) F := ZMod.algebra _ _
  

Proof state:
R : Type u
inst✝⁵ : CommRing R
R' : Type v
inst✝⁴ : CommRing R'
C : Type v
inst✝³ : CommRing C
F : Type u_1
F' : Type u_2
inst✝² : Field F
inst✝¹ : Fintype F
inst✝ : Field F'
h : ringChar F' ≠ ringChar F
p : ℕ := ringChar F
hp : Fact (Nat.Prime p)
pp : ℕ+ := Nat.toPNat p
hp₂ : ¬ringChar F' ∣ p
ψ : PrimitiveAddChar (ZMod ↑pp) F' := primitiveZModChar pp F' (_ : ↑↑pp ≠ 0)
this : Algebra (ZMod p) F := ZMod.algebra F p
⊢ PrimitiveAddChar F F'

Next tactic:
let ψ' := ψ.char.comp (AddMonoidHom.toMultiplicative (Algebra.trace (ZMod p) F).toAddMonoidHom)
/-- There is a primitive additive character on the finite field `F` if the characteristic
of the target is different from that of `F`.
We obtain it as the composition of the trace from `F` to `ZMod p` with a primitive
additive character on `ZMod p`, where `p` is the characteristic of `F`. -/
noncomputable def primitiveCharFiniteField (F F' : Type*) [Field F] [Fintype F] [Field F']
    (h : ringChar F' ≠ ringChar F) : PrimitiveAddChar F F' := by
  let p := ringChar F
  haveI hp : Fact p.Prime := ⟨CharP.char_is_prime F _⟩
  let pp := p.toPNat hp.1.pos
  have hp₂ : ¬ringChar F' ∣ p := by
    cases' CharP.char_is_prime_or_zero F' (ringChar F') with hq hq
    · exact mt (Nat.Prime.dvd_iff_eq hp.1 (Nat.Prime.ne_one hq)).mp h.symm
    · rw [hq]
      exact fun hf => Nat.Prime.ne_zero hp.1 (zero_dvd_iff.mp hf)
  let ψ := primitiveZModChar pp F' (neZero_iff.mp (NeZero.of_not_dvd F' hp₂))
  letI : Algebra (ZMod p) F := ZMod.algebra _ _
  let ψ' := ψ.char.comp (AddMonoidHom.toMultiplicative (Algebra.trace (ZMod p) F).toAddMonoidHom)
  

Proof state:
R : Type u
inst✝⁵ : CommRing R
R' : Type v
inst✝⁴ : CommRing R'
C : Type v
inst✝³ : CommRing C
F : Type u_1
F' : Type u_2
inst✝² : Field F
inst✝¹ : Fintype F
inst✝ : Field F'
h : ringChar F' ≠ ringChar F
p : ℕ := ringChar F
hp : Fact (Nat.Prime p)
pp : ℕ+ := Nat.toPNat p
hp₂ : ¬ringChar F' ∣ p
ψ : PrimitiveAddChar (ZMod ↑pp) F' := primitiveZModChar pp F' (_ : ↑↑pp ≠ 0)
this : Algebra (ZMod p) F := ZMod.algebra F p
ψ' : Multiplicative F →* CyclotomicField (PrimitiveAddChar.n ψ) F' :=
  MonoidHom.comp (PrimitiveAddChar.char ψ)
    (AddMonoidHom.toMultiplicative (LinearMap.toAddMonoidHom (Algebra.trace (ZMod p) F)))
⊢ PrimitiveAddChar F F'

Next tactic:
have hψ' : IsNontrivial ψ' := by
    obtain ⟨a, ha⟩ := FiniteField.trace_to_zmod_nondegenerate F one_ne_zero
    rw [one_mul] at ha
    exact ⟨a, fun hf => ha <| (ψ.prim.zmod_char_eq_one_iff pp <| Algebra.trace (ZMod p) F a).mp hf⟩
/-- There is a primitive additive character on the finite field `F` if the characteristic
of the target is different from that of `F`.
We obtain it as the composition of the trace from `F` to `ZMod p` with a primitive
additive character on `ZMod p`, where `p` is the characteristic of `F`. -/
noncomputable def primitiveCharFiniteField (F F' : Type*) [Field F] [Fintype F] [Field F']
    (h : ringChar F' ≠ ringChar F) : PrimitiveAddChar F F' := by
  let p := ringChar F
  haveI hp : Fact p.Prime := ⟨CharP.char_is_prime F _⟩
  let pp := p.toPNat hp.1.pos
  have hp₂ : ¬ringChar F' ∣ p := by
    cases' CharP.char_is_prime_or_zero F' (ringChar F') with hq hq
    · exact mt (Nat.Prime.dvd_iff_eq hp.1 (Nat.Prime.ne_one hq)).mp h.symm
    · rw [hq]
      exact fun hf => Nat.Prime.ne_zero hp.1 (zero_dvd_iff.mp hf)
  let ψ := primitiveZModChar pp F' (neZero_iff.mp (NeZero.of_not_dvd F' hp₂))
  letI : Algebra (ZMod p) F := ZMod.algebra _ _
  let ψ' := ψ.char.comp (AddMonoidHom.toMultiplicative (Algebra.trace (ZMod p) F).toAddMonoidHom)
  have hψ' : IsNontrivial ψ' := by
    

Proof state:
R : Type u
inst✝⁵ : CommRing R
R' : Type v
inst✝⁴ : CommRing R'
C : Type v
inst✝³ : CommRing C
F : Type u_1
F' : Type u_2
inst✝² : Field F
inst✝¹ : Fintype F
inst✝ : Field F'
h : ringChar F' ≠ ringChar F
p : ℕ := ringChar F
hp : Fact (Nat.Prime p)
pp : ℕ+ := Nat.toPNat p
hp₂ : ¬ringChar F' ∣ p
ψ : PrimitiveAddChar (ZMod ↑pp) F' := primitiveZModChar pp F' (_ : ↑↑pp ≠ 0)
this : Algebra (ZMod p) F := ZMod.algebra F p
ψ' : Multiplicative F →* CyclotomicField (PrimitiveAddChar.n ψ) F' :=
  MonoidHom.comp (PrimitiveAddChar.char ψ)
    (AddMonoidHom.toMultiplicative (LinearMap.toAddMonoidHom (Algebra.trace (ZMod p) F)))
⊢ IsNontrivial ψ'

Next tactic:
obtain ⟨a, ha⟩ := FiniteField.trace_to_zmod_nondegenerate F one_ne_zero
/-- There is a primitive additive character on the finite field `F` if the characteristic
of the target is different from that of `F`.
We obtain it as the composition of the trace from `F` to `ZMod p` with a primitive
additive character on `ZMod p`, where `p` is the characteristic of `F`. -/
noncomputable def primitiveCharFiniteField (F F' : Type*) [Field F] [Fintype F] [Field F']
    (h : ringChar F' ≠ ringChar F) : PrimitiveAddChar F F' := by
  let p := ringChar F
  haveI hp : Fact p.Prime := ⟨CharP.char_is_prime F _⟩
  let pp := p.toPNat hp.1.pos
  have hp₂ : ¬ringChar F' ∣ p := by
    cases' CharP.char_is_prime_or_zero F' (ringChar F') with hq hq
    · exact mt (Nat.Prime.dvd_iff_eq hp.1 (Nat.Prime.ne_one hq)).mp h.symm
    · rw [hq]
      exact fun hf => Nat.Prime.ne_zero hp.1 (zero_dvd_iff.mp hf)
  let ψ := primitiveZModChar pp F' (neZero_iff.mp (NeZero.of_not_dvd F' hp₂))
  letI : Algebra (ZMod p) F := ZMod.algebra _ _
  let ψ' := ψ.char.comp (AddMonoidHom.toMultiplicative (Algebra.trace (ZMod p) F).toAddMonoidHom)
  have hψ' : IsNontrivial ψ' := by
    obtain ⟨a, ha⟩ := FiniteField.trace_to_zmod_nondegenerate F one_ne_zero
    

Proof state:
case intro
R : Type u
inst✝⁵ : CommRing R
R' : Type v
inst✝⁴ : CommRing R'
C : Type v
inst✝³ : CommRing C
F : Type u_1
F' : Type u_2
inst✝² : Field F
inst✝¹ : Fintype F
inst✝ : Field F'
h : ringChar F' ≠ ringChar F
p : ℕ := ringChar F
hp : Fact (Nat.Prime p)
pp : ℕ+ := Nat.toPNat p
hp₂ : ¬ringChar F' ∣ p
ψ : PrimitiveAddChar (ZMod ↑pp) F' := primitiveZModChar pp F' (_ : ↑↑pp ≠ 0)
this : Algebra (ZMod p) F := ZMod.algebra F p
ψ' : Multiplicative F →* CyclotomicField (PrimitiveAddChar.n ψ) F' :=
  MonoidHom.comp (PrimitiveAddChar.char ψ)
    (AddMonoidHom.toMultiplicative (LinearMap.toAddMonoidHom (Algebra.trace (ZMod p) F)))
a : F
ha : (Algebra.trace (ZMod (ringChar F)) F) (1 * a) ≠ 0
⊢ IsNontrivial ψ'

Next tactic:
rw [one_mul] at ha
/-- There is a primitive additive character on the finite field `F` if the characteristic
of the target is different from that of `F`.
We obtain it as the composition of the trace from `F` to `ZMod p` with a primitive
additive character on `ZMod p`, where `p` is the characteristic of `F`. -/
noncomputable def primitiveCharFiniteField (F F' : Type*) [Field F] [Fintype F] [Field F']
    (h : ringChar F' ≠ ringChar F) : PrimitiveAddChar F F' := by
  let p := ringChar F
  haveI hp : Fact p.Prime := ⟨CharP.char_is_prime F _⟩
  let pp := p.toPNat hp.1.pos
  have hp₂ : ¬ringChar F' ∣ p := by
    cases' CharP.char_is_prime_or_zero F' (ringChar F') with hq hq
    · exact mt (Nat.Prime.dvd_iff_eq hp.1 (Nat.Prime.ne_one hq)).mp h.symm
    · rw [hq]
      exact fun hf => Nat.Prime.ne_zero hp.1 (zero_dvd_iff.mp hf)
  let ψ := primitiveZModChar pp F' (neZero_iff.mp (NeZero.of_not_dvd F' hp₂))
  letI : Algebra (ZMod p) F := ZMod.algebra _ _
  let ψ' := ψ.char.comp (AddMonoidHom.toMultiplicative (Algebra.trace (ZMod p) F).toAddMonoidHom)
  have hψ' : IsNontrivial ψ' := by
    obtain ⟨a, ha⟩ := FiniteField.trace_to_zmod_nondegenerate F one_ne_zero
    rw [one_mul] at ha
    

Proof state:
case intro
R : Type u
inst✝⁵ : CommRing R
R' : Type v
inst✝⁴ : CommRing R'
C : Type v
inst✝³ : CommRing C
F : Type u_1
F' : Type u_2
inst✝² : Field F
inst✝¹ : Fintype F
inst✝ : Field F'
h : ringChar F' ≠ ringChar F
p : ℕ := ringChar F
hp : Fact (Nat.Prime p)
pp : ℕ+ := Nat.toPNat p
hp₂ : ¬ringChar F' ∣ p
ψ : PrimitiveAddChar (ZMod ↑pp) F' := primitiveZModChar pp F' (_ : ↑↑pp ≠ 0)
this : Algebra (ZMod p) F := ZMod.algebra F p
ψ' : Multiplicative F →* CyclotomicField (PrimitiveAddChar.n ψ) F' :=
  MonoidHom.comp (PrimitiveAddChar.char ψ)
    (AddMonoidHom.toMultiplicative (LinearMap.toAddMonoidHom (Algebra.trace (ZMod p) F)))
a : F
ha : (Algebra.trace (ZMod (ringChar F)) F) a ≠ 0
⊢ IsNontrivial ψ'

Next tactic:
exact ⟨a, fun hf => ha <| (ψ.prim.zmod_char_eq_one_iff pp <| Algebra.trace (ZMod p) F a).mp hf⟩