/-- The (additive) monoid equivalence between `ZMod k`
and the powers of a primitive root of unity `ζ`. -/
def zmodEquivZPowers (h : IsPrimitiveRoot ζ k) : ZMod k ≃+ Additive (Subgroup.zpowers ζ) :=
  AddEquiv.ofBijective
    (AddMonoidHom.liftOfRightInverse (Int.castAddHom <| ZMod k) _ ZMod.int_cast_rightInverse
      ⟨{  toFun := fun i => Additive.ofMul (⟨_, i, rfl⟩ : Subgroup.zpowers ζ)
          map_zero' := by simp only [zpow_zero]; rfl
          map_add' := by intro i j; simp only [zpow_add]; rfl }, fun i hi => by
        

Proof state:
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F : Type u_6
inst✝³ : CommMonoid M
inst✝² : CommMonoid N
inst✝¹ : DivisionCommMonoid G
k l : ℕ
inst✝ : CommRing R
ζ : Rˣ
h✝ h : IsPrimitiveRoot ζ k
i : ℤ
hi : i ∈ AddMonoidHom.ker (Int.castAddHom (ZMod k))
⊢ i ∈
    AddMonoidHom.ker
      {
        toZeroHom :=
          {
            toFun := fun i =>
              Additive.ofMul
                { val := (fun x => ζ ^ x) i, property := (_ : ∃ y, (fun x => ζ ^ x) y = (fun x => ζ ^ x) i) },
            map_zero' :=
              (_ :
                (fun i =>
                      Additive.ofMul
                        { val := (fun x => ζ ^ x) i, property := (_ : ∃ y, (fun x => ζ ^ x) y = (fun x => ζ ^ x) i) })
                    0 =
                  0) },
        map_add' :=
          (_ :
            ∀ (i j : ℤ),
              ZeroHom.toFun
                  {
                    toFun := fun i =>
                      Additive.ofMul
                        { val := (fun x => ζ ^ x) i, property := (_ : ∃ y, (fun x => ζ ^ x) y = (fun x => ζ ^ x) i) },
                    map_zero' :=
                      (_ :
                        (fun i =>
                              Additive.ofMul
                                { val := (fun x => ζ ^ x) i,
                                  property := (_ : ∃ y, (fun x => ζ ^ x) y = (fun x => ζ ^ x) i) })
                            0 =
                          0) }
                  (i + j) =
                ZeroHom.toFun
                    {
                      toFun := fun i =>
                        Additive.ofMul
                          { val := (fun x => ζ ^ x) i, property := (_ : ∃ y, (fun x => ζ ^ x) y = (fun x => ζ ^ x) i) },
                      map_zero' :=
                        (_ :
                          (fun i =>
                                Additive.ofMul
                                  { val := (fun x => ζ ^ x) i,
                                    property := (_ : ∃ y, (fun x => ζ ^ x) y = (fun x => ζ ^ x) i) })
                              0 =
                            0) }
                    i +
                  ZeroHom.toFun
                    {
                      toFun := fun i =>
                        Additive.ofMul
                          { val := (fun x => ζ ^ x) i, property := (_ : ∃ y, (fun x => ζ ^ x) y = (fun x => ζ ^ x) i) },
                      map_zero' :=
                        (_ :
                          (fun i =>
                                Additive.ofMul
                                  { val := (fun x => ζ ^ x) i,
                                    property := (_ : ∃ y, (fun x => ζ ^ x) y = (fun x => ζ ^ x) i) })
                              0 =
                            0) }
                    j) }

Next tactic:
simp only [AddMonoidHom.mem_ker, CharP.int_cast_eq_zero_iff (ZMod k) k, AddMonoidHom.coe_mk,
          Int.coe_castAddHom] at hi ⊢