ListPair structure

May 20, 2026 ยท View on GitHub

Up to index

The ListPair structure provides operations for working with two lists simultaneously. Operations whose names do not end in Eq silently ignore excess elements of the longer list; those ending in Eq raise UnequalLengths when the lists differ in length.

Specified by the Standard ML Basis Library.

Synopsis

exception UnequalLengths

val zip : 'a list * 'b list -> ('a * 'b) list
val unzip : ('a * 'b) list -> 'a list * 'b list
val map : ('a * 'b -> 'c) -> 'a list * 'b list -> 'c list
val app : ('a * 'b -> unit) -> 'a list * 'b list -> unit
val all : ('a * 'b -> bool) -> 'a list * 'b list -> bool
val exists : ('a * 'b -> bool) -> 'a list * 'b list -> bool
val foldr : ('a * 'b * 'c -> 'c) -> 'c -> 'a list * 'b list -> 'c
val foldl : ('a * 'b * 'c -> 'c) -> 'c -> 'a list * 'b list -> 'c
val allEq : ('a * 'b -> bool) -> 'a list * 'b list -> bool
val zipEq : 'a list * 'b list -> ('a * 'b) list
val mapEq : ('a * 'b -> 'c) -> 'a list * 'b list -> 'c list
val appEq : ('a * 'b -> unit) -> 'a list * 'b list -> unit
val foldrEq : ('a * 'b * 'c -> 'c) -> 'c -> 'a list * 'b list -> 'c
val foldlEq : ('a * 'b * 'c -> 'c) -> 'c -> 'a list * 'b list -> 'c

exception UnequalLengths

is raised by those functions that require arguments of identical length.

zip

zip (l1, l2) combines the two lists l1 and l2 into a list of pairs, with the first element of each list comprising the first element of the result, the second elements comprising the second element of the result, and so on. If the lists are of unequal lengths, zip ignores the excess elements from the tail of the longer one.

unzip

unzip l returns a pair of lists formed by splitting the elements of l. This is the inverse of zip for equal length lists.

map

map f (l1, l2) maps the function f over the list of pairs of elements generated from left to right from the lists l1 and l2, returning the list of results. If the lists are of unequal lengths, ignores the excess elements from the tail of the longer one. It is equivalent to:

List.map f (zip (l1, l2))

ignoring possible side effects of the function f.

app

app f (l1, l2) applies the function f to the list of pairs of elements generated from left to right from the lists l1 and l2. If the lists are of unequal lengths, ignores the excess elements from the tail of the longer one. It is equivalent to:

List.app f (zip (l1, l2))

ignoring possible side effects of the function f.

all

all f (l1, l2) provides short-circuit testing of a predicate over a pair of lists.

It is equivalent to:

List.all f (zip (l1, l2))

exists

exists f (l1, l2) provides short-circuit testing of a predicate over a pair of lists.

It is equivalent to:

List.exists f (zip (l1, l2))

foldr

foldr f init (l1, l2) returns the result of folding the function f in the specified direction over the pair of lists l1 and l2 starting with the value init. It is equivalent to:

List.foldr f' init (zip (l1, l2))

where f' is fn ((a,b),c) => f(a,b,c) and ignoring possible side effects of the function f.

foldl

foldl f init (l1, l2) returns the result of folding the function f in the specified direction over the pair of lists l1 and l2 starting with the value init. It is equivalent to:

List.foldl f' init (zip (l1, l2))

where f' is fn ((a,b),c) => f(a,b,c) and ignoring possible side effects of the function f.

allEq

allEq f (l1, l2) returns true if l1 and l2 have equal length and all pairs of elements satisfy the predicate f. That is, the expression is equivalent to:

(List.length l1 = List.length l2) andalso
(List.all f (zip (l1, l2)))

This function does not appear to have any nice algebraic relation with the other functions, but it is included as providing a useful notion of equality, analogous to the notion of equality of lists over equality types.

Implementation note:

The implementation is simple:

fun allEq p ([], []) = true
  | allEq p (x::xs, y::ys) = p(x,y) andalso allEq p (xs,ys)
  | allEq _ _ = false

zipEq

zipEq (l1, l2) combines the two lists l1 and l2 into a list of pairs, with the first element of each list comprising the first element of the result, the second elements comprising the second element of the result, and so on. If the lists are of unequal lengths, zipEq raises the exception UnequalLengths.

mapEq

mapEq f (l1, l2) maps the function f over the list of pairs of elements generated from left to right from the lists l1 and l2, returning the list of results. If the lists are of unequal lengths, raises UnequalLengths. It is equivalent to:

List.map f (zipEq (l1, l2))

ignoring possible side effects of the function f.

appEq

appEq f (l1, l2) applies the function f to the list of pairs of elements generated from left to right from the lists l1 and l2. If the lists are of unequal lengths, raises UnequalLengths. It is equivalent to:

List.app f (zipEq (l1, l2))

ignoring possible side effects of the function f.

foldrEq

foldrEq f init (l1, l2) returns the result of folding the function f in the specified direction over the pair of lists l1 and l2 starting with the value init. It is equivalent to:

List.foldr f' init (zipEq (l1, l2))

where f' is fn ((a,b),c) => f(a,b,c) and ignoring possible side effects of the function f.

foldlEq

foldlEq f init (l1, l2) returns the result of folding the function f in the specified direction over the pair of lists l1 and l2 starting with the value init. It is equivalent to:

List.foldl f' init (zipEq (l1, l2))

where f' is fn ((a,b),c) => f(a,b,c) and ignoring possible side effects of the function f.