1-- Natural powers in a monoid2-- Part of Cumulus, the Grace17 mathematics library.3-- Copyright (c) 2026 Grant Passmore.4-- Released under the Apache License 2.0. See LICENSE in the repository root.5-- Authors: Grant Passmore67module Grace.Cumulus.Algebra.Group.Power8import Core9import Nat.Core1011-- Natural powers belong to every monoid. The carrier and its multiplication12-- remain explicit here so all concrete algebraic structures share one13-- recursion and one collection of laws.14def monoidPow (op unit x : Set, n : Nat) →Set15| op, unit, x, zero => unit16| op, unit, x, succ(n) => op(x, monoidPow(op, unit, x, n))1718notationscoped monoidPow(R, x, n) => monoidPow(R.mul, R.one, x, n)1920theorem monoidPow.zero (op unit x : Set)21shows monoidPow(op, unit, x, 0) = unit22proof23simp [monoidPow]2425theorem monoidPow.succ (op unit x : Set, n : Nat)26shows monoidPow(op, unit, x, succ(n)) =27 op(x, monoidPow(op, unit, x, n))28proof29simp [monoidPow]3031theorem monoidPow.closed (A op unit x : Set, n : Nat)32requires monoid : IsMonoid(A, op, unit)33requires xInA : x ∈ A34shows monoidPow(op, unit, x, n) ∈ A35proof36induction n37| zero =>38rw monoidPow.zero39exact IsMonoid.unit_in_carrier with monoid40| succ(k) using ih =>41rw monoidPow.succ42exact IsMonoid.closed with monoid, xInA, ih4344theorem monoidPow.add (A op unit x : Set, m n : Nat)45requires monoid : IsMonoid(A, op, unit)46requires xInA : x ∈ A47shows monoidPow(op, unit, x, m + n) =48 op(monoidPow(op, unit, x, m), monoidPow(op, unit, x, n))49proof50induction m51| zero =>52have powerNInA := monoidPow.closed with monoid, xInA53rw [add.left_unit, monoidPow.zero]54have leftIdentity := IsMonoid.left_identity with monoid, powerNInA55rw leftIdentity56rfl57| succ(k) using ih =>58have powerKInA := monoidPow.closed at A, op, unit, x, k with59 monoid, xInA60have powerNInA := monoidPow.closed at A, op, unit, x, n with61 monoid, xInA62have associative := IsMonoid.associative with monoid63rw [add, monoidPow.succ, monoidPow.succ, ih]64have reassociate := Associative.law with associative, xInA, powerKInA, powerNInA65rw reassociate66rfl6768theorem monoidPow.one (A op unit x : Set)69requires monoid : IsMonoid(A, op, unit)70requires hx : x ∈ A71shows monoidPow(op, unit, x, 1) = x72proof73have identity := IsMonoid.right_identity with monoid, hx74simp [monoidPow, identity]7576theorem monoidPow.succ_right (A op unit x : Set, n : Nat)77requires monoid : IsMonoid(A, op, unit)78requires hx : x ∈ A79shows monoidPow(op, unit, x, n +1) =80 op(monoidPow(op, unit, x, n), x)81proof82havesplit:= monoidPow.add at A, op, unit, x, n, 1with monoid, hx83have one := monoidPow.one with monoid, hx84rw [split, one]85rfl8687theorem monoidPow.succ_left (A op unit x : Set, n : Nat)88requires monoid : IsMonoid(A, op, unit)89requires hx : x ∈ A90shows monoidPow(op, unit, x, n +1) =91 op(x, monoidPow(op, unit, x, n))92proof93rw add.right_one94exact monoidPow.succ9596theorem monoidPow.commute (A op unit x : Set, n : Nat)97requires monoid : IsMonoid(A, op, unit)98requires hx : x ∈ A99shows op(x, monoidPow(op, unit, x, n)) =100 op(monoidPow(op, unit, x, n), x)101proof102haveleft:= monoidPow.succ_left with monoid, hx103haveright:= monoidPow.succ_right with monoid, hx104cc105106theorem monoidPow.add_commute (A op unit x : Set, m n : Nat)107requires monoid : IsMonoid(A, op, unit)108requires hx : x ∈ A109shows op(monoidPow(op, unit, x, m), monoidPow(op, unit, x, n)) =110 op(monoidPow(op, unit, x, n), monoidPow(op, unit, x, m))111proof112have first := monoidPow.add at A, op, unit, x, m, n with monoid, hx113have second := monoidPow.add at A, op, unit, x, n, m with monoid, hx114have swap := add.commutative at n, m115rw [← first, ← second, swap]116rfl117118theorem monoidPow.unit (A op unit : Set, n : Nat)119requires monoid : IsMonoid(A, op, unit)120shows monoidPow(op, unit, unit, n) = unit121proof122induction n123| zero =>124exact monoidPow.zero at op, unit, unit125| succ(k) using ih =>126have unitIn := IsMonoid.unit_in_carrier with monoid127have identity := IsMonoid.left_identity with monoid, unitIn128rw [monoidPow.succ, ih]129exact identity130131theorem monoidPow.mul (A op unit x : Set, m n : Nat)132requires monoid : IsMonoid(A, op, unit)133requires hx : x ∈ A134shows monoidPow(op, unit, x, mul(m, n)) =135 monoidPow(op, unit, monoidPow(op, unit, x, m), n)136proof137induction n138| zero =>139rw [mul.right_zero, monoidPow.zero, monoidPow.zero]140rfl141| succ(k) using ih =>142have powerM := monoidPow.closed at A, op, unit, x, m with monoid, hx143have step := mul.succ_right at k, m144havesplit:= monoidPow.add at A, op, unit, x, m, mul(m, k) with monoid, hx145rw [step, split, ih, monoidPow.succ]146rfl147