mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 11:15:31 -05:00
include the sequence module in here, to reduce dependencies.
This commit is contained in:
parent
ec8145448d
commit
fb52aad014
4 changed files with 841 additions and 4 deletions
2
Makefile
2
Makefile
|
|
@ -3,7 +3,7 @@ INTERFACE_FILES = $(shell find -name '*.mli')
|
|||
IMPLEMENTATION_FILES = $(shell find -name '*.ml')
|
||||
|
||||
TARGETS_LIB = containers.cmxa containers.cma
|
||||
OPTIONS = -use-ocamlfind -package sequence
|
||||
OPTIONS = -use-ocamlfind
|
||||
|
||||
all:
|
||||
ocamlbuild $(OPTIONS) $(TARGETS_LIB)
|
||||
|
|
|
|||
3
_tags
3
_tags
|
|
@ -1,3 +0,0 @@
|
|||
<src>: include
|
||||
<**/*.ml*>: package(sequence)
|
||||
<**/*.cm*>: package(sequence)
|
||||
543
sequence.ml
Normal file
543
sequence.ml
Normal file
|
|
@ -0,0 +1,543 @@
|
|||
(*
|
||||
Copyright (c) 2013, Simon Cruanes
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer. Redistributions in binary
|
||||
form must reproduce the above copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other materials provided with
|
||||
the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*)
|
||||
|
||||
(** {1 Transient iterators, that abstract on a finite sequence of elements. *)
|
||||
|
||||
(** Sequence abstract iterator type *)
|
||||
type 'a t = ('a -> unit) -> unit
|
||||
|
||||
(** Build a sequence from a iter function *)
|
||||
let from_iter f = f
|
||||
|
||||
let empty = fun k -> ()
|
||||
|
||||
let singleton x = fun k -> k x
|
||||
|
||||
(** Infinite sequence of the same element *)
|
||||
let repeat x = fun k -> while true do k x done
|
||||
|
||||
(** [iterate f x] is the infinite sequence (x, f(x), f(f(x)), ...) *)
|
||||
let iterate f x =
|
||||
let rec iterate k x = k x; iterate k (f x) in
|
||||
from_iter (fun k -> iterate k x)
|
||||
|
||||
(** Sequence that calls the given function to produce elements *)
|
||||
let forever f =
|
||||
let rec forever k = k (f ()); forever k in
|
||||
from_iter forever
|
||||
|
||||
(** Cycle forever through the given sequence. O(n). *)
|
||||
let cycle s = fun k -> while true do s k; done
|
||||
|
||||
(** Consume the sequence, passing all its arguments to the function *)
|
||||
let iter f seq = seq f
|
||||
|
||||
(** Iterate on elements and their index in the sequence *)
|
||||
let iteri f seq =
|
||||
let r = ref 0 in
|
||||
let k x =
|
||||
f !r x;
|
||||
incr r
|
||||
in seq k
|
||||
|
||||
(** Fold over elements of the sequence, consuming it *)
|
||||
let fold f init seq =
|
||||
let r = ref init in
|
||||
seq (fun elt -> r := f !r elt);
|
||||
!r
|
||||
|
||||
(** Fold over elements of the sequence and their index, consuming it *)
|
||||
let foldi f init seq =
|
||||
let i = ref 0 in
|
||||
let r = ref init in
|
||||
seq (fun elt ->
|
||||
r := f !r !i elt;
|
||||
incr i);
|
||||
!r
|
||||
|
||||
(** Map objects of the sequence into other elements, lazily *)
|
||||
let map f seq =
|
||||
let seq_fun' k = seq (fun x -> k (f x)) in
|
||||
seq_fun'
|
||||
|
||||
(** Map objects, along with their index in the sequence *)
|
||||
let mapi f seq =
|
||||
let seq_fun' k =
|
||||
let i = ref 0 in
|
||||
seq (fun x -> k (f !i x); incr i) in
|
||||
seq_fun'
|
||||
|
||||
(** Filter on elements of the sequence *)
|
||||
let filter p seq =
|
||||
let seq_fun' k = seq (fun x -> if p x then k x) in
|
||||
seq_fun'
|
||||
|
||||
(** Append two sequences *)
|
||||
let append s1 s2 =
|
||||
let seq_fun k = s1 k; s2 k in
|
||||
seq_fun
|
||||
|
||||
(** Concatenate a sequence of sequences into one sequence *)
|
||||
let concat s =
|
||||
from_iter (fun k ->
|
||||
(* function that is called on every sub-sequence *)
|
||||
let k_seq seq = iter k seq in
|
||||
s k_seq)
|
||||
|
||||
(** Monadic bind. It applies the function to every element of the
|
||||
initial sequence, and calls [concat]. *)
|
||||
let flatMap f seq =
|
||||
from_iter
|
||||
(fun k -> seq (fun x -> (f x) k))
|
||||
|
||||
(** Insert the second element between every element of the sequence *)
|
||||
let intersperse seq elem =
|
||||
from_iter
|
||||
(fun k -> seq (fun x -> k x; k elem))
|
||||
|
||||
(** Mutable unrolled list to serve as intermediate storage *)
|
||||
module MList = struct
|
||||
type 'a t = {
|
||||
content : 'a array; (* elements of the node *)
|
||||
mutable len : int; (* number of elements in content *)
|
||||
mutable tl : 'a t; (* tail *)
|
||||
} (** A list that contains some elements, and may point to another list *)
|
||||
|
||||
let _empty () : 'a t = Obj.magic 0
|
||||
(** Empty list, for the tl field *)
|
||||
|
||||
let make n =
|
||||
assert (n > 0);
|
||||
{ content = Array.make n (Obj.magic 0);
|
||||
len = 0;
|
||||
tl = _empty ();
|
||||
}
|
||||
|
||||
let rec is_empty l =
|
||||
l.len = 0 && (l.tl == _empty () || is_empty l.tl)
|
||||
|
||||
let rec iter f l =
|
||||
for i = 0 to l.len - 1 do f l.content.(i); done;
|
||||
if l.tl != _empty () then iter f l.tl
|
||||
|
||||
let iteri f l =
|
||||
let rec iteri i f l =
|
||||
for j = 0 to l.len - 1 do f (i+j) l.content.(j); done;
|
||||
if l.tl != _empty () then iteri (i+l.len) f l.tl
|
||||
in iteri 0 f l
|
||||
|
||||
let rec iter_rev f l =
|
||||
(if l.tl != _empty () then iter_rev f l.tl);
|
||||
for i = l.len - 1 downto 0 do f l.content.(i); done
|
||||
|
||||
let length l =
|
||||
let rec len acc l =
|
||||
if l.tl == _empty () then acc+l.len else len (acc+l.len) l.tl
|
||||
in len 0 l
|
||||
|
||||
(** Get element by index *)
|
||||
let rec get l i =
|
||||
if i < l.len then l.content.(i)
|
||||
else if i >= l.len && l.tl == _empty () then raise (Invalid_argument "MList.get")
|
||||
else get l.tl (i - l.len)
|
||||
|
||||
(** Push [x] at the end of the list. It returns the block in which the
|
||||
element is inserted. *)
|
||||
let rec push x l =
|
||||
if l.len = Array.length l.content
|
||||
then begin (* insert in the next block *)
|
||||
(if l.tl == _empty () then l.tl <- make (Array.length l.content));
|
||||
push x l.tl
|
||||
end else begin (* insert in l *)
|
||||
l.content.(l.len) <- x;
|
||||
l.len <- l.len + 1;
|
||||
l
|
||||
end
|
||||
|
||||
(** Reverse list (in place), and returns the new head *)
|
||||
let rev l =
|
||||
let rec rev prev l =
|
||||
(* reverse array *)
|
||||
for i = 0 to (l.len-1) / 2 do
|
||||
let x = l.content.(i) in
|
||||
l.content.(i) <- l.content.(l.len - i - 1);
|
||||
l.content.(l.len - i - 1) <- x;
|
||||
done;
|
||||
(* reverse next block *)
|
||||
let l' = l.tl in
|
||||
l.tl <- prev;
|
||||
if l' == _empty () then l else rev l l'
|
||||
in
|
||||
rev (_empty ()) l
|
||||
|
||||
(** Build a MList of elements of the Seq. The optional argument indicates
|
||||
the size of the blocks *)
|
||||
let of_seq ?(size=64) seq =
|
||||
(* read sequence into a MList.t *)
|
||||
let start = make size in
|
||||
let l = ref start in
|
||||
seq (fun x -> l := push x !l);
|
||||
start
|
||||
end
|
||||
|
||||
(** Iterate on the sequence, storing elements in a data structure.
|
||||
The resulting sequence can be iterated on as many times as needed. *)
|
||||
let persistent (seq : 'a t) : 'a t =
|
||||
let l = MList.of_seq seq in
|
||||
from_iter (fun k -> MList.iter k l)
|
||||
|
||||
(** Cartesian product of the sequences. *)
|
||||
let product outer inner =
|
||||
let outer = persistent outer in
|
||||
from_iter
|
||||
(fun k ->
|
||||
outer (fun x ->
|
||||
inner (fun y -> k (x,y))))
|
||||
|
||||
(** [unfoldr f b] will apply [f] to [b]. If it
|
||||
yields [Some (x,b')] then [x] is returned
|
||||
and unfoldr recurses with [b']. *)
|
||||
let unfoldr f b =
|
||||
let rec unfold k b = match f b with
|
||||
| None -> ()
|
||||
| Some (x, b') -> k x; unfold k b'
|
||||
in
|
||||
from_iter (fun k -> unfold k b)
|
||||
|
||||
(** Max element of the sequence, using the given comparison
|
||||
function. A default element has to be provided. *)
|
||||
let max ?(lt=fun x y -> x < y) seq m =
|
||||
fold (fun m x -> if lt m x then x else m) m seq
|
||||
|
||||
(** Min element of the sequence, using the given comparison function *)
|
||||
let min ?(lt=fun x y -> x < y) seq m =
|
||||
fold (fun m x -> if lt x m then x else m) m seq
|
||||
|
||||
exception ExitSequence
|
||||
|
||||
(** Take at most [n] elements from the sequence *)
|
||||
let take n seq =
|
||||
let count = ref 0 in
|
||||
fun k ->
|
||||
try
|
||||
seq
|
||||
(fun x -> if !count < n then begin incr count; k x end
|
||||
else raise ExitSequence)
|
||||
with ExitSequence -> ()
|
||||
|
||||
(** Drop the [n] first elements of the sequence *)
|
||||
let drop n seq =
|
||||
let count = ref 0 in
|
||||
fun k -> seq
|
||||
(fun x -> if !count >= n then k x else incr count)
|
||||
|
||||
(** Reverse the sequence. O(n) memory. *)
|
||||
let rev seq =
|
||||
let l = MList.of_seq seq in
|
||||
from_iter (fun k -> MList.iter_rev k l)
|
||||
|
||||
(** Do all elements satisfy the predicate? *)
|
||||
let for_all p seq =
|
||||
try
|
||||
seq (fun x -> if not (p x) then raise ExitSequence);
|
||||
true
|
||||
with ExitSequence -> false
|
||||
|
||||
(** Exists there some element satisfying the predicate? *)
|
||||
let exists p seq =
|
||||
try
|
||||
seq (fun x -> if p x then raise ExitSequence);
|
||||
false
|
||||
with ExitSequence -> true
|
||||
|
||||
(** How long is the sequence? *)
|
||||
let length seq =
|
||||
let r = ref 0 in
|
||||
seq (fun _ -> incr r);
|
||||
!r
|
||||
|
||||
(** Is the sequence empty? *)
|
||||
let is_empty seq =
|
||||
try seq (fun _ -> raise ExitSequence); true
|
||||
with ExitSequence -> false
|
||||
|
||||
let to_list seq = List.rev (fold (fun y x -> x::y) [] seq)
|
||||
|
||||
let to_rev_list seq = fold (fun y x -> x :: y) [] seq
|
||||
(** Get the list of the reversed sequence (more efficient) *)
|
||||
|
||||
let of_list l = from_iter (fun k -> List.iter k l)
|
||||
|
||||
let to_array seq =
|
||||
let l = MList.of_seq seq in
|
||||
let n = MList.length l in
|
||||
if n = 0
|
||||
then [||]
|
||||
else begin
|
||||
let a = Array.make n (MList.get l 0) in
|
||||
MList.iteri (fun i x -> a.(i) <- x) l;
|
||||
a
|
||||
end
|
||||
|
||||
let of_array a = from_iter (fun k -> Array.iter k a)
|
||||
|
||||
let of_array_i a =
|
||||
let seq k =
|
||||
for i = 0 to Array.length a - 1 do k (i, a.(i)) done
|
||||
in from_iter seq
|
||||
|
||||
(** [array_slice a i j] Sequence of elements whose indexes range
|
||||
from [i] to [j] *)
|
||||
let array_slice a i j =
|
||||
assert (i >= 0 && j < Array.length a);
|
||||
fun k ->
|
||||
for idx = i to j do
|
||||
k a.(idx); (* iterate on sub-array *)
|
||||
done
|
||||
|
||||
(** Sequence of elements of a stream (usable only once) *)
|
||||
let of_stream s =
|
||||
let seq k = Stream.iter k s in
|
||||
from_iter seq
|
||||
|
||||
(** Convert to a stream. The sequence is made persistent. *)
|
||||
let to_stream seq =
|
||||
let l = ref (MList.of_seq seq) in
|
||||
let i = ref 0 in
|
||||
let rec get_next () =
|
||||
if !l == MList._empty () then None
|
||||
else if (!l).MList.len = !i then (l := (!l).MList.tl; i := 0; get_next ())
|
||||
else let x = (!l).MList.content.(!i) in (incr i; Some x)
|
||||
in
|
||||
Stream.from (fun _ -> get_next ())
|
||||
|
||||
(** Push elements of the sequence on the stack *)
|
||||
let to_stack s seq = iter (fun x -> Stack.push x s) seq
|
||||
|
||||
(** Sequence of elements of the stack (same order as [Stack.iter]) *)
|
||||
let of_stack s = from_iter (fun k -> Stack.iter k s)
|
||||
|
||||
(** Push elements of the sequence into the queue *)
|
||||
let to_queue q seq = iter (fun x -> Queue.push x q) seq
|
||||
|
||||
(** Sequence of elements contained in the queue, FIFO order *)
|
||||
let of_queue q = from_iter (fun k -> Queue.iter k q)
|
||||
|
||||
let hashtbl_add h seq =
|
||||
iter (fun (k,v) -> Hashtbl.add h k v) seq
|
||||
|
||||
let hashtbl_replace h seq =
|
||||
iter (fun (k,v) -> Hashtbl.replace h k v) seq
|
||||
|
||||
let to_hashtbl seq =
|
||||
let h = Hashtbl.create 3 in
|
||||
hashtbl_replace h seq;
|
||||
h
|
||||
|
||||
let of_hashtbl h =
|
||||
from_iter (fun k -> Hashtbl.iter (fun a b -> k (a, b)) h)
|
||||
|
||||
let hashtbl_keys h =
|
||||
from_iter (fun k -> Hashtbl.iter (fun a b -> k a) h)
|
||||
|
||||
let hashtbl_values h =
|
||||
from_iter (fun k -> Hashtbl.iter (fun a b -> k b) h)
|
||||
|
||||
let of_str s = from_iter (fun k -> String.iter k s)
|
||||
|
||||
let to_str seq =
|
||||
let b = Buffer.create 64 in
|
||||
iter (fun c -> Buffer.add_char b c) seq;
|
||||
Buffer.contents b
|
||||
|
||||
let of_in_channel ic =
|
||||
from_iter (fun k ->
|
||||
try while true do
|
||||
let c = input_char ic in k c
|
||||
done with End_of_file -> ())
|
||||
|
||||
(** Copy content of the sequence into the buffer *)
|
||||
let to_buffer seq buf =
|
||||
iter (fun c -> Buffer.add_char buf c) seq
|
||||
|
||||
(** Iterator on integers in [start...stop] by steps 1 *)
|
||||
let int_range ~start ~stop =
|
||||
fun k ->
|
||||
for i = start to stop do k i done
|
||||
|
||||
(** Convert the given set to a sequence. The set module must be provided. *)
|
||||
let of_set (type s) (type v) m set =
|
||||
let module S = (val m : Set.S with type t = s and type elt = v) in
|
||||
from_iter
|
||||
(fun k -> S.iter k set)
|
||||
|
||||
(** Convert the sequence to a set, given the proper set module *)
|
||||
let to_set (type s) (type v) m seq =
|
||||
let module S = (val m : Set.S with type t = s and type elt = v) in
|
||||
fold
|
||||
(fun set x -> S.add x set)
|
||||
S.empty seq
|
||||
|
||||
(** {2 Functorial conversions between sets and sequences} *)
|
||||
|
||||
module Set = struct
|
||||
module type S = sig
|
||||
type set
|
||||
include Set.S with type t := set
|
||||
val of_seq : elt t -> set
|
||||
val to_seq : set -> elt t
|
||||
end
|
||||
|
||||
(** Create an enriched Set module from the given one *)
|
||||
module Adapt(X : Set.S) : S with type elt = X.elt and type set = X.t = struct
|
||||
type set = X.t
|
||||
|
||||
let to_seq set = from_iter (fun k -> X.iter k set)
|
||||
|
||||
let of_seq seq = fold (fun set x -> X.add x set) X.empty seq
|
||||
|
||||
include X
|
||||
end
|
||||
|
||||
(** Functor to build an extended Set module from an ordered type *)
|
||||
module Make(X : Set.OrderedType) : S with type elt = X.t = struct
|
||||
module MySet = Set.Make(X)
|
||||
include Adapt(MySet)
|
||||
end
|
||||
end
|
||||
|
||||
(** {2 Conversion between maps and sequences.} *)
|
||||
|
||||
module Map = struct
|
||||
module type S = sig
|
||||
type +'a map
|
||||
include Map.S with type 'a t := 'a map
|
||||
val to_seq : 'a map -> (key * 'a) t
|
||||
val of_seq : (key * 'a) t -> 'a map
|
||||
val keys : 'a map -> key t
|
||||
val values : 'a map -> 'a t
|
||||
end
|
||||
|
||||
(** Adapt a pre-existing Map module to make it sequence-aware *)
|
||||
module Adapt(M : Map.S) : S with type key = M.key and type 'a map = 'a M.t = struct
|
||||
type 'a map = 'a M.t
|
||||
|
||||
let to_seq m = from_iter (fun k -> M.iter (fun x y -> k (x,y)) m)
|
||||
|
||||
let of_seq seq = fold (fun m (k,v) -> M.add k v m) M.empty seq
|
||||
|
||||
let keys m = from_iter (fun k -> M.iter (fun x _ -> k x) m)
|
||||
|
||||
let values m = from_iter (fun k -> M.iter (fun _ y -> k y) m)
|
||||
|
||||
include M
|
||||
end
|
||||
|
||||
(** Create an enriched Map module, with sequence-aware functions *)
|
||||
module Make(V : Map.OrderedType) : S with type key = V.t = struct
|
||||
module M = Map.Make(V)
|
||||
include Adapt(M)
|
||||
end
|
||||
end
|
||||
|
||||
(** {2 Infinite sequences of random values} *)
|
||||
|
||||
let random_int bound = forever (fun () -> Random.int bound)
|
||||
|
||||
let random_bool = forever Random.bool
|
||||
|
||||
let random_float bound = forever (fun () -> Random.float bound)
|
||||
|
||||
(** Sequence of choices of an element in the array *)
|
||||
let random_array a =
|
||||
assert (Array.length a > 0);
|
||||
let seq k =
|
||||
while true do
|
||||
let i = Random.int (Array.length a) in
|
||||
k a.(i);
|
||||
done in
|
||||
from_iter seq
|
||||
|
||||
let random_list l = random_array (Array.of_list l)
|
||||
|
||||
(** {2 Type-classes} *)
|
||||
|
||||
module TypeClass = struct
|
||||
(** {3 Classes} *)
|
||||
type ('a,'b) sequenceable = {
|
||||
to_seq : 'b -> 'a t;
|
||||
of_seq : 'a t -> 'b;
|
||||
}
|
||||
|
||||
type ('a,'b) addable = {
|
||||
empty : 'b;
|
||||
add : 'b -> 'a -> 'b;
|
||||
}
|
||||
|
||||
type 'a monoid = ('a,'a) addable
|
||||
|
||||
type ('a,'b) iterable = {
|
||||
iter : ('a -> unit) -> 'b -> unit;
|
||||
}
|
||||
|
||||
(** {3 Instances} *)
|
||||
|
||||
let (sequenceable : ('a,'a t) sequenceable) = {
|
||||
to_seq = (fun seq -> seq);
|
||||
of_seq = (fun seq -> seq);
|
||||
}
|
||||
|
||||
let (iterable : ('a, 'a t) iterable) = {
|
||||
iter = (fun f seq -> iter f seq);
|
||||
}
|
||||
|
||||
let (monoid : 'a t monoid) = {
|
||||
empty = empty;
|
||||
add = (fun s1 s2 -> append s1 s2);
|
||||
}
|
||||
|
||||
(** {3 Conversions} *)
|
||||
|
||||
let of_iterable iterable x =
|
||||
from_iter (fun k -> iterable.iter k x)
|
||||
|
||||
|
||||
let to_addable addable seq =
|
||||
fold addable.add addable.empty seq
|
||||
end
|
||||
|
||||
|
||||
(** {2 Pretty printing of sequences} *)
|
||||
|
||||
(** Pretty print a sequence of ['a], using the given pretty printer
|
||||
to print each elements. An optional separator string can be provided. *)
|
||||
let pp_seq ?(sep=", ") pp_elt formatter seq =
|
||||
let first = ref true in
|
||||
iter
|
||||
(fun x ->
|
||||
(if !first then first := false else Format.pp_print_string formatter sep);
|
||||
pp_elt formatter x;
|
||||
Format.pp_print_cut formatter ())
|
||||
seq
|
||||
297
sequence.mli
Normal file
297
sequence.mli
Normal file
|
|
@ -0,0 +1,297 @@
|
|||
(*
|
||||
copyright (c) 2013, simon cruanes
|
||||
all rights reserved.
|
||||
|
||||
redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer. redistributions in binary
|
||||
form must reproduce the above copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other materials provided with
|
||||
the distribution.
|
||||
|
||||
this software is provided by the copyright holders and contributors "as is" and
|
||||
any express or implied warranties, including, but not limited to, the implied
|
||||
warranties of merchantability and fitness for a particular purpose are
|
||||
disclaimed. in no event shall the copyright holder or contributors be liable
|
||||
for any direct, indirect, incidental, special, exemplary, or consequential
|
||||
damages (including, but not limited to, procurement of substitute goods or
|
||||
services; loss of use, data, or profits; or business interruption) however
|
||||
caused and on any theory of liability, whether in contract, strict liability,
|
||||
or tort (including negligence or otherwise) arising in any way out of the use
|
||||
of this software, even if advised of the possibility of such damage.
|
||||
*)
|
||||
|
||||
(** Transient iterators, that abstract on a finite sequence of elements. They
|
||||
are designed to allow easy transfer (mappings) between data structures,
|
||||
without defining n^2 conversions between the n types. *)
|
||||
|
||||
type +'a t
|
||||
(** Sequence abstract iterator type, representing a finite sequence of
|
||||
values of type ['a]. *)
|
||||
|
||||
(** {2 Build a sequence} *)
|
||||
|
||||
val from_iter : (('a -> unit) -> unit) -> 'a t
|
||||
(** Build a sequence from a iter function *)
|
||||
|
||||
val empty : 'a t
|
||||
(** Empty sequence *)
|
||||
|
||||
val singleton : 'a -> 'a t
|
||||
(** Singleton sequence *)
|
||||
|
||||
val repeat : 'a -> 'a t
|
||||
(** Infinite sequence of the same element *)
|
||||
|
||||
val iterate : ('a -> 'a) -> 'a -> 'a t
|
||||
(** [iterate f x] is the infinite sequence (x, f(x), f(f(x)), ...) *)
|
||||
|
||||
val forever : (unit -> 'b) -> 'b t
|
||||
(** Sequence that calls the given function to produce elements *)
|
||||
|
||||
val cycle : 'a t -> 'a t
|
||||
(** Cycle forever through the given sequence. Assume the
|
||||
given sequence can be traversed any amount of times (not transient). *)
|
||||
|
||||
(** {2 Consume a sequence} *)
|
||||
|
||||
val iter : ('a -> unit) -> 'a t -> unit
|
||||
(** Consume the sequence, passing all its arguments to the function *)
|
||||
|
||||
val iteri : (int -> 'a -> unit) -> 'a t -> unit
|
||||
(** Iterate on elements and their index in the sequence *)
|
||||
|
||||
val fold : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b
|
||||
(** Fold over elements of the sequence, consuming it *)
|
||||
|
||||
val foldi : ('b -> int -> 'a -> 'b) -> 'b -> 'a t -> 'b
|
||||
(** Fold over elements of the sequence and their index, consuming it *)
|
||||
|
||||
val map : ('a -> 'b) -> 'a t -> 'b t
|
||||
(** Map objects of the sequence into other elements, lazily *)
|
||||
|
||||
val mapi : (int -> 'a -> 'b) -> 'a t -> 'b t
|
||||
(** Map objects, along with their index in the sequence *)
|
||||
|
||||
val for_all : ('a -> bool) -> 'a t -> bool
|
||||
(** Do all elements satisfy the predicate? *)
|
||||
|
||||
val exists : ('a -> bool) -> 'a t -> bool
|
||||
(** Exists there some element satisfying the predicate? *)
|
||||
|
||||
val length : 'a t -> int
|
||||
(** How long is the sequence? *)
|
||||
|
||||
val is_empty : 'a t -> bool
|
||||
(** Is the sequence empty? *)
|
||||
|
||||
(** {2 Transform a sequence} *)
|
||||
|
||||
val filter : ('a -> bool) -> 'a t -> 'a t
|
||||
(** Filter on elements of the sequence *)
|
||||
|
||||
val append : 'a t -> 'a t -> 'a t
|
||||
(** Append two sequences *)
|
||||
|
||||
val concat : 'a t t -> 'a t
|
||||
(** Concatenate a sequence of sequences into one sequence *)
|
||||
|
||||
val flatMap : ('a -> 'b t) -> 'a t -> 'b t
|
||||
(** Monadic bind. It applies the function to every element of the
|
||||
initial sequence, and calls [concat]. *)
|
||||
|
||||
val intersperse : 'a t -> 'a -> 'a t
|
||||
(** Insert the second element between every element of the sequence *)
|
||||
|
||||
val persistent : 'a t -> 'a t
|
||||
(** Iterate on the sequence, storing elements in a data structure.
|
||||
The resulting sequence can be iterated on as many times as needed. *)
|
||||
|
||||
val product : 'a t -> 'b t -> ('a * 'b) t
|
||||
(** Cartesian product of the sequences. The first one is transformed
|
||||
by calling [persistent] on it, so that it can be traversed
|
||||
several times (outer loop of the product) *)
|
||||
|
||||
val unfoldr : ('b -> ('a * 'b) option) -> 'b -> 'a t
|
||||
(** [unfoldr f b] will apply [f] to [b]. If it
|
||||
yields [Some (x,b')] then [x] is returned
|
||||
and unfoldr recurses with [b']. *)
|
||||
|
||||
val max : ?lt:('a -> 'a -> bool) -> 'a t -> 'a -> 'a
|
||||
(** Max element of the sequence, using the given comparison
|
||||
function. A default element has to be provided. *)
|
||||
|
||||
val min : ?lt:('a -> 'a -> bool) -> 'a t -> 'a -> 'a
|
||||
(** Min element of the sequence, using the given comparison function *)
|
||||
|
||||
val take : int -> 'a t -> 'a t
|
||||
(** Take at most [n] elements from the sequence *)
|
||||
|
||||
val drop : int -> 'a t -> 'a t
|
||||
(** Drop the [n] first elements of the sequence *)
|
||||
|
||||
val rev : 'a t -> 'a t
|
||||
(** Reverse the sequence. O(n) memory and time. *)
|
||||
|
||||
(** {2 Basic data structures converters} *)
|
||||
|
||||
val to_list : 'a t -> 'a list
|
||||
|
||||
val to_rev_list : 'a t -> 'a list
|
||||
(** Get the list of the reversed sequence (more efficient) *)
|
||||
|
||||
val of_list : 'a list -> 'a t
|
||||
|
||||
val to_array : 'a t -> 'a array
|
||||
(** Convert to an array. Currently not very efficient because
|
||||
and intermediate list is used. *)
|
||||
|
||||
val of_array : 'a array -> 'a t
|
||||
|
||||
val of_array_i : 'a array -> (int * 'a) t
|
||||
(** Elements of the array, with their index *)
|
||||
|
||||
val array_slice : 'a array -> int -> int -> 'a t
|
||||
(** [array_slice a i j] Sequence of elements whose indexes range
|
||||
from [i] to [j] *)
|
||||
|
||||
val of_stream : 'a Stream.t -> 'a t
|
||||
(** Sequence of elements of a stream (usable only once) *)
|
||||
|
||||
val to_stream : 'a t -> 'a Stream.t
|
||||
(** Convert to a stream. linear in memory and time (a copy is made in memory) *)
|
||||
|
||||
val to_stack : 'a Stack.t -> 'a t -> unit
|
||||
(** Push elements of the sequence on the stack *)
|
||||
|
||||
val of_stack : 'a Stack.t -> 'a t
|
||||
(** Sequence of elements of the stack (same order as [Stack.iter]) *)
|
||||
|
||||
val to_queue : 'a Queue.t -> 'a t -> unit
|
||||
(** Push elements of the sequence into the queue *)
|
||||
|
||||
val of_queue : 'a Queue.t -> 'a t
|
||||
(** Sequence of elements contained in the queue, FIFO order *)
|
||||
|
||||
val hashtbl_add : ('a, 'b) Hashtbl.t -> ('a * 'b) t -> unit
|
||||
(** Add elements of the sequence to the hashtable, with
|
||||
Hashtbl.add *)
|
||||
|
||||
val hashtbl_replace : ('a, 'b) Hashtbl.t -> ('a * 'b) t -> unit
|
||||
(** Add elements of the sequence to the hashtable, with
|
||||
Hashtbl.replace (erases conflicting bindings) *)
|
||||
|
||||
val to_hashtbl :('a * 'b) t -> ('a, 'b) Hashtbl.t
|
||||
(** Build a hashtable from a sequence of key/value pairs *)
|
||||
|
||||
val of_hashtbl : ('a, 'b) Hashtbl.t -> ('a * 'b) t
|
||||
(** Sequence of key/value pairs from the hashtable *)
|
||||
|
||||
val hashtbl_keys : ('a, 'b) Hashtbl.t -> 'a t
|
||||
val hashtbl_values : ('a, 'b) Hashtbl.t -> 'b t
|
||||
|
||||
val of_str : string -> char t
|
||||
val to_str : char t -> string
|
||||
val of_in_channel : in_channel -> char t
|
||||
|
||||
val to_buffer : char t -> Buffer.t -> unit
|
||||
(** Copy content of the sequence into the buffer *)
|
||||
|
||||
val int_range : start:int -> stop:int -> int t
|
||||
(** Iterator on integers in [start...stop] by steps 1 *)
|
||||
|
||||
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. *)
|
||||
|
||||
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 *)
|
||||
|
||||
(** {2 Functorial conversions between sets and sequences} *)
|
||||
|
||||
module Set : sig
|
||||
module type S = sig
|
||||
type set
|
||||
include Set.S with type t := set
|
||||
val of_seq : elt t -> set
|
||||
val to_seq : set -> elt t
|
||||
end
|
||||
|
||||
(** Create an enriched Set module from the given one *)
|
||||
module Adapt(X : Set.S) : S with type elt = X.elt and type set = X.t
|
||||
|
||||
(** Functor to build an extended Set module from an ordered type *)
|
||||
module Make(X : Set.OrderedType) : S with type elt = X.t
|
||||
end
|
||||
|
||||
(** {2 Conversion between maps and sequences.} *)
|
||||
|
||||
module Map : sig
|
||||
module type S = sig
|
||||
type +'a map
|
||||
include Map.S with type 'a t := 'a map
|
||||
val to_seq : 'a map -> (key * 'a) t
|
||||
val of_seq : (key * 'a) t -> 'a map
|
||||
val keys : 'a map -> key t
|
||||
val values : 'a map -> 'a t
|
||||
end
|
||||
|
||||
(** Adapt a pre-existing Map module to make it sequence-aware *)
|
||||
module Adapt(M : Map.S) : S with type key = M.key and type 'a map = 'a M.t
|
||||
|
||||
(** Create an enriched Map module, with sequence-aware functions *)
|
||||
module Make(V : Map.OrderedType) : S with type key = V.t
|
||||
end
|
||||
|
||||
(** {2 Infinite sequences of random values} *)
|
||||
|
||||
val random_int : int -> int t
|
||||
|
||||
val random_bool : bool t
|
||||
|
||||
val random_float : float -> float t
|
||||
|
||||
val random_array : 'a array -> 'a t
|
||||
(** Sequence of choices of an element in the array *)
|
||||
|
||||
val random_list : 'a list -> 'a t
|
||||
|
||||
(** {2 Type-classes} *)
|
||||
|
||||
module TypeClass : sig
|
||||
(** {3 Classes} *)
|
||||
type ('a,'b) sequenceable = {
|
||||
to_seq : 'b -> 'a t;
|
||||
of_seq : 'a t -> 'b;
|
||||
}
|
||||
|
||||
type ('a,'b) addable = {
|
||||
empty : 'b;
|
||||
add : 'b -> 'a -> 'b;
|
||||
}
|
||||
|
||||
type 'a monoid = ('a,'a) addable
|
||||
|
||||
type ('a,'b) iterable = {
|
||||
iter : ('a -> unit) -> 'b -> unit;
|
||||
}
|
||||
|
||||
(** {3 Instances} *)
|
||||
|
||||
val sequenceable : ('a,'a t) sequenceable
|
||||
val iterable : ('a,'a t) iterable
|
||||
val monoid : 'a t monoid
|
||||
|
||||
(** {3 Conversions} *)
|
||||
|
||||
val of_iterable : ('a,'b) iterable -> 'b -> 'a t
|
||||
val to_addable : ('a,'b) addable -> 'a t -> 'b
|
||||
end
|
||||
|
||||
(** {2 Pretty printing of sequences} *)
|
||||
|
||||
val pp_seq : ?sep:string -> (Format.formatter -> 'a -> unit) ->
|
||||
Format.formatter -> 'a t -> unit
|
||||
(** Pretty print a sequence of ['a], using the given pretty printer
|
||||
to print each elements. An optional separator string can be provided. *)
|
||||
Loading…
Add table
Reference in a new issue