Record monoid_theory (X : Type) (m : X -> X -> X) (u : X) := mk_monoid {
  monoid_unit_l : forall x, m u x = x;
  monoid_unit_r : forall x, m x u = x;
  monoid_assoc  : forall x y z, m x (m y z) = m (m x y) z;
}.Record monoid_theory (X : Type) (m : X -> X -> X) (u : X) := mk_monoid {
  monoid_unit_l : forall x, m u x = x;
  monoid_unit_r : forall x, m x u = x;
  monoid_assoc  : forall x y z, m x (m y z) = m (m x y) z;
}.Record monoid_theory (X : Type) (m : X -> X -> X) (u : X) := mk_monoid {
  monoid_unit_l : forall x, m u x = x;
  monoid_unit_r : forall x, m x u = x;
  monoid_assoc  : forall x y z, m x (m y z) = m (m x y) z;
}.Record monoid_theory (X : Type) (m : X -> X -> X) (u : X) := mk_monoid {
  monoid_unit_l : forall x, m u x = x;
  monoid_unit_r : forall x, m x u = x;
  monoid_assoc  : forall x y z, m x (m y z) = m (m x y) z;
}.Record monoid_theory (X : Type) (m : X -> X -> X) (u : X) := mk_monoid {
  monoid_unit_l : forall x, m u x = x;
  monoid_unit_r : forall x, m x u = x;
  monoid_assoc  : forall x y z, m x (m y z) = m (m x y) z;
}.Fact Nat_plus_monoid : monoid_theory plus 0.Fact Nat_mult_monoid : monoid_theory mult 1.Fact Zplus_monoid : monoid_theory Zplus 0%Z.Fact Zmult_monoid : monoid_theory Zmult 1%Z.Notation "∑" := (msum plus 0).Fixpoint msum n f := 
    match n with 
      | 0   => u
      | S n => f 0 ⊕ msum n (fun n => f (S n))
    end.Fact msum_fold_map n f : ∑ n f = fold_right m u (map f (list_an 0 n)).Fact msum_0 f : ∑ 0 f = u.Fact msum_S n f : ∑ (S n) f = f 0 ⊕ ∑ n (fun n => f (S n)).Fact msum_1 f : ∑ 1 f = f 0.Fact msum_plus a b f : ∑ (a+b) f = ∑ a f ⊕ ∑ b (fun i => f (a+i)).Fact msum_plus1 n f : ∑ (S n) f = ∑ n f ⊕ f n.Fact msum_ext n f g : (forall i, i < n -> f i = g i) -> ∑ n f = ∑ n g.Fact msum_unit n : ∑ n (fun _ => u) = u.Fact msum_comm a n f : (forall i, i < n -> f i ⊕ a = a ⊕ f i) -> ∑ n f ⊕ a = a ⊕ ∑ n f.Fact msum_sum n f g : (forall i j, i < j < n -> f j ⊕ g i = g i ⊕ f j) -> ∑ n (fun i => f i ⊕ g i) = ∑ n f ⊕ ∑ n g.Fact msum_of_unit n f : (forall i, i < n -> f i = u) -> ∑ n f = u.Fact msum_only_one n f i : i < n
                          -> (forall j, j < n -> i <> j -> f j = u)
                          -> ∑ n f = f i.Fact msum_msum n k f :
          (forall i1 j1 i2 j2, i1 < n -> j1 < k -> i2 < n -> j2 < k -> f i1 j1 ⊕ f i2 j2 = f i2 j2 ⊕ f i1 j1)
       -> ∑ n (fun i => ∑ k (f i)) = ∑ k (fun j => ∑ n (fun i => f i j)).Fact msum_ends n f : (forall i, 0 < i <= n -> f i = u) -> ∑ (n+2) f = f 0 ⊕ f (S n).Fact msum_first_two n f : 2 <= n -> (forall i, 2 <= i -> f i = u) -> ∑ n f = f 0 ⊕ f 1.Definition mscal n x := msum n (fun _ => x).Fact mscal_0 x : mscal 0 x = u.Fact mscal_S n x : mscal (S n) x = x ⊕ mscal n x.Fact mscal_1 x : mscal 1 x = x.Fact mscal_of_unit n : mscal n u = u.Fact mscal_plus a b x : mscal (a+b) x = mscal a x ⊕ mscal b x.Fact mscal_plus1 n x : mscal (S n) x = mscal n x ⊕ x.Fact mscal_comm n x y : x ⊕ y = y ⊕ x -> mscal n x ⊕ y = y ⊕ mscal n x.Fact mscal_sum n x y : x ⊕ y = y ⊕ x -> mscal n (x ⊕ y) = mscal n x ⊕ mscal n y.Fact mscal_mult a b x : mscal (a*b) x = mscal a (mscal b x).Fact msum_mscal n k f : (forall i j, i < n -> j < n -> f i ⊕ f j = f j ⊕ f i) 
                       -> ∑ n (fun i => mscal k (f i)) = mscal k (∑ n f).Fact msum_morph n f : phi (msum m1 u1 n f) = msum m2 u2 n (fun x => phi (f x)).Fact mscal_morph n x : phi (mscal m1 u1 n x) = mscal m2 u2 n (phi x).Notation z := zero.Notation o := one.Notation scal := (mscal sum zero).Notation expo := (mscal times one).Fact times_zero_l x : z ⊗ x = z.Fact times_zero_r x : x ⊗ z = z.Fact sum_0n_scal n k f : ∑ n (fun i => scal k (f i)) = scal k (∑ n f).Fact scal_times k x y : scal k (x⊗y) = x⊗scal k y.Fact scal_one_comm k x : scal k o ⊗ x = x ⊗ scal k o.Corollary scal_one k x : scal k x = scal k o ⊗ x.Fact sum_0n_distr_l b n f : ∑ n (fun i => b⊗f i) = b⊗∑ n f.Fact sum_0n_distr_r b n f : ∑ n (fun i => f i⊗b) = ∑ n f ⊗ b.

(* Specifications: *)
Theorem binomial_Newton n a b : a ⊗ b = b ⊗ a -> expo n (a ⊕ b) = ∑ (S n) (fun i => scal (binomial n i) (expo (n - i) a ⊗ expo i b)).