Structure eparams: Type := {
E:> Set;                      (* the vector type *)
stype:> fparams;              (* the scalar field *)
E0: E;                        (* 0 *)
eqE: E -> E -> bool;          (* = as a boolean function *)
addE : E -> E -> E;          (* + *)
scalE : (K stype) -> E -> E   (* scalar *)
}.
Delimit Scope vector_scope with v.
Notation "x ?= y" := (eqE _ x y) (at level 70): vector_scope.
Notation "0" := (E0 _): vector_scope.
Notation "x + y" := (addE _ x y): vector_scope.
Notation "x .* y" := (scalE _ x%f y) (at level 31, no associativity): vector_scope.
Arguments scalE _ _%field_scope _%vector_scope.
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).

(* Specifications: *)
Lemma cbl_trans l1 l2 x:
(forall i, In i l2 -> cbl l1 i) -> cbl l2 x -> cbl l1 x.