模块 Stdlib.Seq

module Seq: Seq

type 'a t = unit -> 'a node 

一个类型为 'a t 的序列 xs 是一个类型为 'a 的元素的延迟列表。通过执行函数应用 xs() 来查询此类序列。此函数应用返回一个节点,允许调用者确定序列是否为空或非空,以及在后者情况下,获取其头部和尾部。

type 'a node = 
| Nil
| Cons of 'a * 'a t

节点要么是 Nil,表示序列为空,要么是 Cons (x, xs),表示 x 是序列的第一个元素,xs 是序列的其余部分。

消费序列

本节中的函数会部分或完全地消费其参数(一个序列)。

类似地,在消费两个序列的函数中,可以区分两组。

消费两个序列的函数可以应用于两个长度不同的序列:在这种情况下,较长序列中的多余元素将被忽略。(即使不使用此元素,也可能会请求一个多余元素。)

本节中的任何函数都不是惰性的。这些函数是消费者:它们会强制执行一些计算。

val is_empty : 'a t -> bool

is_empty xs 确定序列 xs 是否为空。

建议序列 xs 是持久性的。实际上,is_empty xs 会请求序列 xs 的头部,因此,如果 xs 是短暂的,则在此调用发生后,可能无法再使用 xs

val uncons : 'a t -> ('a * 'a t) option

如果 xs 为空,则 uncons xsNone

如果 xs 不为空,则 uncons xsSome (x, ys),其中 x 是序列的头部,ys 是其尾部。

val length : 'a t -> int

length xs 是序列 xs 的长度。

序列 xs 必须是有限的。

val iter : ('a -> unit) -> 'a t -> unit

iter f xs 会依次对序列 xs 的每个元素 x(从左到右)调用 f x

只有当序列 xs 是有限的时,它才会终止。

val fold_left : ('acc -> 'a -> 'acc) -> 'acc -> 'a t -> 'acc

fold_left f _ xs 会依次对序列 xs 的每个元素 x(从左到右)调用 f _ x

类型为 'a 的累加器会贯穿对 f 的调用。

只有当序列 xs 是有限的时,它才会终止。

val iteri : (int -> 'a -> unit) -> 'a t -> unit

iteri f xs 会依次对序列 xs 中位于索引 i 的每个元素 x 调用 f i x

只有当序列 xs 是有限的时,它才会终止。

iteri f xs 等价于 iter (fun (i, x) -> f i x) (zip (ints 0) xs)

val fold_lefti : ('acc -> int -> 'a -> 'acc) -> 'acc -> 'a t -> 'acc

fold_lefti f _ xs 会依次对序列 xs 中位于索引 i 的每个元素 x 调用 f _ i x

类型为 'b 的累加器会贯穿对 f 的调用。

只有当序列 xs 是有限的时,它才会终止。

fold_lefti f accu xs 等价于 fold_left (fun accu (i, x) -> f accu i x) accu (zip (ints 0) xs)

val for_all : ('a -> bool) -> 'a t -> bool

for_all p xs 确定序列 xs 的所有元素 x 是否都满足 p x

序列 xs 必须是有限的。

val exists : ('a -> bool) -> 'a t -> bool

exists xs p 确定序列 xs 的至少一个元素 x 是否满足 p x

序列 xs 必须是有限的。

val find : ('a -> bool) -> 'a t -> 'a option

find p xs 返回 Some x,其中 x 是序列 xs 中第一个满足 p x 的元素(如果存在)。

如果不存在这样的元素,则返回 None

序列 xs 必须是有限的。

val find_index : ('a -> bool) -> 'a t -> int option

find_index p xs 返回 Some i,其中 i 是序列 xs 中第一个满足 p x 的元素的索引(如果存在)。

如果不存在这样的元素,则返回 None

序列 xs 必须是有限的。

val find_map : ('a -> 'b option) -> 'a t -> 'b option

find_map f xs 返回 Some y,其中 x 是序列 xs 中第一个使得 f x = Some _ 的元素(如果存在),并且 yf x = Some y 定义。

如果不存在这样的元素,则返回 None

序列 xs 必须是有限的。

val find_mapi : (int -> 'a -> 'b option) -> 'a t -> 'b option

find_map 相同,但谓词将元素的索引作为第一个参数(从 0 开始计数),并将元素本身作为第二个参数。

序列 xs 必须是有限的。

val iter2 : ('a -> 'b -> unit) -> 'a t -> 'b t -> unit

iter2 f xs ys 会依次对从序列 xsys 同步提取的每个元素对 (x, y) 调用 f x y

如果序列 xsys 的长度不同,则迭代在其中一个序列耗尽时停止;另一个序列中的多余元素将被忽略。

只有当序列 xsys 中至少有一个是有限的时,迭代才会终止。

iter2 f xs ys 等价于 iter (fun (x, y) -> f x y) (zip xs ys)

val fold_left2 : ('acc -> 'a -> 'b -> 'acc) -> 'acc -> 'a t -> 'b t -> 'acc

fold_left2 f _ xs ys 会依次对从序列 xsys 同步提取的每个元素对 (x, y) 调用 f _ x y

类型为 'a 的累加器会贯穿对 f 的调用。

如果序列 xsys 的长度不同,则迭代在其中一个序列耗尽时停止;另一个序列中的多余元素将被忽略。

只有当序列 xsys 中至少有一个是有限的时,迭代才会终止。

fold_left2 f accu xs ys 等价于 fold_left (fun accu (x, y) -> f accu x y) (zip xs ys)

val for_all2 : ('a -> 'b -> bool) -> 'a t -> 'b t -> bool

for_all2 p xs ys 确定从序列 xsys 同步提取的每个元素对 (x, y) 是否都满足 p x y

如果序列 xsys 的长度不同,则迭代在其中一个序列耗尽时停止;另一个序列中的多余元素将被忽略。特别是,如果 xsys 为空,则 for_all2 p xs ys 为真。这是 for_all2equal 的区别所在:只有当 xsys 的长度相同时,equal eq xs ys 才能为真。

序列 xsys 中至少有一个必须是有限的。

for_all2 p xs ys 等价于 for_all (fun b -> b) (map2 p xs ys)

val exists2 : ('a -> 'b -> bool) -> 'a t -> 'b t -> bool

exists2 p xs ys 确定从序列 xsys 同步提取的某些元素对 (x, y) 是否满足 p x y

如果序列 xsys 的长度不同,则迭代必须在其中一个序列耗尽时停止;另一个序列中的多余元素将被忽略。

序列 xsys 中至少有一个必须是有限的。

exists2 p xs ys 等价于 exists (fun b -> b) (map2 p xs ys)

val equal : ('a -> 'b -> bool) -> 'a t -> 'b t -> bool

假设函数 eq 定义了元素上的相等性,则 equal eq xs ys 确定序列 xsys 是否逐点相等。

序列 xsys 中至少有一个必须是有限的。

val compare : ('a -> 'b -> int) -> 'a t -> 'b t -> int

假设函数 cmp 定义了元素上的预序,则 compare cmp xs ys 根据字典序预序比较序列 xsys

有关比较函数的更多详细信息,请参阅 Array.sort

序列 xsys 中至少有一个必须是有限的。

构建序列

本节中的函数是惰性的:也就是说,它们返回的序列的元素仅在需要时才计算。

val empty : 'a t

empty 是空序列。它没有元素。其长度为 0。

val return : 'a -> 'a t

return x 是唯一元素为 x 的序列。其长度为 1。

val cons : 'a -> 'a t -> 'a t

cons x xs 是以元素 x 开头,后跟序列 xs 的序列。

编写 cons (f()) xs 会导致函数调用 f() 立即发生。为了延迟此调用,直到查询序列时才执行,必须改为编写 (fun () -> Cons(f(), xs))

val init : int -> (int -> 'a) -> 'a t

init n f 是序列 f 0; f 1; ...; f (n-1)

n 必须是非负数。

如果需要,无限序列 f 0; f 1; ... 可以定义为 map f (ints 0)

val unfold : ('b -> ('a * 'b) option) -> 'b -> 'a t

unfold 使用步进函数和初始状态构建序列。

如果 f uNone,则 unfold f u 为空序列。如果 f uSome (x, u'),则 unfold f u 为非空序列 cons x (unfold f u')

例如,unfold (function [] -> None | h :: t -> Some (h, t)) l 等价于 List.to_seq l

val repeat : 'a -> 'a t

repeat x 是一个无限序列,其中元素 x 无限重复。

repeat x 等价于 cycle (return x)

val forever : (unit -> 'a) -> 'a t

forever f 是一个无限序列,其中每个元素都是(按需)通过函数调用 f() 生成的。

例如,forever Random.bool 是一个无限的随机比特序列。

forever f 等价于 map f (repeat ())

val cycle : 'a t -> 'a t

cycle xs 是一个无限序列,它由序列 xs 的无限次重复组成。

如果 xs 是一个空序列,则 cycle xs 也为空。

消费(序列 cycle xs 的一个前缀)一次可能会导致序列 xs 被消费多次。因此,xs 必须是持久性的。

val iterate : ('a -> 'a) -> 'a -> 'a t

iterate f x 是一个无限序列,其元素为 xf xf (f x) 等。

换句话说,它是函数 f 的轨道,从 x 开始。

转换序列

本节中的函数是惰性的:也就是说,它们返回的序列的元素仅在需要时才计算。

val map : ('a -> 'b) -> 'a t -> 'b t

map f xs 是序列 xs 通过变换 f 的像。

如果 xs 是序列 x0; x1; ...,则 map f xs 是序列 f x0; f x1; ...

val mapi : (int -> 'a -> 'b) -> 'a t -> 'b t

mapimap 类似,但它将函数 f 应用于索引和元素。

mapi f xs 等价于 map2 f (ints 0) xs

val filter : ('a -> bool) -> 'a t -> 'a t

filter p xs 是序列 xs 中满足 p x 的元素 x 的序列。

换句话说,filter p xs 是序列 xs,去除了使得 p x 为假的元素 x

val filter_map : ('a -> 'b option) -> 'a t -> 'b t

filter_map f xs 是元素 y 的序列,其中 f x = Some yx 遍历 xs

filter_map f xs 等价于 map Option.get (filter Option.is_some (map f xs))

val scan : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b t

如果 xs 是序列 [x0; x1; x2; ...],则 scan f a0 xs 是累加器 [a0; a1; a2; ...] 的序列,其中 a1f a0 x0a2f a1 x1,依此类推。

因此,scan f a0 xs 在概念上与 fold_left f a0 xs 相关。但是,它不是执行急切迭代并立即返回最终累加器,而是返回累加器序列。

例如,scan (+) 0 将整数序列转换为其部分和的序列。

如果 xs 的长度为 n,则 scan f a0 xs 的长度为 n+1

val take : int -> 'a t -> 'a t

take n xs 是序列 xs 的前 n 个元素的序列。

如果 xs 的元素少于 n 个,则 take n xs 等价于 xs

n 必须是非负数。

val drop : int -> 'a t -> 'a t

drop n xs 是序列 xs,去除了其前 n 个元素。

如果 xs 的元素少于 n 个,则 drop n xs 为空。

n 必须是非负数。

drop 是惰性的:只有当序列 drop n xs 的第一个元素被请求时,才会请求序列 xs 的前 n+1 个元素。因此,drop 1 xs 等价于 tail xs,后者会立即查询 xs

val take_while : ('a -> bool) -> 'a t -> 'a t

take_while p xs 是序列 xs 的最长前缀,其中每个元素 x 都满足 p x

val drop_while : ('a -> bool) -> 'a t -> 'a t

drop_while p xs 是序列 xs,去除了前缀 take_while p xs

val group : ('a -> 'a -> bool) -> 'a t -> 'a t t

假设函数 eq 定义了元素上的相等性,则 group eq xs 是序列 xs 中相邻重复元素的最大运行序列。

group eq xs 的每个元素都是一个非空相等元素序列。

连接 concat (group eq xs) 等于 xs

消费 group eq xs 以及消费它包含的序列,可能会导致 xs 被消费多次。因此,xs 必须是持久性的。

val memoize : 'a t -> 'a t

序列 memoize xs 与序列 xs 具有相同的元素。

无论 xs 是短暂的还是持久的,memoize xs 都是持久的:即使它被查询多次,xs 也最多被查询一次。

序列 memoize xs 的构造在内部依赖于模块 Lazy 提供的挂起。这些挂起不是线程安全的。因此,序列 memoize xs 不能被多个线程并发查询。

exception Forced_twice

当由 Seq.once(或其后缀)返回的序列被查询多次时,将引发此异常。

val once : 'a t -> 'a t

序列 once xs 与序列 xs 具有相同的元素。

无论 xs 是短暂的还是持久的,once xs 都是一个短暂的序列:它最多只能被查询一次。如果它(或其后缀)被查询多次,则会引发异常 Forced_twice。这在调试或测试时非常有用,以确保序列最多被消费一次。

val transpose : 'a t t -> 'a t t

如果 xss 是一个矩阵(行序列),则 transpose xss 是矩阵 xss 的列序列。

矩阵 xss 的行不需要具有相同的长度。

矩阵 xss 不需要是有限的(在任何方向上)。

矩阵 xss 必须是持久性的。

组合序列

val append : 'a t -> 'a t -> 'a t

append xs ys 是序列 xsys 的连接。

其元素是 xs 的元素,后跟 ys 的元素。

val concat : 'a t t -> 'a t

如果 xss 是一个序列序列,则 concat xss 是其连接。

如果 xss 是序列 xs0; xs1; ...,则 concat xss 是序列 xs0 @ xs1 @ ...

val flat_map : ('a -> 'b t) -> 'a t -> 'b t

flat_map f xs 等价于 concat (map f xs)

val concat_map : ('a -> 'b t) -> 'a t -> 'b t

concat_map f xs 等价于 concat (map f xs)

concat_mapflat_map 的别名。

val zip : 'a t -> 'b t -> ('a * 'b) t

zip xs ys 是从序列 xsys 同步提取的配对 (x, y) 的序列。

如果序列 xsys 的长度不同,则序列在其中一个序列耗尽时结束;另一个序列中的多余元素将被忽略。

zip xs ys 等价于 map2 (fun a b -> (a, b)) xs ys

val map2 : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t

map2 f xs ys 是元素 f x y 的序列,其中配对 (x, y) 是从序列 xsys 同步提取的。

如果序列 xsys 的长度不同,则序列在其中一个序列耗尽时结束;另一个序列中的多余元素将被忽略。

map2 f xs ys 等价于 map (fun (x, y) -> f x y) (zip xs ys)

val interleave : 'a t -> 'a t -> 'a t

interleave xs ys 是一个序列,它以 xs 的第一个元素开头,以 ys 的第一个元素继续,依此类推。

xsys 中的一个序列耗尽时,interleave xs ys 将继续使用另一个序列的其余部分。

val sorted_merge : ('a -> 'a -> int) -> 'a t -> 'a t -> 'a t

如果序列 xsys 根据全序 cmp 排序,则 sorted_merge cmp xs ys 是通过合并序列 xsys 获得的排序序列。

有关比较函数的更多详细信息,请参阅 Array.sort

val product : 'a t -> 'b t -> ('a * 'b) t

product xs ys 是序列 xsys 的笛卡尔积。

对于 xs 的每个元素 xys 的每个元素 y,配对 (x, y) 作为 product xs ys 的元素出现一次。

配对出现的顺序未指定。

序列 xsys 不需要是有限的。

序列 xsys 必须是持久性的。

val map_product : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t

序列 map_product f xs ys 是序列 xsys 的笛卡尔积通过 f 的像。

对于 xs 的每个元素 xys 的每个元素 y,元素 f x y 作为 map_product f xs ys 的元素出现一次。

这些元素出现的顺序未指定。

序列 xsys 不需要是有限的。

序列 xsys 必须是持久性的。

map_product f xs ys 等价于 map (fun (x, y) -> f x y) (product xs ys)

将序列拆分为两个序列

val unzip : ('a * 'b) t -> 'a t * 'b t

unzip 将配对序列转换为配对序列。

unzip xs 等价于 (map fst xs, map snd xs)

查询 unzip xs 返回的任何一个序列都会导致查询 xs。因此,查询这两个序列会导致 xs 被查询两次。因此,xs 必须是持久且廉价的。如果不是这种情况,请使用 unzip (memoize xs)

val split : ('a * 'b) t -> 'a t * 'b t

splitunzip 的别名。

val partition_map : ('a -> ('b, 'c) Either.t) -> 'a t -> 'b t * 'c t

partition_map f xs 返回一对序列 (ys, zs),其中

  • ys 是元素 y 的序列,其中 f x = Left y,其中 x 遍历 xs
  • zs 是元素 z 的序列,其中 f x = Right z,其中 x 遍历 xs

partition_map f xs 等价于 filter_map Either.find_left (map f xs)filter_map Either.find_right (map f xs) 的一个对。

查询 partition_map f xs 返回的任何一个序列都会导致查询 xs。因此,查询这两个序列会导致 xs 被查询两次。因此,xs 必须是持久且廉价的。如果不是这种情况,请使用 partition_map f (memoize xs)

val partition : ('a -> bool) -> 'a t -> 'a t * 'a t

partition p xs 返回满足 pxs 元素的子序列和不满足 pxs 元素的子序列的一对。

partition p xs 等价于 filter p xs, filter (fun x -> not (p x)) xs

使用 partition p xs 返回的两个序列都会导致 xs 被使用两次,并导致函数 f 对列表中的每个元素应用两次。因此,f 应该纯净且廉价。此外,xs 应该持久且廉价。如果不是这种情况,请使用 partition p (memoize xs)

在序列和分配器之间转换

分配器是将序列表示为类型为 unit -> 'a option 的函数。每次调用此函数时,它都会返回序列的下一个元素。当没有更多元素时,它会返回 None。分配器具有可变的内部状态,因此是短暂的:它表示的序列最多只能使用一次。

val of_dispenser : (unit -> 'a option) -> 'a t

of_dispenser it 是分配器 it 生成的元素的序列。它是一个短暂的序列:它最多只能使用一次。如果需要持久序列,请使用 memoize (of_dispenser it)

val to_dispenser : 'a t -> unit -> 'a option

to_dispenser xs 是序列 xs 上的一个新的分配器。

此分配器具有可变的内部状态,该状态不受锁保护;因此,它不得被多个线程同时使用。

整数序列

val ints : int -> int t

ints i 是从 i 开始并向上计数的无限整数序列。