Section VectorSpace.
(* This is our scalar space *)
Variable p : eparams.
Open Scope vector_scope.
Implicit Type v x y z: p.
Implicit Type k: stype p.
(* Multiple product for characterizing linear combinations *)
Definition  mprod ks vs :=
fold2 (fun k v r => k .* v + r) ks vs 0.
Notation " x *X* y " := (mprod x y) (at level 40, no associativity): vector_scope.
(* What it means for a sub vector space (i.e a list of vectors) to be free *)
Definition free vs :=
forall ks, length ks = length vs -> ks *X* vs = 0 ->
(forall k, In k ks -> k = 0%f).
(* What it is to be a linear combination *)
Inductive cbl (l: list (E p)): (E p) -> Prop :=
cbl0: cbl l 0
| cbl_in: forall v, In v l -> cbl l v
| cbl_add: forall x y, cbl l x -> cbl l y -> cbl l (x + y)
| cbl_scal: forall k x, cbl l x -> cbl l (k .* x).
Definition is_base vs := free vs /\ forall e, cbl vs e.
Structure vparamsProp: Type := {
sProp : fparamsProp p;
eqE_dec: forall x y, if x ?= y then x = y else x <> y;
(* Boolean equality *)
addE_assoc: forall x y z, (x + y) + z = x + (y + z);
(* Associativity for + *)
addE_com: forall x y, x + y = y + x;
(* Commutativity for + *)
addE0l: forall x, 0 + x = x;
(* Left neutral  for + *)
scalE0l: forall x, 0 .* x = 0;
(* scalar 0 *)
scalE1: forall x, 1 .* x = x;
(* scalar 1 *)
scal_addEl: forall k1 k2 x, (k1 + k2) .* x = (k1.* x) + (k2 .* x);
(* scalar distributivity left *)
scal_addEr: forall k x y, k .* (x + y) = k .* x + k .* y;
(* scalar distributivity right *)
scal_multE: forall k1 k2 x, (k1 * k2) .* x = k1.* (k2 .* x)
(* scalar distributivity left *)
}.
Variable Hp: vparamsProp.
Let sfP := sProp Hp.
(* Lemmas for free *)
(* Lemmas for cbl *)
(* How to generate the multiple product for a constant *)
Fixpoint lgenk (n: nat) (k: K p) {struct n} : list (K p) :=
match n  with
O => nil
| 1 => k :: nil
| S n1 => k::lgenk n1 k
end.

(* A linear combination is a multiple product *)
Lemma cbl_mprod vs v : cbl vs v ->
exists ks, length ks = length vs /\ v = ks *X* vs.