		The Edinburgh Standard ML Program Library
							
			       User's Guide

				Dave Berry

				 10/11/89



		   PART 1: AN OVERVIEW OF THE LIBRARY


		-----------------------------------------

			 What is the library?

		-----------------------------------------

	The Edinburgh Standard ML Program Library is a library of modules
developed at Edinburgh for the Standard ML programming language.  It is
intended to supply the basic functions used in many SML programs, so that
programmers don't have to write them over and over again.  Using the
library will also make your programs easier for other users of the library
to understand.

	The library is also intended to provide a standard interface for
common extensions to the language, such as vectors (both constant and variable
versions).

	A portable version of the library defines all the objects that
it provides, and can be used with any implementation of the language.
Implementers are encouraged to provide more efficient implementations
of the library.

	A few functions are system specific, and raise an exception when
they are called from the portable version of the library.


		-----------------------------------------

			How do I use the library?

		-----------------------------------------

	There are two parts of the library.  The first is called the
basic library, and provides little more than functions on the standard types.
The second part is an assortment of other entries, which are loaded
individually.  All library entries include a signature and an associated
implementation, will be either a functor or a structure.


	If the ML system that you're using includes an implementation of
the library, it will have a command to load the basic structures.  Indeed,
it may even have them loaded when you start ML.  The exact mechanism will
depend on the particular implementation.

	If you are using the portable version, you will have to find out
how to load files in the system and load the library yourself.  The
portable version includes a build file which loads the entries in the
correct order.

	The basic library provides the functions "loadSig", "loadFun" and
"loadStr", all of type "string -> unit", in the "Load" structure.
These load the signature, functor or structure associated with the named
library entry.  These can be used to load entries other than the basic
entries (if the entries aren't already provided).

	Some library entries will depend on others.  A good implementation
of the library will automatically load these others when they are needed,
but (particularly for the near future) you may have to do this yourself.
The portable version uses Nick Rothwell's portable make system; if you
have that you may find it useful.


		-----------------------------------------

		    What has the library got in it?

		-----------------------------------------

	The basic entries in the library are described below.  These
should be provided without the user having to load them individually.

  General.
	Types, exceptions and functions that are widely used or that
	don't fit anywhere else.  In particular, the types "Result",
	"Option" and "Nat" are made global and are used in many other
	library entries.

  InStream, OutStream.
	Input and output streams, offering a better interface than
	the built-in versions.  The types "InStream" and "OutStream"
	are made global and are used in many other entries.
	
  Bool, Byte, Int, Real, String: Object.
	Operations on the simple pervasive types.  Each of these
	structures match the signature Object, used by the MonoVector
	and MonoRefVector functors (see below).

  List: Sequence.
	Operations on the built-in type 'a list.  This structure
	matchers the Sequence signature, used by the SequenceToObject
	functor (see below).

  : RefSequence.
	The RefSequence signature is used by the RefSequenceToObject
	functor (see below).

  System.
	Some suggested functions for interacting with the host file
	system and the ML implementation.

  Load.
	The "loadSig", "loadFun" and "loadStr" functions described above.

	All the functions described as "suggested" in this list are not
implemented in the portable version of the library.  This is also true
of the functions for parsing real numbers and converting them back to
strings.


	The other entries currently provided are as follows.  We hope
that people will contribute further entries for commonly used types and
functions.  A list of entries that we would like to see is included at
the end of this document.

  Pair, ListPair, StreamPair.
	Operations on pairs of objects.  The "StreamPair" entry also
	includes suggested functions for interacting with the host file
	system using pairs of one instream and one outstream.

  User.
	Functions to prompt the user for input.  A window system should
	provide an appropriate replacement for this structure.

  Const.
	Creates unique copies of objects.

  Vector: Sequence.
	One-dimensional constant polymorphic arrays.

  RefVector: RefSequence.
	One-dimensional variable polymorphic arrays.

  MonoVector: Object -> MonoSequence.
	A functor that takes a structure that matches the Object signature
	and produces one-dimensional constant arrays of objects of that type.

  ByteVector, BoolVector.
	One-dimensional constant arrays of bytes and booleans respectively.
 
  MonoRefVector: Object -> MonoSequence.
	A functor that takes a structure that matches the Object signature
	and produces one-dimensional variable arrays of objects of that type.

  ByteRefVector, BoolRefVector.
	One-dimensional variable arrays of bytes and booleans respectively.

  SequenceToObject: Sequence, Object -> Object
	A functor that takes one structure that matches the Object signature
	and one that matches the Sequence signature, and produces a constant
	sequence of objects that matches the Object signature.

  RefSequenceToObject: RefSequence, Object -> Object
	A functor that takes one structure that matches the Object signature
	and one that matches the RefSequence signature, and produces a
	variable sequence of objects that matches the Object signature.

  Combinator.
	Simple combinator functions.

  Memo.
	Memoising functions.



		-----------------------------------------

	 	    What are the Object, Sequence and
		       RefSequence signatures for?

		-----------------------------------------

	Sometimes it is desirable to have a vector type of objects of a known
type, instead of a polymorphic vector.  One reason for this is that such
vectors can sometimes be implemented more efficiently then polymorphic ones.
For example, a vector of booleans can be implemented as a bitset.  Another
reason is that many functions over such vectors have a simpler type, as they
don't need a function parameter to apply to the elements of the vector.
For example, the equality functions on polymorphic vectors and monomorphic
vectors have the types "('a -> 'a -> bool) -> 'a Vector -> 'a Vector -> bool"
and "MonoVector -> MonoVector -> bool" respectively.

	This argument can also be applied to other sequences, such as lists.

	The library includes a general way of structuring such sequences.
The functors MonoVector and MonoRefVector take any structure that matches
the Object signature and produce monomorphic constant and variable vectors.
It is also possible to create monomorphic vectors of sequences, by first
converting a sequence to an object with the RefSequenceToObject or
SequenceToObject functors.

	Monomorphic vectors provide the same features as polymorphic
vectors, with all types "'a Vector" replaced with "MonoVector" and
all function arguments deleted.

	An implementation may provide appropriate special implementations
monomorphic vectors.  These implementations may use more meaningful type
names if appropriate.


		-----------------------------------------

		 How do I know what each entry contains?

		-----------------------------------------

	Each entry is documented by a signature and a sample (possibly
inefficient) implementation.
	
	The signature gives the usual type information, with a short
description of each object (in English), and some introductory material.
The introductory material includes details of the author, maintenance
arrangements and so forth.  Signatures may include Extended ML axioms
(in comments), if the implementer provides them.

	The implementation is a reference implementation of the objects
declared in the signature.  The actual implementation may be more
complex than this, but it must produce the same results and side-effects.
The only exception to this rule is that implementations may produce
debugging or tracing output in addition to their normal effects.

	System specific functions raise an exception in the reference
implementation.  Obviously they can behave differently in a real system!

	In part 2 of this guide we will look at an example entry in some
detail.


		-----------------------------------------

	   	   What lexical conventions are used?

		-----------------------------------------

	The following conventions are designed to make library entries
consistent and therefore easier to use.

  Identifiers.
	All words in alphanumeric identifiers are capitalised, except
	that alphanumeric labels and value identifiers (not including
	constructors and exceptions) begin with a lower case letter.
	Alphanumeric identifiers don't include underscores.  (This
	convention is broken by some of the pervasives and system
	functions.)

	Exception identifiers are often based on the name of the
	functions that raise them.  If the function identifier (f, say)
	is alphanumeric, then the exception identifier is f with its
	first letter in upper case.  If f is symbolic, then the exception
	identifier is f followed by an exclamation mark.

  Currying.
	Nonfix functions are usually curried.  Entries don't usually
	provide both curried and uncurried or infix versions of a function.

  Infix functions.
	Functions that are intended to be used infix are declared as
	such, with a suggested precedence, even though this status
	doesn't propagate when a structure is opened.

  Imperative functions.
	Imperative functions usually return the unit value.

  Equality Types.
	If a function is defined both in a version for equality types
	and in a version where an equality predicate is expected as an
	argument, the name of the first version should be the same as
	that of the second with a prime suffix (e.g.  "eq'" and "eq").

  Exceptions.
	Exceptions are only used for exceptional circumstances, such as
	calling a function with unsuitable arguments.  If a function
	sometimes returns a value and sometimes doesn't, then usually
	its result type will be an instance of the "Result" type defined
	in the "General" structure (and available globally).  Using these
	types forces you to use a case expression instead of a handler to
	check the result, which means that the compiler will report missing
	cases.

	Exceptions usually return some information about the values that
	caused the exception, and the name of the function in which it occurred
	(if more than one function can raise that exception).

  Sharing.
	Most objects defined in a library entry are unique to that entry.
	Shared objects should be defined in the "General" entry.


		-----------------------------------------

		    What naming conventions are used?

		-----------------------------------------

	Many library entries define a type and operations on that type.
These entries have several common names, so that frequently-used operations
are easy to remember.

	The Object signature contains several such functions:

  eq, ne, lt, le, gt, ge:
		The comparison functions.
  
  fixedWidth: 	True if the string representation of the type takes a
		known amount of space (e.g. for Bytes).

  string: 	Converts an object to its string representation.

  parse: 	Converts the string representation of an object to that object.

  parse': 	Like parse, but takes an exploded list.

  read:		Like parse, but takes an InStream.

	The Sequence and RefSequence signatures contain the above functions,
plus variants of the parse, parse' and read functions that let you specify
the start, finish and separating symbols used in a string representation.
The start and finish symbols must be single non-blank characters or empty
strings.  If the separating symbol is a blank, then zero or more formatting
characters are treated as separating elements.  If the separating symbol is
a single non-blank character, then that character plus an arbitrary amount
of whitespace must separate elements.  If the separating symbol is the empty
string, then nothing separates elements - for example, if the elements are
bytes then formatting characters will be read as the appropriate byte values.

	Other common names are:

  create:	Create an object from components.

  generate:	Generate an object by repeatedly applying a function.

  size:		Return the number of elements in a seqeuence.

  empty:	Return true if a sequnce is empty.

  sub, nth:	Return the nth element of a sequence.

  extract:	Return a subsequence of a sequence.

  map, apply, iterate, iterateApply:
		Apply a function to each element of a sequence
		(four variations of the basic idea).

  foldL, foldR, foldL', foldR':
		Combine the elements of a sequence to produce a single
		value (four variations of the basic idea).

  pairwise:	Test that all adjacent pairs of elements in a sequence
		satisfy a binary predicate.

  rev:		Reverse a sequence.

  ^ :		Catenate two sequences.

  same, different:
		Test whether two RefSequences are the same.


		-----------------------------------------

		 What new entries would you like to see?

		-----------------------------------------

	You're going to write one?  Oh good.

  	The following list gives some suggestions for useful entries:

  Associations (as association lists, binary trees, hash tables, or whatever).

  Sets.

  Regular expressions and substitutions over strings.

  Lazy lists.

  Complex numbers, rational numbers.

  Stacks, priority queues, etc.

  Tries (whatever they are - I know that someone's implemented them in SML).

  Scanner generators, parser generators (perhaps converting ML-LEX and
  	ML-YACC to the library format?).

  A portable, easy-to-use interface to host window systems.


		-----------------------------------------

	  What precedences do you recommend for infix operators?

		-----------------------------------------

This is the list of infix operators provided by the pervasives and
by the library:

  infix  1 Bool.or
  infix  2 Bool.&
  infix  3 o  Bool.implies
	   Combinator.oo  Combinator.co  Combinator.fby  Combinator.over
  infix  4 =  <>  <  >  <=  >=
  infix  5 Int.--
  infixr 5 ::  @
  infix  6 +  -  ^
  infix  7 /  *  div  mod  Int.divMod
  infix  8 Int.**  Real.**
  infix  9 *.sub

Note that @ associates to the right in the library.
Remember that infix status is local to each structure.

Equivalent curried functions for some of the above are as follows:

  =       X.eq, for most X
  <>      X.eq, for most X
  <       Int.lt, Real.lt (similar functions for other entries)
  >       Int.gt, Real.gt (  "         "      "    "      "   )
  <=      Int.le, Real.le (  "         "      "    "      "   )
  >=      Int.ge, Real.ge (  "         "      "    "      "   )
  @       List.appendLast (where the first list is non-empty)
  (,)     Pair.create


		       PART 2: AN EXAMPLE ENTRY

	In Part 2 we look at the signature of the "Vector" entry.  This
shows the general form of an entry and gives the types of some commonly used
functions.

	The signature is divided into sections.  A section is introduced
by a comment starting in the left most column; this comment gives the name of
the section (in upper case).  All code in this manual has been indented
two spaces.


  signature Vector =
  sig

		-----------------------------------------

				HEADER

		-----------------------------------------

	The entry begins with the HEADER section.  This is a comment that
includes the following information:

Title:

  (* CONSTANT VECTORS

Author and address:

     Created by:  Dave Berry, LFCS, University of Edinburgh
		  db@lfcs.ed.ac.uk

Creation date:

     Date:        31 Oct 1989

Creation notes (optional):

     Based on the Array signatures provided by Edinburgh ML, NJML and Poly ML.

Maintenance details:

     Maintenance: Author

Change log (optional):

     <currently empty>

	There is a standard syntax used in the HEADER section (and in the other
comments in the signature).  This is specified in the implementer's guide.
The standard makes it easy to write documentation tools that process entries.


		-----------------------------------------

			      DESCRIPTION

		-----------------------------------------

	The next part of the entry is a brief description of the entry in
another comment.  Often these comments are combined.

     DESCRIPTION

     A Vector is a single-dimensional constant polymorphic array.  The first
     element has the index 0.  Vectors are equal if they contain the same
     elements and these elements admit equality.

     To create a Vector of Vectors, use the "generate" functions.


	All entries in the library that admit an indexing operation are
usually indexed from zero.


		-----------------------------------------

		      EXAMPLES, SEE ALSO and NOTES

		-----------------------------------------

	Following the description there may be examples, a list of related
entries or some notes.  If more than one of these are present they should
be in this order.

     SEE ALSO

     RefVector.


     NOTES

     The name was chosen so that there could also be types for matrices (type
     Matrix), variable matrices (type RefMatrix), tensors, etc.  There is
     also scope for a type Array of arbitrary dimension, indexed by an integer
     list of the appropriate length.

     A possible implementation would be a view of a random access file.
     Possibly there should be a ConstVector signature (combining the Const
     and Vector signatures) to make this easier.
  *)

		-----------------------------------------

			   Version number

		-----------------------------------------

	The first object in any entry is the version number.  This is a
real.

  val version: real
   (* version = 1.0 *)

	This shows the convention used for describing very simple objects;
the definition of the object is given in the comment.  This convention is
only used if the definition fits on one line.


	The other objects defined in the entry are grouped under convenient
headings.  The ones used in this example are standard; others can be used
as appropriate.

		-----------------------------------------

			     PERVASIVES

		-----------------------------------------

	One standard heading that isn't used in this example is PERVASIVES.
Several of the basic library entries bind the appropriate pervasives so
that they can be accessed even if the identifier is rebound at top level.
Types aren't rebound, as their constructors may not be rebound.  Equality
isn't rebound either, although since the language doesn't allow the "="
identifier to be rebound you will never need a saved version.  Finally,
the overloaded identifiers are never rebound, as rebinding them loses
their overloaded nature.

		-----------------------------------------

			       SYSTEM

		-----------------------------------------

	Another standard section that appears in some entries is the SYSTEM
section.  This contains definitions of system-specific functions or values.

		-----------------------------------------

			TYPES and the Main Type

		-----------------------------------------

	The next section in our example is the TYPES section.  Often a
library entry defines a type and some specific operations on it.  In such
a case the type s called the MAIN TYPE of the entry, and has the same name
as the entry itself.  There is no need to comment the definition of a main
type, since it should be described in the description section.

  (* TYPES *)

    type 'a Vector
    type 'a T
      sharing type T = Vector

If an entry is to match the Object, Sequence or RefSequence signatures,
it must include a type T.  The features in these signatures are defined
in terms of this type.

		-----------------------------------------

			     CONSTANTS

		-----------------------------------------

	Another heading that isn't used in this example is CONSTANTS.
This contains the definitions of constants provided by the entry.

		-----------------------------------------

			     CREATORS

		-----------------------------------------

	The next section defines some functions to create objects of the main
type from subtypes.  Such functions are called "create" if they take value
parameters and "generate" if they take function parameters.  (Sometimes there
are more appropriate names specific to the types that are used instead.)


  (* CREATORS *)

    val create: Nat -> 'a -> 'a Vector
     (* create n i; create a Vector of n locations, each containing i.
        Raise (Nat ("create", n)) if n < 0. *)

    val generate: Nat -> (int -> 'a) -> 'a Vector
     (* generate n f; create a Vector v of n locations, (v sub 0) to
        (v sub (n-1)) with (v sub i) initialised to (f i).
        Raise (Nat ("generate", n)) if n < 0. *)

    val generate': Nat -> ('b -> 'a * 'b) -> 'b -> 'a Vector
     (* generate' n f base; create a Vector of n locations, (v sub 0) to
        (v sub (n-1)) with (v sub 0) initialised to (# 1 (f base)) and
        (v sub i (i > 0)) initialised to (# 1 (f (# 2 f_i))), where f_i is
        the result of the i^th application of f.
        Raise (Nat ("generate'", n)) if n < 0. *)


	This shows the usual convention used for commenting objects.  The
comments for exceptions and functions begin with a short example of their use;
this is followed by a short description using the parameters from that example.

		-----------------------------------------

			      SEQUENCE

		-----------------------------------------

	This section includes the functions defined in the Sequence
signature.  The Sequence signature could just be included at this point,
but that make the types of functions include references to type T instead
of Vector.  Giving explicit specifications for the functions make the entry
easier to use.

	Other entries may have OBJECT or REFSEQUENCE sections instead of
this one, or omit it entirely.

	Usually the entries in this section aren't commented, because they
are commented in the SEQUENCE signature itself.

    val stringSep: string -> string -> string ->
                   ('a -> string) -> 'a Vector -> string

    val string: ('a -> string) -> 'a Vector -> string

    exception Sep of string * string * string * string

    val parseSepN: string -> string -> string ->
                   (string list -> ('a * string list, 'b) Result) ->
                   Nat -> string -> ('a Vector, 'a Vector Option) Result

    val parseSep: string -> string -> string ->
                  (string list -> ('a * string list, 'b) Result) ->
                  string -> ('a Vector, 'a Vector Option) Result

    val parse: (string list -> ('a * string list, 'b) Result) ->
               string -> ('a Vector, 'a Vector Option) Result

    val parseN: (string list -> ('a * string list, 'b) Result) ->
                Nat -> string -> ('a Vector, 'a Vector Option) Result

    val parseSepN': string -> string -> string ->
                   (string list -> ('a * string list, 'b) Result) ->
                   Nat -> string list ->
                   ('a Vector * string list,
                    'a Vector Option * string list) Result

    val parseSep': string -> string -> string ->
                   (string list -> ('a * string list, 'b) Result) ->
                   string list ->
                   ('a Vector * string list,
                    'a Vector Option * string list) Result

    val parse': (string list -> ('a * string list, 'b) Result) ->
                string list ->
                ('a Vector * string list,
		 'a Vector Option * string list) Result

    val parseN': (string list -> ('a * string list, 'b) Result) ->
                 Nat -> string list ->
                 ('a Vector * string list,
		  'a Vector Option * string list) Result

    val readSep: string -> string -> string ->
                 (InStream -> ('a, 'b) Result) -> InStream ->
                 ('a Vector, 'a Vector Option) Result

    val readSepN: string -> string -> string ->
                 (InStream -> ('a, 'b) Result) -> Nat -> InStream ->
                 ('a Vector, 'a Vector Option) Result

    val read: (InStream -> ('a, 'b) Result) -> InStream ->
              ('a Vector, 'a Vector Option) Result

    val readN: (InStream -> ('a, 'b) Result) -> Nat -> InStream ->
               ('a Vector, 'a Vector Option) Result

    val eq: ('a -> 'a -> bool) -> 'a Vector -> 'a Vector -> bool

    val ne: ('a -> 'a -> bool) -> 'a Vector -> 'a Vector -> bool

    val lt: ('a -> 'a -> bool) -> 'a Vector -> 'a Vector -> bool

    val le: ('a -> 'a -> bool) -> 'a Vector -> 'a Vector -> bool

    val gt: ('a -> 'a -> bool) -> 'a Vector -> 'a Vector -> bool

    val ge: ('a -> 'a -> bool) -> 'a Vector -> 'a Vector -> bool


		-----------------------------------------

			     CONVERTORS

		-----------------------------------------

	The next section defines functions that convert values of the main
type to other types and vice versa.  By convention, functions that convert
values of the main type to another type are given the name of the second type
(e.g. "list").  Functions that convert values of another type to the main type
are given the name of the first type preceded by "from" (e.g. "fromList").
These conventions are overridden when another name is more appropriate
(as is the case with parse, parse' and read).

  (* CONVERTERS *)

    val list: 'a Vector -> 'a list
     (* list v; make a list containing (only) the elements of v, in
        the same order. *)

    val fromList: 'a list -> 'a Vector
     (* from_list l; make a Vector containing (only) the elements of l, in
        the same order. *)

    val fromFile: string -> (instream -> 'a Result) -> 'a Vector
     (* fromFile p name; read the contents of the file called name into a
	vector.  Stops reading from the file as soon as p returns Fail.
        Raises the pervasive exception Io if something goes wrong. *)

    val file: string -> ('a -> string) -> 'a Vector -> unit
     (* file name v; write the contents of v to the new file called name.
        Raises the pervasive exception Io if something goes wrong. *)

		-----------------------------------------

			     OBSERVERS

		-----------------------------------------

	The next section defines functions that return information about values
of the main type.  In this entry there are only two such functions; the
standards "size' and "empty".

  (* OBSERVERS *)
  
    val size: 'a Vector -> Nat
     (* size v; return the number of elements in v. *)

    val empty: 'a Vector -> bool
     (* empty v; returns true if v is empty. *)

		-----------------------------------------

			     SELECTORS

		-----------------------------------------

	The next section defines functions that select a component or
range of components from a value of the main type.  The names "sub", "Sub",
"nth", "extract" and "Extract" are standard.  "sub" is an infix version of
"nth"; this is the only case in the common names when one function is an
infix version of another.

  (* SELECTORS *)

    exception Sub of int
    (* infix 9 sub *)
    val sub: 'a Vector * int -> 'a
     (* v sub n; return the n+1'th element of v.
        Raise (Sub n) if not (0 <= n <= size v). *)

  val nth: int -> 'a Vector -> 'a
   (* v sub n; return the n+1'th element of v.
      Raise (Sub ("nth", n)) if not (0 <= n <= size v). *)

    exception Extract of int * int
    val extract: int -> int -> 'a Vector -> 'a Vector
     (* extract start finish v; returns the sub-vector of v starting with
        (v sub start) and ending with (v sub (finish - 1)).
        Returns the empty vector if (start = finish).
        Raise (Extract (start, finish)) if not (0 <= start,finish <= size v). *)

		-----------------------------------------

			    MANIPULATORS

		-----------------------------------------

	This section includes general functions on vectors that don't fit in
the other sections.

  val rev: 'a Vector -> 'a Vector
   (* rev v; builds a vector containing the elements of v in reverse order. *)

  (* infix 6 ^ *)
  val ^ : 'a Vector * 'a Vector -> 'a Vector
   (* v ^ v'; builds a Vector containing the elements of v' appended to those
      of v. *)

		-----------------------------------------

			      REDUCERS

		-----------------------------------------

	The next section contains functions that fold a function over a
a value of the main type to produce a single value, e.g. the sum of its
components.  The names "foldR", "foldL", "foldR'" , "foldL'" and "Empty"
are standard.

(* REDUCERS *)

  val foldR: ('a -> 'b -> 'b) -> 'b -> 'a Vector -> 'b
   (* foldR op base v; folds using op associating to the right over the
      base element.
      foldR op [a1,a2,...,an] base = op(a1,op(a2,...,op(an,base)...)). *)

  val foldL: ('a -> 'b -> 'b) -> 'b -> 'a Vector -> 'b
   (* foldL op base v; folds using op associating to the left over the
      base element.
      foldL op [a1,a2,...,an] base = op(an,...,op(a2,op(a1,base))...). *)

  exception Empty of string

  val foldR': ('a -> 'a -> 'a) -> 'a Vector -> 'a
   (* foldR' op v; folds using op associating to the right over the
      last element of v.  Raises (Empty "foldR'") if v is empty. *)

  val foldL': ('a -> 'a -> 'a) -> 'a Vector -> 'a
   (* foldL' op v; folds using op associating to the left over the
      first element of v.  Raises (Empty "foldL'") if v is empty. *)

  val pairwise: ('a -> 'a -> bool) -> 'a Vector -> bool
   (* pairwise f v; true if (f (v sub i) (v sub (i + 1))) is true for all
      0 <= i < size v, or if v is empty. *)

		-----------------------------------------

			     ITERATORS

		-----------------------------------------

	The last section contains functions that apply a function to every
element of a value of the main type.

(* ITERATORS *)

  val map: ('a -> 'b) -> 'a Vector -> 'b Vector
   (* map f v; builds a new vector by applying f to each element of l. *)

  val apply: ('a -> unit) -> 'a Vector -> unit
   (* apply f v; applies f to each element of v. *)

  val iterate: ('a * int -> 'b) -> 'a Vector -> 'b Vector
   (* iterate f v; builds a new vector by applying f to each element of l paired
      with its index. *)

  val iterateApply: ('a * int -> unit) -> 'a Vector -> unit
   (* iterateApply f v; applies f to each element of v paired
      with its index. *)
end
