Fixpoint assoc {A B : Type}(eq : A -> A -> bool)(x : A)(l : list (A * B)) : option B :=
  match l with
  | nil => None
  | (x', y) :: l' => if eq x x' then Some y else assoc eq x l'
  end.Definition assoc_default {A B : Type}
  (eqA : A -> A -> bool) (d : B) (l : list (A * B)) (x : A) : B :=
  match assoc eqA x l with
  | None => d
  | Some b => b
  end.

(* Specifications: *)
Lemma in_assoc_neq_None (A B: Type) (beq: A -> A -> bool) (k: A) (l: list (A * B)): (forall a b:A, a = b -> beq a b = true) -> In k (map (@fst _ _) l) -> assoc beq k l <> None.
Lemma assoc_app_eq_None (A B:Type) (eq: A -> A -> bool) (x: A) (l1 l2: list (A * B)) : assoc eq x (l1 ++ l2) = None <-> (assoc eq x l1 = None /\ assoc eq x l2 = None).
Lemma assoc_app_neq_None (A B:Type) (eq: A -> A -> bool) (x: A) (l1 l2: list (A * B)) : assoc eq x (l1 ++ l2) <> None <-> (assoc eq x l1 <> None \/ assoc eq x l2 <> None).
Lemma assoc_app_eq_Some (A B:Type) (eq: A -> A -> bool) (x: A) (v : B) (l1 l2: list (A * B)) : assoc eq x (l1 ++ l2) = Some v <-> (assoc eq x l1 = Some v \/ (assoc eq x l1 = None /\ assoc eq x l2 = Some v)).
Lemma map_in_ext : forall (A B : Type) (f g : A -> B) (l : list A), (forall a : A, In a l -> f a = g a) -> map f l = map g l.
Lemma incl_cons_cons A: forall (a:A) (l1 l2: list A), incl l1 l2 -> incl (a::l1) (a::l2).
Lemma map_incl A B (f : A -> B) l1 l2 : incl l1 l2 -> incl (map f l1) (map f l2).
Lemma map_flat_map (A B C : Type) (f : A -> list B) (g : B -> C) (l : list A) : map g (flat_map f l) = flat_map (fun a => map g (f a)) l.
Lemma incl_filter (A : Type) (f : A -> bool) l: incl (filter f l) l.
Lemma filter_ext_In {A : Type} f g (l : list A): (forall a , In a l -> f a = g a)-> filter f l = filter g l.
Lemma filter_app A (f : A -> bool) l1 l2 : filter f (l1 ++ l2) = filter f l1 ++ filter f l2.
Lemma filter_flat_map A B f (g : A -> list B) l : filter f (flat_map g l) = flat_map (fun x => filter f (g x)) l.
Lemma flat_map_in_ext A B (f g : A -> list B) l : (forall a : A, In a l -> f a = g a) -> flat_map f l = flat_map g l.
Lemma NoDup_filter A f (l : list A) : NoDup l -> NoDup (filter f l).
Lemma map_cons (A B : Type)(f : A -> B) a l : map f (a :: l) = f a :: map f l.
Lemma length_remove A eq_A_dec (a: A) l : length (remove eq_A_dec a l) <= length l.
Lemma length_cons_remove A eq_A_dec (a: A) l : In a l -> length (a :: remove eq_A_dec a l) <= length l.
Lemma neq_in_in_remove A eq_A_dec (a a': A) l: a' <> a -> In a l -> In a (remove eq_A_dec a' l).
Lemma incl_remove_app A l l1 l2 (x : A) : ~ In x l -> incl l (l1 ++ x :: l2) -> incl l (l1 ++ l2).
Lemma flat_map_comp (A B C : Type) (f : A -> B) (g : B -> list C) (h : A -> list C) (l : list A) : (forall x, In x l -> h x = g (f x)) -> flat_map h l = flat_map g (map f l).
Lemma flat_map_app (A B : Type) (f : A -> list B) l1 l2 : flat_map f (l1 ++ l2) = flat_map f l1 ++ flat_map f l2.
Lemma comp_flat_map (A B C : Type) (f : A -> list B) (g : B -> list C) h l : (forall a, In a l -> h a = flat_map g (f a)) -> flat_map h l = flat_map g (flat_map f l).