mirror of
https://github.com/c-cube/iter.git
synced 2025-12-06 03:05:29 -05:00
style and license headers
This commit is contained in:
parent
ae1932fba4
commit
117755aa33
4 changed files with 519 additions and 594 deletions
2
LICENSE
2
LICENSE
|
|
@ -1,4 +1,4 @@
|
||||||
Copyright (c) 2012, Simon Cruanes
|
Copyright (c) 2012-2016, Simon Cruanes
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
|
|
||||||
251
sequence.ml
251
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
|
(* This file is free software, part of sequence. See file "license" for more details. *)
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice, this
|
(** {1 Simple and Efficient Iterators} *)
|
||||||
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.} *)
|
|
||||||
|
|
||||||
(** Sequence abstract iterator type *)
|
(** Sequence abstract iterator type *)
|
||||||
type 'a t = ('a -> unit) -> unit
|
type 'a t = ('a -> unit) -> unit
|
||||||
|
|
@ -31,7 +9,7 @@ type 'a t = ('a -> unit) -> unit
|
||||||
type 'a sequence = 'a t
|
type 'a sequence = 'a t
|
||||||
|
|
||||||
type (+'a, +'b) t2 = ('a -> 'b -> unit) -> unit
|
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 *)
|
(** Build a sequence from a iter function *)
|
||||||
let from_iter f = f
|
let from_iter f = f
|
||||||
|
|
@ -69,8 +47,8 @@ let iteri f seq =
|
||||||
let r = ref 0 in
|
let r = ref 0 in
|
||||||
seq
|
seq
|
||||||
(fun x ->
|
(fun x ->
|
||||||
f !r x;
|
f !r x;
|
||||||
incr r)
|
incr r)
|
||||||
|
|
||||||
let fold f init seq =
|
let fold f init seq =
|
||||||
let r = ref init in
|
let r = ref init in
|
||||||
|
|
@ -82,8 +60,8 @@ let foldi f init seq =
|
||||||
let r = ref init in
|
let r = ref init in
|
||||||
seq
|
seq
|
||||||
(fun elt ->
|
(fun elt ->
|
||||||
r := f !r !i elt;
|
r := f !r !i elt;
|
||||||
incr i);
|
incr i);
|
||||||
!r
|
!r
|
||||||
|
|
||||||
let map f seq k = seq (fun x -> k (f x))
|
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
|
seq (fun x -> match f x with
|
||||||
| None -> ()
|
| None -> ()
|
||||||
| Some y -> k y
|
| Some y -> k y
|
||||||
)
|
)
|
||||||
|
|
||||||
let filter_map = fmap
|
let filter_map = fmap
|
||||||
|
|
||||||
|
|
@ -130,22 +108,20 @@ module MList = struct
|
||||||
let prev, cur = ref start, ref Nil in
|
let prev, cur = ref start, ref Nil in
|
||||||
seq
|
seq
|
||||||
(fun x ->
|
(fun x ->
|
||||||
k x; (* callback *)
|
k x; (* callback *)
|
||||||
match !cur with
|
match !cur with
|
||||||
| Nil ->
|
| Nil ->
|
||||||
let n = !chunk_size in
|
let n = !chunk_size in
|
||||||
if n < 4096 then chunk_size := 2 * !chunk_size;
|
if n < 4096 then chunk_size := 2 * !chunk_size;
|
||||||
cur := Cons (Array.make n x, ref 1, ref Nil)
|
cur := Cons (Array.make n x, ref 1, ref Nil)
|
||||||
| Cons (a,n,next) ->
|
| Cons (a,n,next) ->
|
||||||
assert (!n < Array.length a);
|
assert (!n < Array.length a);
|
||||||
a.(!n) <- x;
|
a.(!n) <- x;
|
||||||
incr n;
|
incr n;
|
||||||
if !n = Array.length a then begin
|
if !n = Array.length a then (
|
||||||
!prev := !cur;
|
!prev := !cur;
|
||||||
prev := next;
|
prev := next;
|
||||||
cur := Nil
|
cur := Nil));
|
||||||
end
|
|
||||||
);
|
|
||||||
!prev := !cur;
|
!prev := !cur;
|
||||||
!start
|
!start
|
||||||
|
|
||||||
|
|
@ -155,13 +131,13 @@ module MList = struct
|
||||||
let rec iter f l = match l with
|
let rec iter f l = match l with
|
||||||
| Nil -> ()
|
| Nil -> ()
|
||||||
| Cons (a, n, tl) ->
|
| Cons (a, n, tl) ->
|
||||||
for i=0 to !n - 1 do f a.(i) done;
|
for i=0 to !n - 1 do f a.(i) done;
|
||||||
iter f !tl
|
iter f !tl
|
||||||
|
|
||||||
let iteri f l =
|
let iteri f l =
|
||||||
let rec iteri i f l = match l with
|
let rec iteri i f l = match l with
|
||||||
| Nil -> ()
|
| Nil -> ()
|
||||||
| Cons (a, n, tl) ->
|
| Cons (a, n, tl) ->
|
||||||
for j=0 to !n - 1 do f (i+j) a.(j) done;
|
for j=0 to !n - 1 do f (i+j) a.(j) done;
|
||||||
iteri (i+ !n) f !tl
|
iteri (i+ !n) f !tl
|
||||||
in iteri 0 f l
|
in iteri 0 f l
|
||||||
|
|
@ -169,8 +145,8 @@ module MList = struct
|
||||||
let rec iter_rev f l = match l with
|
let rec iter_rev f l = match l with
|
||||||
| Nil -> ()
|
| Nil -> ()
|
||||||
| Cons (a, n, tl) ->
|
| Cons (a, n, tl) ->
|
||||||
iter_rev f !tl;
|
iter_rev f !tl;
|
||||||
for i = !n-1 downto 0 do f a.(i) done
|
for i = !n-1 downto 0 do f a.(i) done
|
||||||
|
|
||||||
let length l =
|
let length l =
|
||||||
let rec len acc l = match l with
|
let rec len acc l = match l with
|
||||||
|
|
@ -192,13 +168,13 @@ module MList = struct
|
||||||
let rec get_next _ = match !cur with
|
let rec get_next _ = match !cur with
|
||||||
| Nil -> None
|
| Nil -> None
|
||||||
| Cons (_, n, tl) when !i = !n ->
|
| Cons (_, n, tl) when !i = !n ->
|
||||||
cur := !tl;
|
cur := !tl;
|
||||||
i := 0;
|
i := 0;
|
||||||
get_next arg
|
get_next arg
|
||||||
| Cons (a, _, _) ->
|
| Cons (a, _, _) ->
|
||||||
let x = a.(!i) in
|
let x = a.(!i) in
|
||||||
incr i;
|
incr i;
|
||||||
Some x
|
Some x
|
||||||
in get_next
|
in get_next
|
||||||
|
|
||||||
let to_gen l = _to_next () l
|
let to_gen l = _to_next () l
|
||||||
|
|
@ -228,9 +204,9 @@ let persistent_lazy (seq:'a t) =
|
||||||
match !r with
|
match !r with
|
||||||
| LazyCached seq' -> seq' k
|
| LazyCached seq' -> seq' k
|
||||||
| LazySuspend ->
|
| LazySuspend ->
|
||||||
(* here if this traversal is interruted, no caching occurs *)
|
(* here if this traversal is interruted, no caching occurs *)
|
||||||
let seq' = MList.of_seq_with seq k in
|
let seq' = MList.of_seq_with seq k in
|
||||||
r := LazyCached (MList.to_seq seq')
|
r := LazyCached (MList.to_seq seq')
|
||||||
|
|
||||||
let sort ?(cmp=Pervasives.compare) seq =
|
let sort ?(cmp=Pervasives.compare) seq =
|
||||||
(* use an intermediate list, then sort the list *)
|
(* 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 group_succ_by ?(eq=fun x y -> x = y) seq k =
|
||||||
let cur = ref [] in
|
let cur = ref [] in
|
||||||
seq (fun x ->
|
seq (fun x ->
|
||||||
match !cur with
|
match !cur with
|
||||||
| [] -> cur := [x]
|
| [] -> cur := [x]
|
||||||
| (y::_) as l when eq x y ->
|
| (y::_) as l when eq x y ->
|
||||||
cur := x::l (* [x] belongs to the group *)
|
cur := x::l (* [x] belongs to the group *)
|
||||||
| (_::_) as l ->
|
| (_::_) as l ->
|
||||||
k l; (* yield group, and start another one *)
|
k l; (* yield group, and start another one *)
|
||||||
cur := [x]);
|
cur := [x]);
|
||||||
(* last list *)
|
(* last list *)
|
||||||
if !cur <> [] then k !cur
|
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 group_by (type k) ?(hash=Hashtbl.hash) ?(eq=(=)) seq =
|
||||||
let module Tbl = Hashtbl.Make(struct
|
let module Tbl = Hashtbl.Make(struct
|
||||||
type t = k
|
type t = k
|
||||||
let equal = eq
|
let equal = eq
|
||||||
let hash = hash
|
let hash = hash
|
||||||
end) in
|
end) in
|
||||||
(* compute group table *)
|
(* compute group table *)
|
||||||
let tbl = Tbl.create 32 in
|
let tbl = Tbl.create 32 in
|
||||||
seq
|
seq
|
||||||
(fun x ->
|
(fun x ->
|
||||||
let l = try Tbl.find tbl x with Not_found -> [] in
|
let l = try Tbl.find tbl x with Not_found -> [] in
|
||||||
Tbl.replace tbl x (x::l)
|
Tbl.replace tbl x (x::l)
|
||||||
);
|
);
|
||||||
fun yield ->
|
fun yield ->
|
||||||
Tbl.iter (fun _ l -> yield l) tbl
|
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 uniq ?(eq=fun x y -> x = y) seq k =
|
||||||
let has_prev = ref false
|
let has_prev = ref false
|
||||||
and prev = ref (Obj.magic 0) in (* avoid option type, costly *)
|
and prev = ref (Obj.magic 0) in (* avoid option type, costly *)
|
||||||
seq (fun x ->
|
seq
|
||||||
if !has_prev && eq !prev x
|
(fun x ->
|
||||||
|
if !has_prev && eq !prev x
|
||||||
then () (* duplicate *)
|
then () (* duplicate *)
|
||||||
else begin
|
else (
|
||||||
has_prev := true;
|
has_prev := true;
|
||||||
prev := x;
|
prev := x;
|
||||||
k x
|
k x
|
||||||
end)
|
))
|
||||||
|
|
||||||
let sort_uniq (type elt) ?(cmp=Pervasives.compare) seq =
|
let sort_uniq (type elt) ?(cmp=Pervasives.compare) seq =
|
||||||
let module S = Set.Make(struct
|
let module S = Set.Make(struct
|
||||||
type t = elt
|
type t = elt
|
||||||
let compare = cmp
|
let compare = cmp
|
||||||
end) in
|
end) in
|
||||||
let set = fold (fun acc x -> S.add x acc) S.empty seq in
|
let set = fold (fun acc x -> S.add x acc) S.empty seq in
|
||||||
fun k -> S.iter k set
|
fun k -> S.iter k set
|
||||||
|
|
||||||
let product outer inner k =
|
let product outer inner k =
|
||||||
outer (fun x ->
|
outer (fun x -> inner (fun y -> k (x,y)))
|
||||||
inner (fun y -> k (x,y))
|
|
||||||
)
|
|
||||||
|
|
||||||
let product2 outer inner k =
|
let product2 outer inner k =
|
||||||
outer (fun x ->
|
outer (fun x -> inner (fun y -> k x y))
|
||||||
inner (fun y -> k x y)
|
|
||||||
)
|
|
||||||
|
|
||||||
let join ~join_row s1 s2 k =
|
let join ~join_row s1 s2 k =
|
||||||
s1 (fun a ->
|
s1 (fun a ->
|
||||||
s2 (fun b ->
|
s2 (fun b ->
|
||||||
match join_row a b with
|
match join_row a b with
|
||||||
| None -> ()
|
| None -> ()
|
||||||
| Some c -> k c
|
| Some c -> k c))
|
||||||
)
|
|
||||||
) (* yield the combination of [a] and [b] *)
|
|
||||||
|
|
||||||
let rec unfoldr f b k = match f b with
|
let rec unfoldr f b k = match f b with
|
||||||
| None -> ()
|
| None -> ()
|
||||||
| Some (x, b') ->
|
| Some (x, b') ->
|
||||||
k x;
|
k x;
|
||||||
unfoldr f b' k
|
unfoldr f b' k
|
||||||
|
|
||||||
let scan f acc seq k =
|
let scan f acc seq k =
|
||||||
k acc;
|
k acc;
|
||||||
|
|
@ -321,16 +292,18 @@ let scan f acc seq k =
|
||||||
|
|
||||||
let max ?(lt=fun x y -> x < y) seq =
|
let max ?(lt=fun x y -> x < y) seq =
|
||||||
let ret = ref None in
|
let ret = ref None in
|
||||||
seq (fun x -> match !ret with
|
seq
|
||||||
| None -> ret := Some x
|
(fun x -> match !ret with
|
||||||
| Some y -> if lt y x then ret := Some x);
|
| None -> ret := Some x
|
||||||
|
| Some y -> if lt y x then ret := Some x);
|
||||||
!ret
|
!ret
|
||||||
|
|
||||||
let min ?(lt=fun x y -> x < y) seq =
|
let min ?(lt=fun x y -> x < y) seq =
|
||||||
let ret = ref None in
|
let ret = ref None in
|
||||||
seq (fun x -> match !ret with
|
seq
|
||||||
| None -> ret := Some x
|
(fun x -> match !ret with
|
||||||
| Some y -> if lt x y then ret := Some x);
|
| None -> ret := Some x
|
||||||
|
| Some y -> if lt x y then ret := Some x);
|
||||||
!ret
|
!ret
|
||||||
|
|
||||||
exception ExitHead
|
exception ExitHead
|
||||||
|
|
@ -351,11 +324,11 @@ exception ExitTake
|
||||||
let take n seq k =
|
let take n seq k =
|
||||||
let count = ref 0 in
|
let count = ref 0 in
|
||||||
try
|
try
|
||||||
seq (fun x ->
|
seq
|
||||||
if !count = n then raise ExitTake;
|
(fun x ->
|
||||||
incr count;
|
if !count = n then raise ExitTake;
|
||||||
k x;
|
incr count;
|
||||||
)
|
k x)
|
||||||
with ExitTake -> ()
|
with ExitTake -> ()
|
||||||
|
|
||||||
exception ExitTakeWhile
|
exception ExitTakeWhile
|
||||||
|
|
@ -370,11 +343,11 @@ exception ExitFoldWhile
|
||||||
let fold_while f s seq =
|
let fold_while f s seq =
|
||||||
let state = ref s in
|
let state = ref s in
|
||||||
let consume x =
|
let consume x =
|
||||||
let acc, cont = f (!state) x in
|
let acc, cont = f (!state) x in
|
||||||
state := acc;
|
state := acc;
|
||||||
match cont with
|
match cont with
|
||||||
| `Stop -> raise ExitFoldWhile
|
| `Stop -> raise ExitFoldWhile
|
||||||
| `Continue -> ()
|
| `Continue -> ()
|
||||||
in
|
in
|
||||||
try
|
try
|
||||||
seq consume; !state
|
seq consume; !state
|
||||||
|
|
@ -386,10 +359,11 @@ let drop n seq k =
|
||||||
|
|
||||||
let drop_while p seq k =
|
let drop_while p seq k =
|
||||||
let drop = ref true in
|
let drop = ref true in
|
||||||
seq (fun x ->
|
seq
|
||||||
if !drop
|
(fun x ->
|
||||||
then if p x then () else (drop := false; k x)
|
if !drop
|
||||||
else k x)
|
then if p x then () else (drop := false; k x)
|
||||||
|
else k x)
|
||||||
|
|
||||||
let rev seq =
|
let rev seq =
|
||||||
let l = MList.of_seq seq in
|
let l = MList.of_seq seq in
|
||||||
|
|
@ -418,12 +392,13 @@ exception ExitFind
|
||||||
|
|
||||||
let find f seq =
|
let find f seq =
|
||||||
let r = ref None in
|
let r = ref None in
|
||||||
begin try
|
begin
|
||||||
seq (fun x -> match f x with
|
try
|
||||||
| None -> ()
|
seq
|
||||||
| Some _ as res -> r := res; raise ExitFind
|
(fun x -> match f x with
|
||||||
);
|
| None -> ()
|
||||||
with ExitFind -> ()
|
| Some _ as res -> r := res; raise ExitFind);
|
||||||
|
with ExitFind -> ()
|
||||||
end;
|
end;
|
||||||
!r
|
!r
|
||||||
|
|
||||||
|
|
@ -492,17 +467,14 @@ let to_array seq =
|
||||||
let l = MList.of_seq seq in
|
let l = MList.of_seq seq in
|
||||||
let n = MList.length l in
|
let n = MList.length l in
|
||||||
if n = 0
|
if n = 0
|
||||||
then [||]
|
then [||]
|
||||||
else begin
|
else (
|
||||||
let a = Array.make n (MList.get l 0) in
|
let a = Array.make n (MList.get l 0) in
|
||||||
MList.iteri (fun i x -> a.(i) <- x) l;
|
MList.iteri (fun i x -> a.(i) <- x) l;
|
||||||
a
|
a
|
||||||
end
|
)
|
||||||
|
|
||||||
let of_array a k =
|
let of_array a k = Array.iter k a
|
||||||
for i = 0 to Array.length a - 1 do
|
|
||||||
k (Array.unsafe_get a i)
|
|
||||||
done
|
|
||||||
|
|
||||||
let of_array_i a k =
|
let of_array_i a k =
|
||||||
for i = 0 to Array.length a - 1 do
|
for i = 0 to Array.length a - 1 do
|
||||||
|
|
@ -583,8 +555,7 @@ let of_in_channel ic =
|
||||||
while true do
|
while true do
|
||||||
let c = input_char ic in k c
|
let c = input_char ic in k c
|
||||||
done
|
done
|
||||||
with End_of_file -> ()
|
with End_of_file -> ())
|
||||||
)
|
|
||||||
|
|
||||||
let to_buffer seq buf =
|
let to_buffer seq buf =
|
||||||
seq (fun c -> Buffer.add_char buf c)
|
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
|
let first = ref true in
|
||||||
seq
|
seq
|
||||||
(fun x ->
|
(fun x ->
|
||||||
(if !first then first := false
|
(if !first then first := false
|
||||||
else begin
|
else (
|
||||||
Format.pp_print_string formatter sep;
|
Format.pp_print_string formatter sep;
|
||||||
Format.pp_print_cut formatter ();
|
Format.pp_print_cut formatter ();
|
||||||
end);
|
));
|
||||||
pp_elt formatter x)
|
pp_elt formatter x)
|
||||||
|
|
||||||
let pp_buf ?(sep=", ") pp_elt buf seq =
|
let pp_buf ?(sep=", ") pp_elt buf seq =
|
||||||
let first = ref true in
|
let first = ref true in
|
||||||
seq
|
seq
|
||||||
(fun x ->
|
(fun x ->
|
||||||
if !first then first := false else Buffer.add_string buf sep;
|
if !first then first := false else Buffer.add_string buf sep;
|
||||||
pp_elt buf x)
|
pp_elt buf x)
|
||||||
|
|
||||||
let to_string ?sep pp_elt seq =
|
let to_string ?sep pp_elt seq =
|
||||||
let buf = Buffer.create 25 in
|
let buf = Buffer.create 25 in
|
||||||
|
|
@ -794,7 +765,7 @@ module IO = struct
|
||||||
if n' = 0 then stop := true else n := !n + n';
|
if n' = 0 then stop := true else n := !n + n';
|
||||||
done;
|
done;
|
||||||
if !n > 0
|
if !n > 0
|
||||||
then k (Bytes.sub_string buf 0 !n)
|
then k (Bytes.sub_string buf 0 !n)
|
||||||
done;
|
done;
|
||||||
close_in ic
|
close_in ic
|
||||||
with e ->
|
with e ->
|
||||||
|
|
|
||||||
454
sequence.mli
454
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
|
(* This file is free software, part of sequence. See file "license" for more details. *)
|
||||||
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.
|
|
||||||
*)
|
|
||||||
|
|
||||||
(** {1 Simple and Efficient Iterators} *)
|
(** {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. *)
|
of this memory structure, cheaply and repeatably. *)
|
||||||
|
|
||||||
type +'a t = ('a -> unit) -> unit
|
type +'a t = ('a -> unit) -> unit
|
||||||
(** A sequence of values of type ['a]. If you give it a function ['a -> 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. *)
|
it will be applied to every element of the sequence successively. *)
|
||||||
|
|
||||||
type +'a sequence = 'a t
|
type +'a sequence = 'a t
|
||||||
|
|
||||||
type (+'a, +'b) t2 = ('a -> 'b -> unit) -> unit
|
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} *)
|
(** {2 Build a sequence} *)
|
||||||
|
|
||||||
val from_iter : (('a -> unit) -> unit) -> 'a t
|
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
|
val from_fun : (unit -> 'a option) -> 'a t
|
||||||
(** Call the function repeatedly until it returns None. This
|
(** Call the function repeatedly until it returns None. This
|
||||||
sequence is transient, use {!persistent} if needed! *)
|
sequence is transient, use {!persistent} if needed! *)
|
||||||
|
|
||||||
val empty : 'a t
|
val empty : 'a t
|
||||||
(** Empty sequence. It contains no element. *)
|
(** Empty sequence. It contains no element. *)
|
||||||
|
|
||||||
val singleton : 'a -> 'a t
|
val singleton : 'a -> 'a t
|
||||||
(** Singleton sequence, with exactly one element. *)
|
(** Singleton sequence, with exactly one element. *)
|
||||||
|
|
||||||
val doubleton : 'a -> 'a -> 'a t
|
val doubleton : 'a -> 'a -> 'a t
|
||||||
(** Sequence with exactly two elements *)
|
(** Sequence with exactly two elements *)
|
||||||
|
|
||||||
val cons : 'a -> 'a t -> 'a t
|
val cons : 'a -> 'a t -> 'a t
|
||||||
(** [cons x l] yields [x], then yields from [l].
|
(** [cons x l] yields [x], then yields from [l].
|
||||||
Same as [append (singleton x) l] *)
|
Same as [append (singleton x) l] *)
|
||||||
|
|
||||||
val snoc : 'a t -> 'a -> 'a t
|
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
|
val return : 'a -> 'a t
|
||||||
(** Synonym to {!singleton} *)
|
(** Synonym to {!singleton} *)
|
||||||
|
|
||||||
val pure : 'a -> 'a t
|
val pure : 'a -> 'a t
|
||||||
(** Synonym to {!singleton} *)
|
(** Synonym to {!singleton} *)
|
||||||
|
|
||||||
val repeat : 'a -> 'a t
|
val repeat : 'a -> 'a t
|
||||||
(** Infinite sequence of the same element. You may want to look
|
(** Infinite sequence of the same element. You may want to look
|
||||||
at {!take} and the likes if you iterate on it. *)
|
at {!take} and the likes if you iterate on it. *)
|
||||||
|
|
||||||
val iterate : ('a -> 'a) -> 'a -> 'a t
|
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
|
val forever : (unit -> 'b) -> 'b t
|
||||||
(** Sequence that calls the given function to produce elements.
|
(** Sequence that calls the given function to produce elements.
|
||||||
The sequence may be transient (depending on the function), and definitely
|
The sequence may be transient (depending on the function), and definitely
|
||||||
is infinite. You may want to use {!take} and {!persistent}. *)
|
is infinite. You may want to use {!take} and {!persistent}. *)
|
||||||
|
|
||||||
val cycle : 'a t -> 'a t
|
val cycle : 'a t -> 'a t
|
||||||
(** Cycle forever through the given sequence. Assume the given sequence can
|
(** Cycle forever through the given sequence. Assume the given sequence can
|
||||||
be traversed any amount of times (not transient). This yields an
|
be traversed any amount of times (not transient). This yields an
|
||||||
infinite sequence, you should use something like {!take} not to loop
|
infinite sequence, you should use something like {!take} not to loop
|
||||||
forever. *)
|
forever. *)
|
||||||
|
|
||||||
(** {2 Consume a sequence} *)
|
(** {2 Consume a sequence} *)
|
||||||
|
|
||||||
val iter : ('a -> unit) -> 'a t -> unit
|
val iter : ('a -> unit) -> 'a t -> unit
|
||||||
(** Consume the sequence, passing all its arguments to the function.
|
(** Consume the sequence, passing all its arguments to the function.
|
||||||
Basically [iter f seq] is just [seq f]. *)
|
Basically [iter f seq] is just [seq f]. *)
|
||||||
|
|
||||||
val iteri : (int -> 'a -> unit) -> 'a t -> unit
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
val mem : ?eq:('a -> 'a -> bool) -> 'a -> 'a t -> bool
|
||||||
(** Is the value a member of the sequence?
|
(** 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 *)
|
@since 0.5 *)
|
||||||
|
|
||||||
val find : ('a -> 'b option) -> 'a t -> 'b option
|
val find : ('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]
|
||||||
@since 0.5 *)
|
@since 0.5 *)
|
||||||
|
|
||||||
val length : 'a t -> int
|
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
|
val is_empty : 'a t -> bool
|
||||||
(** Is the sequence empty? Forces the sequence. *)
|
(** Is the sequence empty? Forces the sequence. *)
|
||||||
|
|
||||||
(** {2 Transform a sequence} *)
|
(** {2 Transform a sequence} *)
|
||||||
|
|
||||||
val filter : ('a -> bool) -> 'a t -> 'a t
|
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
|
val append : 'a t -> 'a t -> 'a t
|
||||||
(** Append two sequences. Iterating on the result is like iterating
|
(** Append two sequences. Iterating on the result is like iterating
|
||||||
on the first, then on the second. *)
|
on the first, then on the second. *)
|
||||||
|
|
||||||
val concat : 'a t t -> 'a t
|
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
|
val flatten : 'a t t -> 'a t
|
||||||
(** Alias for {!concat} *)
|
(** Alias for {!concat} *)
|
||||||
|
|
||||||
val flatMap : ('a -> 'b t) -> 'a t -> 'b t
|
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
|
val flat_map : ('a -> 'b t) -> 'a t -> 'b t
|
||||||
(** Monadic bind. Intuitively, it applies the function to every element of the
|
(** Monadic bind. Intuitively, it applies the function to every
|
||||||
initial sequence, and calls {!concat}.
|
element of the initial sequence, and calls {!concat}.
|
||||||
@since 0.5 *)
|
@since 0.5 *)
|
||||||
|
|
||||||
val fmap : ('a -> 'b option) -> 'a t -> 'b t
|
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
|
val filter_map : ('a -> 'b option) -> 'a t -> 'b t
|
||||||
(** Map and only keep non-[None] elements
|
(** Map and only keep non-[None] elements
|
||||||
@since 0.5 *)
|
@since 0.5 *)
|
||||||
|
|
||||||
val intersperse : 'a -> 'a t -> 'a t
|
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} *)
|
(** {2 Caching} *)
|
||||||
|
|
||||||
val persistent : 'a t -> 'a t
|
val persistent : 'a t -> 'a t
|
||||||
(** Iterate on the sequence, storing elements in an efficient internal structure..
|
(** Iterate on the sequence, storing elements in an efficient internal structure..
|
||||||
The resulting sequence can be iterated on as many times as needed.
|
The resulting sequence can be iterated on as many times as needed.
|
||||||
{b Note}: calling persistent on an already persistent sequence
|
{b Note}: calling persistent on an already persistent sequence
|
||||||
will still make a new copy of the sequence! *)
|
will still make a new copy of the sequence! *)
|
||||||
|
|
||||||
val persistent_lazy : 'a t -> 'a t
|
val persistent_lazy : 'a t -> 'a t
|
||||||
(** Lazy version of {!persistent}. When calling [persistent_lazy s],
|
(** Lazy version of {!persistent}. When calling [persistent_lazy s],
|
||||||
a new sequence [s'] is immediately returned (without actually consuming
|
a new sequence [s'] is immediately returned (without actually consuming
|
||||||
[s]) in constant time; the first time [s'] is iterated on,
|
[s]) in constant time; the first time [s'] is iterated on,
|
||||||
it also consumes [s] and caches its content into a inner data
|
it also consumes [s] and caches its content into a inner data
|
||||||
structure that will back [s'] for future iterations.
|
structure that will back [s'] for future iterations.
|
||||||
|
|
||||||
{b warning}: on the first traversal of [s'], if the traversal
|
{b warning}: on the first traversal of [s'], if the traversal
|
||||||
is interrupted prematurely ({!take}, etc.) then [s'] will not be
|
is interrupted prematurely ({!take}, etc.) then [s'] will not be
|
||||||
memorized, and the next call to [s'] will traverse [s] again. *)
|
memorized, and the next call to [s'] will traverse [s] again. *)
|
||||||
|
|
||||||
(** {2 Misc} *)
|
(** {2 Misc} *)
|
||||||
|
|
||||||
val sort : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t
|
val sort : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t
|
||||||
(** Sort the sequence. Eager, O(n) ram and O(n ln(n)) time.
|
(** Sort the sequence. Eager, O(n) ram and O(n ln(n)) time.
|
||||||
It iterates on elements of the argument sequence immediately,
|
It iterates on elements of the argument sequence immediately,
|
||||||
before it sorts them. *)
|
before it sorts them. *)
|
||||||
|
|
||||||
val sort_uniq : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t
|
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
|
val group : ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t
|
||||||
(** Group equal consecutive elements.
|
(** Group equal consecutive elements.
|
||||||
@deprecated use {!group_succ_by} *)
|
@deprecated use {!group_succ_by} *)
|
||||||
|
|
||||||
val group_succ_by : ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t
|
val group_succ_by : ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t
|
||||||
(** Group equal consecutive elements.
|
(** Group equal consecutive elements.
|
||||||
Synonym to {!group}.
|
Synonym to {!group}.
|
||||||
@since NEXT_RELEASE *)
|
@since NEXT_RELEASE *)
|
||||||
|
|
||||||
val group_by : ?hash:('a -> int) -> ?eq:('a -> 'a -> bool) ->
|
val group_by : ?hash:('a -> int) -> ?eq:('a -> 'a -> bool) ->
|
||||||
'a t -> 'a list t
|
'a t -> 'a list t
|
||||||
(** Group equal elements, disregarding their order of appearance.
|
(** Group equal elements, disregarding their order of appearance.
|
||||||
The result sequence is traversable as many times as required.
|
The result sequence is traversable as many times as required.
|
||||||
@since NEXT_RELEASE *)
|
@since NEXT_RELEASE *)
|
||||||
|
|
||||||
val uniq : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t
|
val uniq : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t
|
||||||
(** Remove consecutive duplicate elements. Basically this is
|
(** Remove consecutive duplicate elements. Basically this is
|
||||||
like [fun seq -> map List.hd (group seq)]. *)
|
like [fun seq -> map List.hd (group seq)]. *)
|
||||||
|
|
||||||
val product : 'a t -> 'b t -> ('a * 'b) t
|
val product : 'a t -> 'b t -> ('a * 'b) t
|
||||||
(** Cartesian product of the sequences. When calling [product a b],
|
(** Cartesian product of the sequences. When calling [product a b],
|
||||||
the caller {b MUST} ensure that [b] can be traversed as many times
|
the caller {b MUST} ensure that [b] can be traversed as many times
|
||||||
as required (several times), possibly by calling {!persistent} on it
|
as required (several times), possibly by calling {!persistent} on it
|
||||||
beforehand. *)
|
beforehand. *)
|
||||||
|
|
||||||
val product2 : 'a t -> 'b t -> ('a, 'b) t2
|
val product2 : 'a t -> 'b t -> ('a, 'b) t2
|
||||||
(** Binary version of {!product}. Same requirements.
|
(** Binary version of {!product}. Same requirements.
|
||||||
@since 0.5 *)
|
@since 0.5 *)
|
||||||
|
|
||||||
val join : join_row:('a -> 'b -> 'c option) -> 'a t -> 'b t -> 'c t
|
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
|
(** [join ~join_row a b] combines every element of [a] with every
|
||||||
element of [b] using [join_row]. If [join_row] returns None, then
|
element of [b] using [join_row]. If [join_row] returns None, then
|
||||||
the two elements do not combine. Assume that [b] allows for multiple
|
the two elements do not combine. Assume that [b] allows for multiple
|
||||||
iterations. *)
|
iterations. *)
|
||||||
|
|
||||||
val unfoldr : ('b -> ('a * 'b) option) -> 'b -> 'a t
|
val unfoldr : ('b -> ('a * 'b) option) -> 'b -> 'a t
|
||||||
(** [unfoldr f b] will apply [f] to [b]. If it
|
(** [unfoldr f b] will apply [f] to [b]. If it
|
||||||
yields [Some (x,b')] then [x] is returned
|
yields [Some (x,b')] then [x] is returned
|
||||||
and unfoldr recurses with [b']. *)
|
and unfoldr recurses with [b']. *)
|
||||||
|
|
||||||
val scan : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b t
|
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
|
val max : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option
|
||||||
(** Max element of the sequence, using the given comparison function.
|
(** Max element of the sequence, using the given comparison function.
|
||||||
@return None if the sequence is empty, Some [m] where [m] is the maximal
|
@return None if the sequence is empty, Some [m] where [m] is the maximal
|
||||||
element otherwise *)
|
element otherwise *)
|
||||||
|
|
||||||
val min : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option
|
val min : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option
|
||||||
(** Min element of the sequence, using the given comparison function.
|
(** Min element of the sequence, using the given comparison function.
|
||||||
see {!max} for more details. *)
|
see {!max} for more details. *)
|
||||||
|
|
||||||
val head : 'a t -> 'a option
|
val head : 'a t -> 'a option
|
||||||
(** First element, if any, otherwise [None]
|
(** First element, if any, otherwise [None]
|
||||||
@since 0.5.1 *)
|
@since 0.5.1 *)
|
||||||
|
|
||||||
val head_exn : 'a t -> 'a
|
val head_exn : 'a t -> 'a
|
||||||
(** First element, if any, fails
|
(** 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 *)
|
@since 0.5.1 *)
|
||||||
|
|
||||||
val take : int -> 'a t -> 'a t
|
val take : int -> 'a t -> 'a t
|
||||||
(** Take at most [n] elements from the sequence. Works on infinite
|
(** Take at most [n] elements from the sequence. Works on infinite
|
||||||
sequences. *)
|
sequences. *)
|
||||||
|
|
||||||
val take_while : ('a -> bool) -> 'a t -> 'a t
|
val take_while : ('a -> bool) -> 'a t -> 'a t
|
||||||
(** Take elements while they satisfy the predicate, then stops iterating.
|
(** Take elements while they satisfy the predicate, then stops iterating.
|
||||||
Will work on an infinite sequence [s] if the predicate is false for at
|
Will work on an infinite sequence [s] if the predicate is false for at
|
||||||
least one element of [s]. *)
|
least one element of [s]. *)
|
||||||
|
|
||||||
val fold_while : ('a -> 'b -> 'a * [`Stop | `Continue]) -> 'a -> 'b t -> 'a
|
val fold_while : ('a -> 'b -> 'a * [`Stop | `Continue]) -> 'a -> 'b t -> 'a
|
||||||
(** Folds over elements of the sequence, stopping early if the accumulator
|
(** Folds over elements of the sequence, stopping early if the accumulator
|
||||||
returns [('a, `Stop)]
|
returns [('a, `Stop)]
|
||||||
@since 0.5.5 *)
|
@since 0.5.5 *)
|
||||||
|
|
||||||
val drop : int -> 'a t -> 'a t
|
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
|
val drop_while : ('a -> bool) -> 'a t -> 'a t
|
||||||
(** Predicate version of {!drop} *)
|
(** Predicate version of {!drop} *)
|
||||||
|
|
||||||
val rev : 'a t -> 'a t
|
val rev : 'a t -> 'a t
|
||||||
(** Reverse the sequence. O(n) memory and time, needs the
|
(** Reverse the sequence. O(n) memory and time, needs the
|
||||||
sequence to be finite. The result is persistent and does
|
sequence to be finite. The result is persistent and does
|
||||||
not depend on the input being repeatable. *)
|
not depend on the input being repeatable. *)
|
||||||
|
|
||||||
(** {2 Binary sequences} *)
|
(** {2 Binary sequences} *)
|
||||||
|
|
||||||
|
|
@ -313,7 +291,7 @@ val zip : ('a, 'b) t2 -> ('a * 'b) t
|
||||||
val unzip : ('a * 'b) t -> ('a, 'b) t2
|
val unzip : ('a * 'b) t -> ('a, 'b) t2
|
||||||
|
|
||||||
val zip_i : 'a t -> (int, 'a) 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
|
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 : ('a -> 'b -> 'c) -> ('a, 'b) t2 -> 'c t
|
||||||
|
|
||||||
val map2_2 : ('a -> 'b -> 'c) -> ('a -> 'b -> 'd) -> ('a, 'b) t2 -> ('c, 'd) t2
|
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} *)
|
(** {2 Basic data structures converters} *)
|
||||||
|
|
||||||
val to_list : 'a t -> 'a list
|
val to_list : 'a t -> 'a list
|
||||||
(** Convert the sequence into a list. Preserves order of elements.
|
(** Convert the sequence into a list. Preserves order of elements.
|
||||||
This function is tail-recursive, but consumes 2*n memory.
|
This function is tail-recursive, but consumes 2*n memory.
|
||||||
If order doesn't matter to you, consider {!to_rev_list}. *)
|
If order doesn't matter to you, consider {!to_rev_list}. *)
|
||||||
|
|
||||||
val to_rev_list : 'a t -> 'a 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
|
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
|
val to_opt : 'a t -> 'a option
|
||||||
(** Alias to {!head}
|
(** Alias to {!head}
|
||||||
@since 0.5.1 *)
|
@since 0.5.1 *)
|
||||||
|
|
||||||
val to_array : 'a t -> 'a array
|
val to_array : 'a t -> 'a array
|
||||||
(** Convert to an array. Currently not very efficient because
|
(** Convert to an array. Currently not very efficient because
|
||||||
an intermediate list is used. *)
|
an intermediate list is used. *)
|
||||||
|
|
||||||
val of_array : 'a array -> 'a t
|
val of_array : 'a array -> 'a t
|
||||||
|
|
||||||
val of_array_i : 'a array -> (int * '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 of_array2 : 'a array -> (int, 'a) t2
|
||||||
|
|
||||||
val array_slice : 'a array -> int -> int -> 'a t
|
val array_slice : 'a array -> int -> int -> 'a t
|
||||||
(** [array_slice a i j] Sequence of elements whose indexes range
|
(** [array_slice a i j] Sequence of elements whose indexes range
|
||||||
from [i] to [j] *)
|
from [i] to [j] *)
|
||||||
|
|
||||||
val of_opt : 'a option -> 'a t
|
val of_opt : 'a option -> 'a t
|
||||||
(** Iterate on 0 or 1 values.
|
(** Iterate on 0 or 1 values.
|
||||||
@since 0.5.1 *)
|
@since 0.5.1 *)
|
||||||
|
|
||||||
val of_stream : 'a Stream.t -> 'a t
|
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
|
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
|
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
|
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
|
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
|
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
|
val hashtbl_add : ('a, 'b) Hashtbl.t -> ('a * 'b) t -> unit
|
||||||
(** Add elements of the sequence to the hashtable, with
|
(** Add elements of the sequence to the hashtable, with
|
||||||
Hashtbl.add *)
|
Hashtbl.add *)
|
||||||
|
|
||||||
val hashtbl_replace : ('a, 'b) Hashtbl.t -> ('a * 'b) t -> unit
|
val hashtbl_replace : ('a, 'b) Hashtbl.t -> ('a * 'b) t -> unit
|
||||||
(** Add elements of the sequence to the hashtable, with
|
(** Add elements of the sequence to the hashtable, with
|
||||||
Hashtbl.replace (erases conflicting bindings) *)
|
Hashtbl.replace (erases conflicting bindings) *)
|
||||||
|
|
||||||
val to_hashtbl : ('a * 'b) t -> ('a, 'b) Hashtbl.t
|
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
|
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
|
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
|
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_keys : ('a, 'b) Hashtbl.t -> 'a t
|
||||||
val hashtbl_values : ('a, 'b) Hashtbl.t -> 'b 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 to_str : char t -> string
|
||||||
|
|
||||||
val concat_str : string t -> string
|
val concat_str : string t -> string
|
||||||
(** Concatenate strings together, eagerly.
|
(** Concatenate strings together, eagerly.
|
||||||
Also see {!intersperse} to add a separator.
|
Also see {!intersperse} to add a separator.
|
||||||
@since 0.5 *)
|
@since 0.5 *)
|
||||||
|
|
||||||
exception OneShotSequence
|
exception OneShotSequence
|
||||||
(** Raised when the user tries to iterate several times on
|
(** Raised when the user tries to iterate several times on
|
||||||
a transient iterator *)
|
a transient iterator *)
|
||||||
|
|
||||||
val of_in_channel : in_channel -> char t
|
val of_in_channel : in_channel -> char t
|
||||||
(** Iterates on characters of the input (can block when one
|
(** Iterates on characters of the input (can block when one
|
||||||
iterates over the sequence). If you need to iterate
|
iterates over the sequence). If you need to iterate
|
||||||
several times on this sequence, use {!persistent}.
|
several times on this sequence, use {!persistent}.
|
||||||
@raise OneShotSequence when used more than once. *)
|
@raise OneShotSequence when used more than once. *)
|
||||||
|
|
||||||
val to_buffer : char t -> Buffer.t -> unit
|
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
|
val int_range : start:int -> stop:int -> int t
|
||||||
(** Iterator on integers in [start...stop] by steps 1. Also see
|
(** Iterator on integers in [start...stop] by steps 1. Also see
|
||||||
{!(--)} for an infix version. *)
|
{!(--)} for an infix version. *)
|
||||||
|
|
||||||
val int_range_dec : start:int -> stop:int -> int t
|
val int_range_dec : start:int -> stop:int -> int t
|
||||||
(** Iterator on decreasing integers in [stop...start] by steps -1.
|
(** Iterator on decreasing integers in [stop...start] by steps -1.
|
||||||
See {!(--^)} for an infix version *)
|
See {!(--^)} for an infix version *)
|
||||||
|
|
||||||
val bools : bool t
|
val bools : bool t
|
||||||
(** Iterates on [true] and [false]
|
(** Iterates on [true] and [false]
|
||||||
@since NEXT_RELEASE *)
|
@since NEXT_RELEASE *)
|
||||||
|
|
||||||
val of_set : (module Set.S with type elt = 'a and type t = 'b) -> 'b -> 'a t
|
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
|
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 gen = unit -> 'a option
|
||||||
type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist]
|
type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist]
|
||||||
|
|
||||||
val of_gen : 'a gen -> 'a t
|
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
|
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
|
val of_klist : 'a klist -> 'a t
|
||||||
(** Iterate on the lazy list *)
|
(** Iterate on the lazy list *)
|
||||||
|
|
||||||
val to_klist : 'a t -> 'a klist
|
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} *)
|
(** {2 Functorial conversions between sets and sequences} *)
|
||||||
|
|
||||||
|
|
@ -500,48 +478,48 @@ end
|
||||||
(** {2 Infinite sequences of random values} *)
|
(** {2 Infinite sequences of random values} *)
|
||||||
|
|
||||||
val random_int : int -> int t
|
val random_int : int -> int t
|
||||||
(** Infinite sequence of random integers between 0 and
|
(** Infinite sequence of random integers between 0 and
|
||||||
the given higher bound (see Random.int) *)
|
the given higher bound (see Random.int) *)
|
||||||
|
|
||||||
val random_bool : bool t
|
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_float : float -> float t
|
||||||
|
|
||||||
val random_array : 'a array -> 'a 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
|
val random_list : 'a list -> 'a t
|
||||||
(** Infinite sequence of random elements of the list. Basically the
|
(** Infinite sequence of random elements of the list. Basically the
|
||||||
same as {!random_array}. *)
|
same as {!random_array}. *)
|
||||||
|
|
||||||
(** {2 Infix functions} *)
|
(** {2 Infix functions} *)
|
||||||
|
|
||||||
module Infix : sig
|
module Infix : sig
|
||||||
val (--) : int -> int -> int t
|
val (--) : int -> int -> int t
|
||||||
(** [a -- b] is the range of integers from [a] to [b], both included,
|
(** [a -- b] is the range of integers from [a] to [b], both included,
|
||||||
in increasing order. It will therefore be empty if [a > b]. *)
|
in increasing order. It will therefore be empty if [a > b]. *)
|
||||||
|
|
||||||
val (--^) : int -> int -> int t
|
val (--^) : int -> int -> int t
|
||||||
(** [a --^ b] is the range of integers from [b] to [a], both included,
|
(** [a --^ b] is the range of integers from [b] to [a], both included,
|
||||||
in decreasing order (starts from [a]).
|
in decreasing order (starts from [a]).
|
||||||
It will therefore be empty if [a < b]. *)
|
It will therefore be empty if [a < b]. *)
|
||||||
|
|
||||||
val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
|
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 *)
|
@since 0.5 *)
|
||||||
|
|
||||||
val (>|=) : 'a t -> ('a -> 'b) -> 'b t
|
val (>|=) : 'a t -> ('a -> 'b) -> 'b t
|
||||||
(** Infix version of {!map}
|
(** Infix version of {!map}
|
||||||
@since 0.5 *)
|
@since 0.5 *)
|
||||||
|
|
||||||
val (<*>) : ('a -> 'b) t -> 'a t -> 'b t
|
val (<*>) : ('a -> 'b) t -> 'a t -> 'b t
|
||||||
(** Applicative operator (product+application)
|
(** Applicative operator (product+application)
|
||||||
@since 0.5 *)
|
@since 0.5 *)
|
||||||
|
|
||||||
val (<+>) : 'a t -> 'a t -> 'a t
|
val (<+>) : 'a t -> 'a t -> 'a t
|
||||||
(** Concatenation of sequences
|
(** Concatenation of sequences
|
||||||
@since 0.5 *)
|
@since 0.5 *)
|
||||||
end
|
end
|
||||||
|
|
||||||
include module type of Infix
|
include module type of Infix
|
||||||
|
|
@ -549,46 +527,46 @@ include module type of Infix
|
||||||
(** {2 Pretty printing of sequences} *)
|
(** {2 Pretty printing of sequences} *)
|
||||||
|
|
||||||
val pp_seq : ?sep:string -> (Format.formatter -> 'a -> unit) ->
|
val pp_seq : ?sep:string -> (Format.formatter -> 'a -> unit) ->
|
||||||
Format.formatter -> 'a t -> unit
|
Format.formatter -> 'a t -> unit
|
||||||
(** Pretty print a sequence of ['a], using the given pretty printer
|
(** Pretty print a sequence of ['a], using the given pretty printer
|
||||||
to print each elements. An optional separator string can be provided. *)
|
to print each elements. An optional separator string can be provided. *)
|
||||||
|
|
||||||
val pp_buf : ?sep:string -> (Buffer.t -> 'a -> unit) ->
|
val pp_buf : ?sep:string -> (Buffer.t -> 'a -> unit) ->
|
||||||
Buffer.t -> 'a t -> unit
|
Buffer.t -> 'a t -> unit
|
||||||
(** Print into a buffer *)
|
(** Print into a buffer *)
|
||||||
|
|
||||||
val to_string : ?sep:string -> ('a -> string) -> 'a t -> string
|
val to_string : ?sep:string -> ('a -> string) -> 'a t -> string
|
||||||
(** Print into a string *)
|
(** Print into a string *)
|
||||||
|
|
||||||
(** {2 Basic IO}
|
(** {2 Basic IO}
|
||||||
|
|
||||||
Very basic interface to manipulate files as sequence of chunks/lines. The
|
Very basic interface to manipulate files as sequence of chunks/lines. The
|
||||||
sequences take care of opening and closing files properly; every time
|
sequences take care of opening and closing files properly; every time
|
||||||
one iterates over a sequence, the file is opened/closed again.
|
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
|
module IO : sig
|
||||||
val lines_of : ?mode:int -> ?flags:open_flag list ->
|
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
|
(** [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
|
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
|
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]] *)
|
@param flags default: [[Open_rdonly]] *)
|
||||||
|
|
||||||
val chunks_of : ?mode:int -> ?flags:open_flag list -> ?size:int ->
|
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
|
(** Read chunks of the given [size] from the file. The last chunk might be
|
||||||
smaller. Behaves like {!lines_of} regarding errors and options.
|
smaller. Behaves like {!lines_of} regarding errors and options.
|
||||||
Every time the sequence is iterated on, the file is opened again, so
|
Every time the sequence is iterated on, the file is opened again, so
|
||||||
different iterations might return different results *)
|
different iterations might return different results *)
|
||||||
|
|
||||||
val write_to : ?mode:int -> ?flags:open_flag list ->
|
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
|
(** [write_to filename seq] writes all strings from [seq] into the given
|
||||||
file. It takes care of opening and closing the file.
|
file. It takes care of opening and closing the file.
|
||||||
@param mode default [0o644]
|
@param mode default [0o644]
|
||||||
@param flags used by [open_out_gen]. Default: [[Open_creat;Open_wronly]]. *)
|
@param flags used by [open_out_gen]. Default: [[Open_creat;Open_wronly]]. *)
|
||||||
|
|
||||||
val write_bytes_to : ?mode:int -> ?flags:open_flag list ->
|
val write_bytes_to : ?mode:int -> ?flags:open_flag list ->
|
||||||
string -> Bytes.t t -> unit
|
string -> Bytes.t t -> unit
|
||||||
(** @since 0.5.4 *)
|
(** @since 0.5.4 *)
|
||||||
|
|
||||||
val write_lines : ?mode:int -> ?flags:open_flag list ->
|
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 *)
|
(** Same as {!write_to}, but intercales ['\n'] between each string *)
|
||||||
|
|
||||||
val write_bytes_lines : ?mode:int -> ?flags:open_flag list ->
|
val write_bytes_lines : ?mode:int -> ?flags:open_flag list ->
|
||||||
string -> Bytes.t t -> unit
|
string -> Bytes.t t -> unit
|
||||||
(** @since 0.5.4 *)
|
(** @since 0.5.4 *)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,263 +1,239 @@
|
||||||
(*
|
|
||||||
copyright (c) 2013, simon cruanes
|
|
||||||
all rights reserved.
|
|
||||||
|
|
||||||
redistribution and use in source and binary forms, with or without
|
(* This file is free software, part of sequence. See file "license" for more details. *)
|
||||||
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.
|
|
||||||
*)
|
|
||||||
|
|
||||||
(** {1 Simple and Efficient Iterators}
|
(** {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
|
type +'a t = ('a -> unit) -> unit
|
||||||
(** A sequence of values of type ['a]. If you give it a function ['a -> 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. *)
|
it will be applied to every element of the sequence successively. *)
|
||||||
|
|
||||||
type +'a sequence = 'a t
|
type +'a sequence = 'a t
|
||||||
|
|
||||||
type (+'a, +'b) t2 = ('a -> 'b -> unit) -> unit
|
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} *)
|
(** {2 Build a sequence} *)
|
||||||
|
|
||||||
val from_iter : (('a -> unit) -> unit) -> 'a t
|
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
|
val from_fun : (unit -> 'a option) -> 'a t
|
||||||
(** Call the function repeatedly until it returns None. This
|
(** Call the function repeatedly until it returns None. This
|
||||||
sequence is transient, use {!persistent} if needed! *)
|
sequence is transient, use {!persistent} if needed! *)
|
||||||
|
|
||||||
val empty : 'a t
|
val empty : 'a t
|
||||||
(** Empty sequence. It contains no element. *)
|
(** Empty sequence. It contains no element. *)
|
||||||
|
|
||||||
val singleton : 'a -> 'a t
|
val singleton : 'a -> 'a t
|
||||||
(** Singleton sequence, with exactly one element. *)
|
(** Singleton sequence, with exactly one element. *)
|
||||||
|
|
||||||
val doubleton : 'a -> 'a -> 'a t
|
val doubleton : 'a -> 'a -> 'a t
|
||||||
(** Sequence with exactly two elements *)
|
(** Sequence with exactly two elements *)
|
||||||
|
|
||||||
val cons : 'a -> 'a t -> 'a t
|
val cons : 'a -> 'a t -> 'a t
|
||||||
(** [cons x l] yields [x], then yields from [l].
|
(** [cons x l] yields [x], then yields from [l].
|
||||||
Same as [append (singleton x) l] *)
|
Same as [append (singleton x) l] *)
|
||||||
|
|
||||||
val snoc : 'a t -> 'a -> 'a t
|
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
|
val return : 'a -> 'a t
|
||||||
(** Synonym to {!singleton} *)
|
(** Synonym to {!singleton} *)
|
||||||
|
|
||||||
val pure : 'a -> 'a t
|
val pure : 'a -> 'a t
|
||||||
(** Synonym to {!singleton} *)
|
(** Synonym to {!singleton} *)
|
||||||
|
|
||||||
val repeat : 'a -> 'a t
|
val repeat : 'a -> 'a t
|
||||||
(** Infinite sequence of the same element. You may want to look
|
(** Infinite sequence of the same element. You may want to look
|
||||||
at {!take} and the likes if you iterate on it. *)
|
at {!take} and the likes if you iterate on it. *)
|
||||||
|
|
||||||
val iterate : ('a -> 'a) -> 'a -> 'a t
|
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
|
val forever : (unit -> 'b) -> 'b t
|
||||||
(** Sequence that calls the given function to produce elements.
|
(** Sequence that calls the given function to produce elements.
|
||||||
The sequence may be transient (depending on the function), and definitely
|
The sequence may be transient (depending on the function), and definitely
|
||||||
is infinite. You may want to use {!take} and {!persistent}. *)
|
is infinite. You may want to use {!take} and {!persistent}. *)
|
||||||
|
|
||||||
val cycle : 'a t -> 'a t
|
val cycle : 'a t -> 'a t
|
||||||
(** Cycle forever through the given sequence. Assume the given sequence can
|
(** Cycle forever through the given sequence. Assume the given sequence can
|
||||||
be traversed any amount of times (not transient). This yields an
|
be traversed any amount of times (not transient). This yields an
|
||||||
infinite sequence, you should use something like {!take} not to loop
|
infinite sequence, you should use something like {!take} not to loop
|
||||||
forever. *)
|
forever. *)
|
||||||
|
|
||||||
(** {2 Consume a sequence} *)
|
(** {2 Consume a sequence} *)
|
||||||
|
|
||||||
val iter : f:('a -> unit) -> 'a t -> unit
|
val iter : f:('a -> unit) -> 'a t -> unit
|
||||||
(** Consume the sequence, passing all its arguments to the function.
|
(** Consume the sequence, passing all its arguments to the function.
|
||||||
Basically [iter f seq] is just [seq f]. *)
|
Basically [iter f seq] is just [seq f]. *)
|
||||||
|
|
||||||
val iteri : f:(int -> 'a -> unit) -> 'a t -> unit
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
val mem : ?eq:('a -> 'a -> bool) -> x:'a -> 'a t -> bool
|
||||||
(** Is the value a member of the sequence?
|
(** Is the value a member of the sequence?
|
||||||
@param eq the equality predicate to use (default [(=)]) *)
|
@param eq the equality predicate to use (default [(=)]) *)
|
||||||
|
|
||||||
val find : f:('a -> 'b option) -> 'a t -> 'b option
|
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
|
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
|
val is_empty : 'a t -> bool
|
||||||
(** Is the sequence empty? Forces the sequence. *)
|
(** Is the sequence empty? Forces the sequence. *)
|
||||||
|
|
||||||
(** {2 Transform a sequence} *)
|
(** {2 Transform a sequence} *)
|
||||||
|
|
||||||
val filter : f:('a -> bool) -> 'a t -> 'a t
|
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
|
val append : 'a t -> 'a t -> 'a t
|
||||||
(** Append two sequences. Iterating on the result is like iterating
|
(** Append two sequences. Iterating on the result is like iterating
|
||||||
on the first, then on the second. *)
|
on the first, then on the second. *)
|
||||||
|
|
||||||
val concat : 'a t t -> 'a t
|
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
|
val flatten : 'a t t -> 'a t
|
||||||
(** Alias for {!concat} *)
|
(** Alias for {!concat} *)
|
||||||
|
|
||||||
val flatMap : f:('a -> 'b t) -> 'a t -> 'b t
|
val flatMap : f:('a -> 'b t) -> 'a t -> 'b t
|
||||||
(** Monadic bind. Intuitively, it applies the function to every element of the
|
(** @deprecated use {!flat_map} *)
|
||||||
initial sequence, and calls {!concat}.
|
|
||||||
@deprecated use {!flat_map} *)
|
|
||||||
|
|
||||||
val flat_map : f:('a -> 'b t) -> 'a t -> 'b t
|
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
|
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
|
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
|
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} *)
|
(** {2 Caching} *)
|
||||||
|
|
||||||
val persistent : 'a t -> 'a t
|
val persistent : 'a t -> 'a t
|
||||||
(** Iterate on the sequence, storing elements in an efficient internal structure..
|
(** Iterate on the sequence, storing elements in an efficient internal structure..
|
||||||
The resulting sequence can be iterated on as many times as needed.
|
The resulting sequence can be iterated on as many times as needed.
|
||||||
{b Note}: calling persistent on an already persistent sequence
|
{b Note}: calling persistent on an already persistent sequence
|
||||||
will still make a new copy of the sequence! *)
|
will still make a new copy of the sequence! *)
|
||||||
|
|
||||||
val persistent_lazy : 'a t -> 'a t
|
val persistent_lazy : 'a t -> 'a t
|
||||||
(** Lazy version of {!persistent}. When calling [persistent_lazy s],
|
(** Lazy version of {!persistent}. When calling [persistent_lazy s],
|
||||||
a new sequence [s'] is immediately returned (without actually consuming
|
a new sequence [s'] is immediately returned (without actually consuming
|
||||||
[s]) in constant time; the first time [s'] is iterated on,
|
[s]) in constant time; the first time [s'] is iterated on,
|
||||||
it also consumes [s] and caches its content into a inner data
|
it also consumes [s] and caches its content into a inner data
|
||||||
structure that will back [s'] for future iterations.
|
structure that will back [s'] for future iterations.
|
||||||
|
|
||||||
{b warning}: on the first traversal of [s'], if the traversal
|
{b warning}: on the first traversal of [s'], if the traversal
|
||||||
is interrupted prematurely ({!take}, etc.) then [s'] will not be
|
is interrupted prematurely ({!take}, etc.) then [s'] will not be
|
||||||
memorized, and the next call to [s'] will traverse [s] again. *)
|
memorized, and the next call to [s'] will traverse [s] again. *)
|
||||||
|
|
||||||
(** {2 Misc} *)
|
(** {2 Misc} *)
|
||||||
|
|
||||||
val sort : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t
|
val sort : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t
|
||||||
(** Sort the sequence. Eager, O(n) ram and O(n ln(n)) time.
|
(** Sort the sequence. Eager, O(n) ram and O(n ln(n)) time.
|
||||||
It iterates on elements of the argument sequence immediately,
|
It iterates on elements of the argument sequence immediately,
|
||||||
before it sorts them. *)
|
before it sorts them. *)
|
||||||
|
|
||||||
val sort_uniq : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t
|
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
|
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
|
val uniq : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t
|
||||||
(** Remove consecutive duplicate elements. Basically this is
|
(** Remove consecutive duplicate elements. Basically this is
|
||||||
like [fun seq -> map List.hd (group seq)]. *)
|
like [fun seq -> map List.hd (group seq)]. *)
|
||||||
|
|
||||||
val product : 'a t -> 'b t -> ('a * 'b) t
|
val product : 'a t -> 'b t -> ('a * 'b) t
|
||||||
(** Cartesian product of the sequences. When calling [product a b],
|
(** Cartesian product of the sequences. When calling [product a b],
|
||||||
the caller {b MUST} ensure that [b] can be traversed as many times
|
the caller {b MUST} ensure that [b] can be traversed as many times
|
||||||
as required (several times), possibly by calling {!persistent} on it
|
as required (several times), possibly by calling {!persistent} on it
|
||||||
beforehand. *)
|
beforehand. *)
|
||||||
|
|
||||||
val product2 : 'a t -> 'b t -> ('a, 'b) t2
|
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
|
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
|
(** [join ~join_row a b] combines every element of [a] with every
|
||||||
element of [b] using [join_row]. If [join_row] returns None, then
|
element of [b] using [join_row]. If [join_row] returns None, then
|
||||||
the two elements do not combine. Assume that [b] allows for multiple
|
the two elements do not combine. Assume that [b] allows for multiple
|
||||||
iterations. *)
|
iterations. *)
|
||||||
|
|
||||||
val unfoldr : ('b -> ('a * 'b) option) -> 'b -> 'a t
|
val unfoldr : ('b -> ('a * 'b) option) -> 'b -> 'a t
|
||||||
(** [unfoldr f b] will apply [f] to [b]. If it
|
(** [unfoldr f b] will apply [f] to [b]. If it
|
||||||
yields [Some (x,b')] then [x] is returned
|
yields [Some (x,b')] then [x] is returned
|
||||||
and unfoldr recurses with [b']. *)
|
and unfoldr recurses with [b']. *)
|
||||||
|
|
||||||
val scan : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b t
|
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
|
val max : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option
|
||||||
(** Max element of the sequence, using the given comparison function.
|
(** Max element of the sequence, using the given comparison function.
|
||||||
@return None if the sequence is empty, Some [m] where [m] is the maximal
|
@return None if the sequence is empty, Some [m] where [m] is the maximal
|
||||||
element otherwise *)
|
element otherwise *)
|
||||||
|
|
||||||
val min : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option
|
val min : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option
|
||||||
(** Min element of the sequence, using the given comparison function.
|
(** Min element of the sequence, using the given comparison function.
|
||||||
see {!max} for more details. *)
|
see {!max} for more details. *)
|
||||||
|
|
||||||
val head : 'a t -> 'a option
|
val head : 'a t -> 'a option
|
||||||
(** First element, if any, otherwise [None] *)
|
(** First element, if any, otherwise [None] *)
|
||||||
|
|
||||||
val head_exn : 'a t -> 'a
|
val head_exn : 'a t -> 'a
|
||||||
(** First element, if any, fails
|
(** First element, if any, fails
|
||||||
@raise Invalid_argument if the sequence is empty *)
|
@raise Invalid_argument if the sequence is empty *)
|
||||||
|
|
||||||
val take : int -> 'a t -> 'a t
|
val take : int -> 'a t -> 'a t
|
||||||
(** Take at most [n] elements from the sequence. Works on infinite
|
(** Take at most [n] elements from the sequence. Works on infinite
|
||||||
sequences. *)
|
sequences. *)
|
||||||
|
|
||||||
val take_while : f:('a -> bool) -> 'a t -> 'a t
|
val take_while : f:('a -> bool) -> 'a t -> 'a t
|
||||||
(** Take elements while they satisfy the predicate, then stops iterating.
|
(** Take elements while they satisfy the predicate, then stops iterating.
|
||||||
Will work on an infinite sequence [s] if the predicate is false for at
|
Will work on an infinite sequence [s] if the predicate is false for at
|
||||||
least one element of [s]. *)
|
least one element of [s]. *)
|
||||||
|
|
||||||
val fold_while : f:('a -> 'b -> 'a * [`Stop | `Continue]) -> init:'a -> 'b t -> 'a
|
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
|
(** Folds over elements of the sequence, stopping early if the accumulator
|
||||||
returns [('a, `Stop)] *)
|
returns [('a, `Stop)] *)
|
||||||
|
|
||||||
val drop : int -> 'a t -> 'a t
|
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
|
val drop_while : f:('a -> bool) -> 'a t -> 'a t
|
||||||
(** Predicate version of {!drop} *)
|
(** Predicate version of {!drop} *)
|
||||||
|
|
||||||
val rev : 'a t -> 'a t
|
val rev : 'a t -> 'a t
|
||||||
(** Reverse the sequence. O(n) memory and time, needs the
|
(** Reverse the sequence. O(n) memory and time, needs the
|
||||||
sequence to be finite. The result is persistent and does
|
sequence to be finite. The result is persistent and does
|
||||||
not depend on the input being repeatable. *)
|
not depend on the input being repeatable. *)
|
||||||
|
|
||||||
(** {2 Binary sequences} *)
|
(** {2 Binary sequences} *)
|
||||||
|
|
||||||
|
|
@ -272,7 +248,7 @@ val zip : ('a, 'b) t2 -> ('a * 'b) t
|
||||||
val unzip : ('a * 'b) t -> ('a, 'b) t2
|
val unzip : ('a * 'b) t -> ('a, 'b) t2
|
||||||
|
|
||||||
val zip_i : 'a t -> (int, 'a) 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
|
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 : f:('a -> 'b -> 'c) -> ('a, 'b) t2 -> 'c t
|
||||||
|
|
||||||
val map2_2 : ('a -> 'b -> 'c) -> ('a -> 'b -> 'd) -> ('a, 'b) t2 -> ('c, 'd) t2
|
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} *)
|
(** {2 Basic data structures converters} *)
|
||||||
|
|
||||||
val to_list : 'a t -> 'a list
|
val to_list : 'a t -> 'a list
|
||||||
(** Convert the sequence into a list. Preserves order of elements.
|
(** Convert the sequence into a list. Preserves order of elements.
|
||||||
This function is tail-recursive, but consumes 2*n memory.
|
This function is tail-recursive, but consumes 2*n memory.
|
||||||
If order doesn't matter to you, consider {!to_rev_list}. *)
|
If order doesn't matter to you, consider {!to_rev_list}. *)
|
||||||
|
|
||||||
val to_rev_list : 'a t -> 'a 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
|
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]. *)
|
(** [on_list f l] is equivalent to [to_list @@ f @@ of_list l]. *)
|
||||||
|
|
||||||
val to_opt : 'a t -> 'a option
|
val to_opt : 'a t -> 'a option
|
||||||
(** Alias to {!head} *)
|
(** Alias to {!head} *)
|
||||||
|
|
||||||
val to_array : 'a t -> 'a array
|
val to_array : 'a t -> 'a array
|
||||||
(** Convert to an array. Currently not very efficient because
|
(** Convert to an array. Currently not very efficient because
|
||||||
an intermediate list is used. *)
|
an intermediate list is used. *)
|
||||||
|
|
||||||
val of_array : 'a array -> 'a t
|
val of_array : 'a array -> 'a t
|
||||||
|
|
||||||
val of_array_i : 'a array -> (int * '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 of_array2 : 'a array -> (int, 'a) t2
|
||||||
|
|
||||||
val array_slice : 'a array -> int -> int -> 'a t
|
val array_slice : 'a array -> int -> int -> 'a t
|
||||||
(** [array_slice a i j] Sequence of elements whose indexes range
|
(** [array_slice a i j] Sequence of elements whose indexes range
|
||||||
from [i] to [j] *)
|
from [i] to [j] *)
|
||||||
|
|
||||||
val of_opt : 'a option -> 'a t
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
val hashtbl_add : ('a, 'b) Hashtbl.t -> ('a * 'b) t -> unit
|
||||||
(** Add elements of the sequence to the hashtable, with
|
(** Add elements of the sequence to the hashtable, with
|
||||||
Hashtbl.add *)
|
Hashtbl.add *)
|
||||||
|
|
||||||
val hashtbl_replace : ('a, 'b) Hashtbl.t -> ('a * 'b) t -> unit
|
val hashtbl_replace : ('a, 'b) Hashtbl.t -> ('a * 'b) t -> unit
|
||||||
(** Add elements of the sequence to the hashtable, with
|
(** Add elements of the sequence to the hashtable, with
|
||||||
Hashtbl.replace (erases conflicting bindings) *)
|
Hashtbl.replace (erases conflicting bindings) *)
|
||||||
|
|
||||||
val to_hashtbl : ('a * 'b) t -> ('a, 'b) Hashtbl.t
|
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
|
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
|
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
|
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_keys : ('a, 'b) Hashtbl.t -> 'a t
|
||||||
val hashtbl_values : ('a, 'b) Hashtbl.t -> 'b 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 to_str : char t -> string
|
||||||
|
|
||||||
val concat_str : string t -> string
|
val concat_str : string t -> string
|
||||||
(** Concatenate strings together, eagerly.
|
(** Concatenate strings together, eagerly.
|
||||||
Also see {!intersperse} to add a separator. *)
|
Also see {!intersperse} to add a separator. *)
|
||||||
|
|
||||||
exception OneShotSequence
|
exception OneShotSequence
|
||||||
(** Raised when the user tries to iterate several times on
|
(** Raised when the user tries to iterate several times on
|
||||||
a transient iterator *)
|
a transient iterator *)
|
||||||
|
|
||||||
val of_in_channel : in_channel -> char t
|
val of_in_channel : in_channel -> char t
|
||||||
(** Iterates on characters of the input (can block when one
|
(** Iterates on characters of the input (can block when one
|
||||||
iterates over the sequence). If you need to iterate
|
iterates over the sequence). If you need to iterate
|
||||||
several times on this sequence, use {!persistent}.
|
several times on this sequence, use {!persistent}.
|
||||||
@raise OneShotSequence when used more than once. *)
|
@raise OneShotSequence when used more than once. *)
|
||||||
|
|
||||||
val to_buffer : char t -> Buffer.t -> unit
|
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
|
val int_range : start:int -> stop:int -> int t
|
||||||
(** Iterator on integers in [start...stop] by steps 1. Also see
|
(** Iterator on integers in [start...stop] by steps 1. Also see
|
||||||
{!(--)} for an infix version. *)
|
{!(--)} for an infix version. *)
|
||||||
|
|
||||||
val int_range_dec : start:int -> stop:int -> int t
|
val int_range_dec : start:int -> stop:int -> int t
|
||||||
(** Iterator on decreasing integers in [stop...start] by steps -1.
|
(** Iterator on decreasing integers in [stop...start] by steps -1.
|
||||||
See {!(--^)} for an infix version *)
|
See {!(--^)} for an infix version *)
|
||||||
|
|
||||||
val of_set : (module Set.S with type elt = 'a and type t = 'b) -> 'b -> 'a t
|
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
|
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 gen = unit -> 'a option
|
||||||
type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist]
|
type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist]
|
||||||
|
|
||||||
val of_gen : 'a gen -> 'a t
|
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
|
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
|
val of_klist : 'a klist -> 'a t
|
||||||
(** Iterate on the lazy list *)
|
(** Iterate on the lazy list *)
|
||||||
|
|
||||||
val to_klist : 'a t -> 'a klist
|
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} *)
|
(** {2 Functorial conversions between sets and sequences} *)
|
||||||
|
|
||||||
|
|
@ -450,44 +426,44 @@ end
|
||||||
(** {2 Infinite sequences of random values} *)
|
(** {2 Infinite sequences of random values} *)
|
||||||
|
|
||||||
val random_int : int -> int t
|
val random_int : int -> int t
|
||||||
(** Infinite sequence of random integers between 0 and
|
(** Infinite sequence of random integers between 0 and
|
||||||
the given higher bound (see Random.int) *)
|
the given higher bound (see Random.int) *)
|
||||||
|
|
||||||
val random_bool : bool t
|
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_float : float -> float t
|
||||||
|
|
||||||
val random_array : 'a array -> 'a 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
|
val random_list : 'a list -> 'a t
|
||||||
(** Infinite sequence of random elements of the list. Basically the
|
(** Infinite sequence of random elements of the list. Basically the
|
||||||
same as {!random_array}. *)
|
same as {!random_array}. *)
|
||||||
|
|
||||||
(** {2 Infix functions} *)
|
(** {2 Infix functions} *)
|
||||||
|
|
||||||
module Infix : sig
|
module Infix : sig
|
||||||
val (--) : int -> int -> int t
|
val (--) : int -> int -> int t
|
||||||
(** [a -- b] is the range of integers from [a] to [b], both included,
|
(** [a -- b] is the range of integers from [a] to [b], both included,
|
||||||
in increasing order. It will therefore be empty if [a > b]. *)
|
in increasing order. It will therefore be empty if [a > b]. *)
|
||||||
|
|
||||||
val (--^) : int -> int -> int t
|
val (--^) : int -> int -> int t
|
||||||
(** [a --^ b] is the range of integers from [b] to [a], both included,
|
(** [a --^ b] is the range of integers from [b] to [a], both included,
|
||||||
in decreasing order (starts from [a]).
|
in decreasing order (starts from [a]).
|
||||||
It will therefore be empty if [a < b]. *)
|
It will therefore be empty if [a < b]. *)
|
||||||
|
|
||||||
val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
|
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
|
val (>|=) : 'a t -> ('a -> 'b) -> 'b t
|
||||||
(** Infix version of {!map} *)
|
(** Infix version of {!map} *)
|
||||||
|
|
||||||
val (<*>) : ('a -> 'b) t -> 'a t -> 'b t
|
val (<*>) : ('a -> 'b) t -> 'a t -> 'b t
|
||||||
(** Applicative operator (product+application) *)
|
(** Applicative operator (product+application) *)
|
||||||
|
|
||||||
val (<+>) : 'a t -> 'a t -> 'a t
|
val (<+>) : 'a t -> 'a t -> 'a t
|
||||||
(** Concatenation of sequences *)
|
(** Concatenation of sequences *)
|
||||||
end
|
end
|
||||||
|
|
||||||
include module type of Infix
|
include module type of Infix
|
||||||
|
|
@ -496,46 +472,46 @@ include module type of Infix
|
||||||
(** {2 Pretty printing of sequences} *)
|
(** {2 Pretty printing of sequences} *)
|
||||||
|
|
||||||
val pp_seq : ?sep:string -> (Format.formatter -> 'a -> unit) ->
|
val pp_seq : ?sep:string -> (Format.formatter -> 'a -> unit) ->
|
||||||
Format.formatter -> 'a t -> unit
|
Format.formatter -> 'a t -> unit
|
||||||
(** Pretty print a sequence of ['a], using the given pretty printer
|
(** Pretty print a sequence of ['a], using the given pretty printer
|
||||||
to print each elements. An optional separator string can be provided. *)
|
to print each elements. An optional separator string can be provided. *)
|
||||||
|
|
||||||
val pp_buf : ?sep:string -> (Buffer.t -> 'a -> unit) ->
|
val pp_buf : ?sep:string -> (Buffer.t -> 'a -> unit) ->
|
||||||
Buffer.t -> 'a t -> unit
|
Buffer.t -> 'a t -> unit
|
||||||
(** Print into a buffer *)
|
(** Print into a buffer *)
|
||||||
|
|
||||||
val to_string : ?sep:string -> ('a -> string) -> 'a t -> string
|
val to_string : ?sep:string -> ('a -> string) -> 'a t -> string
|
||||||
(** Print into a string *)
|
(** Print into a string *)
|
||||||
|
|
||||||
(** {2 Basic IO}
|
(** {2 Basic IO}
|
||||||
|
|
||||||
Very basic interface to manipulate files as sequence of chunks/lines. The
|
Very basic interface to manipulate files as sequence of chunks/lines. The
|
||||||
sequences take care of opening and closing files properly; every time
|
sequences take care of opening and closing files properly; every time
|
||||||
one iterates over a sequence, the file is opened/closed again.
|
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
|
module IO : sig
|
||||||
val lines_of : ?mode:int -> ?flags:open_flag list ->
|
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
|
(** [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
|
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
|
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]] *)
|
@param flags default: [[Open_rdonly]] *)
|
||||||
|
|
||||||
val chunks_of : ?mode:int -> ?flags:open_flag list -> ?size:int ->
|
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
|
(** Read chunks of the given [size] from the file. The last chunk might be
|
||||||
smaller. Behaves like {!lines_of} regarding errors and options.
|
smaller. Behaves like {!lines_of} regarding errors and options.
|
||||||
Every time the sequence is iterated on, the file is opened again, so
|
Every time the sequence is iterated on, the file is opened again, so
|
||||||
different iterations might return different results *)
|
different iterations might return different results *)
|
||||||
|
|
||||||
val write_to : ?mode:int -> ?flags:open_flag list ->
|
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
|
(** [write_to filename seq] writes all strings from [seq] into the given
|
||||||
file. It takes care of opening and closing the file.
|
file. It takes care of opening and closing the file.
|
||||||
@param mode default [0o644]
|
@param mode default [0o644]
|
||||||
@param flags used by [open_out_gen]. Default: [[Open_creat;Open_wronly]]. *)
|
@param flags used by [open_out_gen]. Default: [[Open_creat;Open_wronly]]. *)
|
||||||
|
|
||||||
val write_bytes_to : ?mode:int -> ?flags:open_flag list ->
|
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 ->
|
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 *)
|
(** Same as {!write_to}, but intercales ['\n'] between each string *)
|
||||||
|
|
||||||
val write_bytes_lines : ?mode:int -> ?flags:open_flag list ->
|
val write_bytes_lines : ?mode:int -> ?flags:open_flag list ->
|
||||||
string -> Bytes.t t -> unit
|
string -> Bytes.t t -> unit
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue