# 1 "src/batSeq.mliv"
(*
 * Copyright (C) 2009 Jeremie Dimino
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version,
 * with the special exception on linking described in file LICENSE.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *)

(** Sequence of elements *)

(** A sequence represent a collection of elements, for which you never
    construct the complete representation.

    Basically you should use a sequence when you would prefer using a
    list or a lazy-list but constructing the whole list explicitly
    would explode your memory.

    All functions returning a sequence operates in time and space
    O(1).

    Note that if you want a ``consumable sequence'', you should prefer
    using enumerations (from module {!BatEnum}).

    @author Jeremie Dimino
*)

# 39 "src/batSeq.mliv"
 type 'a t = 'a Stdlib.Seq.t
(** A sequence is a computation which returns a list-like node *)

and 'a node =
 'a Stdlib.Seq.node =
  | Nil
  | Cons of 'a * 'a t

include BatInterfaces.Mappable with type 'a mappable = 'a t

val enum : 'a t -> 'a BatEnum.t
(** [enum s] returns the enumeration of all element of [s].

    Since enumerations are consumable and sequence are not, it is
    not possible to have the inverse operations, i.e. [of_enum] *)

(** {6 Base operations} *)

val length : 'a t -> int
(** Return the number of elements of the given sequence. This may
    never return if the sequence is infinite. *)

val hd : 'a t -> 'a
(** Returns the first element of the sequence or raise [Invalid_argument] if
    the sequence is empty. *)

val tl : 'a t -> 'a t
(** Returns the sequence without its first elements or raise
    [Invalid_argument] if the sequence is empty. *)

val is_empty : 'a t -> bool
(** [is_empty e] returns true if [e] does not contains any
    element. *)

val first : 'a t -> 'a
(** Same as {!hd} *)

val last : 'a t -> 'a
(** Returns the last element of the sequence, or raise [Invalid_argument] if
    the sequence is empty. *)

val at : 'a t -> int -> 'a
(** [at l n] returns the element at index [n] (starting from [0]) in
    the sequence [l] or raise [Invalid_argument] is the index is
    outside of [l] bounds. *)

val append : 'a t -> 'a t -> 'a t
(** [append s1 s2] returns the sequence which first returns all
    elements of [s1] then all elements of [s2]. *)

val concat : 'a t t -> 'a t
(** [concat s] returns the sequence which returns all the elements
    of all the elements of [s], in the same order. *)

val flatten : 'a t t -> 'a t
(** Same as {!concat}. *)

(** {6 Constructors} *)

val nil : 'a t
(** [nil = fun () -> Nil] *)

val empty : 'a t
(** the empty sequence, containing no elements

    @since 3.3.0 *)

val return : 'a -> 'a t
(** the singleton sequence, containing only the given element

    @since 3.3.0 *)

val cons : 'a -> 'a t -> 'a t
(** [cons e s = fun () -> Cons(e, s)] *)

val make : int -> 'a -> 'a t
(** [make n e] returns the sequence of length [n] where all elements
    are [e] *)

val init : int -> (int -> 'a) -> 'a t
(** [init n f] returns the sequence returning the results of [f 0],
    [f 1].... [f (n-1)]. @raise Invalid_argument if [n < 0]. *)

val of_list : 'a list -> 'a t
(** Convenience function to build a seq from a list.
    @since 2.2.0 *)

val unfold : ('b -> ('a * 'b) option) -> 'b -> 'a t
(** Build a sequence from a step function and an initial value.
    [unfold f u] returns [empty] if [f u] returns [None],
    or [fun () -> Cons (x, unfold f y)] if [f u] returns [Some (x, y)].

    For example, [unfold (function [] -> None | h::t -> Some (h,t)) l]
    is equivalent to [List.to_seq l].

    @since 3.3.0 *)

val flat_map : ('a -> 'b t) -> 'a t -> 'b t
(** Map each element to a subsequence, then return each element of this
    sub-sequence in turn. This transformation is lazy, it only applies
    when the result is traversed.

    @since 3.3.0 *)

val concat_map: ('a -> 'b t) -> 'a t -> 'b t
(** Alias for {!flat_map}.
    @since 3.4.0 *)

(** {6 Iterators} *)

val iter : ('a -> unit) -> 'a t -> unit
(** [iter f s] applies [f] to all the elements of the sequence. Eager. *)

val iteri : (int -> 'a -> unit) -> 'a t -> unit
(** [iteri f s] is the same as [iter f s], but [f] is given the index
    of each element (starting at 0).
    @since 2.2.0 *)

val iter2 : ('a -> 'b -> unit) -> 'a t -> 'b t -> unit
(** [iter2 f s1 s2] iterates on elements of [s1] and [s2] pairwise, and
    stops when it meets the end of [s1] or [s2]
    @since 2.2.0 *)

val map : ('a -> 'b) -> 'a t -> 'b t
(** [map f s] returns the sequence where elements are elements of
    [s] mapped with [f]. Lazy. *)

val mapi : (int -> 'a -> 'b) -> 'a t -> 'b t
(** [mapi f s] lazily maps elements of [s] into a new sequence,
    using [f]. [f] is also given elements' indexes.
    @since 2.2.0 *)

val map2 : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t
(** [map2 f s1 s2] returns a sequence of elements, resulting from combininig
    elements of [s1] and [s2] at the same index using [f]. The result is as
    long as the shortest argument.
    @since 2.2.0 *)

val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a
(** [fold_left f a (cons b0 (... bn))] is [f (... (f (f a b0) b1) ...)
    bn]. Tail-recursive, eager.
*)

val fold_right : ('a -> 'b -> 'b) -> 'a t -> 'b -> 'b
(** [fold_right f (cons a0 (cons a1 (cons a2 ...))) b] is [f a0 (f
    a1 (f a2 ...))].
    Not tail-recursive, eager.
*)

val reduce : ('a -> 'a -> 'a) -> 'a t -> 'a
(** [reduce f (cons e s)] is [fold_left f e s].

    @raise Invalid_argument on empty sequences. *)

val max : 'a t -> 'a
(** [max s] returns the largest value in [s] as judged by
    [Pervasives.compare]

    @raise Invalid_argument on empty sequences. *)

val min : 'a t -> 'a
(** [min s] returns the smallest value in [s] as judged by
    [Pervasives.compare]

    @raise Invalid_argument on empty sequences. *)

val equal : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t -> bool
  (** [equal ~eq s1 s2] compares elements of [s1] and [s2] pairwise
      using [eq]
      @param eq optional equality function (default {!Pervasives.(=)})
      @since 2.2.0 *)

(** {6 Sequence scanning}

    Most functions in the following sections have a shortcut semantic
    similar to the behavior of the usual (&&) and (||) operators :
    they will force the sequence until they find an satisfying
    element, and then return immediately.

    For example, [for_all] will only diverge if the sequence begins
    with an infinite number of true elements --- elements for which
    the predicate [p] returns [true].
*)

val for_all : ('a -> bool) -> 'a t -> bool
(** [for_all p (cons a0 (cons a1 ...))] checks if all elements of the
    given sequence satisfy the predicate [p]. That is, it returns
    [(p a0) && (p a1) && ...]. Eager, shortcut.
*)

val exists : ('a -> bool) -> 'a t -> bool
(** [exists p (cons a0 (cons a1 ...))] checks if at least one element of
    the sequence satisfies the predicate [p]. That is, it returns
    [(p a0) || (p a1) || ...]. Eager, shortcut.
*)

val mem : 'a -> 'a t -> bool
(** [mem a l] is true if and only if [a] is equal to an element of
    [l]. Eager, shortcut.
*)

(** {6 Sequence searching} *)

val find : ('a -> bool) -> 'a t -> 'a option
(** [find p s] returns the first element of [s] such as [p e]
    returns [true], if any. Eager, shortcut.
*)

val find_map : ('a -> 'b option) -> 'a t -> 'b option
(** [find_map p s] finds the first element of [s] for which [p e]
    returns [Some r], if any. Eager, short-cut.
*)

val filter : ('a -> bool) -> 'a t -> 'a t
(** [filter p s] returns the sequence of elements of [s] satisfying
    [p]. Lazy.

    {b Note} filter is lazy in that it returns a lazy sequence, but
    each element in the result is eagerly searched in the input
    sequence. Therefore, the access to a given element in the result
    will diverge if it is preceded, in the input sequence, by
    infinitely many false elements (elements on which the predicate
    [p] returns [false]).

    Other functions that may drop an unbound number of elements
    ([filter_map], [take_while], etc.) have the same behavior.
*)

val filter_map : ('a -> 'b option) -> 'a t -> 'b t
(** [filter_map f s] returns the sequence of elements filtered and
    mapped by [f]. Lazy.
*)

(** {6 Association sequences} *)

val assoc : 'a -> ('a * 'b) t -> 'b option
(** [assoc a s] returns the value associated with key [a] in the
    sequence of pairs [s]. Eager, shortcut.  *)

(** {6 Sequence transformations} *)

val take : int -> 'a t -> 'a t
(** [take n s] returns up to the [n] first elements from sequence
    [s], if available. Lazy. *)

val drop : int -> 'a t -> 'a t
(** [drop n s] returns [s] without the first [n] elements, or the
    empty sequence if [s] have less than [n] elements. Lazy. *)

val take_while : ('a -> bool) -> 'a t -> 'a t
(** [take_while f s] returns the first elements of sequence [s]
    which satisfy the predicate [f]. Lazy. *)

val drop_while : ('a -> bool) -> 'a t -> 'a t
(** [drop_while f s] returns the sequence [s] with the first
    elements satisfying the predicate [f] dropped. Lazy. *)

(** {6 Sequence of pairs} *)

val split : ('a * 'b) t -> 'a t * 'b t
(** [split s = (map fst s, map snd s)]. Lazy. *)

val combine : 'a t -> 'b t -> ('a * 'b) t
(** Transform a pair of sequences into a sequence of pairs. Lazy.

    @raise Invalid_argument if given sequences of different length. *)

(** {6 Printing} *)

val print : ?first:string -> ?last:string -> ?sep:string -> ('a BatInnerIO.output -> 'b -> unit) ->  'a BatInnerIO.output -> 'b t -> unit
(**Print the contents of a sequence*)

val to_buffer : ?first:string -> ?last:string -> ?sep:string -> ('a -> string) -> Buffer.t -> (unit -> 'a node) -> unit
(** Convert a sequence to a string in the given buffer; eager.
    @since 2.10.0
*)

val to_string : ?first:string -> ?last:string -> ?sep:string -> ('a -> string) -> 'a t -> string
(** Convert the sequence to a string; eager.
    @since 2.10.0
*)

val of_string : ?first:string -> ?last:string -> ?sep:string -> (string -> 'a) -> string -> 'a t
(** Create a sequence by parsing a string.
    @raise Invalid_argument if the string is not prefixed by [first].
    @raise Invalid_argument if the string is not suffixed by [last].
    @since 2.10.0
*)

module Infix : sig
  (** Infix operators matching those provided by {!BatEnum.Infix} *)

  val ( -- ) : int -> int -> int t
  val ( --^ ) : int -> int -> int t
  val ( --. ) : float * float -> float -> float t
  val ( --- ) : int -> int -> int t
  val ( --~ ) : char -> char -> char t
  val ( // ) : 'a t -> ('a -> bool) -> 'a t
  val ( /@ ) : 'a t -> ('a -> 'b) -> 'b t
  val ( @/ ) : ('a -> 'b) -> 'a t -> 'b t
  val ( //@ ) : 'a t -> ('a -> 'b option) -> 'b t
  val ( @// ) : ('a -> 'b option) -> 'a t -> 'b t
end

include module type of Infix

module Exceptionless : sig
  val hd : 'a t -> 'a option
  val tl : 'a t -> 'a t option
  val first : 'a t -> 'a option
  val last : 'a t -> 'a option
  val at : 'a t -> int -> 'a option
  (*
  val make : int -> 'a -> 'a t
  val init : int -> (int -> 'a) -> 'a t
  *)
  val reduce : ('a -> 'a -> 'a) -> 'a t -> 'a option
  val max : 'a t -> 'a option
  val min : 'a t -> 'a option
  val combine : 'a t -> 'b t -> ('a * 'b) t
end

val is_empty : 'a t -> bool
(** [is_empty xs] determines whether the sequence [xs] is empty.

    It is recommended that the sequence [xs] be persistent.
    Indeed, [is_empty xs] demands the head of the sequence [xs],
    so, if [xs] is ephemeral, it may be the case that [xs] cannot
    be used any more after this call has taken place.

    @since 4.14 *)

val uncons : 'a t -> ('a * 'a t) option
(** If [xs] is empty, then [uncons xs] is [None].

    If [xs] is nonempty, then [uncons xs] is
    [Some (head xs, tail xs)],
    that is, a pair of the head and tail of the sequence [xs].

    This equivalence holds if [xs] is persistent.
    If [xs] is ephemeral, then [uncons] must be preferred
    over separate calls to [head] and [tail],
    which would cause [xs] to be queried twice.

    @since 4.14 *)

val length : 'a t -> int
(** [length xs] is the length of the sequence [xs].

    The sequence [xs] must be finite.

    @since 4.14 *)

val iteri : (int -> 'a -> unit) -> 'a t -> unit
(** [iteri f xs] invokes [f i x] successively
    for every element [x] located at index [i] in the sequence [xs].

    It terminates only if the sequence [xs] is finite.

    [iteri f xs] is equivalent to
    [iter (fun (i, x) -> f i x) (zip (ints 0) xs)].

    @since 4.14 *)

val fold_lefti : ('b -> int -> 'a -> 'b) -> 'b -> 'a t -> 'b
(** [fold_lefti f _ xs] invokes [f _ i x] successively
    for every element [x] located at index [i] of the sequence [xs].

    An accumulator of type ['b] is threaded through the calls to [f].

    It terminates only if the sequence [xs] is finite.

    [fold_lefti f accu xs] is equivalent to
    [fold_left (fun accu (i, x) -> f accu i x) accu (zip (ints 0) xs)].

    @since 4.14 *)

val for_all : ('a -> bool) -> 'a t -> bool
(** [for_all p xs] determines whether all elements [x] of the sequence [xs]
    satisfy [p x].

    The sequence [xs] must be finite.

    @since 4.14 *)

val exists : ('a -> bool) -> 'a t -> bool
(** [exists xs p] determines whether at least one element [x]
    of the sequence [xs] satisfies [p x].

    The sequence [xs] must be finite.

    @since 4.14 *)

val find : ('a -> bool) -> 'a t -> 'a option
(** [find p xs] returns [Some x], where [x] is the first element of the
    sequence [xs] that satisfies [p x], if there is such an element.

    It returns [None] if there is no such element.

    The sequence [xs] must be finite.

    @since 4.14 *)

val find_map : ('a -> 'b option) -> 'a t -> 'b option
(** [find_map f xs] returns [Some y], where [x] is the first element of the
    sequence [xs] such that [f x = Some _], if there is such an element,
    and where [y] is defined by [f x = Some y].

    It returns [None] if there is no such element.

    The sequence [xs] must be finite.

    @since 4.14 *)

val iter2 : ('a -> 'b -> unit) -> 'a t -> 'b t -> unit
(** [iter2 f xs ys] invokes [f x y] successively for every pair [(x, y)] of
    elements drawn synchronously from the sequences [xs] and [ys].

    If the sequences [xs] and [ys] have different lengths, then
    iteration stops as soon as one sequence is exhausted;
    the excess elements in the other sequence are ignored.

    Iteration terminates only if at least one of the sequences
    [xs] and [ys] is finite.

    [iter2 f xs ys] is equivalent to
    [iter (fun (x, y) -> f x y) (zip xs ys)].

    @since 4.14 *)

val fold_left2 : ('a -> 'b -> 'c -> 'a) -> 'a -> 'b t -> 'c t -> 'a
(** [fold_left2 f _ xs ys] invokes [f _ x y] successively
    for every pair [(x, y)] of elements drawn synchronously
    from the sequences [xs] and [ys].

    An accumulator of type ['a] is threaded through the calls to [f].

    If the sequences [xs] and [ys] have different lengths, then
    iteration stops as soon as one sequence is exhausted;
    the excess elements in the other sequence are ignored.

    Iteration terminates only if at least one of the sequences
    [xs] and [ys] is finite.

    [fold_left2 f accu xs ys] is equivalent to
    [fold_left (fun accu (x, y) -> f accu x y) (zip xs ys)].

    @since 4.14 *)

val for_all2 : ('a -> 'b -> bool) -> 'a t -> 'b t -> bool
(** [for_all2 p xs ys] determines whether all pairs [(x, y)] of elements
    drawn synchronously from the sequences [xs] and [ys] satisfy [p x y].

    If the sequences [xs] and [ys] have different lengths, then
    iteration stops as soon as one sequence is exhausted;
    the excess elements in the other sequence are ignored.
    In particular, if [xs] or [ys] is empty, then
    [for_all2 p xs ys] is true. This is where
    [for_all2] and [equal] differ: [equal eq xs ys] can
    be true only if [xs] and [ys] have the same length.

    At least one of the sequences [xs] and [ys] must be finite.

    [for_all2 p xs ys] is equivalent to [for_all (fun b -> b) (map2 p xs ys)].

    @since 4.14 *)

val exists2 : ('a -> 'b -> bool) -> 'a t -> 'b t -> bool
(** [exists2 p xs ys] determines whether some pair [(x, y)] of elements
    drawn synchronously from the sequences [xs] and [ys] satisfies [p x y].

    If the sequences [xs] and [ys] have different lengths, then
    iteration must stop as soon as one sequence is exhausted;
    the excess elements in the other sequence are ignored.

    At least one of the sequences [xs] and [ys] must be finite.

    [exists2 p xs ys] is equivalent to [exists (fun b -> b) (map2 p xs ys)].

    @since 4.14 *)

val equal_stdlib : ('a -> 'b -> bool) -> 'a t -> 'b t -> bool
(** Provided the function [eq] defines an equality on elements,
    [equal eq xs ys] determines whether the sequences [xs] and [ys]
    are pointwise equal.

    At least one of the sequences [xs] and [ys] must be finite.

    @since 4.14 *)

val compare : ('a -> 'b -> int) -> 'a t -> 'b t -> int
(** Provided the function [cmp] defines a preorder on elements,
    [compare cmp xs ys] compares the sequences [xs] and [ys]
    according to the lexicographic preorder.

    For more details on comparison functions, see {!Array.sort}.

    At least one of the sequences [xs] and [ys] must be finite.

    @since 4.14 *)

val init : int -> (int -> 'a) -> 'a t
(** [init n f] is the sequence [f 0; f 1; ...; f (n-1)].

    [n] must be nonnegative.

    If desired, the infinite sequence [f 0; f 1; ...]
    can be defined as [map f (ints 0)].

    @raise Invalid_argument if [n] is negative.

    @since 4.14 *)

val repeat : 'a -> 'a t
(** [repeat x] is the infinite sequence
    where the element [x] is repeated indefinitely.

    [repeat x] is equivalent to [cycle (return x)].

    @since 4.14 *)

val forever : (unit -> 'a) -> 'a t
(** [forever f] is an infinite sequence where every element is produced
    (on demand) by the function call [f()].

    For instance,
    [forever Random.bool] is an infinite sequence of random bits.

    [forever f] is equivalent to [map f (repeat ())].

    @since 4.14 *)

val cycle : 'a t -> 'a t
(** [cycle xs] is the infinite sequence that consists of an infinite
    number of repetitions of the sequence [xs].

    If [xs] is an empty sequence,
    then [cycle xs] is empty as well.

    Consuming (a prefix of) the sequence [cycle xs] once
    can cause the sequence [xs] to be consumed more than once.
    Therefore, [xs] must be persistent.

    @since 4.14 *)

val iterate : ('a -> 'a) -> 'a -> 'a t
(** [iterate f x] is the infinite sequence whose elements are
    [x], [f x], [f (f x)], and so on.

    In other words, it is the orbit of the function [f],
    starting at [x].

    @since 4.14 *)

val mapi : (int -> 'a -> 'b) -> 'a t -> 'b t
(** [mapi] is analogous to [map], but applies the function [f] to
    an index and an element.

    [mapi f xs] is equivalent to [map2 f (ints 0) xs].

    @since 4.14 *)

val scan : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b t
(** If [xs] is a sequence [[x0; x1; x2; ...]], then
    [scan f a0 xs] is a sequence of accumulators
    [[a0; a1; a2; ...]]
    where [a1] is [f a0 x0], [a2] is [f a1 x1], and so on.

    Thus, [scan f a0 xs] is conceptually related to
    [fold_left f a0 xs]. However, instead of performing an
    eager iteration and immediately returning the final accumulator,
    it returns a sequence of accumulators.

    For instance, [scan (+) 0] transforms a sequence of integers
    into the sequence of its partial sums.

    If [xs] has length [n]
    then [scan f a0 xs] has length [n+1].

    @since 4.14 *)

val take : int -> 'a t -> 'a t
(** [take n xs] is the sequence of the first [n] elements of [xs].

    If [xs] has fewer than [n] elements,
    then [take n xs] is equivalent to [xs].

    [n] must be nonnegative.

    @raise Invalid_argument if [n] is negative.

    @since 4.14 *)

val drop : int -> 'a t -> 'a t
(** [drop n xs] is the sequence [xs], deprived of its first [n] elements.

    If [xs] has fewer than [n] elements,
    then [drop n xs] is empty.

    [n] must be nonnegative.

    [drop] is lazy: the first [n+1] elements of the sequence [xs]
    are demanded only when the first element of [drop n xs] is
    demanded. For this reason, [drop 1 xs] is {i not} equivalent
    to [tail xs], which queries [xs] immediately.

    @raise Invalid_argument if [n] is negative.

    @since 4.14 *)

val take_while : ('a -> bool) -> 'a t -> 'a t
(** [take_while p xs] is the longest prefix of the sequence [xs]
    where every element [x] satisfies [p x].

    @since 4.14 *)

val drop_while : ('a -> bool) -> 'a t -> 'a t
(** [drop_while p xs] is the sequence [xs], deprived of the prefix
    [take_while p xs].

    @since 4.14 *)

val group : ('a -> 'a -> bool) -> 'a t -> 'a t t
(** Provided the function [eq] defines an equality on elements,
    [group eq xs] is the sequence of the maximal runs
    of adjacent duplicate elements of the sequence [xs].

    Every element of [group eq xs] is a nonempty sequence of equal elements.

    The concatenation [concat (group eq xs)] is equal to [xs].

    Consuming [group eq xs], and consuming the sequences that it contains,
    can cause [xs] to be consumed more than once. Therefore, [xs] must be
    persistent.

    @since 4.14 *)

val memoize : 'a t -> 'a t
(** The sequence [memoize xs] has the same elements as the sequence [xs].

    Regardless of whether [xs] is ephemeral or persistent,
    [memoize xs] is persistent: even if it is queried several times,
    [xs] is queried at most once.

    The construction of the sequence [memoize xs] internally relies on
    suspensions provided by the module {!Lazy}. These suspensions are
    {i not} thread-safe. Therefore, the sequence [memoize xs]
    must {i not} be queried by multiple threads concurrently.

    @since 4.14 *)

exception Forced_twice
(** This exception is raised when a sequence returned by {!once}
    (or a suffix of it) is queried more than once.

    @since 4.14 *)

val once : 'a t -> 'a t
(** The sequence [once xs] has the same elements as the sequence [xs].

    Regardless of whether [xs] is ephemeral or persistent,
    [once xs] is an ephemeral sequence: it can be queried at most once.
    If it (or a suffix of it) is queried more than once, then the exception
    [Forced_twice] is raised. This can be useful, while debugging or testing,
    to ensure that a sequence is consumed at most once.

    @raise Forced_twice if [once xs], or a suffix of it,
           is queried more than once.

    @since 4.14 *)

val transpose : 'a t t -> 'a t t
(** If [xss] is a matrix (a sequence of rows), then [transpose xss] is
    the sequence of the columns of the matrix [xss].

    The rows of the matrix [xss] are not required to have the same length.

    The matrix [xss] is not required to be finite (in either direction).

    The matrix [xss] must be persistent.

    @since 4.14 *)

val zip : 'a t -> 'b t -> ('a * 'b) t
(** [zip xs ys] is the sequence of pairs [(x, y)]
    drawn synchronously from the sequences [xs] and [ys].

    If the sequences [xs] and [ys] have different lengths, then
    the sequence ends as soon as one sequence is exhausted;
    the excess elements in the other sequence are ignored.

    [zip xs ys] is equivalent to [map2 (fun a b -> (a, b)) xs ys].

    @since 4.14 *)

val map2 : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t
(** [map2 f xs ys] is the sequence of the elements [f x y],
    where the pairs [(x, y)] are drawn synchronously from the
    sequences [xs] and [ys].

    If the sequences [xs] and [ys] have different lengths, then
    the sequence ends as soon as one sequence is exhausted;
    the excess elements in the other sequence are ignored.

    [map2 f xs ys] is equivalent to [map (fun (x, y) -> f x y) (zip xs ys)].

    @since 4.14 *)

val interleave : 'a t -> 'a t -> 'a t
(** [interleave xs ys] is the sequence that begins with the first element of
    [xs], continues with the first element of [ys], and so on.

    When one of the sequences [xs] and [ys] is exhausted,
    [interleave xs ys] continues with the rest of the other sequence.

    @since 4.14 *)

val sorted_merge : ('a -> 'a -> int) -> 'a t -> 'a t -> 'a t
(** If the sequences [xs] and [ys] are sorted according to the total preorder
    [cmp], then [sorted_merge cmp xs ys] is the sorted sequence obtained by
    merging the sequences [xs] and [ys].

    For more details on comparison functions, see {!Array.sort}.

    @since 4.14 *)

val product : 'a t -> 'b t -> ('a * 'b) t
(** [product xs ys] is the Cartesian product of the sequences [xs] and [ys].

    For every element [x] of [xs] and for every element [y] of [ys],
    the pair [(x, y)] appears once as an element of [product xs ys].

    The order in which the pairs appear is unspecified.

    The sequences [xs] and [ys] are not required to be finite.

    The sequences [xs] and [ys] must be persistent.

    @since 4.14 *)

val map_product : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t
(** The sequence [map_product f xs ys] is the image through [f]
    of the Cartesian product of the sequences [xs] and [ys].

    For every element [x] of [xs] and for every element [y] of [ys],
    the element [f x y] appears once as an element of [map_product f xs ys].

    The order in which these elements appear is unspecified.

    The sequences [xs] and [ys] are not required to be finite.

    The sequences [xs] and [ys] must be persistent.

    [map_product f xs ys] is equivalent to
    [map (fun (x, y) -> f x y) (product xs ys)].

    @since 4.14 *)

val unzip : ('a * 'b) t -> 'a t * 'b t
(** [unzip] transforms a sequence of pairs into a pair of sequences.

    [unzip xs] is equivalent to [(map fst xs, map snd xs)].

    Querying either of the sequences returned by [unzip xs]
    causes [xs] to be queried.
    Therefore, querying both of them
    causes [xs] to be queried twice.
    Thus, [xs] must be persistent and cheap.
    If that is not the case, use [unzip (memoize xs)].

    @since 4.14 *)

val split : ('a * 'b) t -> 'a t * 'b t
(** [split] is an alias for [unzip].

    @since 4.14 *)

val partition_map : ('a -> ('b, 'c) Either.t) -> 'a t -> 'b t * 'c t
(** [partition_map f xs] returns a pair of sequences [(ys, zs)], where:

    - [ys] is the sequence of the elements [y] such that
      [f x = Left y], where [x] ranges over [xs];

    - [zs] is the sequence of the elements [z] such that
      [f x = Right z], where [x] ranges over [xs].

    [partition_map f xs] is equivalent to a pair of
    [filter_map Either.find_left (map f xs)] and
    [filter_map Either.find_right (map f xs)].

    Querying either of the sequences returned by [partition_map f xs]
    causes [xs] to be queried.
    Therefore, querying both of them
    causes [xs] to be queried twice.
    Thus, [xs] must be persistent and cheap.
    If that is not the case, use [partition_map f (memoize xs)].

    @since 4.14 *)

val partition : ('a -> bool) -> 'a t -> 'a t * 'a t
(** [partition p xs] returns a pair of the subsequence of the elements
    of [xs] that satisfy [p] and the subsequence of the elements of
    [xs] that do not satisfy [p].

    [partition p xs] is equivalent to
    [filter p xs, filter (fun x -> not (p x)) xs].

    Consuming both of the sequences returned by [partition p xs] causes
    [xs] to be consumed twice and causes the function [f] to be applied
    twice to each element of the list.
    Therefore, [f] should be pure and cheap.
    Furthermore, [xs] should be persistent and cheap.
    If that is not the case, use [partition p (memoize xs)].

    @since 4.14 *)

(** {1 Converting between sequences and dispensers} *)

(** A dispenser is a representation of a sequence as a function of type
    [unit -> 'a option]. Every time this function is invoked, it returns
    the next element of the sequence. When there are no more elements,
    it returns [None]. A dispenser has mutable internal state, therefore
    is ephemeral: the sequence that it represents can be consumed at most
    once. *)

val of_dispenser : (unit -> 'a option) -> 'a t
(** [of_dispenser it] is the sequence of the elements produced by the
    dispenser [it]. It is an ephemeral sequence: it can be consumed at most
    once. If a persistent sequence is needed, use
    [memoize (of_dispenser it)].

    @since 4.14 *)

val to_dispenser : 'a t -> (unit -> 'a option)
(** [to_dispenser xs] is a fresh dispenser on the sequence [xs].

    This dispenser has mutable internal state,
    which is not protected by a lock;
    so, it must not be used by several threads concurrently.

    @since 4.14 *)

(** {1 Sequences of integers} *)

val ints : int -> int t
(** [ints i] is the infinite sequence of the integers beginning at [i] and
    counting up.

    @since 4.14 *)

