From f66d636b0ec148bf872e5cff2596f9951ace0365 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Wed, 22 Feb 2017 10:19:58 +0100 Subject: [PATCH 01/21] remove useless files --- descr | 6 ------ sequence.mldylib | 4 ---- sequence.mllib | 4 ---- 3 files changed, 14 deletions(-) delete mode 100644 descr delete mode 100644 sequence.mldylib delete mode 100644 sequence.mllib diff --git a/descr b/descr deleted file mode 100644 index 25f3a49..0000000 --- a/descr +++ /dev/null @@ -1,6 +0,0 @@ -Simple and lightweight sequence abstract data type. - -Simple sequence abstract data type, intended to transfer a finite number of -elements from one data structure to another. Some transformations on sequences, -like `filter`, `map`, `take`, `drop` and `append` can be performed before the -sequence is iterated/folded on. diff --git a/sequence.mldylib b/sequence.mldylib deleted file mode 100644 index 2f635d2..0000000 --- a/sequence.mldylib +++ /dev/null @@ -1,4 +0,0 @@ -# OASIS_START -# DO NOT EDIT (digest: 3ff39d3acb327553070a64ef0cb321d5) -Sequence -# OASIS_STOP diff --git a/sequence.mllib b/sequence.mllib deleted file mode 100644 index 2f635d2..0000000 --- a/sequence.mllib +++ /dev/null @@ -1,4 +0,0 @@ -# OASIS_START -# DO NOT EDIT (digest: 3ff39d3acb327553070a64ef0cb321d5) -Sequence -# OASIS_STOP From e91a77f3deca65c00226f32651391568dd05f661 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Fri, 24 Feb 2017 10:31:37 +0100 Subject: [PATCH 02/21] tweak in makefile --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 6606084..03e60f1 100644 --- a/Makefile +++ b/Makefile @@ -83,6 +83,7 @@ update_next_tag: watch: while find src/ -print0 | xargs -0 inotifywait -e delete_self -e modify ; do \ echo "============ at `date` ==========" ; \ + sleep 0.2; \ make all; \ done From 5a14ec723350c4fb96e0423a15c6cda5e91f081a Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Mon, 13 Mar 2017 20:19:38 +0100 Subject: [PATCH 03/21] add `seq_list` and `seq_list_map` --- src/Sequence.ml | 13 +++++++++++++ src/Sequence.mli | 10 ++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/Sequence.ml b/src/Sequence.ml index 3bdb9fc..9afa5de 100644 --- a/src/Sequence.ml +++ b/src/Sequence.ml @@ -181,6 +181,19 @@ let flat_map f seq k = seq (fun x -> f x k) let flat_map_l f seq k = seq (fun x -> List.iter k (f x)) +let rec seq_list_map f l k = match l with + | [] -> k [] + | x :: tail -> + f x (fun x' -> seq_list_map f tail (fun tail' -> k (x'::tail'))) + +let seq_list l = seq_list_map (fun x->x) l + +(*$= & ~printer:Q.Print.(list @@ list int) + [[1;2];[1;3]] (seq_list [singleton 1; doubleton 2 3] |> to_list) + [] (seq_list [singleton 1; empty; doubleton 2 3] |> to_list) + [[1;2;4];[1;3;4]] (seq_list [singleton 1; doubleton 2 3; singleton 4] |> to_list) +*) + let filter_map f seq k = seq (fun x -> match f x with | None -> () diff --git a/src/Sequence.mli b/src/Sequence.mli index f7f367a..032e7a2 100644 --- a/src/Sequence.mli +++ b/src/Sequence.mli @@ -200,6 +200,16 @@ val flat_map_l : ('a -> 'b list) -> 'a t -> 'b t (** Convenience function combining {!flat_map} and {!of_list} @since 0.9 *) +val seq_list : 'a t list -> 'a list t +(** [seq_list l] returns all the ways to pick one element in each sub-sequence + in [l]. Assumes the sub-sequences can be iterated on several times. + @since NEXT_RELEASE *) + +val seq_list_map : ('a -> 'b t) -> 'a list -> 'b list t +(** [seq_list_map f l] maps [f] over every element of [l], + then calls {!seq_list} + @since NEXT_RELEASE *) + val filter_map : ('a -> 'b option) -> 'a t -> 'b t (** Map and only keep non-[None] elements Formerly [fmap] From f79309a6f259aa1a1df709721988d794bae235d1 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Tue, 5 Sep 2017 08:06:13 +0200 Subject: [PATCH 04/21] add `{sum,sumf}` for summation over sequences --- src/Sequence.ml | 27 +++++++++++++++++++++++++++ src/Sequence.mli | 8 ++++++++ 2 files changed, 35 insertions(+) diff --git a/src/Sequence.ml b/src/Sequence.ml index 9afa5de..6ecd54e 100644 --- a/src/Sequence.ml +++ b/src/Sequence.ml @@ -727,6 +727,33 @@ let min_exn ?lt seq = match min ?lt seq with 0 (0 -- 100 |> min_exn ?lt:None) *) +let sum seq = + let n = ref 0 in + seq (fun x -> n := !n + x); + !n + +(*$T + (of_list [1;2;3] |> sum) = 6 +*) + +(* https://en.wikipedia.org/wiki/Kahan_summation_algorithm *) +let sumf seq : float = + let sum = ref 0. in + let c = ref 0. in (* error compensation *) + seq + (fun x -> + let y = x -. !c in + let t = !sum +. y in + c := (t -. !sum) -. y; + sum := t); + !sum + +(*$R + let cmp x y = (abs_float (x-.y)) < 0.05 in + let seq = of_list [10000.0; 3.14159; 2.71828] in + assert_equal ~printer:string_of_float ~cmp 10005.9 (sumf seq) +*) + exception ExitHead let head seq = diff --git a/src/Sequence.mli b/src/Sequence.mli index 032e7a2..d3effc8 100644 --- a/src/Sequence.mli +++ b/src/Sequence.mli @@ -412,6 +412,14 @@ val min_exn : ?lt:('a -> 'a -> bool) -> 'a t -> 'a @raise Not_found if the sequence is empty @since 0.10 *) +val sum : int t -> int +(** Sum of elements + @since NEXT_RELEASE *) + +val sumf : float t -> float +(** Sum of elements, using Kahan summation + @since NEXT_RELEASE *) + val head : 'a t -> 'a option (** First element, if any, otherwise [None] @since 0.5.1 *) From 952c7a4529d128c4e704dcd32d9f6a8f2adbe6cb Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Tue, 5 Sep 2017 08:11:07 +0200 Subject: [PATCH 05/21] update test --- src/Sequence.ml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Sequence.ml b/src/Sequence.ml index 6ecd54e..5ecfd23 100644 --- a/src/Sequence.ml +++ b/src/Sequence.ml @@ -749,9 +749,8 @@ let sumf seq : float = !sum (*$R - let cmp x y = (abs_float (x-.y)) < 0.05 in let seq = of_list [10000.0; 3.14159; 2.71828] in - assert_equal ~printer:string_of_float ~cmp 10005.9 (sumf seq) + assert_equal ~printer:string_of_float 10005.85987 (sumf seq) *) exception ExitHead From 11529ea6ff859f5288ad2a83d487cb5283cbe28b Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Thu, 14 Sep 2017 09:09:05 +0200 Subject: [PATCH 06/21] update compile flags --- .merlin | 2 +- _tags | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.merlin b/.merlin index a047e25..68e740a 100644 --- a/.merlin +++ b/.merlin @@ -7,4 +7,4 @@ B _build/bench/ PKG oUnit qcheck PKG benchmark FLG -safe-string -FLG -w +a -w -4 -w -44 +FLG -w+a-4-44-48-60@8 diff --git a/_tags b/_tags index 493c238..fd66075 100644 --- a/_tags +++ b/_tags @@ -27,8 +27,8 @@ : pkg_benchmark : use_sequence # OASIS_STOP -true: bin_annot -<**/*.ml>: warn_A, warn(-4) +true: bin_annot, color(always) +<**/*.ml>: warn(+a-4-44-48@8) true: mark_tag_used <**/*.cmx>: optimize(3) : nolabels From 92205b6c36d55ba7f84471eddf7155b831614551 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Thu, 14 Sep 2017 09:12:34 +0200 Subject: [PATCH 07/21] add `Sequence.pair_with_idx` --- src/Sequence.ml | 4 ++++ src/Sequence.mli | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/Sequence.ml b/src/Sequence.ml index 5ecfd23..a9c0f96 100644 --- a/src/Sequence.ml +++ b/src/Sequence.ml @@ -971,6 +971,10 @@ let of_list l k = List.iter k l let on_list f l = to_list (f (of_list l)) +let pair_with_idx seq k = + let r = ref 0 in + seq (fun x -> let n = !r in incr r; k (n,x)) + let to_opt = head let of_opt o k = match o with diff --git a/src/Sequence.mli b/src/Sequence.mli index d3effc8..2d686da 100644 --- a/src/Sequence.mli +++ b/src/Sequence.mli @@ -495,6 +495,10 @@ val on_list : ('a t -> 'b t) -> 'a list -> 'b list @since 0.5.2 *) +val pair_with_idx : 'a t -> (int * 'a) t +(** Similar to {!zip_i} but returns a normal sequence of tuples + @since NEXT_RELEASE *) + val to_opt : 'a t -> 'a option (** Alias to {!head} @since 0.5.1 *) From dee62387aae49d02317c6243fcab9e2f4d4e131a Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Thu, 14 Sep 2017 09:15:43 +0200 Subject: [PATCH 08/21] update `SequenceLabels` with missing functions --- src/sequenceLabels.mli | 151 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 144 insertions(+), 7 deletions(-) diff --git a/src/sequenceLabels.mli b/src/sequenceLabels.mli index b28e492..940c28d 100644 --- a/src/sequenceLabels.mli +++ b/src/sequenceLabels.mli @@ -17,6 +17,9 @@ type +'a sequence = 'a t type (+'a, +'b) t2 = ('a -> 'b -> unit) -> unit (** Sequence of pairs of values of type ['a] and ['b]. *) +type 'a equal = 'a -> 'a -> bool +type 'a hash = 'a -> int + (** {2 Build a sequence} *) val from_iter : (('a -> unit) -> unit) -> 'a t @@ -120,10 +123,18 @@ val mem : ?eq:('a -> 'a -> bool) -> x:'a -> 'a t -> bool val find : f:('a -> 'b option) -> 'a t -> 'b option (** Find the first element on which the function doesn't return [None] *) +val find_map : f:('a -> 'b option) -> 'a t -> 'b option +(** Alias to {!find} + @since NEXT_RELEASE *) + val findi : f:(int -> 'a -> 'b option) -> 'a t -> 'b option (** Indexed version of {!find} @since 0.9 *) +val find_mapi : f:(int -> 'a -> 'b option) -> 'a t -> 'b option +(** Alias to {!findi} + @since NEXT_RELEASE *) + val find_pred : f:('a -> bool) -> 'a t -> 'a option (** [find_pred p l] finds the first element of [l] that satisfies [p], or returns [None] if no element satisfies [p] @@ -165,6 +176,16 @@ val flat_map_l : f:('a -> 'b list) -> 'a t -> 'b t val filter_map : f:('a -> 'b option) -> 'a t -> 'b t (** Alias to {!fmap} with a more explicit name *) +val seq_list : 'a t list -> 'a list t +(** [seq_list l] returns all the ways to pick one element in each sub-sequence + in [l]. Assumes the sub-sequences can be iterated on several times. + @since NEXT_RELEASE *) + +val seq_list_map : f:('a -> 'b t) -> 'a list -> 'b list t +(** [seq_list_map f l] maps [f] over every element of [l], + then calls {!seq_list} + @since NEXT_RELEASE *) + val intersperse : x:'a -> 'a t -> 'a t (** Insert the single element between every element of the sequence *) @@ -247,6 +268,93 @@ val join : join_row:('a -> 'b -> 'c option) -> 'a t -> 'b t -> 'c t the two elements do not combine. Assume that [b] allows for multiple iterations. *) +val join_by : ?eq:'key equal -> ?hash:'key hash -> + ('a -> 'key) -> ('b -> 'key) -> + merge:('key -> 'a -> 'b -> 'c option) -> + 'a t -> + 'b t -> + 'c t +(** [join key1 key2 ~merge] is a binary operation + that takes two sequences [a] and [b], projects their + elements resp. with [key1] and [key2], and combine + values [(x,y)] from [(a,b)] with the same [key] + using [merge]. If [merge] returns [None], the combination + of values is discarded. + @since NEXT_RELEASE *) + +val join_all_by : ?eq:'key equal -> ?hash:'key hash -> + ('a -> 'key) -> ('b -> 'key) -> + merge:('key -> 'a list -> 'b list -> 'c option) -> + 'a t -> + 'b t -> + 'c t +(** [join_all_by key1 key2 ~merge] is a binary operation + that takes two sequences [a] and [b], projects their + elements resp. with [key1] and [key2], and, for each key [k] + occurring in at least one of them: + - compute the list [l1] of elements of [a] that map to [k] + - compute the list [l2] of elements of [b] that map to [k] + - call [merge k l1 l2]. If [merge] returns [None], the combination + of values is discarded, otherwise it returns [Some c] + and [c] is inserted in the result. + @since NEXT_RELEASE *) + +val group_join_by : ?eq:'a equal -> ?hash:'a hash -> + ('b -> 'a) -> + 'a t -> + 'b t -> + ('a * 'b list) t +(** [group_join_by key2] associates to every element [x] of + the first sequence, all the elements [y] of the second + sequence such that [eq x (key y)]. Elements of the first + sequences without corresponding values in the second one + are mapped to [[]] + @since NEXT_RELEASE *) + +val inter : + ?eq:'a equal -> ?hash:'a hash -> + 'a t -> 'a t -> 'a t +(** Intersection of two collections. Each element will occur at most once + in the result. Eager. + @since NEXT_RELEASE *) + +(*$= + [2;4;5;6] (inter (1--6) (cons 2 (4--10)) |> sort |> to_list) + [] (inter (0--5) (6--10) |> to_list) +*) + +val union : + ?eq:'a equal -> ?hash:'a hash -> + 'a t -> 'a t -> 'a t +(** Union of two collections. Each element will occur at most once + in the result. Eager. + @since NEXT_RELEASE *) + +(*$= + [2;4;5;6] (union (4--6) (cons 2 (4--5)) |> sort |> to_list) +*) + +val diff : + ?eq:'a equal -> ?hash:'a hash -> + 'a t -> 'a t -> 'a t +(** Set difference. Eager. + @since NEXT_RELEASE *) + +(*$= + [1;2;8;9;10] (diff (1--10) (3--7) |> to_list) +*) + +val subset : + ?eq:'a equal -> ?hash:'a hash -> + 'a t -> 'a t -> bool +(** [subset a b] returns [true] if all elements of [a] belong to [b]. Eager. + @since NEXT_RELEASE *) + +(*$T + subset (2 -- 4) (1 -- 4) + not (subset (1 -- 4) (2 -- 10)) +*) + val unfoldr : ('b -> ('a * 'b) option) -> 'b -> 'a t (** [unfoldr f b] will apply [f] to [b]. If it yields [Some (x,b')] then [x] is returned @@ -260,10 +368,28 @@ val max : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option @return None if the sequence is empty, Some [m] where [m] is the maximal element otherwise *) +val max_exn : ?lt:('a -> 'a -> bool) -> 'a t -> 'a +(** Unsafe version of {!max} + @raise Not_found if the sequence is empty + @since NEXT_RELEASE *) + val min : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option (** Min element of the sequence, using the given comparison function. see {!max} for more details. *) +val min_exn : ?lt:('a -> 'a -> bool) -> 'a t -> 'a +(** Unsafe version of {!min} + @raise Not_found if the sequence is empty + @since NEXT_RELEASE *) + +val sum : int t -> int +(** Sum of elements + @since NEXT_RELEASE *) + +val sumf : float t -> float +(** Sum of elements, using Kahan summation + @since NEXT_RELEASE *) + val head : 'a t -> 'a option (** First element, if any, otherwise [None] *) @@ -332,7 +458,13 @@ val to_rev_list : 'a t -> 'a list val of_list : 'a list -> 'a t val on_list : ('a t -> 'b t) -> 'a list -> 'b list -(** [on_list f l] is equivalent to [to_list @@ f @@ of_list l]. *) +(** [on_list f l] is equivalent to [to_list @@ f @@ of_list l]. + @since 0.5.2 +*) + +val pair_with_idx : 'a t -> (int * 'a) t +(** Similar to {!zip_i} but returns a normal sequence of tuples + @since NEXT_RELEASE *) val to_opt : 'a t -> 'a option (** Alias to {!head} *) @@ -547,16 +679,20 @@ module Infix : sig It will therefore be empty if [a < b]. *) val (>>=) : 'a t -> ('a -> 'b t) -> 'b t - (** Monadic bind (infix version of {!flat_map} *) + (** Monadic bind (infix version of {!flat_map} + @since 0.5 *) val (>|=) : 'a t -> ('a -> 'b) -> 'b t - (** Infix version of {!map} *) + (** Infix version of {!map} + @since 0.5 *) val (<*>) : ('a -> 'b) t -> 'a t -> 'b t - (** Applicative operator (product+application) *) + (** Applicative operator (product+application) + @since 0.5 *) val (<+>) : 'a t -> 'a t -> 'a t - (** Concatenation of sequences *) + (** Concatenation of sequences + @since 0.5 *) end include module type of Infix @@ -600,7 +736,7 @@ val to_string : ?sep:string -> ('a -> string) -> 'a t -> string Sequence.IO.lines "a" |> Sequence.to_list ]} -*) + @since 0.5.1 *) module IO : sig val lines_of : ?mode:int -> ?flags:open_flag list -> @@ -630,7 +766,7 @@ module IO : sig val write_bytes_to : ?mode:int -> ?flags:open_flag list -> string -> Bytes.t t -> unit - (** *) + (** @since 0.5.4 *) val write_lines : ?mode:int -> ?flags:open_flag list -> string -> string t -> unit @@ -638,4 +774,5 @@ module IO : sig val write_bytes_lines : ?mode:int -> ?flags:open_flag list -> string -> Bytes.t t -> unit + (** @since 0.5.4 *) end From d59d96a5137b6871f0ea92942baa999c0577a5b0 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Thu, 14 Sep 2017 09:18:02 +0200 Subject: [PATCH 09/21] add `Sequence.filter_mapi` --- src/Sequence.ml | 12 ++++++++++-- src/Sequence.mli | 4 ++++ src/sequenceLabels.mli | 4 ++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/Sequence.ml b/src/Sequence.ml index a9c0f96..9397ae1 100644 --- a/src/Sequence.ml +++ b/src/Sequence.ml @@ -197,8 +197,16 @@ let seq_list l = seq_list_map (fun x->x) l let filter_map f seq k = seq (fun x -> match f x with | None -> () - | Some y -> k y - ) + | Some y -> k y) + +let filter_mapi f seq k = + let i = ref 0 in + seq (fun x -> + let j = !i in + incr i; + match f j x with + | None -> () + | Some y -> k y) let intersperse elem seq k = let first = ref true in diff --git a/src/Sequence.mli b/src/Sequence.mli index 2d686da..d08af7b 100644 --- a/src/Sequence.mli +++ b/src/Sequence.mli @@ -215,6 +215,10 @@ val filter_map : ('a -> 'b option) -> 'a t -> 'b t Formerly [fmap] @since 0.5 *) +val filter_mapi : (int -> 'a -> 'b option) -> 'a t -> 'b t +(** Map with indices, and only keep non-[None] elements + @since NEXT_RELEASE *) + val intersperse : 'a -> 'a t -> 'a t (** Insert the single element between every element of the sequence *) diff --git a/src/sequenceLabels.mli b/src/sequenceLabels.mli index 940c28d..d764c69 100644 --- a/src/sequenceLabels.mli +++ b/src/sequenceLabels.mli @@ -176,6 +176,10 @@ val flat_map_l : f:('a -> 'b list) -> 'a t -> 'b t val filter_map : f:('a -> 'b option) -> 'a t -> 'b t (** Alias to {!fmap} with a more explicit name *) +val filter_mapi : f:(int -> 'a -> 'b option) -> 'a t -> 'b t +(** Map with indices, and only keep non-[None] elements + @since NEXT_RELEASE *) + val seq_list : 'a t list -> 'a list t (** [seq_list l] returns all the ways to pick one element in each sub-sequence in [l]. Assumes the sub-sequences can be iterated on several times. From e3f4e068c13395773f006fa7dda44c42293024ba Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Thu, 14 Sep 2017 09:18:33 +0200 Subject: [PATCH 10/21] remove spurious warning --- _tags | 1 + 1 file changed, 1 insertion(+) diff --git a/_tags b/_tags index fd66075..831c1ef 100644 --- a/_tags +++ b/_tags @@ -29,6 +29,7 @@ # OASIS_STOP true: bin_annot, color(always) <**/*.ml>: warn(+a-4-44-48@8) +: warn(-33) true: mark_tag_used <**/*.cmx>: optimize(3) : nolabels From cdf43fd3546f0049938085cd42b4ddd3b4236adb Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Wed, 11 Oct 2017 17:20:55 +0200 Subject: [PATCH 11/21] add `Sequence.append_l` --- src/Sequence.ml | 2 ++ src/Sequence.mli | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/src/Sequence.ml b/src/Sequence.ml index 9397ae1..5819f21 100644 --- a/src/Sequence.ml +++ b/src/Sequence.ml @@ -150,6 +150,8 @@ let filter p seq k = seq (fun x -> if p x then k x) let append s1 s2 k = s1 k; s2 k +let append_l l k = List.iter (fun sub -> sub k) l + let concat s k = s (fun s' -> s' k) (*$R diff --git a/src/Sequence.mli b/src/Sequence.mli index d08af7b..f9635cf 100644 --- a/src/Sequence.mli +++ b/src/Sequence.mli @@ -184,6 +184,11 @@ val append : 'a t -> 'a t -> 'a t (** Append two sequences. Iterating on the result is like iterating on the first, then on the second. *) +val append_l : 'a t list -> 'a t +(** Append sequences. Iterating on the result is like iterating + on the each sequence of the list in order. + @since NEXT_RELEASE *) + val concat : 'a t t -> 'a t (** Concatenate a sequence of sequences into one sequence. *) From d7fd225a73484adb3f54746afab7e3cf14aaca16 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Mon, 30 Oct 2017 13:41:48 +0100 Subject: [PATCH 12/21] add `prefix` to opam file (close #11) --- opam | 1 + 1 file changed, 1 insertion(+) diff --git a/opam b/opam index 9f3cdf6..7a37f04 100644 --- a/opam +++ b/opam @@ -8,6 +8,7 @@ build: [ ["./configure" "--disable-docs" "--%{delimcc:enable}%-invert" "--%{base-bigarray:enable}%-bigarray" + "--prefix" "%{prefix}%" ] [make "build"] ] From b3fdd356ca23c49a81036dcbf7f51adf023b8a58 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Fri, 15 Dec 2017 12:38:02 +0100 Subject: [PATCH 13/21] update doc with some explanations about equality and hash --- src/Sequence.mli | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Sequence.mli b/src/Sequence.mli index f9635cf..503b998 100644 --- a/src/Sequence.mli +++ b/src/Sequence.mli @@ -269,6 +269,7 @@ val group_by : ?hash:('a -> int) -> ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t (** Group equal elements, disregarding their order of appearance. The result sequence is traversable as many times as required. + precondition: for any [x] and [y], if [eq x y] then [hash x=hash y] must hold. @since 0.6 *) val count : ?hash:('a -> int) -> ?eq:('a -> 'a -> bool) -> @@ -319,6 +320,7 @@ val join_by : ?eq:'key equal -> ?hash:'key hash -> values [(x,y)] from [(a,b)] with the same [key] using [merge]. If [merge] returns [None], the combination of values is discarded. + precondition: for any [x] and [y], if [eq x y] then [hash x=hash y] must hold. @since 0.10 *) val join_all_by : ?eq:'key equal -> ?hash:'key hash -> @@ -348,6 +350,7 @@ val group_join_by : ?eq:'a equal -> ?hash:'a hash -> sequence such that [eq x (key y)]. Elements of the first sequences without corresponding values in the second one are mapped to [[]] + precondition: for any [x] and [y], if [eq x y] then [hash x=hash y] must hold. @since 0.10 *) val inter : @@ -355,6 +358,7 @@ val inter : 'a t -> 'a t -> 'a t (** Intersection of two collections. Each element will occur at most once in the result. Eager. + precondition: for any [x] and [y], if [eq x y] then [hash x=hash y] must hold. @since 0.10 *) (*$= @@ -367,6 +371,7 @@ val union : 'a t -> 'a t -> 'a t (** Union of two collections. Each element will occur at most once in the result. Eager. + precondition: for any [x] and [y], if [eq x y] then [hash x=hash y] must hold. @since 0.10 *) (*$= @@ -387,6 +392,7 @@ val subset : ?eq:'a equal -> ?hash:'a hash -> 'a t -> 'a t -> bool (** [subset a b] returns [true] if all elements of [a] belong to [b]. Eager. + precondition: for any [x] and [y], if [eq x y] then [hash x=hash y] must hold. @since 0.10 *) (*$T From b24ebfb405d8ddf99ffc47344738e98f34aed5ad Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Fri, 15 Dec 2017 12:40:43 +0100 Subject: [PATCH 14/21] update `sequenceLabels.mli` --- src/sequenceLabels.mli | 62 ++++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/src/sequenceLabels.mli b/src/sequenceLabels.mli index d764c69..7b51d97 100644 --- a/src/sequenceLabels.mli +++ b/src/sequenceLabels.mli @@ -118,14 +118,16 @@ val exists : f:('a -> bool) -> 'a t -> bool val mem : ?eq:('a -> 'a -> bool) -> x:'a -> 'a t -> bool (** Is the value a member of the sequence? - @param eq the equality predicate to use (default [(=)]) *) + @param eq the equality predicate to use (default [(=)]) + @since 0.5 *) -val find : f:('a -> 'b option) -> 'a t -> 'b option -(** Find the first element on which the function doesn't return [None] *) +val find : ('a -> 'b option) -> 'a t -> 'b option +(** Find the first element on which the function doesn't return [None] + @since 0.5 *) val find_map : f:('a -> 'b option) -> 'a t -> 'b option (** Alias to {!find} - @since NEXT_RELEASE *) + @since 0.10 *) val findi : f:(int -> 'a -> 'b option) -> 'a t -> 'b option (** Indexed version of {!find} @@ -133,7 +135,7 @@ val findi : f:(int -> 'a -> 'b option) -> 'a t -> 'b option val find_mapi : f:(int -> 'a -> 'b option) -> 'a t -> 'b option (** Alias to {!findi} - @since NEXT_RELEASE *) + @since 0.10 *) val find_pred : f:('a -> bool) -> 'a t -> 'a option (** [find_pred p l] finds the first element of [l] that satisfies [p], @@ -160,6 +162,11 @@ val append : 'a t -> 'a t -> 'a t (** Append two sequences. Iterating on the result is like iterating on the first, then on the second. *) +val append_l : 'a t list -> 'a t +(** Append sequences. Iterating on the result is like iterating + on the each sequence of the list in order. + @since NEXT_RELEASE *) + val concat : 'a t t -> 'a t (** Concatenate a sequence of sequences into one sequence. *) @@ -235,6 +242,7 @@ val group_by : ?hash:('a -> int) -> ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t (** Group equal elements, disregarding their order of appearance. The result sequence is traversable as many times as required. + precondition: for any [x] and [y], if [eq x y] then [hash x=hash y] must hold. @since 0.6 *) val count : ?hash:('a -> int) -> ?eq:('a -> 'a -> bool) -> @@ -264,7 +272,8 @@ val diagonal : 'a t -> ('a * 'a) t @since 0.9 *) val product2 : 'a t -> 'b t -> ('a, 'b) t2 -(** Binary version of {!product}. Same requirements. *) +(** Binary version of {!product}. Same requirements. + @since 0.5 *) val join : join_row:('a -> 'b -> 'c option) -> 'a t -> 'b t -> 'c t (** [join ~join_row a b] combines every element of [a] with every @@ -284,7 +293,8 @@ val join_by : ?eq:'key equal -> ?hash:'key hash -> values [(x,y)] from [(a,b)] with the same [key] using [merge]. If [merge] returns [None], the combination of values is discarded. - @since NEXT_RELEASE *) + precondition: for any [x] and [y], if [eq x y] then [hash x=hash y] must hold. + @since 0.10 *) val join_all_by : ?eq:'key equal -> ?hash:'key hash -> ('a -> 'key) -> ('b -> 'key) -> @@ -301,7 +311,7 @@ val join_all_by : ?eq:'key equal -> ?hash:'key hash -> - call [merge k l1 l2]. If [merge] returns [None], the combination of values is discarded, otherwise it returns [Some c] and [c] is inserted in the result. - @since NEXT_RELEASE *) + @since 0.10 *) val group_join_by : ?eq:'a equal -> ?hash:'a hash -> ('b -> 'a) -> @@ -313,14 +323,16 @@ val group_join_by : ?eq:'a equal -> ?hash:'a hash -> sequence such that [eq x (key y)]. Elements of the first sequences without corresponding values in the second one are mapped to [[]] - @since NEXT_RELEASE *) + precondition: for any [x] and [y], if [eq x y] then [hash x=hash y] must hold. + @since 0.10 *) val inter : ?eq:'a equal -> ?hash:'a hash -> 'a t -> 'a t -> 'a t (** Intersection of two collections. Each element will occur at most once in the result. Eager. - @since NEXT_RELEASE *) + precondition: for any [x] and [y], if [eq x y] then [hash x=hash y] must hold. + @since 0.10 *) (*$= [2;4;5;6] (inter (1--6) (cons 2 (4--10)) |> sort |> to_list) @@ -332,7 +344,8 @@ val union : 'a t -> 'a t -> 'a t (** Union of two collections. Each element will occur at most once in the result. Eager. - @since NEXT_RELEASE *) + precondition: for any [x] and [y], if [eq x y] then [hash x=hash y] must hold. + @since 0.10 *) (*$= [2;4;5;6] (union (4--6) (cons 2 (4--5)) |> sort |> to_list) @@ -342,7 +355,7 @@ val diff : ?eq:'a equal -> ?hash:'a hash -> 'a t -> 'a t -> 'a t (** Set difference. Eager. - @since NEXT_RELEASE *) + @since 0.10 *) (*$= [1;2;8;9;10] (diff (1--10) (3--7) |> to_list) @@ -352,7 +365,8 @@ val subset : ?eq:'a equal -> ?hash:'a hash -> 'a t -> 'a t -> bool (** [subset a b] returns [true] if all elements of [a] belong to [b]. Eager. - @since NEXT_RELEASE *) + precondition: for any [x] and [y], if [eq x y] then [hash x=hash y] must hold. + @since 0.10 *) (*$T subset (2 -- 4) (1 -- 4) @@ -375,7 +389,7 @@ val max : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option val max_exn : ?lt:('a -> 'a -> bool) -> 'a t -> 'a (** Unsafe version of {!max} @raise Not_found if the sequence is empty - @since NEXT_RELEASE *) + @since 0.10 *) val min : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option (** Min element of the sequence, using the given comparison function. @@ -384,7 +398,7 @@ val min : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option val min_exn : ?lt:('a -> 'a -> bool) -> 'a t -> 'a (** Unsafe version of {!min} @raise Not_found if the sequence is empty - @since NEXT_RELEASE *) + @since 0.10 *) val sum : int t -> int (** Sum of elements @@ -395,11 +409,13 @@ val sumf : float t -> float @since NEXT_RELEASE *) val head : 'a t -> 'a option -(** First element, if any, otherwise [None] *) +(** First element, if any, otherwise [None] + @since 0.5.1 *) val head_exn : 'a t -> 'a (** First element, if any, fails - @raise Invalid_argument if the sequence is empty *) + @raise Invalid_argument if the sequence is empty + @since 0.5.1 *) val take : int -> 'a t -> 'a t (** Take at most [n] elements from the sequence. Works on infinite @@ -412,7 +428,8 @@ val take_while : f:('a -> bool) -> 'a t -> 'a t val fold_while : f:('a -> 'b -> 'a * [`Stop | `Continue]) -> init:'a -> 'b t -> 'a (** Folds over elements of the sequence, stopping early if the accumulator - returns [('a, `Stop)] *) + returns [('a, `Stop)] + @since 0.5.5 *) val drop : int -> 'a t -> 'a t (** Drop the [n] first elements of the sequence. Lazy. *) @@ -471,7 +488,8 @@ val pair_with_idx : 'a t -> (int * 'a) t @since NEXT_RELEASE *) val to_opt : 'a t -> 'a option -(** Alias to {!head} *) +(** Alias to {!head} + @since 0.5.1 *) val to_array : 'a t -> 'a array (** Convert to an array. Currently not very efficient because @@ -489,7 +507,8 @@ val array_slice : 'a array -> int -> int -> 'a t from [i] to [j] *) val of_opt : 'a option -> 'a t -(** Iterate on 0 or 1 values. *) +(** Iterate on 0 or 1 values. + @since 0.5.1 *) val of_stream : 'a Stream.t -> 'a t (** Sequence of elements of a stream (usable only once) *) @@ -537,7 +556,8 @@ val to_str : char t -> string val concat_str : string t -> string (** Concatenate strings together, eagerly. - Also see {!intersperse} to add a separator. *) + Also see {!intersperse} to add a separator. + @since 0.5 *) exception OneShotSequence (** Raised when the user tries to iterate several times on From 17801b35587315210ae5bb6eaa70e8af7f6aaca2 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Fri, 15 Dec 2017 12:42:13 +0100 Subject: [PATCH 15/21] remove symlink trick for SequenceLabels implem --- _tags | 2 +- src/SequenceLabels.ml | 1 + src/sequenceLabels.ml | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 src/SequenceLabels.ml delete mode 120000 src/sequenceLabels.ml diff --git a/_tags b/_tags index 831c1ef..825dc26 100644 --- a/_tags +++ b/_tags @@ -32,4 +32,4 @@ true: bin_annot, color(always) : warn(-33) true: mark_tag_used <**/*.cmx>: optimize(3) -: nolabels +: nolabels diff --git a/src/SequenceLabels.ml b/src/SequenceLabels.ml new file mode 100644 index 0000000..fb15e92 --- /dev/null +++ b/src/SequenceLabels.ml @@ -0,0 +1 @@ +include Sequence diff --git a/src/sequenceLabels.ml b/src/sequenceLabels.ml deleted file mode 120000 index b990b32..0000000 --- a/src/sequenceLabels.ml +++ /dev/null @@ -1 +0,0 @@ -Sequence.ml \ No newline at end of file From ab4a22f8a742eea6198c07072df163c6683b247d Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Fri, 15 Dec 2017 13:08:02 +0100 Subject: [PATCH 16/21] capitalize files --- src/{sequenceLabels.mli => SequenceLabels.mli} | 0 src/bigarray/{sequenceBigarray.ml => SequenceBigarray.ml} | 0 src/bigarray/{sequenceBigarray.mli => SequenceBigarray.mli} | 0 src/invert/{sequenceInvert.ml => SequenceInvert.ml} | 0 src/invert/{sequenceInvert.mli => SequenceInvert.mli} | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename src/{sequenceLabels.mli => SequenceLabels.mli} (100%) rename src/bigarray/{sequenceBigarray.ml => SequenceBigarray.ml} (100%) rename src/bigarray/{sequenceBigarray.mli => SequenceBigarray.mli} (100%) rename src/invert/{sequenceInvert.ml => SequenceInvert.ml} (100%) rename src/invert/{sequenceInvert.mli => SequenceInvert.mli} (100%) diff --git a/src/sequenceLabels.mli b/src/SequenceLabels.mli similarity index 100% rename from src/sequenceLabels.mli rename to src/SequenceLabels.mli diff --git a/src/bigarray/sequenceBigarray.ml b/src/bigarray/SequenceBigarray.ml similarity index 100% rename from src/bigarray/sequenceBigarray.ml rename to src/bigarray/SequenceBigarray.ml diff --git a/src/bigarray/sequenceBigarray.mli b/src/bigarray/SequenceBigarray.mli similarity index 100% rename from src/bigarray/sequenceBigarray.mli rename to src/bigarray/SequenceBigarray.mli diff --git a/src/invert/sequenceInvert.ml b/src/invert/SequenceInvert.ml similarity index 100% rename from src/invert/sequenceInvert.ml rename to src/invert/SequenceInvert.ml diff --git a/src/invert/sequenceInvert.mli b/src/invert/SequenceInvert.mli similarity index 100% rename from src/invert/sequenceInvert.mli rename to src/invert/SequenceInvert.mli From 6be7dddee2326ad5a6af3a3c15fa06e000facfc4 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Fri, 15 Dec 2017 12:45:27 +0100 Subject: [PATCH 17/21] make `group_by` lazy --- src/Sequence.ml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/Sequence.ml b/src/Sequence.ml index 5819f21..dd6ea4c 100644 --- a/src/Sequence.ml +++ b/src/Sequence.ml @@ -422,14 +422,16 @@ let group_by (type k) ?(hash=Hashtbl.hash) ?(eq=(=)) seq = let hash = hash end) in (* compute group table *) - let tbl = Tbl.create 32 in - seq - (fun x -> - let l = try Tbl.find tbl x with Not_found -> [] in - Tbl.replace tbl x (x::l) - ); + let tbl = lazy ( + let tbl = Tbl.create 32 in + seq + (fun x -> + let l = try Tbl.find tbl x with Not_found -> [] in + Tbl.replace tbl x (x::l)); + tbl + ) in fun yield -> - Tbl.iter (fun _ l -> yield l) tbl + Tbl.iter (fun _ l -> yield l) (Lazy.force tbl) (*$R [1;2;3;3;2;2;3;4] From c3590de261c2a572dd97259fefc4b33fcdd6d267 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Fri, 15 Dec 2017 12:46:59 +0100 Subject: [PATCH 18/21] make `count` lazy --- src/Sequence.ml | 16 +++++++++------- src/Sequence.mli | 1 + 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Sequence.ml b/src/Sequence.ml index dd6ea4c..af94eb8 100644 --- a/src/Sequence.ml +++ b/src/Sequence.ml @@ -446,14 +446,16 @@ let count (type k) ?(hash=Hashtbl.hash) ?(eq=(=)) seq = let hash = hash end) in (* compute group table *) - let tbl = Tbl.create 32 in - seq - (fun x -> - let n = try Tbl.find tbl x with Not_found -> 0 in - Tbl.replace tbl x (n+1) - ); + let tbl = lazy ( + let tbl = Tbl.create 32 in + seq + (fun x -> + let n = try Tbl.find tbl x with Not_found -> 0 in + Tbl.replace tbl x (n+1)); + tbl + ) in fun yield -> - Tbl.iter (fun x n -> yield (x,n)) tbl + Tbl.iter (fun x n -> yield (x,n)) (Lazy.force tbl) (*$R [1;2;3;3;2;2;3;4] diff --git a/src/Sequence.mli b/src/Sequence.mli index 503b998..c7b19a2 100644 --- a/src/Sequence.mli +++ b/src/Sequence.mli @@ -276,6 +276,7 @@ val count : ?hash:('a -> int) -> ?eq:('a -> 'a -> bool) -> 'a t -> ('a * int) t (** Map each distinct element to its number of occurrences in the whole seq. Similar to [group_by seq |> map (fun l->List.hd l, List.length l)] + precondition: for any [x] and [y], if [eq x y] then [hash x=hash y] must hold. @since 0.10 *) val uniq : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t From eace3581f121d078b371977d6096652e951d76f8 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Fri, 15 Dec 2017 12:47:55 +0100 Subject: [PATCH 19/21] small details --- src/Sequence.ml | 5 ++++- src/Sequence.mli | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Sequence.ml b/src/Sequence.ml index af94eb8..47b8f70 100644 --- a/src/Sequence.ml +++ b/src/Sequence.ml @@ -407,7 +407,10 @@ let group_succ_by ?(eq=fun x y -> x = y) seq k = k l; (* yield group, and start another one *) cur := [x]); (* last list *) - if !cur <> [] then k !cur + begin match !cur with + | [] -> () + | (_::_) as l -> k l + end (*$R [1;2;3;3;2;2;3;4] diff --git a/src/Sequence.mli b/src/Sequence.mli index c7b19a2..8e1d525 100644 --- a/src/Sequence.mli +++ b/src/Sequence.mli @@ -261,7 +261,7 @@ val sorted : ?cmp:('a -> 'a -> int) -> 'a t -> bool @since 0.9 *) val group_succ_by : ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t -(** Group equal consecutive elements. +(** Group equal consecutive elements. Linear time. Formerly synonym to [group]. @since 0.6 *) From 2417b8e5fd80c5de632c9c661d5a0c92120f8110 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Fri, 15 Dec 2017 12:49:56 +0100 Subject: [PATCH 20/21] small fixes --- _tags | 2 +- src/Sequence.ml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/_tags b/_tags index 825dc26..2e4613b 100644 --- a/_tags +++ b/_tags @@ -27,7 +27,7 @@ : pkg_benchmark : use_sequence # OASIS_STOP -true: bin_annot, color(always) +true: safe_string, bin_annot, color(always) <**/*.ml>: warn(+a-4-44-48@8) : warn(-33) true: mark_tag_used diff --git a/src/Sequence.ml b/src/Sequence.ml index 47b8f70..aa0e350 100644 --- a/src/Sequence.ml +++ b/src/Sequence.ml @@ -1107,7 +1107,7 @@ let to_buffer seq buf = (*$R let b = Buffer.create 4 in "hello world" - |> of_str |> rev |> map Char.uppercase + |> of_str |> rev |> map Char.uppercase_ascii |> (fun seq -> to_buffer seq b); OUnit.assert_equal "DLROW OLLEH" (Buffer.contents b); *) From d3d5881a28501d395646f02fd23e2aa56ceef00a Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Fri, 15 Dec 2017 12:51:02 +0100 Subject: [PATCH 21/21] prepare for 0.11 --- _oasis | 2 +- opam | 4 ++-- src/Sequence.mli | 14 +++++++------- src/SequenceLabels.mli | 14 +++++++------- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/_oasis b/_oasis index ce827cf..d0a407a 100644 --- a/_oasis +++ b/_oasis @@ -1,6 +1,6 @@ OASISFormat: 0.4 Name: sequence -Version: 0.10 +Version: 0.11 Homepage: https://github.com/c-cube/sequence Authors: Simon Cruanes License: BSD-2-clause diff --git a/opam b/opam index 7a37f04..f3bb2b5 100644 --- a/opam +++ b/opam @@ -1,8 +1,8 @@ opam-version: "1.2" name: "sequence" -version: "0.10" +version: "0.11" author: "Simon Cruanes" -maintainer: "simon.cruanes@inria.fr" +maintainer: "simon.cruanes.2007@m4x.org" license: "BSD-2-clauses" build: [ ["./configure" "--disable-docs" diff --git a/src/Sequence.mli b/src/Sequence.mli index 8e1d525..0d6fb79 100644 --- a/src/Sequence.mli +++ b/src/Sequence.mli @@ -187,7 +187,7 @@ val append : 'a t -> 'a t -> 'a t val append_l : 'a t list -> 'a t (** Append sequences. Iterating on the result is like iterating on the each sequence of the list in order. - @since NEXT_RELEASE *) + @since 0.11 *) val concat : 'a t t -> 'a t (** Concatenate a sequence of sequences into one sequence. *) @@ -208,12 +208,12 @@ val flat_map_l : ('a -> 'b list) -> 'a t -> 'b t val seq_list : 'a t list -> 'a list t (** [seq_list l] returns all the ways to pick one element in each sub-sequence in [l]. Assumes the sub-sequences can be iterated on several times. - @since NEXT_RELEASE *) + @since 0.11 *) val seq_list_map : ('a -> 'b t) -> 'a list -> 'b list t (** [seq_list_map f l] maps [f] over every element of [l], then calls {!seq_list} - @since NEXT_RELEASE *) + @since 0.11 *) val filter_map : ('a -> 'b option) -> 'a t -> 'b t (** Map and only keep non-[None] elements @@ -222,7 +222,7 @@ val filter_map : ('a -> 'b option) -> 'a t -> 'b t val filter_mapi : (int -> 'a -> 'b option) -> 'a t -> 'b t (** Map with indices, and only keep non-[None] elements - @since NEXT_RELEASE *) + @since 0.11 *) val intersperse : 'a -> 'a t -> 'a t (** Insert the single element between every element of the sequence *) @@ -430,11 +430,11 @@ val min_exn : ?lt:('a -> 'a -> bool) -> 'a t -> 'a val sum : int t -> int (** Sum of elements - @since NEXT_RELEASE *) + @since 0.11 *) val sumf : float t -> float (** Sum of elements, using Kahan summation - @since NEXT_RELEASE *) + @since 0.11 *) val head : 'a t -> 'a option (** First element, if any, otherwise [None] @@ -513,7 +513,7 @@ val on_list : ('a t -> 'b t) -> 'a list -> 'b list val pair_with_idx : 'a t -> (int * 'a) t (** Similar to {!zip_i} but returns a normal sequence of tuples - @since NEXT_RELEASE *) + @since 0.11 *) val to_opt : 'a t -> 'a option (** Alias to {!head} diff --git a/src/SequenceLabels.mli b/src/SequenceLabels.mli index 7b51d97..5b582e2 100644 --- a/src/SequenceLabels.mli +++ b/src/SequenceLabels.mli @@ -165,7 +165,7 @@ val append : 'a t -> 'a t -> 'a t val append_l : 'a t list -> 'a t (** Append sequences. Iterating on the result is like iterating on the each sequence of the list in order. - @since NEXT_RELEASE *) + @since 0.11 *) val concat : 'a t t -> 'a t (** Concatenate a sequence of sequences into one sequence. *) @@ -185,17 +185,17 @@ val filter_map : f:('a -> 'b option) -> 'a t -> 'b t val filter_mapi : f:(int -> 'a -> 'b option) -> 'a t -> 'b t (** Map with indices, and only keep non-[None] elements - @since NEXT_RELEASE *) + @since 0.11 *) val seq_list : 'a t list -> 'a list t (** [seq_list l] returns all the ways to pick one element in each sub-sequence in [l]. Assumes the sub-sequences can be iterated on several times. - @since NEXT_RELEASE *) + @since 0.11 *) val seq_list_map : f:('a -> 'b t) -> 'a list -> 'b list t (** [seq_list_map f l] maps [f] over every element of [l], then calls {!seq_list} - @since NEXT_RELEASE *) + @since 0.11 *) val intersperse : x:'a -> 'a t -> 'a t (** Insert the single element between every element of the sequence *) @@ -402,11 +402,11 @@ val min_exn : ?lt:('a -> 'a -> bool) -> 'a t -> 'a val sum : int t -> int (** Sum of elements - @since NEXT_RELEASE *) + @since 0.11 *) val sumf : float t -> float (** Sum of elements, using Kahan summation - @since NEXT_RELEASE *) + @since 0.11 *) val head : 'a t -> 'a option (** First element, if any, otherwise [None] @@ -485,7 +485,7 @@ val on_list : ('a t -> 'b t) -> 'a list -> 'b list val pair_with_idx : 'a t -> (int * 'a) t (** Similar to {!zip_i} but returns a normal sequence of tuples - @since NEXT_RELEASE *) + @since 0.11 *) val to_opt : 'a t -> 'a option (** Alias to {!head}