module Seq: Seq
type'a
t =unit -> 'a node
一个类型为 'a t
的序列 xs
是一个类型为 'a
的元素的延迟列表。通过执行函数应用 xs()
来查询此类序列。此函数应用返回一个节点,允许调用者确定序列是否为空或非空,以及在后者情况下,获取其头部和尾部。
type 'a
node =
| |
Nil |
| |
Cons of |
节点要么是 Nil
,表示序列为空,要么是 Cons (x, xs)
,表示 x
是序列的第一个元素,xs
是序列的其余部分。
本节中的函数会部分或完全地消费其参数(一个序列)。
is_empty
和 uncons
会将序列消耗到深度 1。也就是说,它们会请求序列的第一个参数(如果存在)。iter
、fold_left
、length
等会一直消耗序列到其末尾。只有当序列是有限的时,它们才会终止。for_all
、exists
、find
等会将序列消耗到某个深度,该深度是先验不可预测的。类似地,在消费两个序列的函数中,可以区分两组。
iter2
和 fold_left2
会一直消耗两个序列到末尾,前提是序列具有相同的长度。for_all2
、exists2
、equal
、compare
会将序列消耗到某个深度,该深度是先验不可预测的。消费两个序列的函数可以应用于两个长度不同的序列:在这种情况下,较长序列中的多余元素将被忽略。(即使不使用此元素,也可能会请求一个多余元素。)
本节中的任何函数都不是惰性的。这些函数是消费者:它们会强制执行一些计算。
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 xs
为 None
。
如果 xs
不为空,则 uncons xs
为 Some (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 _
的元素(如果存在),并且 y
由 f 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
会依次对从序列 xs
和 ys
同步提取的每个元素对 (x, y)
调用 f x y
。
如果序列 xs
和 ys
的长度不同,则迭代在其中一个序列耗尽时停止;另一个序列中的多余元素将被忽略。
只有当序列 xs
和 ys
中至少有一个是有限的时,迭代才会终止。
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
会依次对从序列 xs
和 ys
同步提取的每个元素对 (x, y)
调用 f _ x y
。
类型为 'a
的累加器会贯穿对 f
的调用。
如果序列 xs
和 ys
的长度不同,则迭代在其中一个序列耗尽时停止;另一个序列中的多余元素将被忽略。
只有当序列 xs
和 ys
中至少有一个是有限的时,迭代才会终止。
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
确定从序列 xs
和 ys
同步提取的每个元素对 (x, y)
是否都满足 p x y
。
如果序列 xs
和 ys
的长度不同,则迭代在其中一个序列耗尽时停止;另一个序列中的多余元素将被忽略。特别是,如果 xs
或 ys
为空,则 for_all2 p xs ys
为真。这是 for_all2
和 equal
的区别所在:只有当 xs
和 ys
的长度相同时,equal eq xs ys
才能为真。
序列 xs
和 ys
中至少有一个必须是有限的。
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
确定从序列 xs
和 ys
同步提取的某些元素对 (x, y)
是否满足 p x y
。
如果序列 xs
和 ys
的长度不同,则迭代必须在其中一个序列耗尽时停止;另一个序列中的多余元素将被忽略。
序列 xs
和 ys
中至少有一个必须是有限的。
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
确定序列 xs
和 ys
是否逐点相等。
序列 xs
和 ys
中至少有一个必须是有限的。
val compare : ('a -> 'b -> int) -> 'a t -> 'b t -> int
假设函数 cmp
定义了元素上的预序,则 compare cmp xs ys
根据字典序预序比较序列 xs
和 ys
。
有关比较函数的更多详细信息,请参阅 Array.sort
。
序列 xs
和 ys
中至少有一个必须是有限的。
本节中的函数是惰性的:也就是说,它们返回的序列的元素仅在需要时才计算。
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)
。
Invalid_argument
,如果 n
为负数。val unfold : ('b -> ('a * 'b) option) -> 'b -> 'a t
unfold
使用步进函数和初始状态构建序列。
如果 f u
为 None
,则 unfold f u
为空序列。如果 f u
为 Some (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
是一个无限序列,其元素为 x
、f x
、f (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
mapi
与 map
类似,但它将函数 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 y
,x
遍历 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; ...]
的序列,其中 a1
是 f a0 x0
,a2
是 f 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
必须是非负数。
Invalid_argument
,如果 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
。
Invalid_argument
,如果 n
为负数。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
。这在调试或测试时非常有用,以确保序列最多被消费一次。
Forced_twice
如果 once xs
或其后缀被查询多次。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
是序列 xs
和 ys
的连接。
其元素是 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_map
是 flat_map
的别名。
val zip : 'a t -> 'b t -> ('a * 'b) t
zip xs ys
是从序列 xs
和 ys
同步提取的配对 (x, y)
的序列。
如果序列 xs
和 ys
的长度不同,则序列在其中一个序列耗尽时结束;另一个序列中的多余元素将被忽略。
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)
是从序列 xs
和 ys
同步提取的。
如果序列 xs
和 ys
的长度不同,则序列在其中一个序列耗尽时结束;另一个序列中的多余元素将被忽略。
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
的第一个元素继续,依此类推。
当 xs
和 ys
中的一个序列耗尽时,interleave xs ys
将继续使用另一个序列的其余部分。
val sorted_merge : ('a -> 'a -> int) -> 'a t -> 'a t -> 'a t
如果序列 xs
和 ys
根据全序 cmp
排序,则 sorted_merge cmp xs ys
是通过合并序列 xs
和 ys
获得的排序序列。
有关比较函数的更多详细信息,请参阅 Array.sort
。
val product : 'a t -> 'b t -> ('a * 'b) t
product xs ys
是序列 xs
和 ys
的笛卡尔积。
对于 xs
的每个元素 x
和 ys
的每个元素 y
,配对 (x, y)
作为 product xs ys
的元素出现一次。
配对出现的顺序未指定。
序列 xs
和 ys
不需要是有限的。
序列 xs
和 ys
必须是持久性的。
val map_product : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t
序列 map_product f xs ys
是序列 xs
和 ys
的笛卡尔积通过 f
的像。
对于 xs
的每个元素 x
和 ys
的每个元素 y
,元素 f x y
作为 map_product f xs ys
的元素出现一次。
这些元素出现的顺序未指定。
序列 xs
和 ys
不需要是有限的。
序列 xs
和 ys
必须是持久性的。
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
split
是 unzip
的别名。
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
返回满足 p
的 xs
元素的子序列和不满足 p
的 xs
元素的子序列的一对。
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
开始并向上计数的无限整数序列。