/-- 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
        simp only [AddMonoidHom.mem_ker, CharP.int_cast_eq_zero_iff (ZMod k) k, AddMonoidHom.coe_mk,
          Int.coe_castAddHom] at hi ⊢
        obtain ⟨i, rfl⟩ := hi
        simp [zpow_mul, h.pow_eq_one, one_zpow, zpow_ofNat]⟩)
    (by
      constructor
      · rw [injective_iff_map_eq_zero]
        intro i hi
        rw [Subtype.ext_iff] at hi
        have := (h.zpow_eq_one_iff_dvd _).mp hi
        rw [← (CharP.int_cast_eq_zero_iff (ZMod k) k _).mpr this, eq_comm]
        exact ZMod.int_cast_rightInverse i
      · rintro ⟨ξ, i, rfl⟩
        

Proof state:
case right.mk.intro
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 : ℤ
⊢ ∃ a,
    ((AddMonoidHom.liftOfRightInverse (Int.castAddHom (ZMod k)) ZMod.cast
            (_ : Function.RightInverse ZMod.cast Int.cast))
          {
            val :=
              {
                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) },
            property :=
              (_ :
                ∀ 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) }) })
        a =
      { val := (fun x => ζ ^ x) i, property := (_ : ∃ y, (fun x => ζ ^ x) y = (fun x => ζ ^ x) i) }

Next tactic:
refine' ⟨Int.castAddHom (ZMod k) i, _⟩