Fixpoint suml (l : list nat) : nat :=
  match l with
  | nil => 0
  | n :: l' => n + suml l'
  end.

(* Specifications: *)
Lemma suml_cons n l : suml (n :: l) = n + suml l.
Lemma suml_map_const A n (l : list A) : suml (map (fun _ => n) l) = n * length l.
Lemma mult_suml_r m l : m * suml l = suml (map (fun n => m * n) l).
Lemma suml_app l1 l2 : suml (l1 ++ l2) = suml l1 + suml l2.
Lemma suml_flat_map (A : Type)(f : A -> list nat)(l :list A) : suml (flat_map f l) = suml (map suml (map f l)).
Lemma suml_flat_map_map (A B : Type) (f : A -> list B) (g : B -> nat) l : suml (flat_map (fun x => map g (f x)) l) = suml (map (fun x => suml (map g (f x))) l).
Lemma suml_map_plus (A : Type)(f g : A -> nat)(l : list A) : suml (map (fun x => f x + g x) l) = suml (map f l) + suml (map g l).
Lemma suml_map_le : forall (A : Type)(f g : A -> nat)(l : list A), (forall x, In x l -> f x <= g x) -> suml (map f l) <= suml (map g l).
Lemma suml_map_eq : forall (A : Type)(f g : A -> nat)(l : list A), (forall x, In x l -> f x = g x) -> suml (map f l) = suml (map g l).
Lemma suml_map_le_plus_length : forall (A : Type)(f g : A -> nat)(l : list A), (forall x, In x l -> f x <= g x + 1) -> suml (map f l) <= suml (map g l) + length l.
Lemma suml_le_len_times_bound l b : (forall x, In x l -> x <= b) -> suml l <= length l * b.
Lemma in_le_suml : forall (n : nat)(l : list nat), In n l -> n <= suml l.
Lemma maxl_le_suml l: maxl l <= suml l.
Lemma forall2_le_suml : forall (l1 l2 : list nat), Forall2 le l1 l2 -> suml l1 <= suml l2.
Lemma maxl_le_suml_map (A B : Type) (f : A -> list B) (g : B -> nat) (h : A -> nat) (l : list A) : (forall a, In a l -> maxl (map g (f a)) <= h a) -> maxl (map g (flat_map f l)) <= suml (map h l).
Lemma suml_map_mult_le_suml_mult_maxl (A : Type) f g (l : list A) : suml (map (fun x => f x * g x) l) <= suml (map f l) * maxl (map g l).
Lemma suml_map_mult_le_suml_mult_suml (A : Type) f g (l : list A) : suml (map (fun x => f x * g x) l) <= suml (map f l) * suml (map g l).
Lemma length_flat_map (A B : Type) ( f : A -> list B) (l : list A) : length (flat_map f l) = suml (map (@length _) (map f l)).
Lemma Permutation_filter {A : Type} f (l : list A) : Permutation l (filter f l ++ filter (fun x => negb (f x)) l).
Lemma filter_compose {A : Type} f g (l : list A) : (forall x, In x l -> ( f x = true -> g x = true)) -> filter f (filter g l) = filter f l.
Lemma in_seq : forall len start n : nat, In n (seq start len) <-> start <= n < start + len.
Lemma Permutation_partition_list_nat b n l : (forall x, In x l -> b <= x < b + n) -> Permutation l (flat_map (fun n => filter (beq_nat n) l) (seq b n)).
Lemma length_suml_filter b n l: (forall x, In x l -> b <= x < b + n) -> suml (map (fun r => length(filter (beq_nat r) l )) (seq b n)) = length l.