diff --git a/LICENSE b/LICENSE index 7e29992..28fdb73 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2012, Simon Cruanes +Copyright (c) 2012-2016, Simon Cruanes All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/sequence.ml b/sequence.ml index c781d53..c118fb9 100644 --- a/sequence.ml +++ b/sequence.ml @@ -1,29 +1,7 @@ -(* -Copyright (c) 2013, Simon Cruanes -All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: +(* This file is free software, part of sequence. See file "license" for more details. *) -Redistributions of source code must retain the above copyright notice, this -list of conditions and the following disclaimer. Redistributions in binary -form must reproduce the above copyright notice, this list of conditions and the -following disclaimer in the documentation and/or other materials provided with -the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*) - -(** {1 Transient iterators, that abstract on a finite sequence of elements.} *) +(** {1 Simple and Efficient Iterators} *) (** Sequence abstract iterator type *) type 'a t = ('a -> unit) -> unit @@ -31,7 +9,7 @@ type 'a t = ('a -> unit) -> unit type 'a sequence = 'a t type (+'a, +'b) t2 = ('a -> 'b -> unit) -> unit - (** Sequence of pairs of values of type ['a] and ['b]. *) +(** Sequence of pairs of values of type ['a] and ['b]. *) (** Build a sequence from a iter function *) let from_iter f = f @@ -69,8 +47,8 @@ let iteri f seq = let r = ref 0 in seq (fun x -> - f !r x; - incr r) + f !r x; + incr r) let fold f init seq = let r = ref init in @@ -82,8 +60,8 @@ let foldi f init seq = let r = ref init in seq (fun elt -> - r := f !r !i elt; - incr i); + r := f !r !i elt; + incr i); !r let map f seq k = seq (fun x -> k (f x)) @@ -108,7 +86,7 @@ let fmap f seq k = seq (fun x -> match f x with | None -> () | Some y -> k y - ) + ) let filter_map = fmap @@ -130,22 +108,20 @@ module MList = struct let prev, cur = ref start, ref Nil in seq (fun x -> - k x; (* callback *) - match !cur with - | Nil -> - let n = !chunk_size in - if n < 4096 then chunk_size := 2 * !chunk_size; - cur := Cons (Array.make n x, ref 1, ref Nil) - | Cons (a,n,next) -> - assert (!n < Array.length a); - a.(!n) <- x; - incr n; - if !n = Array.length a then begin - !prev := !cur; - prev := next; - cur := Nil - end - ); + k x; (* callback *) + match !cur with + | Nil -> + let n = !chunk_size in + if n < 4096 then chunk_size := 2 * !chunk_size; + cur := Cons (Array.make n x, ref 1, ref Nil) + | Cons (a,n,next) -> + assert (!n < Array.length a); + a.(!n) <- x; + incr n; + if !n = Array.length a then ( + !prev := !cur; + prev := next; + cur := Nil)); !prev := !cur; !start @@ -155,13 +131,13 @@ module MList = struct let rec iter f l = match l with | Nil -> () | Cons (a, n, tl) -> - for i=0 to !n - 1 do f a.(i) done; - iter f !tl + for i=0 to !n - 1 do f a.(i) done; + iter f !tl let iteri f l = let rec iteri i f l = match l with - | Nil -> () - | Cons (a, n, tl) -> + | Nil -> () + | Cons (a, n, tl) -> for j=0 to !n - 1 do f (i+j) a.(j) done; iteri (i+ !n) f !tl in iteri 0 f l @@ -169,8 +145,8 @@ module MList = struct let rec iter_rev f l = match l with | Nil -> () | Cons (a, n, tl) -> - iter_rev f !tl; - for i = !n-1 downto 0 do f a.(i) done + iter_rev f !tl; + for i = !n-1 downto 0 do f a.(i) done let length l = let rec len acc l = match l with @@ -192,13 +168,13 @@ module MList = struct let rec get_next _ = match !cur with | Nil -> None | Cons (_, n, tl) when !i = !n -> - cur := !tl; - i := 0; - get_next arg + cur := !tl; + i := 0; + get_next arg | Cons (a, _, _) -> - let x = a.(!i) in - incr i; - Some x + let x = a.(!i) in + incr i; + Some x in get_next let to_gen l = _to_next () l @@ -228,9 +204,9 @@ let persistent_lazy (seq:'a t) = match !r with | LazyCached seq' -> seq' k | LazySuspend -> - (* here if this traversal is interruted, no caching occurs *) - let seq' = MList.of_seq_with seq k in - r := LazyCached (MList.to_seq seq') + (* here if this traversal is interruted, no caching occurs *) + let seq' = MList.of_seq_with seq k in + r := LazyCached (MList.to_seq seq') let sort ?(cmp=Pervasives.compare) seq = (* use an intermediate list, then sort the list *) @@ -241,13 +217,13 @@ let sort ?(cmp=Pervasives.compare) seq = let group_succ_by ?(eq=fun x y -> x = y) seq k = let cur = ref [] in seq (fun x -> - match !cur with - | [] -> cur := [x] - | (y::_) as l when eq x y -> - cur := x::l (* [x] belongs to the group *) - | (_::_) as l -> - k l; (* yield group, and start another one *) - cur := [x]); + match !cur with + | [] -> cur := [x] + | (y::_) as l when eq x y -> + cur := x::l (* [x] belongs to the group *) + | (_::_) as l -> + k l; (* yield group, and start another one *) + cur := [x]); (* last list *) if !cur <> [] then k !cur @@ -255,16 +231,16 @@ let group = group_succ_by let group_by (type k) ?(hash=Hashtbl.hash) ?(eq=(=)) seq = let module Tbl = Hashtbl.Make(struct - type t = k - let equal = eq - let hash = hash - end) in + type t = k + let equal = eq + 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 l = try Tbl.find tbl x with Not_found -> [] in + Tbl.replace tbl x (x::l) ); fun yield -> Tbl.iter (fun _ l -> yield l) tbl @@ -272,47 +248,42 @@ let group_by (type k) ?(hash=Hashtbl.hash) ?(eq=(=)) seq = let uniq ?(eq=fun x y -> x = y) seq k = let has_prev = ref false and prev = ref (Obj.magic 0) in (* avoid option type, costly *) - seq (fun x -> - if !has_prev && eq !prev x + seq + (fun x -> + if !has_prev && eq !prev x then () (* duplicate *) - else begin + else ( has_prev := true; prev := x; k x - end) + )) let sort_uniq (type elt) ?(cmp=Pervasives.compare) seq = let module S = Set.Make(struct - type t = elt - let compare = cmp - end) in + type t = elt + let compare = cmp + end) in let set = fold (fun acc x -> S.add x acc) S.empty seq in fun k -> S.iter k set let product outer inner k = - outer (fun x -> - inner (fun y -> k (x,y)) - ) + outer (fun x -> inner (fun y -> k (x,y))) let product2 outer inner k = - outer (fun x -> - inner (fun y -> k x y) - ) + outer (fun x -> inner (fun y -> k x y)) let join ~join_row s1 s2 k = s1 (fun a -> - s2 (fun b -> - match join_row a b with - | None -> () - | Some c -> k c - ) - ) (* yield the combination of [a] and [b] *) + s2 (fun b -> + match join_row a b with + | None -> () + | Some c -> k c)) let rec unfoldr f b k = match f b with | None -> () | Some (x, b') -> - k x; - unfoldr f b' k + k x; + unfoldr f b' k let scan f acc seq k = k acc; @@ -321,16 +292,18 @@ let scan f acc seq k = let max ?(lt=fun x y -> x < y) seq = let ret = ref None in - seq (fun x -> match !ret with - | None -> ret := Some x - | Some y -> if lt y x then ret := Some x); + seq + (fun x -> match !ret with + | None -> ret := Some x + | Some y -> if lt y x then ret := Some x); !ret let min ?(lt=fun x y -> x < y) seq = let ret = ref None in - seq (fun x -> match !ret with - | None -> ret := Some x - | Some y -> if lt x y then ret := Some x); + seq + (fun x -> match !ret with + | None -> ret := Some x + | Some y -> if lt x y then ret := Some x); !ret exception ExitHead @@ -351,11 +324,11 @@ exception ExitTake let take n seq k = let count = ref 0 in try - seq (fun x -> - if !count = n then raise ExitTake; - incr count; - k x; - ) + seq + (fun x -> + if !count = n then raise ExitTake; + incr count; + k x) with ExitTake -> () exception ExitTakeWhile @@ -370,11 +343,11 @@ exception ExitFoldWhile let fold_while f s seq = let state = ref s in let consume x = - let acc, cont = f (!state) x in - state := acc; - match cont with - | `Stop -> raise ExitFoldWhile - | `Continue -> () + let acc, cont = f (!state) x in + state := acc; + match cont with + | `Stop -> raise ExitFoldWhile + | `Continue -> () in try seq consume; !state @@ -386,10 +359,11 @@ let drop n seq k = let drop_while p seq k = let drop = ref true in - seq (fun x -> - if !drop - then if p x then () else (drop := false; k x) - else k x) + seq + (fun x -> + if !drop + then if p x then () else (drop := false; k x) + else k x) let rev seq = let l = MList.of_seq seq in @@ -418,12 +392,13 @@ exception ExitFind let find f seq = let r = ref None in - begin try - seq (fun x -> match f x with - | None -> () - | Some _ as res -> r := res; raise ExitFind - ); - with ExitFind -> () + begin + try + seq + (fun x -> match f x with + | None -> () + | Some _ as res -> r := res; raise ExitFind); + with ExitFind -> () end; !r @@ -492,17 +467,14 @@ let to_array seq = let l = MList.of_seq seq in let n = MList.length l in if n = 0 - then [||] - else begin - let a = Array.make n (MList.get l 0) in - MList.iteri (fun i x -> a.(i) <- x) l; - a - end + then [||] + else ( + let a = Array.make n (MList.get l 0) in + MList.iteri (fun i x -> a.(i) <- x) l; + a + ) -let of_array a k = - for i = 0 to Array.length a - 1 do - k (Array.unsafe_get a i) - done +let of_array a k = Array.iter k a let of_array_i a k = for i = 0 to Array.length a - 1 do @@ -583,8 +555,7 @@ let of_in_channel ic = while true do let c = input_char ic in k c done - with End_of_file -> () - ) + with End_of_file -> ()) let to_buffer seq buf = seq (fun c -> Buffer.add_char buf c) @@ -744,19 +715,19 @@ let pp_seq ?(sep=", ") pp_elt formatter seq = let first = ref true in seq (fun x -> - (if !first then first := false - else begin + (if !first then first := false + else ( Format.pp_print_string formatter sep; Format.pp_print_cut formatter (); - end); - pp_elt formatter x) + )); + pp_elt formatter x) let pp_buf ?(sep=", ") pp_elt buf seq = let first = ref true in seq (fun x -> - if !first then first := false else Buffer.add_string buf sep; - pp_elt buf x) + if !first then first := false else Buffer.add_string buf sep; + pp_elt buf x) let to_string ?sep pp_elt seq = let buf = Buffer.create 25 in @@ -794,7 +765,7 @@ module IO = struct if n' = 0 then stop := true else n := !n + n'; done; if !n > 0 - then k (Bytes.sub_string buf 0 !n) + then k (Bytes.sub_string buf 0 !n) done; close_in ic with e -> diff --git a/sequence.mli b/sequence.mli index 26d0f6b..593f477 100644 --- a/sequence.mli +++ b/sequence.mli @@ -1,27 +1,5 @@ -(* -copyright (c) 2013, simon cruanes -all rights reserved. -redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -redistributions of source code must retain the above copyright notice, this -list of conditions and the following disclaimer. redistributions in binary -form must reproduce the above copyright notice, this list of conditions and the -following disclaimer in the documentation and/or other materials provided with -the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*) +(* This file is free software, part of sequence. See file "license" for more details. *) (** {1 Simple and Efficient Iterators} *) @@ -53,252 +31,252 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. of this memory structure, cheaply and repeatably. *) type +'a t = ('a -> unit) -> unit - (** A sequence of values of type ['a]. If you give it a function ['a -> unit] - it will be applied to every element of the sequence successively. *) +(** A sequence of values of type ['a]. If you give it a function ['a -> unit] + it will be applied to every element of the sequence successively. *) type +'a sequence = 'a t type (+'a, +'b) t2 = ('a -> 'b -> unit) -> unit - (** Sequence of pairs of values of type ['a] and ['b]. *) +(** Sequence of pairs of values of type ['a] and ['b]. *) (** {2 Build a sequence} *) val from_iter : (('a -> unit) -> unit) -> 'a t - (** Build a sequence from a iter function *) +(** Build a sequence from a iter function *) val from_fun : (unit -> 'a option) -> 'a t - (** Call the function repeatedly until it returns None. This - sequence is transient, use {!persistent} if needed! *) +(** Call the function repeatedly until it returns None. This + sequence is transient, use {!persistent} if needed! *) val empty : 'a t - (** Empty sequence. It contains no element. *) +(** Empty sequence. It contains no element. *) val singleton : 'a -> 'a t - (** Singleton sequence, with exactly one element. *) +(** Singleton sequence, with exactly one element. *) val doubleton : 'a -> 'a -> 'a t - (** Sequence with exactly two elements *) +(** Sequence with exactly two elements *) val cons : 'a -> 'a t -> 'a t - (** [cons x l] yields [x], then yields from [l]. - Same as [append (singleton x) l] *) +(** [cons x l] yields [x], then yields from [l]. + Same as [append (singleton x) l] *) val snoc : 'a t -> 'a -> 'a t - (** Same as {!cons} but yields the element after iterating on [l] *) +(** Same as {!cons} but yields the element after iterating on [l] *) val return : 'a -> 'a t - (** Synonym to {!singleton} *) +(** Synonym to {!singleton} *) val pure : 'a -> 'a t - (** Synonym to {!singleton} *) +(** Synonym to {!singleton} *) val repeat : 'a -> 'a t - (** Infinite sequence of the same element. You may want to look - at {!take} and the likes if you iterate on it. *) +(** Infinite sequence of the same element. You may want to look + at {!take} and the likes if you iterate on it. *) val iterate : ('a -> 'a) -> 'a -> 'a t - (** [iterate f x] is the infinite sequence [x, f(x), f(f(x)), ...] *) +(** [iterate f x] is the infinite sequence [x, f(x), f(f(x)), ...] *) val forever : (unit -> 'b) -> 'b t - (** Sequence that calls the given function to produce elements. - The sequence may be transient (depending on the function), and definitely - is infinite. You may want to use {!take} and {!persistent}. *) +(** Sequence that calls the given function to produce elements. + The sequence may be transient (depending on the function), and definitely + is infinite. You may want to use {!take} and {!persistent}. *) val cycle : 'a t -> 'a t - (** Cycle forever through the given sequence. Assume the given sequence can - be traversed any amount of times (not transient). This yields an - infinite sequence, you should use something like {!take} not to loop - forever. *) +(** Cycle forever through the given sequence. Assume the given sequence can + be traversed any amount of times (not transient). This yields an + infinite sequence, you should use something like {!take} not to loop + forever. *) (** {2 Consume a sequence} *) val iter : ('a -> unit) -> 'a t -> unit - (** Consume the sequence, passing all its arguments to the function. - Basically [iter f seq] is just [seq f]. *) +(** Consume the sequence, passing all its arguments to the function. + Basically [iter f seq] is just [seq f]. *) val iteri : (int -> 'a -> unit) -> 'a t -> unit - (** Iterate on elements and their index in the sequence *) +(** Iterate on elements and their index in the sequence *) val fold : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a - (** Fold over elements of the sequence, consuming it *) +(** Fold over elements of the sequence, consuming it *) val foldi : ('a -> int -> 'b -> 'a) -> 'a -> 'b t -> 'a - (** Fold over elements of the sequence and their index, consuming it *) +(** Fold over elements of the sequence and their index, consuming it *) val map : ('a -> 'b) -> 'a t -> 'b t - (** Map objects of the sequence into other elements, lazily *) +(** Map objects of the sequence into other elements, lazily *) val mapi : (int -> 'a -> 'b) -> 'a t -> 'b t - (** Map objects, along with their index in the sequence *) +(** Map objects, along with their index in the sequence *) val for_all : ('a -> bool) -> 'a t -> bool - (** Do all elements satisfy the predicate? *) +(** Do all elements satisfy the predicate? *) val exists : ('a -> bool) -> 'a t -> bool - (** Exists there some element satisfying the predicate? *) +(** Exists there some element satisfying the predicate? *) val mem : ?eq:('a -> 'a -> bool) -> 'a -> 'a t -> bool - (** Is the value a member of the sequence? - @param eq the equality predicate to use (default [(=)]) - @since 0.5 *) +(** Is the value a member of the sequence? + @param eq the equality predicate to use (default [(=)]) + @since 0.5 *) val find : ('a -> 'b option) -> 'a t -> 'b option - (** Find the first element on which the function doesn't return [None] - @since 0.5 *) +(** Find the first element on which the function doesn't return [None] + @since 0.5 *) val length : 'a t -> int - (** How long is the sequence? Forces the sequence. *) +(** How long is the sequence? Forces the sequence. *) val is_empty : 'a t -> bool - (** Is the sequence empty? Forces the sequence. *) +(** Is the sequence empty? Forces the sequence. *) (** {2 Transform a sequence} *) val filter : ('a -> bool) -> 'a t -> 'a t - (** Filter on elements of the sequence *) +(** Filter on elements of the sequence *) 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. *) +(** Append two sequences. Iterating on the result is like iterating + on the first, then on the second. *) val concat : 'a t t -> 'a t - (** Concatenate a sequence of sequences into one sequence. *) +(** Concatenate a sequence of sequences into one sequence. *) val flatten : 'a t t -> 'a t - (** Alias for {!concat} *) +(** Alias for {!concat} *) val flatMap : ('a -> 'b t) -> 'a t -> 'b t - (** @deprecated use {!flat_map} since NEXT_RELEASE *) +(** @deprecated use {!flat_map} since NEXT_RELEASE *) val flat_map : ('a -> 'b t) -> 'a t -> 'b t - (** Monadic bind. Intuitively, it applies the function to every element of the - initial sequence, and calls {!concat}. - @since 0.5 *) +(** Monadic bind. Intuitively, it applies the function to every + element of the initial sequence, and calls {!concat}. + @since 0.5 *) val fmap : ('a -> 'b option) -> 'a t -> 'b t - (** @deprecated use {!filter_map} since NEXT_RELEASE *) +(** @deprecated use {!filter_map} since NEXT_RELEASE *) val filter_map : ('a -> 'b option) -> 'a t -> 'b t - (** Map and only keep non-[None] elements - @since 0.5 *) +(** Map and only keep non-[None] elements + @since 0.5 *) val intersperse : 'a -> 'a t -> 'a t - (** Insert the single element between every element of the sequence *) +(** Insert the single element between every element of the sequence *) (** {2 Caching} *) val persistent : 'a t -> 'a t - (** Iterate on the sequence, storing elements in an efficient internal structure.. - The resulting sequence can be iterated on as many times as needed. - {b Note}: calling persistent on an already persistent sequence - will still make a new copy of the sequence! *) +(** Iterate on the sequence, storing elements in an efficient internal structure.. + The resulting sequence can be iterated on as many times as needed. + {b Note}: calling persistent on an already persistent sequence + will still make a new copy of the sequence! *) val persistent_lazy : 'a t -> 'a t - (** Lazy version of {!persistent}. When calling [persistent_lazy s], - a new sequence [s'] is immediately returned (without actually consuming - [s]) in constant time; the first time [s'] is iterated on, - it also consumes [s] and caches its content into a inner data - structure that will back [s'] for future iterations. +(** Lazy version of {!persistent}. When calling [persistent_lazy s], + a new sequence [s'] is immediately returned (without actually consuming + [s]) in constant time; the first time [s'] is iterated on, + it also consumes [s] and caches its content into a inner data + structure that will back [s'] for future iterations. - {b warning}: on the first traversal of [s'], if the traversal - is interrupted prematurely ({!take}, etc.) then [s'] will not be - memorized, and the next call to [s'] will traverse [s] again. *) + {b warning}: on the first traversal of [s'], if the traversal + is interrupted prematurely ({!take}, etc.) then [s'] will not be + memorized, and the next call to [s'] will traverse [s] again. *) (** {2 Misc} *) val sort : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t - (** Sort the sequence. Eager, O(n) ram and O(n ln(n)) time. - It iterates on elements of the argument sequence immediately, - before it sorts them. *) +(** Sort the sequence. Eager, O(n) ram and O(n ln(n)) time. + It iterates on elements of the argument sequence immediately, + before it sorts them. *) val sort_uniq : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t - (** Sort the sequence and remove duplicates. Eager, same as [sort] *) +(** Sort the sequence and remove duplicates. Eager, same as [sort] *) val group : ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t - (** Group equal consecutive elements. - @deprecated use {!group_succ_by} *) +(** Group equal consecutive elements. + @deprecated use {!group_succ_by} *) val group_succ_by : ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t - (** Group equal consecutive elements. - Synonym to {!group}. - @since NEXT_RELEASE *) +(** Group equal consecutive elements. + Synonym to {!group}. + @since NEXT_RELEASE *) 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. - @since NEXT_RELEASE *) + 'a t -> 'a list t +(** Group equal elements, disregarding their order of appearance. + The result sequence is traversable as many times as required. + @since NEXT_RELEASE *) val uniq : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t - (** Remove consecutive duplicate elements. Basically this is - like [fun seq -> map List.hd (group seq)]. *) +(** Remove consecutive duplicate elements. Basically this is + like [fun seq -> map List.hd (group seq)]. *) val product : 'a t -> 'b t -> ('a * 'b) t - (** Cartesian product of the sequences. When calling [product a b], - the caller {b MUST} ensure that [b] can be traversed as many times - as required (several times), possibly by calling {!persistent} on it - beforehand. *) +(** Cartesian product of the sequences. When calling [product a b], + the caller {b MUST} ensure that [b] can be traversed as many times + as required (several times), possibly by calling {!persistent} on it + beforehand. *) val product2 : 'a t -> 'b t -> ('a, 'b) t2 - (** Binary version of {!product}. Same requirements. - @since 0.5 *) +(** 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 - element of [b] using [join_row]. If [join_row] returns None, then - the two elements do not combine. Assume that [b] allows for multiple - iterations. *) +(** [join ~join_row a b] combines every element of [a] with every + element of [b] using [join_row]. If [join_row] returns None, then + the two elements do not combine. Assume that [b] allows for multiple + iterations. *) 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 - and unfoldr recurses with [b']. *) +(** [unfoldr f b] will apply [f] to [b]. If it + yields [Some (x,b')] then [x] is returned + and unfoldr recurses with [b']. *) val scan : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b t - (** Sequence of intermediate results *) +(** Sequence of intermediate results *) val max : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option - (** Max element of the sequence, using the given comparison function. - @return None if the sequence is empty, Some [m] where [m] is the maximal - element otherwise *) +(** Max element of the sequence, using the given comparison function. + @return None if the sequence is empty, Some [m] where [m] is the maximal + element otherwise *) 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. *) +(** Min element of the sequence, using the given comparison function. + see {!max} for more details. *) val head : 'a t -> 'a option - (** First element, if any, otherwise [None] - @since 0.5.1 *) +(** 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 - @since 0.5.1 *) +(** First element, if any, fails + @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 - sequences. *) +(** Take at most [n] elements from the sequence. Works on infinite + sequences. *) val take_while : ('a -> bool) -> 'a t -> 'a t - (** Take elements while they satisfy the predicate, then stops iterating. - Will work on an infinite sequence [s] if the predicate is false for at - least one element of [s]. *) +(** Take elements while they satisfy the predicate, then stops iterating. + Will work on an infinite sequence [s] if the predicate is false for at + least one element of [s]. *) val fold_while : ('a -> 'b -> 'a * [`Stop | `Continue]) -> 'a -> 'b t -> 'a - (** Folds over elements of the sequence, stopping early if the accumulator - returns [('a, `Stop)] - @since 0.5.5 *) +(** Folds over elements of the sequence, stopping early if the accumulator + returns [('a, `Stop)] + @since 0.5.5 *) val drop : int -> 'a t -> 'a t - (** Drop the [n] first elements of the sequence. Lazy. *) +(** Drop the [n] first elements of the sequence. Lazy. *) val drop_while : ('a -> bool) -> 'a t -> 'a t - (** Predicate version of {!drop} *) +(** Predicate version of {!drop} *) val rev : 'a t -> 'a t - (** Reverse the sequence. O(n) memory and time, needs the - sequence to be finite. The result is persistent and does - not depend on the input being repeatable. *) +(** Reverse the sequence. O(n) memory and time, needs the + sequence to be finite. The result is persistent and does + not depend on the input being repeatable. *) (** {2 Binary sequences} *) @@ -313,7 +291,7 @@ val zip : ('a, 'b) t2 -> ('a * 'b) t val unzip : ('a * 'b) t -> ('a, 'b) t2 val zip_i : 'a t -> (int, 'a) t2 - (** Zip elements of the sequence with their index in the sequence *) +(** Zip elements of the sequence with their index in the sequence *) val fold2 : ('c -> 'a -> 'b -> 'c) -> 'c -> ('a, 'b) t2 -> 'c @@ -322,17 +300,17 @@ val iter2 : ('a -> 'b -> unit) -> ('a, 'b) t2 -> unit val map2 : ('a -> 'b -> 'c) -> ('a, 'b) t2 -> 'c t val map2_2 : ('a -> 'b -> 'c) -> ('a -> 'b -> 'd) -> ('a, 'b) t2 -> ('c, 'd) t2 - (** [map2_2 f g seq2] maps each [x, y] of seq2 into [f x y, g x y] *) +(** [map2_2 f g seq2] maps each [x, y] of seq2 into [f x y, g x y] *) (** {2 Basic data structures converters} *) val to_list : 'a t -> 'a list - (** Convert the sequence into a list. Preserves order of elements. - This function is tail-recursive, but consumes 2*n memory. - If order doesn't matter to you, consider {!to_rev_list}. *) +(** Convert the sequence into a list. Preserves order of elements. + This function is tail-recursive, but consumes 2*n memory. + If order doesn't matter to you, consider {!to_rev_list}. *) val to_rev_list : 'a t -> 'a list - (** Get the list of the reversed sequence (more efficient than {!to_list}) *) +(** Get the list of the reversed sequence (more efficient than {!to_list}) *) val of_list : 'a list -> 'a t @@ -342,65 +320,65 @@ val on_list : ('a t -> 'b t) -> 'a list -> 'b list *) val to_opt : 'a t -> 'a option - (** Alias to {!head} - @since 0.5.1 *) +(** Alias to {!head} + @since 0.5.1 *) val to_array : 'a t -> 'a array - (** Convert to an array. Currently not very efficient because - an intermediate list is used. *) +(** Convert to an array. Currently not very efficient because + an intermediate list is used. *) val of_array : 'a array -> 'a t val of_array_i : 'a array -> (int * 'a) t - (** Elements of the array, with their index *) +(** Elements of the array, with their index *) val of_array2 : 'a array -> (int, 'a) t2 val array_slice : 'a array -> int -> int -> 'a t - (** [array_slice a i j] Sequence of elements whose indexes range - from [i] to [j] *) +(** [array_slice a i j] Sequence of elements whose indexes range + from [i] to [j] *) val of_opt : 'a option -> 'a t - (** Iterate on 0 or 1 values. - @since 0.5.1 *) +(** 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) *) +(** Sequence of elements of a stream (usable only once) *) val to_stream : 'a t -> 'a Stream.t - (** Convert to a stream. linear in memory and time (a copy is made in memory) *) +(** Convert to a stream. linear in memory and time (a copy is made in memory) *) val to_stack : 'a Stack.t -> 'a t -> unit - (** Push elements of the sequence on the stack *) +(** Push elements of the sequence on the stack *) val of_stack : 'a Stack.t -> 'a t - (** Sequence of elements of the stack (same order as [Stack.iter]) *) +(** Sequence of elements of the stack (same order as [Stack.iter]) *) val to_queue : 'a Queue.t -> 'a t -> unit - (** Push elements of the sequence into the queue *) +(** Push elements of the sequence into the queue *) val of_queue : 'a Queue.t -> 'a t - (** Sequence of elements contained in the queue, FIFO order *) +(** Sequence of elements contained in the queue, FIFO order *) val hashtbl_add : ('a, 'b) Hashtbl.t -> ('a * 'b) t -> unit - (** Add elements of the sequence to the hashtable, with - Hashtbl.add *) +(** Add elements of the sequence to the hashtable, with + Hashtbl.add *) val hashtbl_replace : ('a, 'b) Hashtbl.t -> ('a * 'b) t -> unit - (** Add elements of the sequence to the hashtable, with - Hashtbl.replace (erases conflicting bindings) *) +(** Add elements of the sequence to the hashtable, with + Hashtbl.replace (erases conflicting bindings) *) val to_hashtbl : ('a * 'b) t -> ('a, 'b) Hashtbl.t - (** Build a hashtable from a sequence of key/value pairs *) +(** Build a hashtable from a sequence of key/value pairs *) val to_hashtbl2 : ('a, 'b) t2 -> ('a, 'b) Hashtbl.t - (** Build a hashtable from a sequence of key/value pairs *) +(** Build a hashtable from a sequence of key/value pairs *) val of_hashtbl : ('a, 'b) Hashtbl.t -> ('a * 'b) t - (** Sequence of key/value pairs from the hashtable *) +(** Sequence of key/value pairs from the hashtable *) val of_hashtbl2 : ('a, 'b) Hashtbl.t -> ('a, 'b) t2 - (** Sequence of key/value pairs from the hashtable *) +(** Sequence of key/value pairs from the hashtable *) val hashtbl_keys : ('a, 'b) Hashtbl.t -> 'a t val hashtbl_values : ('a, 'b) Hashtbl.t -> 'b t @@ -409,55 +387,55 @@ val of_str : string -> char t val to_str : char t -> string val concat_str : string t -> string - (** Concatenate strings together, eagerly. - Also see {!intersperse} to add a separator. - @since 0.5 *) +(** Concatenate strings together, eagerly. + Also see {!intersperse} to add a separator. + @since 0.5 *) exception OneShotSequence - (** Raised when the user tries to iterate several times on - a transient iterator *) +(** Raised when the user tries to iterate several times on + a transient iterator *) val of_in_channel : in_channel -> char t - (** Iterates on characters of the input (can block when one - iterates over the sequence). If you need to iterate - several times on this sequence, use {!persistent}. - @raise OneShotSequence when used more than once. *) +(** Iterates on characters of the input (can block when one + iterates over the sequence). If you need to iterate + several times on this sequence, use {!persistent}. + @raise OneShotSequence when used more than once. *) val to_buffer : char t -> Buffer.t -> unit - (** Copy content of the sequence into the buffer *) +(** Copy content of the sequence into the buffer *) val int_range : start:int -> stop:int -> int t - (** Iterator on integers in [start...stop] by steps 1. Also see - {!(--)} for an infix version. *) +(** Iterator on integers in [start...stop] by steps 1. Also see + {!(--)} for an infix version. *) val int_range_dec : start:int -> stop:int -> int t - (** Iterator on decreasing integers in [stop...start] by steps -1. - See {!(--^)} for an infix version *) +(** Iterator on decreasing integers in [stop...start] by steps -1. + See {!(--^)} for an infix version *) val bools : bool t - (** Iterates on [true] and [false] - @since NEXT_RELEASE *) +(** Iterates on [true] and [false] + @since NEXT_RELEASE *) val of_set : (module Set.S with type elt = 'a and type t = 'b) -> 'b -> 'a t - (** Convert the given set to a sequence. The set module must be provided. *) +(** Convert the given set to a sequence. The set module must be provided. *) val to_set : (module Set.S with type elt = 'a and type t = 'b) -> 'a t -> 'b - (** Convert the sequence to a set, given the proper set module *) +(** Convert the sequence to a set, given the proper set module *) type 'a gen = unit -> 'a option type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist] val of_gen : 'a gen -> 'a t - (** Traverse eagerly the generator and build a sequence from it *) +(** Traverse eagerly the generator and build a sequence from it *) val to_gen : 'a t -> 'a gen - (** Make the sequence persistent (O(n)) and then iterate on it. Eager. *) +(** Make the sequence persistent (O(n)) and then iterate on it. Eager. *) val of_klist : 'a klist -> 'a t - (** Iterate on the lazy list *) +(** Iterate on the lazy list *) val to_klist : 'a t -> 'a klist - (** Make the sequence persistent and then iterate on it. Eager. *) +(** Make the sequence persistent and then iterate on it. Eager. *) (** {2 Functorial conversions between sets and sequences} *) @@ -500,48 +478,48 @@ end (** {2 Infinite sequences of random values} *) val random_int : int -> int t - (** Infinite sequence of random integers between 0 and - the given higher bound (see Random.int) *) +(** Infinite sequence of random integers between 0 and + the given higher bound (see Random.int) *) val random_bool : bool t - (** Infinite sequence of random bool values *) +(** Infinite sequence of random bool values *) val random_float : float -> float t val random_array : 'a array -> 'a t - (** Sequence of choices of an element in the array *) +(** Sequence of choices of an element in the array *) val random_list : 'a list -> 'a t - (** Infinite sequence of random elements of the list. Basically the - same as {!random_array}. *) +(** Infinite sequence of random elements of the list. Basically the + same as {!random_array}. *) (** {2 Infix functions} *) module Infix : sig val (--) : int -> int -> int t - (** [a -- b] is the range of integers from [a] to [b], both included, - in increasing order. It will therefore be empty if [a > b]. *) + (** [a -- b] is the range of integers from [a] to [b], both included, + in increasing order. It will therefore be empty if [a > b]. *) val (--^) : int -> int -> int t - (** [a --^ b] is the range of integers from [b] to [a], both included, - in decreasing order (starts from [a]). - It will therefore be empty if [a < b]. *) + (** [a --^ b] is the range of integers from [b] to [a], both included, + in decreasing order (starts from [a]). + It will therefore be empty if [a < b]. *) val (>>=) : 'a t -> ('a -> 'b t) -> 'b t - (** Monadic bind (infix version of {!flat_map} - @since 0.5 *) + (** Monadic bind (infix version of {!flat_map} + @since 0.5 *) val (>|=) : 'a t -> ('a -> 'b) -> 'b t - (** Infix version of {!map} - @since 0.5 *) + (** Infix version of {!map} + @since 0.5 *) val (<*>) : ('a -> 'b) t -> 'a t -> 'b t - (** Applicative operator (product+application) - @since 0.5 *) + (** Applicative operator (product+application) + @since 0.5 *) val (<+>) : 'a t -> 'a t -> 'a t - (** Concatenation of sequences - @since 0.5 *) + (** Concatenation of sequences + @since 0.5 *) end include module type of Infix @@ -549,46 +527,46 @@ include module type of Infix (** {2 Pretty printing of sequences} *) val pp_seq : ?sep:string -> (Format.formatter -> 'a -> unit) -> - Format.formatter -> 'a t -> unit - (** Pretty print a sequence of ['a], using the given pretty printer - to print each elements. An optional separator string can be provided. *) + Format.formatter -> 'a t -> unit +(** Pretty print a sequence of ['a], using the given pretty printer + to print each elements. An optional separator string can be provided. *) val pp_buf : ?sep:string -> (Buffer.t -> 'a -> unit) -> - Buffer.t -> 'a t -> unit - (** Print into a buffer *) + Buffer.t -> 'a t -> unit +(** Print into a buffer *) val to_string : ?sep:string -> ('a -> string) -> 'a t -> string - (** Print into a string *) +(** Print into a string *) (** {2 Basic IO} -Very basic interface to manipulate files as sequence of chunks/lines. The -sequences take care of opening and closing files properly; every time -one iterates over a sequence, the file is opened/closed again. + Very basic interface to manipulate files as sequence of chunks/lines. The + sequences take care of opening and closing files properly; every time + one iterates over a sequence, the file is opened/closed again. -Example: copy a file ["a"] into file ["b"], removing blank lines: + Example: copy a file ["a"] into file ["b"], removing blank lines: -{[ - Sequence.(IO.lines_of "a" |> filter (fun l-> l<> "") |> IO.write_lines "b");; -]} + {[ + Sequence.(IO.lines_of "a" |> filter (fun l-> l<> "") |> IO.write_lines "b");; + ]} -By chunks of [4096] bytes: + By chunks of [4096] bytes: -{[ - Sequence.IO.(chunks_of ~size:4096 "a" |> write_to "b");; -]} + {[ + Sequence.IO.(chunks_of ~size:4096 "a" |> write_to "b");; + ]} -Read the lines of a file into a list: + Read the lines of a file into a list: -{[ - Sequence.IO.lines "a" |> Sequence.to_list -]} + {[ + Sequence.IO.lines "a" |> Sequence.to_list + ]} -@since 0.5.1 *) + @since 0.5.1 *) module IO : sig val lines_of : ?mode:int -> ?flags:open_flag list -> - string -> string t + string -> string t (** [lines_of filename] reads all lines of the given file. It raises the same exception as would opening the file and read from it, except from [End_of_file] (which is caught). The file is {b always} properly @@ -599,28 +577,28 @@ module IO : sig @param flags default: [[Open_rdonly]] *) val chunks_of : ?mode:int -> ?flags:open_flag list -> ?size:int -> - string -> string t + string -> string t (** Read chunks of the given [size] from the file. The last chunk might be smaller. Behaves like {!lines_of} regarding errors and options. Every time the sequence is iterated on, the file is opened again, so different iterations might return different results *) val write_to : ?mode:int -> ?flags:open_flag list -> - string -> string t -> unit + string -> string t -> unit (** [write_to filename seq] writes all strings from [seq] into the given file. It takes care of opening and closing the file. @param mode default [0o644] @param flags used by [open_out_gen]. Default: [[Open_creat;Open_wronly]]. *) val write_bytes_to : ?mode:int -> ?flags:open_flag list -> - string -> Bytes.t t -> unit + string -> Bytes.t t -> unit (** @since 0.5.4 *) val write_lines : ?mode:int -> ?flags:open_flag list -> - string -> string t -> unit + string -> string t -> unit (** Same as {!write_to}, but intercales ['\n'] between each string *) val write_bytes_lines : ?mode:int -> ?flags:open_flag list -> - string -> Bytes.t t -> unit + string -> Bytes.t t -> unit (** @since 0.5.4 *) end diff --git a/sequenceLabels.mli b/sequenceLabels.mli index ca4bf90..08f9a71 100644 --- a/sequenceLabels.mli +++ b/sequenceLabels.mli @@ -1,263 +1,239 @@ -(* -copyright (c) 2013, simon cruanes -all rights reserved. -redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: +(* This file is free software, part of sequence. See file "license" for more details. *) -redistributions of source code must retain the above copyright notice, this -list of conditions and the following disclaimer. redistributions in binary -form must reproduce the above copyright notice, this list of conditions and the -following disclaimer in the documentation and/or other materials provided with -the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*) (** {1 Simple and Efficient Iterators} -Version of {!Sequence} with labels + Version of {!Sequence} with labels -@since 0.5.5 *) + @since 0.5.5 *) type +'a t = ('a -> unit) -> unit - (** A sequence of values of type ['a]. If you give it a function ['a -> unit] - it will be applied to every element of the sequence successively. *) +(** A sequence of values of type ['a]. If you give it a function ['a -> unit] + it will be applied to every element of the sequence successively. *) type +'a sequence = 'a t type (+'a, +'b) t2 = ('a -> 'b -> unit) -> unit - (** Sequence of pairs of values of type ['a] and ['b]. *) +(** Sequence of pairs of values of type ['a] and ['b]. *) (** {2 Build a sequence} *) val from_iter : (('a -> unit) -> unit) -> 'a t - (** Build a sequence from a iter function *) +(** Build a sequence from a iter function *) val from_fun : (unit -> 'a option) -> 'a t - (** Call the function repeatedly until it returns None. This - sequence is transient, use {!persistent} if needed! *) +(** Call the function repeatedly until it returns None. This + sequence is transient, use {!persistent} if needed! *) val empty : 'a t - (** Empty sequence. It contains no element. *) +(** Empty sequence. It contains no element. *) val singleton : 'a -> 'a t - (** Singleton sequence, with exactly one element. *) +(** Singleton sequence, with exactly one element. *) val doubleton : 'a -> 'a -> 'a t - (** Sequence with exactly two elements *) +(** Sequence with exactly two elements *) val cons : 'a -> 'a t -> 'a t - (** [cons x l] yields [x], then yields from [l]. - Same as [append (singleton x) l] *) +(** [cons x l] yields [x], then yields from [l]. + Same as [append (singleton x) l] *) val snoc : 'a t -> 'a -> 'a t - (** Same as {!cons} but yields the element after iterating on [l] *) +(** Same as {!cons} but yields the element after iterating on [l] *) val return : 'a -> 'a t - (** Synonym to {!singleton} *) +(** Synonym to {!singleton} *) val pure : 'a -> 'a t - (** Synonym to {!singleton} *) +(** Synonym to {!singleton} *) val repeat : 'a -> 'a t - (** Infinite sequence of the same element. You may want to look - at {!take} and the likes if you iterate on it. *) +(** Infinite sequence of the same element. You may want to look + at {!take} and the likes if you iterate on it. *) val iterate : ('a -> 'a) -> 'a -> 'a t - (** [iterate f x] is the infinite sequence [x, f(x), f(f(x)), ...] *) +(** [iterate f x] is the infinite sequence [x, f(x), f(f(x)), ...] *) val forever : (unit -> 'b) -> 'b t - (** Sequence that calls the given function to produce elements. - The sequence may be transient (depending on the function), and definitely - is infinite. You may want to use {!take} and {!persistent}. *) +(** Sequence that calls the given function to produce elements. + The sequence may be transient (depending on the function), and definitely + is infinite. You may want to use {!take} and {!persistent}. *) val cycle : 'a t -> 'a t - (** Cycle forever through the given sequence. Assume the given sequence can - be traversed any amount of times (not transient). This yields an - infinite sequence, you should use something like {!take} not to loop - forever. *) +(** Cycle forever through the given sequence. Assume the given sequence can + be traversed any amount of times (not transient). This yields an + infinite sequence, you should use something like {!take} not to loop + forever. *) (** {2 Consume a sequence} *) val iter : f:('a -> unit) -> 'a t -> unit - (** Consume the sequence, passing all its arguments to the function. - Basically [iter f seq] is just [seq f]. *) +(** Consume the sequence, passing all its arguments to the function. + Basically [iter f seq] is just [seq f]. *) val iteri : f:(int -> 'a -> unit) -> 'a t -> unit - (** Iterate on elements and their index in the sequence *) +(** Iterate on elements and their index in the sequence *) val fold : f:('a -> 'b -> 'a) -> init:'a -> 'b t -> 'a - (** Fold over elements of the sequence, consuming it *) +(** Fold over elements of the sequence, consuming it *) val foldi : f:('a -> int -> 'b -> 'a) -> init:'a -> 'b t -> 'a - (** Fold over elements of the sequence and their index, consuming it *) +(** Fold over elements of the sequence and their index, consuming it *) val map : f:('a -> 'b) -> 'a t -> 'b t - (** Map objects of the sequence into other elements, lazily *) +(** Map objects of the sequence into other elements, lazily *) val mapi : f:(int -> 'a -> 'b) -> 'a t -> 'b t - (** Map objects, along with their index in the sequence *) +(** Map objects, along with their index in the sequence *) val for_all : f:('a -> bool) -> 'a t -> bool - (** Do all elements satisfy the predicate? *) +(** Do all elements satisfy the predicate? *) val exists : f:('a -> bool) -> 'a t -> bool - (** Exists there some element satisfying the predicate? *) +(** Exists there some element satisfying the predicate? *) 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 [(=)]) *) +(** Is the value a member of the sequence? + @param eq the equality predicate to use (default [(=)]) *) val find : f:('a -> 'b option) -> 'a t -> 'b option - (** Find the first element on which the function doesn't return [None] *) +(** Find the first element on which the function doesn't return [None] *) val length : 'a t -> int - (** How long is the sequence? Forces the sequence. *) +(** How long is the sequence? Forces the sequence. *) val is_empty : 'a t -> bool - (** Is the sequence empty? Forces the sequence. *) +(** Is the sequence empty? Forces the sequence. *) (** {2 Transform a sequence} *) val filter : f:('a -> bool) -> 'a t -> 'a t - (** Filter on elements of the sequence *) +(** Filter on elements of the sequence *) 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. *) +(** Append two sequences. Iterating on the result is like iterating + on the first, then on the second. *) val concat : 'a t t -> 'a t - (** Concatenate a sequence of sequences into one sequence. *) +(** Concatenate a sequence of sequences into one sequence. *) val flatten : 'a t t -> 'a t - (** Alias for {!concat} *) +(** Alias for {!concat} *) val flatMap : f:('a -> 'b t) -> 'a t -> 'b t - (** Monadic bind. Intuitively, it applies the function to every element of the - initial sequence, and calls {!concat}. - @deprecated use {!flat_map} *) +(** @deprecated use {!flat_map} *) val flat_map : f:('a -> 'b t) -> 'a t -> 'b t - (** Alias to {!flatMap} with a more explicit name *) +(** Alias to {!flatMap} with a more explicit name *) val fmap : f:('a -> 'b option) -> 'a t -> 'b t - (** Specialized version of {!flatMap} for options. - @deprecated use {!filter_map} *) +(** @deprecated use {!filter_map} *) val filter_map : f:('a -> 'b option) -> 'a t -> 'b t - (** Alias to {!fmap} with a more explicit name *) +(** Alias to {!fmap} with a more explicit name *) val intersperse : x:'a -> 'a t -> 'a t - (** Insert the single element between every element of the sequence *) +(** Insert the single element between every element of the sequence *) (** {2 Caching} *) val persistent : 'a t -> 'a t - (** Iterate on the sequence, storing elements in an efficient internal structure.. - The resulting sequence can be iterated on as many times as needed. - {b Note}: calling persistent on an already persistent sequence - will still make a new copy of the sequence! *) +(** Iterate on the sequence, storing elements in an efficient internal structure.. + The resulting sequence can be iterated on as many times as needed. + {b Note}: calling persistent on an already persistent sequence + will still make a new copy of the sequence! *) val persistent_lazy : 'a t -> 'a t - (** Lazy version of {!persistent}. When calling [persistent_lazy s], - a new sequence [s'] is immediately returned (without actually consuming - [s]) in constant time; the first time [s'] is iterated on, - it also consumes [s] and caches its content into a inner data - structure that will back [s'] for future iterations. +(** Lazy version of {!persistent}. When calling [persistent_lazy s], + a new sequence [s'] is immediately returned (without actually consuming + [s]) in constant time; the first time [s'] is iterated on, + it also consumes [s] and caches its content into a inner data + structure that will back [s'] for future iterations. - {b warning}: on the first traversal of [s'], if the traversal - is interrupted prematurely ({!take}, etc.) then [s'] will not be - memorized, and the next call to [s'] will traverse [s] again. *) + {b warning}: on the first traversal of [s'], if the traversal + is interrupted prematurely ({!take}, etc.) then [s'] will not be + memorized, and the next call to [s'] will traverse [s] again. *) (** {2 Misc} *) val sort : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t - (** Sort the sequence. Eager, O(n) ram and O(n ln(n)) time. - It iterates on elements of the argument sequence immediately, - before it sorts them. *) +(** Sort the sequence. Eager, O(n) ram and O(n ln(n)) time. + It iterates on elements of the argument sequence immediately, + before it sorts them. *) val sort_uniq : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t - (** Sort the sequence and remove duplicates. Eager, same as [sort] *) +(** Sort the sequence and remove duplicates. Eager, same as [sort] *) val group : ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t - (** Group equal consecutive elements. *) +(** Group equal consecutive elements. *) val uniq : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t - (** Remove consecutive duplicate elements. Basically this is - like [fun seq -> map List.hd (group seq)]. *) +(** Remove consecutive duplicate elements. Basically this is + like [fun seq -> map List.hd (group seq)]. *) val product : 'a t -> 'b t -> ('a * 'b) t - (** Cartesian product of the sequences. When calling [product a b], - the caller {b MUST} ensure that [b] can be traversed as many times - as required (several times), possibly by calling {!persistent} on it - beforehand. *) +(** Cartesian product of the sequences. When calling [product a b], + the caller {b MUST} ensure that [b] can be traversed as many times + as required (several times), possibly by calling {!persistent} on it + beforehand. *) val product2 : 'a t -> 'b t -> ('a, 'b) t2 - (** Binary version of {!product}. Same requirements. *) +(** Binary version of {!product}. Same requirements. *) 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 - element of [b] using [join_row]. If [join_row] returns None, then - the two elements do not combine. Assume that [b] allows for multiple - iterations. *) +(** [join ~join_row a b] combines every element of [a] with every + element of [b] using [join_row]. If [join_row] returns None, then + the two elements do not combine. Assume that [b] allows for multiple + iterations. *) 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 - and unfoldr recurses with [b']. *) +(** [unfoldr f b] will apply [f] to [b]. If it + yields [Some (x,b')] then [x] is returned + and unfoldr recurses with [b']. *) val scan : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b t - (** Sequence of intermediate results *) +(** Sequence of intermediate results *) val max : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option - (** Max element of the sequence, using the given comparison function. - @return None if the sequence is empty, Some [m] where [m] is the maximal - element otherwise *) +(** Max element of the sequence, using the given comparison function. + @return None if the sequence is empty, Some [m] where [m] is the maximal + element otherwise *) 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. *) +(** Min element of the sequence, using the given comparison function. + see {!max} for more details. *) val head : 'a t -> 'a option - (** First element, if any, otherwise [None] *) +(** First element, if any, otherwise [None] *) val head_exn : 'a t -> 'a - (** First element, if any, fails - @raise Invalid_argument if the sequence is empty *) +(** First element, if any, fails + @raise Invalid_argument if the sequence is empty *) val take : int -> 'a t -> 'a t - (** Take at most [n] elements from the sequence. Works on infinite - sequences. *) +(** Take at most [n] elements from the sequence. Works on infinite + sequences. *) val take_while : f:('a -> bool) -> 'a t -> 'a t - (** Take elements while they satisfy the predicate, then stops iterating. - Will work on an infinite sequence [s] if the predicate is false for at - least one element of [s]. *) +(** Take elements while they satisfy the predicate, then stops iterating. + Will work on an infinite sequence [s] if the predicate is false for at + least one element of [s]. *) 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)] *) +(** Folds over elements of the sequence, stopping early if the accumulator + returns [('a, `Stop)] *) val drop : int -> 'a t -> 'a t - (** Drop the [n] first elements of the sequence. Lazy. *) +(** Drop the [n] first elements of the sequence. Lazy. *) val drop_while : f:('a -> bool) -> 'a t -> 'a t - (** Predicate version of {!drop} *) +(** Predicate version of {!drop} *) val rev : 'a t -> 'a t - (** Reverse the sequence. O(n) memory and time, needs the - sequence to be finite. The result is persistent and does - not depend on the input being repeatable. *) +(** Reverse the sequence. O(n) memory and time, needs the + sequence to be finite. The result is persistent and does + not depend on the input being repeatable. *) (** {2 Binary sequences} *) @@ -272,7 +248,7 @@ val zip : ('a, 'b) t2 -> ('a * 'b) t val unzip : ('a * 'b) t -> ('a, 'b) t2 val zip_i : 'a t -> (int, 'a) t2 - (** Zip elements of the sequence with their index in the sequence *) +(** Zip elements of the sequence with their index in the sequence *) val fold2 : f:('c -> 'a -> 'b -> 'c) -> init:'c -> ('a, 'b) t2 -> 'c @@ -281,17 +257,17 @@ val iter2 : f:('a -> 'b -> unit) -> ('a, 'b) t2 -> unit val map2 : f:('a -> 'b -> 'c) -> ('a, 'b) t2 -> 'c t val map2_2 : ('a -> 'b -> 'c) -> ('a -> 'b -> 'd) -> ('a, 'b) t2 -> ('c, 'd) t2 - (** [map2_2 f g seq2] maps each [x, y] of seq2 into [f x y, g x y] *) +(** [map2_2 f g seq2] maps each [x, y] of seq2 into [f x y, g x y] *) (** {2 Basic data structures converters} *) val to_list : 'a t -> 'a list - (** Convert the sequence into a list. Preserves order of elements. - This function is tail-recursive, but consumes 2*n memory. - If order doesn't matter to you, consider {!to_rev_list}. *) +(** Convert the sequence into a list. Preserves order of elements. + This function is tail-recursive, but consumes 2*n memory. + If order doesn't matter to you, consider {!to_rev_list}. *) val to_rev_list : 'a t -> 'a list - (** Get the list of the reversed sequence (more efficient than {!to_list}) *) +(** Get the list of the reversed sequence (more efficient than {!to_list}) *) val of_list : 'a list -> 'a t @@ -299,63 +275,63 @@ val on_list : ('a t -> 'b t) -> 'a list -> 'b list (** [on_list f l] is equivalent to [to_list @@ f @@ of_list l]. *) val to_opt : 'a t -> 'a option - (** Alias to {!head} *) +(** Alias to {!head} *) val to_array : 'a t -> 'a array - (** Convert to an array. Currently not very efficient because - an intermediate list is used. *) +(** Convert to an array. Currently not very efficient because + an intermediate list is used. *) val of_array : 'a array -> 'a t val of_array_i : 'a array -> (int * 'a) t - (** Elements of the array, with their index *) +(** Elements of the array, with their index *) val of_array2 : 'a array -> (int, 'a) t2 val array_slice : 'a array -> int -> int -> 'a t - (** [array_slice a i j] Sequence of elements whose indexes range - from [i] to [j] *) +(** [array_slice a i j] Sequence of elements whose indexes range + from [i] to [j] *) val of_opt : 'a option -> 'a t - (** Iterate on 0 or 1 values. *) +(** Iterate on 0 or 1 values. *) val of_stream : 'a Stream.t -> 'a t - (** Sequence of elements of a stream (usable only once) *) +(** Sequence of elements of a stream (usable only once) *) val to_stream : 'a t -> 'a Stream.t - (** Convert to a stream. linear in memory and time (a copy is made in memory) *) +(** Convert to a stream. linear in memory and time (a copy is made in memory) *) val to_stack : 'a Stack.t -> 'a t -> unit - (** Push elements of the sequence on the stack *) +(** Push elements of the sequence on the stack *) val of_stack : 'a Stack.t -> 'a t - (** Sequence of elements of the stack (same order as [Stack.iter]) *) +(** Sequence of elements of the stack (same order as [Stack.iter]) *) val to_queue : 'a Queue.t -> 'a t -> unit - (** Push elements of the sequence into the queue *) +(** Push elements of the sequence into the queue *) val of_queue : 'a Queue.t -> 'a t - (** Sequence of elements contained in the queue, FIFO order *) +(** Sequence of elements contained in the queue, FIFO order *) val hashtbl_add : ('a, 'b) Hashtbl.t -> ('a * 'b) t -> unit - (** Add elements of the sequence to the hashtable, with - Hashtbl.add *) +(** Add elements of the sequence to the hashtable, with + Hashtbl.add *) val hashtbl_replace : ('a, 'b) Hashtbl.t -> ('a * 'b) t -> unit - (** Add elements of the sequence to the hashtable, with - Hashtbl.replace (erases conflicting bindings) *) +(** Add elements of the sequence to the hashtable, with + Hashtbl.replace (erases conflicting bindings) *) val to_hashtbl : ('a * 'b) t -> ('a, 'b) Hashtbl.t - (** Build a hashtable from a sequence of key/value pairs *) +(** Build a hashtable from a sequence of key/value pairs *) val to_hashtbl2 : ('a, 'b) t2 -> ('a, 'b) Hashtbl.t - (** Build a hashtable from a sequence of key/value pairs *) +(** Build a hashtable from a sequence of key/value pairs *) val of_hashtbl : ('a, 'b) Hashtbl.t -> ('a * 'b) t - (** Sequence of key/value pairs from the hashtable *) +(** Sequence of key/value pairs from the hashtable *) val of_hashtbl2 : ('a, 'b) Hashtbl.t -> ('a, 'b) t2 - (** Sequence of key/value pairs from the hashtable *) +(** Sequence of key/value pairs from the hashtable *) val hashtbl_keys : ('a, 'b) Hashtbl.t -> 'a t val hashtbl_values : ('a, 'b) Hashtbl.t -> 'b t @@ -364,50 +340,50 @@ val of_str : string -> char t val to_str : char t -> string val concat_str : string t -> string - (** Concatenate strings together, eagerly. - Also see {!intersperse} to add a separator. *) +(** Concatenate strings together, eagerly. + Also see {!intersperse} to add a separator. *) exception OneShotSequence - (** Raised when the user tries to iterate several times on - a transient iterator *) +(** Raised when the user tries to iterate several times on + a transient iterator *) val of_in_channel : in_channel -> char t - (** Iterates on characters of the input (can block when one - iterates over the sequence). If you need to iterate - several times on this sequence, use {!persistent}. - @raise OneShotSequence when used more than once. *) +(** Iterates on characters of the input (can block when one + iterates over the sequence). If you need to iterate + several times on this sequence, use {!persistent}. + @raise OneShotSequence when used more than once. *) val to_buffer : char t -> Buffer.t -> unit - (** Copy content of the sequence into the buffer *) +(** Copy content of the sequence into the buffer *) val int_range : start:int -> stop:int -> int t - (** Iterator on integers in [start...stop] by steps 1. Also see - {!(--)} for an infix version. *) +(** Iterator on integers in [start...stop] by steps 1. Also see + {!(--)} for an infix version. *) val int_range_dec : start:int -> stop:int -> int t - (** Iterator on decreasing integers in [stop...start] by steps -1. - See {!(--^)} for an infix version *) +(** Iterator on decreasing integers in [stop...start] by steps -1. + See {!(--^)} for an infix version *) val of_set : (module Set.S with type elt = 'a and type t = 'b) -> 'b -> 'a t - (** Convert the given set to a sequence. The set module must be provided. *) +(** Convert the given set to a sequence. The set module must be provided. *) val to_set : (module Set.S with type elt = 'a and type t = 'b) -> 'a t -> 'b - (** Convert the sequence to a set, given the proper set module *) +(** Convert the sequence to a set, given the proper set module *) type 'a gen = unit -> 'a option type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist] val of_gen : 'a gen -> 'a t - (** Traverse eagerly the generator and build a sequence from it *) +(** Traverse eagerly the generator and build a sequence from it *) val to_gen : 'a t -> 'a gen - (** Make the sequence persistent (O(n)) and then iterate on it. Eager. *) +(** Make the sequence persistent (O(n)) and then iterate on it. Eager. *) val of_klist : 'a klist -> 'a t - (** Iterate on the lazy list *) +(** Iterate on the lazy list *) val to_klist : 'a t -> 'a klist - (** Make the sequence persistent and then iterate on it. Eager. *) +(** Make the sequence persistent and then iterate on it. Eager. *) (** {2 Functorial conversions between sets and sequences} *) @@ -450,44 +426,44 @@ end (** {2 Infinite sequences of random values} *) val random_int : int -> int t - (** Infinite sequence of random integers between 0 and - the given higher bound (see Random.int) *) +(** Infinite sequence of random integers between 0 and + the given higher bound (see Random.int) *) val random_bool : bool t - (** Infinite sequence of random bool values *) +(** Infinite sequence of random bool values *) val random_float : float -> float t val random_array : 'a array -> 'a t - (** Sequence of choices of an element in the array *) +(** Sequence of choices of an element in the array *) val random_list : 'a list -> 'a t - (** Infinite sequence of random elements of the list. Basically the - same as {!random_array}. *) +(** Infinite sequence of random elements of the list. Basically the + same as {!random_array}. *) (** {2 Infix functions} *) module Infix : sig val (--) : int -> int -> int t - (** [a -- b] is the range of integers from [a] to [b], both included, - in increasing order. It will therefore be empty if [a > b]. *) + (** [a -- b] is the range of integers from [a] to [b], both included, + in increasing order. It will therefore be empty if [a > b]. *) val (--^) : int -> int -> int t - (** [a --^ b] is the range of integers from [b] to [a], both included, - in decreasing order (starts from [a]). - It will therefore be empty if [a < b]. *) + (** [a --^ b] is the range of integers from [b] to [a], both included, + in decreasing order (starts from [a]). + 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} *) val (>|=) : 'a t -> ('a -> 'b) -> 'b t - (** Infix version of {!map} *) + (** Infix version of {!map} *) val (<*>) : ('a -> 'b) t -> 'a t -> 'b t - (** Applicative operator (product+application) *) + (** Applicative operator (product+application) *) val (<+>) : 'a t -> 'a t -> 'a t - (** Concatenation of sequences *) + (** Concatenation of sequences *) end include module type of Infix @@ -496,46 +472,46 @@ include module type of Infix (** {2 Pretty printing of sequences} *) val pp_seq : ?sep:string -> (Format.formatter -> 'a -> unit) -> - Format.formatter -> 'a t -> unit - (** Pretty print a sequence of ['a], using the given pretty printer - to print each elements. An optional separator string can be provided. *) + Format.formatter -> 'a t -> unit +(** Pretty print a sequence of ['a], using the given pretty printer + to print each elements. An optional separator string can be provided. *) val pp_buf : ?sep:string -> (Buffer.t -> 'a -> unit) -> - Buffer.t -> 'a t -> unit - (** Print into a buffer *) + Buffer.t -> 'a t -> unit +(** Print into a buffer *) val to_string : ?sep:string -> ('a -> string) -> 'a t -> string - (** Print into a string *) +(** Print into a string *) (** {2 Basic IO} -Very basic interface to manipulate files as sequence of chunks/lines. The -sequences take care of opening and closing files properly; every time -one iterates over a sequence, the file is opened/closed again. + Very basic interface to manipulate files as sequence of chunks/lines. The + sequences take care of opening and closing files properly; every time + one iterates over a sequence, the file is opened/closed again. -Example: copy a file ["a"] into file ["b"], removing blank lines: + Example: copy a file ["a"] into file ["b"], removing blank lines: -{[ - Sequence.(IO.lines_of "a" |> filter (fun l-> l<> "") |> IO.write_lines "b");; -]} + {[ + Sequence.(IO.lines_of "a" |> filter (fun l-> l<> "") |> IO.write_lines "b");; + ]} -By chunks of [4096] bytes: + By chunks of [4096] bytes: -{[ - Sequence.IO.(chunks_of ~size:4096 "a" |> write_to "b");; -]} + {[ + Sequence.IO.(chunks_of ~size:4096 "a" |> write_to "b");; + ]} -Read the lines of a file into a list: + Read the lines of a file into a list: -{[ - Sequence.IO.lines "a" |> Sequence.to_list -]} + {[ + Sequence.IO.lines "a" |> Sequence.to_list + ]} *) module IO : sig val lines_of : ?mode:int -> ?flags:open_flag list -> - string -> string t + string -> string t (** [lines_of filename] reads all lines of the given file. It raises the same exception as would opening the file and read from it, except from [End_of_file] (which is caught). The file is {b always} properly @@ -546,27 +522,27 @@ module IO : sig @param flags default: [[Open_rdonly]] *) val chunks_of : ?mode:int -> ?flags:open_flag list -> ?size:int -> - string -> string t + string -> string t (** Read chunks of the given [size] from the file. The last chunk might be smaller. Behaves like {!lines_of} regarding errors and options. Every time the sequence is iterated on, the file is opened again, so different iterations might return different results *) val write_to : ?mode:int -> ?flags:open_flag list -> - string -> string t -> unit + string -> string t -> unit (** [write_to filename seq] writes all strings from [seq] into the given file. It takes care of opening and closing the file. @param mode default [0o644] @param flags used by [open_out_gen]. Default: [[Open_creat;Open_wronly]]. *) val write_bytes_to : ?mode:int -> ?flags:open_flag list -> - string -> Bytes.t t -> unit + string -> Bytes.t t -> unit (** *) val write_lines : ?mode:int -> ?flags:open_flag list -> - string -> string t -> unit + string -> string t -> unit (** Same as {!write_to}, but intercales ['\n'] between each string *) val write_bytes_lines : ?mode:int -> ?flags:open_flag list -> - string -> Bytes.t t -> unit + string -> Bytes.t t -> unit end