SEQUENCE signature
The SEQUENCE signature is a comprehensive interface for a
persistent sequence type. We use a number of notational conventions which
can be seen here.
For example, we write $|s|$ and $s[i]$ for the length and $i^\text{th}$
element of $s$, respectively.
type 'a t
type 'a seq = 'a t
type 'a ord = 'a * 'a → order
datatype 'a listview = NIL | CONS of 'a * 'a seq
datatype 'a treeview = EMPTY | ONE of 'a | PAIR of 'a seq * 'a seq
exception Range
exception Size
val nth : 'a seq → int → 'a
val length : 'a seq → int
val toList : 'a seq → 'a list
val toString : ('a → string) → 'a seq → string
val equal : ('a * 'a → bool) → 'a seq * 'a seq → bool
val empty : unit → 'a seq
val singleton : 'a → 'a seq
val tabulate : (int → 'a) → int → 'a seq
val fromList : 'a list → 'a seq
val rev : 'a seq → 'a seq
val append : 'a seq * 'a seq → 'a seq
val flatten : 'a seq seq → 'a seq
val filter : ('a → bool) → 'a seq → 'a seq
val map : ('a → 'b) → 'a seq → 'b seq
val zip : 'a seq * 'b seq → ('a * 'b) seq
val zipWith : ('a * 'b → 'c) → 'a seq * 'b seq → 'c seq
val enum : 'a seq → (int * 'a) seq
val filterIdx : (int * 'a → bool) → 'a seq → 'a seq
val mapIdx : (int * 'a → 'b) → 'a seq → 'b seq
val update : 'a seq * (int * 'a) → 'a seq
val inject : 'a seq * (int * 'a) seq → 'a seq
val subseq : 'a seq → int * int → 'a seq
val take : 'a seq → int → 'a seq
val drop : 'a seq → int → 'a seq
val splitHead : 'a seq → 'a listview
val splitMid : 'a seq → 'a treeview
val iterate : ('b * 'a → 'b) → 'b → 'a seq → 'b
val iteratePrefixes : ('b * 'a → 'b) → 'b → 'a seq → 'b seq * 'b
val iteratePrefixesIncl : ('b * 'a → 'b) → 'b → 'a seq → 'b seq
val reduce : ('a * 'a → 'a) → 'a → 'a seq → 'a
val scan : ('a * 'a → 'a) → 'a → 'a seq → 'a seq * 'a
val scanIncl : ('a * 'a → 'a) → 'a → 'a seq → 'a seq
val sort : 'a ord → 'a seq → 'a seq
val merge : 'a ord → 'a seq * 'a seq → 'a seq
val collect : 'a ord → ('a * 'b) seq → ('a * 'b seq) seq
val collate : 'a ord → 'a seq ord
val argmax : 'a ord → 'a seq → int
val $ : 'a → 'a seq
val % : 'a list → 'a seq
type 'a ttype 'a seq = 'a t'a t has elements of type 'a.
The alias 'a seq is for readability.
type 'a ord = 'a * 'a → order'a, for readability.datatype 'a listview =
NIL | CONS of 'a * 'a seqsplitHead.datatype 'a treeview =
EMPTY | ONE of 'a | PAIR of 'a seq * 'a seqsplitMid.exception RangeRange is raised whenever an invalid index into a sequence is used.exception SizeSize is raised whenever a function is given a negative size.val nth :
'a seq → int → 'anth s i evaluates to $s[i]$,
the $i^\text{th}$ element of $s$.
Raises Range if $i$ is out of
bounds.val length :
'a seq → intlength s evaluates to $|s|$, the number of elements in $s$.val toList :
'a seq → 'a listval toString :
('a → string) → 'a seq → stringtoString f s produces a string
representation of $s$. Each element of $s$ is converted to a string via $f$.
For example,
(toString Int.toString $\langle 1,2,3 \rangle$)
evaluates to the string “<1,2,3>”.
val equal :
('a * 'a → bool) → 'a seq * 'a seq → boolequal f (s, t) returns whether or not $s$ and $t$ contain
exactly the same elements, in the same order.
Individual element pairs are compared for equality with $f$. val empty :
unit → 'a seqval singleton :
'a → 'a seq(singleton x) evaluates to $\langle x \rangle$.val tabulate :
(int → 'a) → int → 'a seq(tabulate f n) evaluates to the length-$n$ sequence where
the $i^\text{th}$ element is given by $f(i)$. Raises
Size if $n<0$.
val fromList :
'a list → 'a seqval rev :
'a seq → 'a seqrev s reverses the indexing of a sequence.
That is, nth (rev s) i is equivalent to
nth s (length s - i - 1).
val append :
'a seq * 'a seq → 'a seqval flatten :
'a seq seq → 'a seqflatten $\langle \langle 1, 2 \rangle, \langle \rangle, \langle 3 \rangle \rangle$
evaluates to $\langle 1, 2, 3 \rangle$.val filter :
('a → bool) → 'a seq → 'a seqfilter p s evaluates to the subsequence of $s$ which contains
every element satisfying the predicate $p$.
val map :
('a → 'b) → 'a seq → 'b seqmap f s applies $f$ to each element of $s$.
It is logically equivalent to tabulate (f o nth s) (length s).val zip :
'a seq * 'b seq → ('a * 'b) seqzip (s, t) evaluates to a sequence of length
$\min(|s|, |t|)$ whose $i^\text{th}$ element is the pair $(s[i], t[i])$.val zipWith :
('a * 'b → 'c) → 'a seq * 'b seq → 'c seqzipWith f (s, t) is logically equivalent to
map f (zip (s, t)).val enum :
'a seq → (int * 'a) seqenum s evaluates to a sequence where each
element is paired with its index.
It is logically equivalent to tabulate
(fn i => (i, nth s i)) (length s)
.
val filterIdx :
(int * 'a → bool) → 'a seq → 'a seqfilterIdx f s is logically equivalent to
map (fn (_, x) => x) (filter f (enum s))
.
val mapIdx :
(int * 'a → 'b) → 'a seq → 'b seqmapIdx f s is logically equivalent to
map f (enum s).val update :
'a seq * (int * 'a) → 'a sequpdate (s, (i, x)) evaluates to the sequence
whose $i^\text{th}$ element is $x$, and whose other elements are
unchanged from $s$.
If $i$ is out-of-bounds, it raises Range,
otherwise it is logically equivalent to
tabulate (fn j => if i = j then x else nth s j) (length s)
.
val inject :
'a seq * (int * 'a) seq → 'a seqinject (s, u) produces a new sequence where, for each
$(i,x) \in u$, the $i^\text{th}$ element of s has been
replaced with $x$. If there are multiple updates specified at the same
index, then all but one of them are ignored non-deterministically. Raises
Range if any $(i,\_) \in u$ is
out-of-bounds.
When all indices in $u$ are distinct, inject (s, u)
is logically equivalent to iterate update s u.
val subseq :
'a seq → int * int → 'a seqsubseq s (i, n) evaluates to the
contiguous subsequence of $s$
starting at index $i$ with length $n$.
Raises
Size if $n<0$. Raises
Range if the subsequence is
out of bounds.val take :
'a seq → int → 'a seqtake s n takes the prefix of $s$ of length $n$.
It is logically equivalent to
subseq s (0, n).val drop :
'a seq → int → 'a seqdrop s n drops the prefix of $s$ of length $n$. It is logically equivalent to
subseq s (n, length s - n).val splitHead :
'a seq → 'a listviewsplitHead s evaluates to NIL if $s$ is
empty, and otherwise is logically equivalent to
CONS ($s[0]$, drop $s$ 1).
val splitMid :
'a seq → 'a treeviewsplitMid s evaluates to EMPTY if
$s$ is empty, ONE $x$ if
$s = \langle x \rangle$, and PAIR ($l, r$)
otherwise, where both $l$ and $r$ are nonempty and their concatenation
is $s$. The sizes of $l$ and $r$ are implementation-defined.val iterate :
('b * 'a → 'b) → 'b → 'a seq → 'b(iterate f b s) computes the iteration of $f$ on $s$
with left-association, using $b$ as the base case. It is
logically equivalent to
\[ f(\dots f(f(b,~ s[0]),~ s[1]) \dots,~ s[|s|-1]) \]
When $s$ is empty, it returns $b$.
iterate op+ 13 (fromList [1,2,3]) evaluates to 19.
val iteratePrefixes :
('b * 'a → 'b) → 'b → 'a seq → 'b seq * 'biteratePrefixes f b s is logically equivalent to
(tabulate (fn i => iterate f b (take s i)) (length s), iterate f b s)
That is, it produces the iteration of $f$ for each prefix of $s$.
val iteratePrefixesIncl :
('b * 'a → 'b) → 'b → 'a seq → 'b seqiteratePrefixesIncl f b s is inclusive of $s[i]$, rather than exclusive.
It is logically equivalent to
tabulate (fn i => iterate f b (take s (i+1))) (length s)
The return type of iteratePrefixesIncl is slightly different than iteratePrefixes.
val reduce :
('a * 'a → 'a) → 'a → 'a seq → 'areduce f b s evaluates to $b$ when $s = \langle \rangle$,
$x$ when $s = \langle x \rangle$, and otherwise is logically equivalent to
f (reduce f b l, reduce f b r)
where l = take s (n div 2) and r = drop s (n div 2).
reduce f b s is logically equivalent to iterate f b s when $f$ is associative
and $b$ is a corresponding identity.
val scan :
('a * 'a → 'a) → 'a → 'a seq → 'a seq * 'ascan f b s is logically equivalent to
iteratePrefixes f b s.
val scanIncl :
('a * 'a → 'a) → 'a → 'a seq → 'a seqscanIncl f b s is logically equivalent to
iteratePrefixesIncl f b s.
val sort :
'a ord → 'a seq → 'a seq(sort c s) reorders the elements of $s$ with respect
to the comparison function $c$. The output is stable:
any two elements considered equal by $c$ will appear in the same relative order
in the output as they were in the input.
val merge :
'a ord → 'a seq * 'a seq → 'a seqc,
(merge c (s, t)) is logically equivalent to sort c (append (s, t)).
val collect :
'a ord → ('a * 'b) seq → ('a * 'b seq) seqcollect cmp s takes a sequence $s$ of key-value pairs,
deduplicates the keys, sorts them with respect to $c$, and pairs each unique key
with all values that were originally associated with it in $s$.
The resulting value-sequences retain their relative ordering from $s$.
Collecting $\langle (3,7), (2,6), (1,8), (3,5) \rangle$ produces
$\left\langle (1, \langle 8 \rangle), (2, \langle 6 \rangle), (3, \langle 7, 5 \rangle) \right\rangle$.
val collate :
'a ord → 'a seq ordcollate c produces an ordering on sequences,
derived lexicographically from c.val argmax :
'a ord → 'a seq → intargmax c s produces the index
of the maximal value in $s$ with respect to c. Raises
Range when $s$ is empty. val $ :
'a → 'a seqsingleton. val % :
'a list → 'a seqfromList.