diff --git a/src/Arrays.ml b/src/Arrays.ml new file mode 100644 index 0000000000000000000000000000000000000000..5c943ae7ae7b90defe49042debe04e31f0f5d189 --- /dev/null +++ b/src/Arrays.ml @@ -0,0 +1,88 @@ +module QArray = struct + + (* Most functions are inherited from the module [Array]. *) + + include Array + + (* Types. *) + + type mut + type immut + type ('m, 'a) qarray = 'a array + type ('m, 'a) t = ('m, 'a) qarray + + (* In the future, we might wish to publish the type equality + [(mut, 'a) qarray = 'a array]. + This could be done by exploiting an equality GADT. + However, the type [(_, _) eq] does not yet exist in OCaml's + standard library, so let us wait. *) + + (* The type equality [(immut, 'a) qarray = 'a array] + must of course not be published. *) + + (* The empty array. *) + + let empty = [||] + + (* Weak type equality witnesses. *) + + let import a = a + let export a = a + +end + +(* The implementation of [IArray] exploits the type equality + [('m, 'a) qarray = 'a array], which is not part of the public + interface of [QArray]. For this reason, [QArray] and [IArray] + must be placed in the same file (or [QArray] must publish unsafe + operations). *) + +module IArray = struct + + (* Most functions are inherited from the module [Array]. *) + + include Array + + (* The type ['a iarray]. *) + + type 'a iarray = 'a array + + (* The type ['a t], another name for the same type. *) + + type 'a t = 'a iarray + + (* The empty array. *) + + let empty = [||] + + (* Conversions between mutable arrays and immutable arrays. + In either direction, a copy is required; we cannot allow + a single array to be viewed both as mutable and immutable. *) + + let to_array = Array.copy + let of_array = Array.copy + + (* Sorting requires a copy, followed with an in-place sorting step. + It might be possible to propose a faster sorting algorithm, by + taking advantage of the fact that we are allowed to allocate an + auxiliary array. *) + + let sort cmp a = + let a = copy a in + sort cmp a; + a + + let stable_sort cmp a = + let a = copy a in + stable_sort cmp a; + a + + let fast_sort cmp a = + let a = copy a in + fast_sort cmp a; + a + + (* It would be nice if we could redefine the array access notation + [a.(i)], but OCaml does not allow this. *) + +end diff --git a/src/Arrays.mli b/src/Arrays.mli new file mode 100644 index 0000000000000000000000000000000000000000..69368f62417034b54a88fa03506bb22ac72e20dc --- /dev/null +++ b/src/Arrays.mli @@ -0,0 +1,170 @@ +module QArray : sig + + (**Mutability-polymorphic arrays. *) + + (**{1 Types} *) + + (**An array of type [(mut, 'a) qarray] is definitely mutable. It can be + read, written, and used in a context where a mutable array is expected. + + An array of type [(immut, 'a) qarray] is definitely immutable. It can be + read, but not written. It can be used in a context where an immutable + array is expected. + + An array of type [('q, 'a) qarray], where the qualifier ['q] is abstract, + could be mutable or immutable. It can be read, but not written, and + cannot be used in a context where a mutable array or an immutable array + is expected. + + When a function takes an argument of type [(_, 'a) qarray], this function + does not care whether the array is mutable or immutable; this function + can only read this array. + + When a function returns a result of type [(_, 'a) qarray], this function + creates a fresh array, and does not care whether the array is viewed by + the caller as mutable or immutable, but the caller must choose one of + these two possibilities: an array cannot be both mutable and immutable. + + The function [copy] can be used to turn a mutable array into an immutable + array, and vice-versa. Indeed, [copy] can be applied to an arbitrary + array (mutable, immutable, or abstract) and the new array can be regarded + either as mutable or as immutable, as one wishes. *) + + type mut + type immut + type ('q, 'a) qarray + type ('q, 'a) t = ('q, 'a) qarray + + (** {1 New Operations} *) + + (**[empty] is an array of length 0. It is both mutable and immutable. *) + val empty : (_, 'a) qarray + + (**[import] is an identity function. *) + val import: 'a array -> (mut, 'a) qarray + + (**[export] is an identity function. *) + val export: (mut, 'a) qarray -> 'a array + + (** {1 Standard Operations} *) + + val length : (_, 'a) qarray -> int + val get : (_, 'a) qarray -> int -> 'a + val set : (mut, 'a) qarray -> int -> 'a -> unit + val make : int -> 'a -> (_, 'a) qarray + val create_float : int -> (mut, float) qarray + val init : int -> (int -> 'a) -> (_, 'a) qarray + val make_matrix : int -> int -> 'a -> (mut, (mut, 'a) qarray) qarray + val append : (_, 'a) qarray -> (_, 'a) qarray -> (_, 'a) qarray + val concat : (_, 'a) qarray list -> (_, 'a) qarray + val sub : (_, 'a) qarray -> int -> int -> (_, 'a) qarray + val copy : (_, 'a) qarray -> (_, 'a) qarray + val fill : (mut, 'a) qarray -> int -> int -> 'a -> unit + val blit : (_, 'a) qarray -> int -> (mut, 'a) qarray -> int -> int -> unit + val to_list : (_, 'a) qarray -> 'a list + val of_list : 'a list -> (_, 'a) qarray + val iter : ('a -> unit) -> (_, 'a) qarray -> unit + val iteri : (int -> 'a -> unit) -> (_, 'a) qarray -> unit + val map : ('a -> 'b) -> (_, 'a) qarray -> (_, 'b) qarray + val mapi : (int -> 'a -> 'b) -> (_, 'a) qarray -> (_, 'b) qarray + val fold_left : ('a -> 'b -> 'a) -> 'a -> (_, 'b) qarray -> 'a + val fold_left_map : ('a -> 'b -> 'a * 'c) -> 'a -> (_, 'b) qarray -> 'a * (_, 'c) qarray + val fold_right : ('b -> 'a -> 'a) -> (_, 'b) qarray -> 'a -> 'a + val iter2 : ('a -> 'b -> unit) -> (_, 'a) qarray -> (_, 'b) qarray -> unit + val map2 : ('a -> 'b -> 'c) -> (_, 'a) qarray -> (_, 'b) qarray -> (_, 'c) qarray + val for_all : ('a -> bool) -> (_, 'a) qarray -> bool + val exists : ('a -> bool) -> (_, 'a) qarray -> bool + val for_all2 : ('a -> 'b -> bool) -> (_, 'a) qarray -> (_, 'b) qarray -> bool + val exists2 : ('a -> 'b -> bool) -> (_, 'a) qarray -> (_, 'b) qarray -> bool + val mem : 'a -> (_, 'a) qarray -> bool + val memq : 'a -> (_, 'a) qarray -> bool + val find_opt : ('a -> bool) -> (_, 'a) qarray -> 'a option + val find_map : ('a -> 'b option) -> (_, 'a) qarray -> 'b option + val split : (_, 'a * 'b) qarray -> (_, 'a) qarray * (_, 'b) qarray + val combine : (_, 'a) qarray -> (_, 'b) qarray -> (_, 'a * 'b) qarray + val sort : ('a -> 'a -> int) -> (mut, 'a) qarray -> unit + val stable_sort : ('a -> 'a -> int) -> (mut, 'a) qarray -> unit + val fast_sort : ('a -> 'a -> int) -> (mut, 'a) qarray -> unit + val to_seq : (_, 'a) qarray -> 'a Seq.t + val to_seqi : (_, 'a) qarray -> (int * 'a) Seq.t + val of_seq : 'a Seq.t -> (_, 'a) qarray + +end + +module IArray : sig + + (**This module provides a type of immutable arrays and operations on + immutable arrays. An immutable array is internally represented exactly in + the same way as a mutable array, but the type system guarantees that an + immutable array cannot be modified. + + This module offers a fragment of the functionality of the module + [QArray]. The type ['a iarray] is a synonym for [(immut, 'a) qarray], and + the operations provided by this module are a subset of the operations + provided by [QArray]. + + As a slight exception to this rule, the three [sort] functions provided + by [IArray] return a sorted copy of the original array, whereas the + [sort] functions in [QArray] sort a mutable array in place. *) + + (** {1 Types} *) + + open QArray (* useful on the next line *) + type 'a iarray = (immut, 'a) qarray + type 'a t = 'a iarray + + (** {1 New Operations} *) + + (**[empty] is an immutable array of length 0. *) + val empty : 'a iarray + + (**[to_array a] creates a fresh mutable copy of the immutable array [a]. *) + val to_array : 'a iarray -> 'a array + + (**[of_array a] is an immutable copy of the mutable array [a]. *) + val of_array : 'a array -> 'a iarray + + (** {1 Standard Operations} *) + + val length : 'a iarray -> int + val get : 'a iarray -> int -> 'a + (* no [set] *) + val make : int -> 'a -> 'a iarray + (* no [create_float] *) + val init : int -> (int -> 'a) -> 'a iarray + (* no [make_matrix] *) + val append : 'a iarray -> 'a iarray -> 'a iarray + val concat : 'a iarray list -> 'a iarray + val sub : 'a iarray -> int -> int -> 'a iarray + (* no [copy] *) + (* no [fill] *) + val blit : 'a iarray -> int -> 'a array -> int -> int -> unit + val to_list : 'a iarray -> 'a list + val of_list : 'a list -> 'a iarray + val iter : ('a -> unit) -> 'a iarray -> unit + val iteri : (int -> 'a -> unit) -> 'a iarray -> unit + val map : ('a -> 'b) -> 'a iarray -> 'b iarray + val mapi : (int -> 'a -> 'b) -> 'a iarray -> 'b iarray + val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b iarray -> 'a + val fold_left_map : ('a -> 'b -> 'a * 'c) -> 'a -> 'b iarray -> 'a * 'c iarray + val fold_right : ('b -> 'a -> 'a) -> 'b iarray -> 'a -> 'a + val iter2 : ('a -> 'b -> unit) -> 'a iarray -> 'b iarray -> unit + val map2 : ('a -> 'b -> 'c) -> 'a iarray -> 'b iarray -> 'c iarray + val for_all : ('a -> bool) -> 'a iarray -> bool + val exists : ('a -> bool) -> 'a iarray -> bool + val for_all2 : ('a -> 'b -> bool) -> 'a iarray -> 'b iarray -> bool + val exists2 : ('a -> 'b -> bool) -> 'a iarray -> 'b iarray -> bool + val mem : 'a -> 'a iarray -> bool + val memq : 'a -> 'a iarray -> bool + val find_opt : ('a -> bool) -> 'a iarray -> 'a option + val find_map : ('a -> 'b option) -> 'a iarray -> 'b option + val split : ('a * 'b) iarray -> 'a iarray * 'b iarray + val combine : 'a iarray -> 'b iarray -> ('a * 'b) iarray + val sort : ('a -> 'a -> int) -> 'a iarray -> 'a iarray + val stable_sort : ('a -> 'a -> int) -> 'a iarray -> 'a iarray + val fast_sort : ('a -> 'a -> int) -> 'a iarray -> 'a iarray + val to_seq : 'a iarray -> 'a Seq.t + val to_seqi : 'a iarray -> (int * 'a) Seq.t + val of_seq : 'a Seq.t -> 'a iarray + +end