diff --git a/src/core/CCList.ml b/src/core/CCList.ml index 8087df0d..d7426cd1 100644 --- a/src/core/CCList.ml +++ b/src/core/CCList.ml @@ -654,71 +654,69 @@ let filter_map f l = [ 1; 2; 3; 4; 5; 6 ]) *) -module Set = struct - let mem ?(eq=(=)) x l = - let rec search eq x l = match l with - | [] -> false - | y::l' -> eq x y || search eq x l' - in search eq x l +let mem ?(eq=(=)) x l = + let rec search eq x l = match l with + | [] -> false + | y::l' -> eq x y || search eq x l' + in search eq x l - let add ?(eq=(=)) x l = - if mem ~eq x l then l else x::l +let add_nodup ?(eq=(=)) x l = + if mem ~eq x l then l else x::l - let remove ?(eq=(=)) x l = - let rec remove_one ~eq x acc l = match l with - | [] -> assert false - | y :: tl when eq x y -> List.rev_append acc tl - | y :: tl -> remove_one ~eq x (y::acc) tl - in - if mem ~eq x l then remove_one ~eq x [] l else l +let remove_one ?(eq=(=)) x l = + let rec remove_one ~eq x acc l = match l with + | [] -> assert false + | y :: tl when eq x y -> List.rev_append acc tl + | y :: tl -> remove_one ~eq x (y::acc) tl + in + if mem ~eq x l then remove_one ~eq x [] l else l - (*$Q - Q.(pair int (list int)) (fun (x,l) -> \ - Set.remove x (Set.add x l) = l) - Q.(pair int (list int)) (fun (x,l) -> \ - Set.mem x l || List.length (Set.add x l) = List.length l + 1) - Q.(pair int (list int)) (fun (x,l) -> \ - not (Set.mem x l) || List.length (Set.remove x l) = List.length l - 1) - *) +(*$Q + Q.(pair int (list int)) (fun (x,l) -> \ + remove_one x (add_nodup x l) = l) + Q.(pair int (list int)) (fun (x,l) -> \ + mem x l || List.length (add_nodup x l) = List.length l + 1) + Q.(pair int (list int)) (fun (x,l) -> \ + not (mem x l) || List.length (remove_one x l) = List.length l - 1) +*) - let subset ?(eq=(=)) l1 l2 = - List.for_all - (fun t -> mem ~eq t l2) - l1 +let subset ?(eq=(=)) l1 l2 = + List.for_all + (fun t -> mem ~eq t l2) + l1 - let uniq ?(eq=(=)) l = - let rec uniq eq acc l = match l with - | [] -> List.rev acc - | x::xs when List.exists (eq x) xs -> uniq eq acc xs - | x::xs -> uniq eq (x::acc) xs - in uniq eq [] l +let uniq ?(eq=(=)) l = + let rec uniq eq acc l = match l with + | [] -> List.rev acc + | x::xs when List.exists (eq x) xs -> uniq eq acc xs + | x::xs -> uniq eq (x::acc) xs + in uniq eq [] l - (*$T - Set.uniq [1;1;2;2;3;4;4;2;4;1;5] |> List.sort Pervasives.compare = [1;2;3;4;5] - *) +(*$T + uniq [1;1;2;2;3;4;4;2;4;1;5] |> List.sort Pervasives.compare = [1;2;3;4;5] +*) - let union ?(eq=(=)) l1 l2 = - let rec union eq acc l1 l2 = match l1 with - | [] -> List.rev_append acc l2 - | x::xs when mem ~eq x l2 -> union eq acc xs l2 - | x::xs -> union eq (x::acc) xs l2 - in union eq [] l1 l2 +let union ?(eq=(=)) l1 l2 = + let rec union eq acc l1 l2 = match l1 with + | [] -> List.rev_append acc l2 + | x::xs when mem ~eq x l2 -> union eq acc xs l2 + | x::xs -> union eq (x::acc) xs l2 + in union eq [] l1 l2 - (*$T - Set.union [1;2;4] [2;3;4;5] = [1;2;3;4;5] - *) +(*$T + union [1;2;4] [2;3;4;5] = [1;2;3;4;5] +*) - let inter ?(eq=(=)) l1 l2 = - let rec inter eq acc l1 l2 = match l1 with - | [] -> List.rev acc - | x::xs when mem ~eq x l2 -> inter eq (x::acc) xs l2 - | _::xs -> inter eq acc xs l2 - in inter eq [] l1 l2 +let inter ?(eq=(=)) l1 l2 = + let rec inter eq acc l1 l2 = match l1 with + | [] -> List.rev acc + | x::xs when mem ~eq x l2 -> inter eq (x::acc) xs l2 + | _::xs -> inter eq acc xs l2 + in inter eq [] l1 l2 - (*$T - Set.inter [1;2;4] [2;3;4;5] = [2;4] - *) -end +(*$T + inter [1;2;4] [2;3;4;5] = [2;4] +*) module Idx = struct let mapi f l = diff --git a/src/core/CCList.mli b/src/core/CCList.mli index 41cd0888..5dcbc579 100644 --- a/src/core/CCList.mli +++ b/src/core/CCList.mli @@ -251,35 +251,36 @@ module Idx : sig too high. *) end -(** {2 Set Operators} *) +(** {2 Set Operators} -module Set : sig - val add : ?eq:('a -> 'a -> bool) -> 'a -> 'a t -> 'a t - (** [add x set] adds [x] to [set] if it was not already present. Linear time. - @since 0.11 *) + Those operations maintain the invariant that the list does not + contain duplicates (if it already satisfies it) *) - val remove : ?eq:('a -> 'a -> bool) -> 'a -> 'a t -> 'a t - (** [remove x set] removes one occurrence of [x] from [set]. Linear time. - @since 0.11 *) +val add_nodup : ?eq:('a -> 'a -> bool) -> 'a -> 'a t -> 'a t +(** [add_nodup x set] adds [x] to [set] if it was not already present. Linear time. + @since 0.11 *) - val mem : ?eq:('a -> 'a -> bool) -> 'a -> 'a t -> bool - (** Membership to the list. Linear time *) +val remove_one : ?eq:('a -> 'a -> bool) -> 'a -> 'a t -> 'a t +(** [remove_one x set] removes one occurrence of [x] from [set]. Linear time. + @since 0.11 *) - val subset : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t -> bool - (** Test for inclusion *) +val mem : ?eq:('a -> 'a -> bool) -> 'a -> 'a t -> bool +(** Membership to the list. Linear time *) - val uniq : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t - (** List uniq. Remove duplicates w.r.t the equality predicate. - Complexity is quadratic in the length of the list, but the order - of elements is preserved. If you wish for a faster de-duplication - but do not care about the order, use {!sort_uniq}*) +val subset : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t -> bool +(** Test for inclusion *) - val union : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t -> 'a t - (** List union. Complexity is product of length of inputs. *) +val uniq : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t +(** Remove duplicates w.r.t the equality predicate. + Complexity is quadratic in the length of the list, but the order + of elements is preserved. If you wish for a faster de-duplication + but do not care about the order, use {!sort_uniq}*) - val inter : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t -> 'a t - (** List intersection. Complexity is product of length of inputs. *) -end +val union : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t -> 'a t +(** List union. Complexity is product of length of inputs. *) + +val inter : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t -> 'a t +(** List intersection. Complexity is product of length of inputs. *) (** {2 Other Constructors} *)