(************************************************************************)
(*         *      The Rocq Prover / The Rocq Development Team           *)
(*  v      *         Copyright INRIA, CNRS and contributors             *)
(* <O___,, * (see version control and CREDITS file for authors & dates) *)
(*   \VV/  **************************************************************)
(*    //   *    This file is distributed under the terms of the         *)
(*         *     GNU Lesser General Public License Version 2.1          *)
(*         *     (see LICENSE file for the text of the license)         *)
(************************************************************************)
(** A library for finite sets, implemented as lists *)
(** This is a light implementation of finite sets as lists; for a more extensive library, you might rather consider MSetWeakList.v. In addition, if your domain is totally ordered, you might also consider implementations of finite sets with access in logarithmic time (e.g. MSetRBT.v which is based on red-black trees). *)
Set Implicit Arguments.
Section first_definitions.
Variable A : Type.
Hypothesis Aeq_dec : forall x y:A, {x = y} + {x <> y}.
Definition set := list A.
Definition empty_set : set := nil.
Fixpoint set_add (a:A) (x:set) : set :=
match x with
| nil => a :: nil
| a1 :: x1 =>
match Aeq_dec a a1 with
| left _ => a1 :: x1
| right _ => a1 :: set_add a x1
end
end.
Fixpoint set_mem (a:A) (x:set) : bool :=
match x with
| nil => false
| a1 :: x1 =>
match Aeq_dec a a1 with
| left _ => true
| right _ => set_mem a x1
end
end.
(** If [a] belongs to [x], removes [a] from [x]. If not, does nothing. Invariant: any element should occur at most once in [x], see for instance [set_add]. We hence remove here only the first occurrence of [a] in [x]. *)
Fixpoint set_remove (a:A) (x:set) : set :=
match x with
| nil => empty_set
| a1 :: x1 =>
match Aeq_dec a a1 with
| left _ => x1
| right _ => a1 :: set_remove a x1
end
end.
Fixpoint set_inter (x:set) : set -> set :=
match x with
| nil => fun y => nil
| a1 :: x1 =>
fun y =>
if set_mem a1 y then a1 :: set_inter x1 y else set_inter x1 y
end.
Fixpoint set_union (x y:set) : set :=
match y with
| nil => x
| a1 :: y1 => set_add a1 (set_union x y1)
end.
(** returns the set of all els of [x] that does not belong to [y] *)
Fixpoint set_diff (x y:set) : set :=
match x with
| nil => nil
| a1 :: x1 =>
if set_mem a1 y then set_diff x1 y else set_add a1 (set_diff x1 y)
end.
Definition set_In : A -> set -> Prop := In (A:=A).

(* Specifications: *)
Lemma set_In_dec : forall (a:A) (x:set), {set_In a x} + {~ set_In a x}.
Lemma set_mem_ind2 :
forall (B:Type) (P:B -> Prop) (y z:B) (a:A) (x:set),
(set_In a x -> P y) ->
(~ set_In a x -> P z) -> P (if set_mem a x then y else z).
Lemma set_mem_correct1 :
forall (a:A) (x:set), set_mem a x = true -> set_In a x.
Lemma set_mem_correct2 :
forall (a:A) (x:set), set_In a x -> set_mem a x = true.
Lemma set_mem_complete1 :
forall (a:A) (x:set), set_mem a x = false -> ~ set_In a x.
Lemma set_mem_complete2 :
forall (a:A) (x:set), ~ set_In a x -> set_mem a x = false.
Lemma set_add_intro1 :
forall (a b:A) (x:set), set_In a x -> set_In a (set_add b x).
Lemma set_add_intro2 :
forall (a b:A) (x:set), a = b -> set_In a (set_add b x).