Notation member := (in_dec eq_nat_dec).

(* Specifications: *)
Lemma seq_range : forall n a x, In x (seq a n) -> a <= x < a + n.
Lemma plus_gt_0 : forall a b, a + b > 0 -> a > 0 \/ b > 0.
Lemma list_neq_cons : forall (l : list A) x, x :: l <> l.
Lemma remove_preserve : forall (x y : A) xs, x <> y -> In y xs -> In y (remove A_eq_dec x xs).
Lemma in_remove : forall (x y : A) xs, In y (remove A_eq_dec x xs) -> In y xs.
Lemma remove_partition : forall xs (p : A) ys, remove A_eq_dec p (xs ++ p :: ys) = remove A_eq_dec p (xs ++ ys).
Lemma remove_not_in : forall (x : A) xs, ~ In x xs -> remove A_eq_dec x xs = xs.
Lemma remove_app_comm : forall a xs ys, remove A_eq_dec a (xs ++ ys) = remove A_eq_dec a xs ++ remove A_eq_dec a ys.
Lemma filter_app : forall (f : A -> bool) xs ys, filter f (xs ++ ys) = filter f xs ++ filter f ys.
Lemma filter_fun_ext_eq : forall f g xs, (forall a : A, In a xs -> f a = g a) -> filter f xs = filter g xs.
Lemma not_in_filter_false : forall (f : A -> bool) l x, In x l -> ~ In x (filter f l) -> f x = false.
Lemma filter_length_bound : forall f (l : list A), length (filter f l) <= length l.
Lemma NoDup_map_injective : forall (f : A -> B) xs, (forall x y, In x xs -> In y xs -> f x = f y -> x = y) -> NoDup xs -> NoDup (map f xs).
Lemma NoDup_disjoint_append : forall (l : list A) l', NoDup l -> NoDup l' -> (forall a, In a l -> ~ In a l') -> NoDup (l ++ l').
Lemma NoDup_map_partition : forall (f : A -> B) xs l y zs xs' y' zs', NoDup (map f l) -> l = xs ++ y :: zs -> l = xs' ++ y' :: zs' -> f y = f y' -> xs = xs'.
Lemma filter_NoDup : forall p (l : list A), NoDup l -> NoDup (filter p l).
Lemma NoDup_map_filter : forall (f : A -> B) g l, NoDup (map f l) -> NoDup (map f (filter g l)).
Lemma filter_true_id : forall (f : A -> bool) xs, (forall x, In x xs -> f x = true) -> filter f xs = xs.
Lemma map_of_map : forall (f : A -> B) (g : B -> C) xs, map g (map f xs) = map (fun x => g (f x)) xs.
Lemma filter_except_one : forall (f g : A -> bool) x xs, (forall y, In y xs -> x <> y -> f y = g y) -> g x = false -> filter f (remove A_eq_dec x xs) = filter g xs.
Lemma flat_map_nil : forall (f : A -> list B) l, flat_map f l = [] -> l = [] \/ (forall x, In x l -> f x = []).
Theorem NoDup_Permutation_NoDup : forall (l l' : list A), NoDup l -> Permutation l l' -> NoDup l'.
Theorem NoDup_append : forall l (a : A), NoDup (l ++ [a]) <-> NoDup (a :: l).
Lemma NoDup_map_elim : forall (f : A -> B) xs x y, f x = f y -> NoDup (map f xs) -> In x xs -> In y xs -> x = y.
Lemma remove_length_not_in : forall (x : A) xs, ~ In x xs -> length (remove A_eq_dec x xs) = length xs.
Lemma remove_length_in : forall (x : A) xs, In x xs -> NoDup xs -> S (length (remove A_eq_dec x xs)) = length xs.
Lemma subset_size_eq : forall xs, NoDup xs -> forall ys, NoDup ys -> (forall x : A, In x xs -> In x ys) -> length xs = length ys -> (forall x, In x ys -> In x xs).
Lemma remove_NoDup : forall (x : A) xs, NoDup xs -> NoDup (remove A_eq_dec x xs).
Lemma remove_length_ge : forall (x : A) xs, NoDup xs -> length (remove A_eq_dec x xs) >= length xs - 1.
Lemma remove_length_le : forall (x : A) xs eq_dec, length xs >= length (remove eq_dec x xs).
Lemma remove_length_lt : forall (x : A) xs eq_dec, In x xs -> length xs > length (remove eq_dec x xs).
Lemma subset_length : forall xs ys, NoDup xs -> (forall x : A, In x xs -> In x ys) -> length ys >= length xs.
Lemma app_cons_singleton_inv : forall xs (y : A) zs w, xs ++ y :: zs = [w] -> xs = [] /\ y = w /\ zs = [].
Lemma app_cons_in : forall (l : list A) xs a ys, l = xs ++ a :: ys -> In a l.
Lemma app_cons_in_rest: forall (l : list A) xs a b ys, l = xs ++ a :: ys -> In b (xs ++ ys) -> In b l.
Lemma in_rest_app_cons: forall (l xs ys : list A) a b, l = xs ++ a :: ys -> In b l -> a <> b -> In b (xs ++ ys).
Lemma remove_filter_commute : forall (l : list A) A_eq_dec f x, remove A_eq_dec x (filter f l) = filter f (remove A_eq_dec x l).
Lemma In_filter_In : forall (f : A -> bool) x l l', filter f l = l' -> In x l' -> In x l.
Lemma filter_partition : forall (l1 : list A) f l2 x l1' l2', NoDup (l1 ++ x :: l2) -> filter f (l1 ++ x :: l2) = (l1' ++ x :: l2') -> filter f l1 = l1' /\ filter f l2 = l2'.
Lemma map_inverses : forall (la : list A) (lb : list B) (f : A -> B) g, (forall a, g (f a) = a) -> (forall b, f (g b) = b) -> lb = map f la -> la = map g lb.
Lemma In_notIn_implies_neq : forall x y l, In(A:=A) x l -> ~ In(A:=A) y l -> x <> y.
Lemma In_cons_neq : forall a x xs, In(A:=A) a (x :: xs) -> a <> x -> In a xs.
Lemma NoDup_app3_not_in_1 : forall (xs ys zs : list A) b, NoDup (xs ++ ys ++ b :: zs) -> In b xs -> False.
Lemma NoDup_app3_not_in_2 : forall (xs ys zs : list A) b, NoDup (xs ++ ys ++ b :: zs) -> In b ys -> False.
Lemma NoDup_app3_not_in_3 : forall (xs ys zs : list A) b, NoDup (xs ++ ys ++ b :: zs) -> In b zs -> False.
Lemma In_cons_2_3 : forall xs ys zs x y a, In (A:=A) a (xs ++ ys ++ zs) -> In a (xs ++ x :: ys ++ y :: zs).
Lemma In_cons_2_3_neq : forall a x y xs ys zs, In (A:=A) a (xs ++ x :: ys ++ y :: zs) -> a <> x -> a <> y -> In a (xs ++ ys ++ zs).
Lemma in_middle_reduce : forall a xs y zs, In (A:=A) a (xs ++ y :: zs) -> a <> y -> In a (xs ++ zs).
Lemma in_middle_insert : forall a xs y zs, In (A:=A) a (xs ++ zs) -> In a (xs ++ y :: zs).
Lemma NoDup_rev : forall l, NoDup (A:=A) l -> NoDup (rev l).
Lemma NoDup_map_map : forall (f : A -> B) (g : A -> C) xs, (forall x y, In x xs -> In y xs -> f x = f y -> g x = g y) -> NoDup (map g xs) -> NoDup (map f xs).
Lemma pigeon : forall (l : list A) sub1 sub2, (forall a, In a sub1 -> In a l) -> (forall a, In a sub2 -> In a l) -> NoDup l -> NoDup sub1 -> NoDup sub2 -> length sub1 + length sub2 > length l -> exists a, In a sub1 /\ In a sub2.
Lemma snoc_assoc : forall (l : list A) x y, l ++ [x; y] = (l ++ [x]) ++ [y].
Lemma cons_cons_app : forall (x y : A), [x; y] = [x] ++ [y].
Lemma map_eq_inv : forall (f : A -> B) l xs ys, map f l = xs ++ ys -> exists l1 l2, l = l1 ++ l2 /\ map f l1 = xs /\ map f l2 = ys.
Lemma map_partition : forall p l (x : B) p' (f : A -> B), map f l = (p ++ x :: p') -> exists ap a ap', l = ap ++ a :: ap' /\ map f ap = p /\ f a = x /\ map f ap' = p'.
Lemma map_eq_inv_eq : forall (f : A -> B), (forall a a', f a = f a' -> a = a') -> forall l l', map f l = map f l' -> l = l'.
Lemma map_fst_snd_id : forall l, map (fun t : A * B => (fst t, snd t)) l = l.
Lemma in_firstn : forall n (x : A) xs, In x (firstn n xs) -> In x xs.
Lemma firstn_NoDup : forall n (xs : list A), NoDup xs -> NoDup (firstn n xs).
Lemma NoDup_mid_not_in : forall (a : A) (l l' : list A), NoDup (l ++ a :: l') -> ~ In a (l ++ l').
Lemma Permutation_split : forall (ns ns' : list A) (n : A), Permutation (n :: ns) ns' -> exists ns0, exists ns1, ns' = ns0 ++ n :: ns1.
Lemma NoDup_app_left : forall (l l' : list A), NoDup (l ++ l') -> NoDup l.
Lemma NoDup_app_right : forall (l l' : list A), NoDup (l ++ l') -> NoDup l'.
Lemma NoDup_in_not_in_right : forall (l l' : list A) (a : A), NoDup (l ++ l') -> In a l -> ~ In a l'.
Lemma NoDup_in_not_in_left : forall (l l' : list A) (a : A), NoDup (l ++ l') -> In a l' -> ~ In a l.
Lemma count_occ_app : forall l l' (a : A), count_occ A_eq_dec (l ++ l') a = count_occ A_eq_dec l a + count_occ A_eq_dec l' a.
Lemma Permutation_map_fst : forall l l' : list (A * B), Permutation l l' -> Permutation (map fst l) (map fst l').
Lemma snd_eq_not_in_map : forall (l : list (A * B)) n m, (forall nm, In nm l -> snd nm = m) -> ~ In (n, m) l -> ~ In n (map fst l).
Lemma NoDup_map_snd_fst : forall nms : list (A * B), NoDup nms -> (forall nm nm', In nm nms -> In nm' nms -> snd nm = snd nm') -> NoDup (map fst nms).
Lemma in_fold_left_by_cons_in : forall (l : list B) (g : B -> A) x acc, In x (fold_left (fun a b => g b :: a) l acc) -> In x acc \/ exists y, In y l /\ x = g y.
Lemma fold_left_for_each_not_in : forall (f : A -> B -> A) (g : A -> B -> C), (forall a b b', b <> b' -> g (f a b') b = g a b) -> forall l a b, ~ In b l -> g (fold_left f l a) b = g a b.
Lemma fold_left_for_each_in : forall (f : A -> B -> A) (g : A -> B -> C) (B_eq_dec : forall x y : B, {x = y} + {x <> y}), (forall a b b', b <> b' -> g (f a b') b = g a b) -> forall l a b, In b l -> exists a', g (fold_left f l a) b = g (f a' b) b.
Lemma hd_error_tl_exists : forall (l : list A) x, hd_error l = Some x -> exists tl, l = x :: tl.
Lemma hd_error_None : forall (l : list A), hd_error l = None -> l = [].