This is mercury_library.info, produced by makeinfo version 4.11 from
library.texi_pp.

INFO-DIR-SECTION The Mercury Programming Language
START-INFO-DIR-ENTRY
* Mercury Library: (mercury_library).  The Mercury Library Reference Manual.
END-INFO-DIR-ENTRY

   This file documents the Mercury standard library, version 11.07.

   Copyright (C) 1995-1997,1999-2011 The University of Melbourne.

   Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
preserved on all copies.

   Permission is granted to copy and distribute modified versions of
this manual under the conditions for verbatim copying, provided also
that the entire resulting derived work is distributed under the terms
of a permission notice identical to this one.

   Permission is granted to copy and distribute translations of this
manual into another language, under the above conditions for modified
versions.


File: mercury_library.info,  Node: int,  Next: io,  Prev: integer,  Up: Top

35 int
******

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 1994-2011 The University of Melbourne.
     % This file may only be copied under the terms of the GNU Library General
     % Public License - see the file COPYING.LIB in the Mercury distribution.
     %--------------------------------------------------%
     %
     % File: int.m.
     % Main authors: conway, fjh.
     % Stability: medium.
     %
     % Predicates and functions for dealing with machine-size integer numbers.
     %
     % The behaviour of a computation for which overflow occurs is undefined.
     % (In the current implementation, the predicates and functions in this
     % module do not check for overflow, and the results you get are those
     % delivered by the C compiler.  However, future implementations
     % might check for overflow.)
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module int.
     :- interface.

     :- import_module array.
     :- import_module enum.
     :- import_module pretty_printer.

     %--------------------------------------------------%

     :- instance enum(int).

         % Less than.
         %
     :- pred (int::in) < (int::in) is semidet.

         % Greater than.
         %
     :- pred (int::in) > (int::in) is semidet.

         % Less than or equal.
         %
     :- pred (int::in) =< (int::in) is semidet.

         % Greater than or equal.
         %
     :- pred (int::in) >= (int::in) is semidet.

         % Absolute value.
         %
     :- func int.abs(int) = int.
     :- pred int.abs(int::in, int::out) is det.

         % Maximum.
         %
     :- func int.max(int, int) = int.
     :- pred int.max(int::in, int::in, int::out) is det.

         % Minimum.
         %
     :- func int.min(int, int) = int.
     :- pred int.min(int::in, int::in, int::out) is det.

         % Exponentiation.
         % int.pow(X, Y, Z): Z is X raised to the Yth power.
         % Throws a `math.domain_error' exception if Y is negative.
         %
     :- func int.pow(int, int) = int.
     :- pred int.pow(int::in, int::in, int::out) is det.

         % Base 2 logarithm.
         % int.log2(X) = N is the least integer such that 2 to the power N
         % is greater than or equal to X.
         % Throws a `math.domain_error' exception if X is not positive.
         %
     :- func int.log2(int) = int.
     :- pred int.log2(int::in, int::out) is det.

         % addition
         %
     :- func int + int = int.
     :- mode in  + in  = uo  is det.
     :- mode uo  + in  = in  is det.
     :- mode in  + uo  = in  is det.

     :- func int.plus(int, int) = int.

         % Multiplication.
         %
     :- func (int::in) * (int::in) = (int::uo) is det.
     :- func int.times(int, int) = int.

         % Subtraction.
         %
     :- func int - int = int.
     :- mode in  - in  = uo  is det.
     :- mode uo  - in  = in  is det.
     :- mode in  - uo  = in  is det.

     :- func int.minus(int, int) = int.

         % Flooring integer division.
         % Truncates towards minus infinity, e.g. (-10) div 3 = (-4).
         %
         % Throws a `math.domain_error' exception if the right operand is zero.
         % See the comments at the top of math.m to find out how to disable
         % domain checks.
         %
     :- func div(int::in, int::in) = (int::uo) is det.

         % Truncating integer division.
         % Truncates towards zero, e.g. (-10) // 3 = (-3).
         % `div' has nicer mathematical properties for negative operands,
         % but `//' is typically more efficient.
         %
         % Throws a `math.domain_error' exception if the right operand is zero.
         % See the comments at the top of math.m to find out how to disable
         % domain checks.
         %
     :- func (int::in) // (int::in) = (int::uo) is det.

         % (/)/2 is a synonym for (//)/2 to bring Mercury into line with
         % the common convention for naming integer division.
         %
     :- func (int::in) / (int::in) = (int::uo) is det.

         % unchecked_quotient(X, Y) is the same as X // Y, but the behaviour
         % is undefined if the right operand is zero.
         %
     :- func unchecked_quotient(int::in, int::in) = (int::uo) is det.

         % Modulus.
         % X mod Y = X - (X div Y) * Y
         %
     :- func (int::in) mod (int::in) = (int::uo) is det.

         % Remainder.
         % X rem Y = X - (X // Y) * Y
         % `mod' has nicer mathematical properties for negative X,
         % but `rem' is typically more efficient.
         %
         % Throws a `math.domain_error' exception if the right operand is zero.
         % See the comments at the top of math.m to find out how to disable
         % domain checks.
         %
     :- func (int::in) rem (int::in) = (int::uo) is det.

         % unchecked_rem(X, Y) is the same as X rem Y, but the behaviour
         % is undefined if the right operand is zero.
         %
     :- func unchecked_rem(int::in, int::in) = (int::uo) is det.

         % Left shift.
         % X << Y returns X "left shifted" by Y bits.
         % To be precise, if Y is negative, the result is
         % X div (2^(-Y)), otherwise the result is X * (2^Y).
         %
     :- func (int::in) << (int::in) = (int::uo) is det.

         % unchecked_left_shift(X, Y) is the same as X << Y
         % except that the behaviour is undefined if Y is negative,
         % or greater than or equal to the result of `int.bits_per_int/1'.
         % It will typically be implemented more efficiently than X << Y.
         %
     :- func unchecked_left_shift(int::in, int::in) = (int::uo) is det.

         % Right shift.
         % X >> Y returns X "arithmetic right shifted" by Y bits.
         % To be precise, if Y is negative, the result is
         % X * (2^(-Y)), otherwise the result is X div (2^Y).
         %
     :- func (int::in) >> (int::in) = (int::uo) is det.

         % unchecked_right_shift(X, Y) is the same as X >> Y
         % except that the behaviour is undefined if Y is negative,
         % or greater than or equal to the result of `int.bits_per_int/1'.
         % It will typically be implemented more efficiently than X >> Y.
         %
     :- func unchecked_right_shift(int::in, int::in) = (int::uo) is det.

         % even(X) is equivalent to (X mod 2 = 0).
         %
     :- pred even(int::in) is semidet.

         % odd(X) is equivalent to (not even(X)), i.e. (X mod 2 = 1).
         %
     :- pred odd(int::in) is semidet.

         % Bitwise and.
         %
     :- func (int::in) /\ (int::in) = (int::uo) is det.

         % Bitwise or.
         %
     :- func (int::in) \/ (int::in) = (int::uo) is det.

         % Bitwise exclusive or (xor).
         %
     :- func int.xor(int, int) = int.
     :- mode int.xor(in, in) = uo is det.
     :- mode int.xor(in, uo) = in is det.
     :- mode int.xor(uo, in) = in is det.

         % Bitwise complement.
         %
     :- func \ (int::in) = (int::uo) is det.

         % Unary plus.
         %
     :- func + (int::in) = (int::uo) is det.

         % Unary minus.
         %
     :- func - (int::in) = (int::uo) is det.

         % is/2, for backwards compatibility with Prolog.
         %
     :- pred is(T, T) is det.
     :- mode is(uo, di) is det.
     :- mode is(out, in) is det.

         % int.max_int is the maximum value of an int on this machine.
         %
     :- func int.max_int = int.
     :- pred int.max_int(int::out) is det.

         % int.min_int is the minimum value of an int on this machine.
         %
     :- func int.min_int = int.
     :- pred int.min_int(int::out) is det.

         % int.bits_per_int is the number of bits in an int on this machine.
         %
     :- func int.bits_per_int = int.
     :- pred int.bits_per_int(int::out) is det.

         % fold_up(F, Low, High, !Acc) <=> list.foldl(F, Low .. High, !Acc)
         %
         % NOTE: fold_up/5 is undefined if High = int.max_int.
         %
     :- pred int.fold_up(pred(int, T, T), int, int, T, T).
     :- mode int.fold_up(pred(in, in, out) is det, in, in, in, out) is det.
     :- mode int.fold_up(pred(in, mdi, muo) is det, in, in, mdi, muo) is det.
     :- mode int.fold_up(pred(in, di, uo) is det, in, in, di, uo) is det.
     :- mode int.fold_up(pred(in, array_di, array_uo) is det, in, in,
         array_di, array_uo) is det.
     :- mode int.fold_up(pred(in, in, out) is semidet, in, in, in, out)
         is semidet.
     :- mode int.fold_up(pred(in, mdi, muo) is semidet, in, in, mdi, muo)
         is semidet.
     :- mode int.fold_up(pred(in, di, uo) is semidet, in, in, di, uo)
         is semidet.
     :- mode int.fold_up(pred(in, in, out) is nondet, in, in, in, out)
         is nondet.
     :- mode int.fold_up(pred(in, mdi, muo) is nondet, in, in, mdi, muo)
         is nondet.
     :- mode int.fold_up(pred(in, di, uo) is cc_multi, in, in, di, uo)
         is cc_multi.
     :- mode int.fold_up(pred(in, in, out) is cc_multi, in, in, in, out)
         is cc_multi.

         % fold_up(F, Low, High, Acc) <=> list.foldl(F, Low .. High, Acc)
         %
         % NOTE: fold_up/4 is undefined if High = int.max_int.
         %
     :- func int.fold_up(func(int, T) = T, int, int, T) = T.

         % fold_down(F, Low, High, !Acc) <=> list.foldr(F, Low .. High, !Acc)
         %
         % NOTE: fold_down/5 is undefined if Low int.min_int.
         %
     :- pred int.fold_down(pred(int, T, T), int, int, T, T).
     :- mode int.fold_down(pred(in, in, out) is det, in, in, in, out) is det.
     :- mode int.fold_down(pred(in, mdi, muo) is det, in, in, mdi, muo) is det.
     :- mode int.fold_down(pred(in, di, uo) is det, in, in, di, uo) is det.
     :- mode int.fold_down(pred(in, array_di, array_uo) is det, in, in,
         array_di, array_uo) is det.
     :- mode int.fold_down(pred(in, in, out) is semidet, in, in, in, out)
         is semidet.
     :- mode int.fold_down(pred(in, mdi, muo) is semidet, in, in, mdi, muo)
         is semidet.
     :- mode int.fold_down(pred(in, di, uo) is semidet, in, in, di, uo)
         is semidet.
     :- mode int.fold_down(pred(in, in, out) is nondet, in, in, in, out)
         is nondet.
     :- mode int.fold_down(pred(in, mdi, muo) is nondet, in, in, mdi, muo)
         is nondet.
     :- mode int.fold_down(pred(in, in, out) is cc_multi, in, in, in, out)
         is cc_multi.
     :- mode int.fold_down(pred(in, di, uo) is cc_multi, in, in, di, uo)
         is cc_multi.

         % fold_down(F, Low, High, Acc) <=> list.foldr(F, Low .. High, Acc)
         %
         % NOTE: fold_down/4 is undefined if Low = int.min_int.
         %
     :- func int.fold_down(func(int, T) = T, int, int, T) = T.

         % fold_up2(F, Low, High, !Acc1, Acc2) <=>
         %   list.foldl2(F, Low .. High, !Acc1, !Acc2)
         %
         % NOTE: fold_up2/7 is undefined if High = int.max_int.
         %
     :- pred int.fold_up2(pred(int, T, T, U, U), int, int, T, T, U, U).
     :- mode int.fold_up2(pred(in, in, out, in, out) is det, in, in, in, out,
         in, out) is det.
     :- mode int.fold_up2(pred(in, in, out, mdi, muo) is det, in, in, in, out,
         mdi, muo) is det.
     :- mode int.fold_up2(pred(in, in, out, di, uo) is det, in, in, in, out,
         di, uo) is det.
     :- mode int.fold_up2(pred(in, di, uo, di, uo) is det, in, in, di, uo,
         di, uo) is det.
     :- mode int.fold_up2(pred(in, in, out, array_di, array_uo) is det, in, in,
         in, out, array_di, array_uo) is det.
     :- mode int.fold_up2(pred(in, in, out, in, out) is semidet, in, in,
         in, out, in, out) is semidet.
     :- mode int.fold_up2(pred(in, in, out, mdi, muo) is semidet, in, in,
         in, out, mdi, muo) is semidet.
     :- mode int.fold_up2(pred(in, in, out, di, uo) is semidet, in, in,
         in, out, di, uo) is semidet.
     :- mode int.fold_up2(pred(in, in, out, in, out) is nondet, in, in,
         in, out, in, out) is nondet.
     :- mode int.fold_up2(pred(in, in, out, mdi, muo) is nondet, in, in,
         in, out, mdi, muo) is nondet.

         % fold_down2(F, Low, High, !Acc1, !Acc2) <=>
         %   list.foldr2(F, Low .. High, !Acc1, Acc2).
         %
         % NOTE: fold_down2/7 is undefined if Low = int.min_int.
         %
     :- pred int.fold_down2(pred(int, T, T, U, U), int, int, T, T, U, U).
     :- mode int.fold_down2(pred(in, in, out, in, out) is det, in, in, in, out,
         in, out) is det.
     :- mode int.fold_down2(pred(in, in, out, mdi, muo) is det, in, in, in, out,
         mdi, muo) is det.
     :- mode int.fold_down2(pred(in, in, out, di, uo) is det, in, in, in, out,
         di, uo) is det.
     :- mode int.fold_down2(pred(in, di, uo, di, uo) is det, in, in, di, uo,
         di, uo) is det.
     :- mode int.fold_down2(pred(in, in, out, array_di, array_uo) is det, in, in,
         in, out, array_di, array_uo) is det.
     :- mode int.fold_down2(pred(in, in, out, in, out) is semidet, in, in,
         in, out, in, out) is semidet.
     :- mode int.fold_down2(pred(in, in, out, di, uo) is semidet, in, in,
         in, out, di, uo) is semidet.
     :- mode int.fold_down2(pred(in, in, out, in, out) is nondet, in, in,
         in, out, in, out) is nondet.
     :- mode int.fold_down2(pred(in, in, out, mdi, muo) is nondet, in, in,
         in, out, mdi, muo) is nondet.

         % nondet_int_in_range(Lo, Hi, I):
         %
         % On successive successes, set I to every integer from Lo to Hi.
         %
     :- pred nondet_int_in_range(int::in, int::in, int::out) is nondet.

         % Convert an int to a pretty_printer.doc for formatting.
         %
     :- func int.int_to_doc(int) = pretty_printer.doc.

     %--------------------------------------------------%
     %--------------------------------------------------%


File: mercury_library.info,  Node: io,  Next: lazy,  Prev: int,  Up: Top

36 io
*****

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 1993-2011 The University of Melbourne.
     % This file may only be copied under the terms of the GNU Library General
     % Public License - see the file COPYING.LIB in the Mercury distribution.
     %--------------------------------------------------%
     %
     % File: io.m.
     % Main author: fjh.
     % Stability: medium to high.
     %
     % This file encapsulates all the file I/O.
     %
     % We implement a purely logical I/O system using non-logical I/O primitives of
     % the underlying system.  We ensure referential transparency by passing around
     % a ``state-of-the-world'' argument using unique modes. The compiler will check
     % that the state of the world argument is properly single-threaded, and will
     % also ensure that you don't attempt to backtrack over any I/O.
     %
     % Attempting any operation on a stream which has already been closed results
     % in undefined behaviour.
     %
     % In multithreaded programs, each thread in the program has its own set of
     % "current" input and output streams. At the time it is created, a child
     % thread inherits the current streams from its parent. Predicates that
     % change which stream is current affect only the calling thread.
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module io.
     :- interface.

     :- import_module bitmap.
     :- import_module bool.
     :- import_module char.
     :- import_module deconstruct.
     :- import_module list.
     :- import_module map.
     :- import_module maybe.
     :- import_module stream.
     :- import_module string.
     :- import_module time.
     :- import_module univ.

     %--------------------------------------------------%
     %
     % Exported types
     %
         % The state of the universe.
         %
     :- type io.state.

         % An alternative, more concise name for `io.state'.
         %
     :- type io.io == io.state.

         % Opaque handles for text I/O streams.
         %
     :- type io.input_stream.
     :- type io.output_stream.

         % Alternative names for the above.
         %
     :- type io.text_input_stream == io.input_stream.
     :- type io.text_output_stream == io.output_stream.

         % Opaque handles for binary I/O streams.
         %
     :- type io.binary_input_stream.
     :- type io.binary_output_stream.

         % A unique identifier for an I/O stream.
         %
     :- type io.stream_id.

         % Various types used for the result from the access predicates.
         %
     :- type io.res
         --->    ok
         ;       error(io.error).

     :- type io.res(T)
         --->    ok(T)
         ;       error(io.error).

         % io.maybe_partial_res is used where it is possible to return
         % a partial result when an error occurs.
         %
     :- type io.maybe_partial_res(T)
         --->    ok(T)
         ;       error(T, io.error).

     :- inst io.maybe_partial_res(T)
         --->    ok(T)
         ;       error(T, ground).

     :- type io.result
         --->    ok
         ;       eof
         ;       error(io.error).

     :- type io.result(T)
         --->    ok(T)
         ;       eof
         ;       error(io.error).

     :- type io.read_result(T)
         --->    ok(T)
         ;       eof
         ;       error(string, int). % error message, line number

     :- type io.error.   % Use io.error_message to decode it.

         % Poly-type is used for io.write_many and io.format,
         % which do printf-like formatting.
         %
     :- type io.poly_type == string.poly_type.

         % io.whence denotes the base for a seek operation.
         %   set - seek relative to the start of the file
         %   cur - seek relative to the current position in the file
         %   end - seek relative to the end of the file.
         %
     :- type io.whence
         --->    set
         ;       cur
         ;       end.

     %--------------------------------------------------%
     %
     % Text input predicates
     %

         % Reads a character (code point) from the current input stream.
         %
     :- pred io.read_char(io.result(char)::out, io::di, io::uo) is det.

         % Reads a whitespace delimited word from the current input stream.
         %
     :- pred io.read_word(io.result(list(char))::out, io::di, io::uo) is det.

         % Reads a line from the current input stream, returns the result
         % as a list of characters (code points).
         %
     :- pred io.read_line(io.result(list(char))::out, io::di, io::uo) is det.

         % Reads a line from the current input stream, returns the result
         % as a string. See the documentation for `string.line' for the
         % definition of a line.
         %
     :- pred io.read_line_as_string(io.result(string)::out, io::di, io::uo) is det.

         % Reads all the characters (code points) from the current input stream
         % until eof or error.
         %
     :- pred io.read_file(io.maybe_partial_res(list(char))::out, io::di, io::uo)
         is det.

         % Reads all the characters (code points) from the current input stream
         % until eof or error. Returns the result as a string rather than
         % as a list of char.
         %
         % Returns an error if the file contains a null character, because
         % null characters are not allowed in Mercury strings.
         %
     :- pred io.read_file_as_string(io.maybe_partial_res(string)::out,
         io::di, io::uo) is det.

         % Applies the given closure to each character (code point) read from
         % the input stream in turn, until eof or error.
         %
     :- pred io.input_stream_foldl(pred(char, T, T), T, io.maybe_partial_res(T),
         io, io).
     :- mode io.input_stream_foldl((pred(in, in, out) is det), in, out,
         di, uo) is det.
     :- mode io.input_stream_foldl((pred(in, in, out) is cc_multi), in, out,
         di, uo) is cc_multi.

         % Applies the given closure to each character (code point) read from
         % the input stream in turn, until eof or error.
         %
     :- pred io.input_stream_foldl_io(pred(char, io, io), io.res, io, io).
     :- mode io.input_stream_foldl_io((pred(in, di, uo) is det), out, di, uo)
         is det.
     :- mode io.input_stream_foldl_io((pred(in, di, uo) is cc_multi), out, di, uo)
         is cc_multi.

         % Applies the given closure to each character (code point) read from
         % the input stream in turn, until eof or error.
         %
     :- pred io.input_stream_foldl2_io(pred(char, T, T, io, io),
         T, io.maybe_partial_res(T), io, io).
     :- mode io.input_stream_foldl2_io((pred(in, in, out, di, uo) is det),
         in, out, di, uo) is det.
     :- mode io.input_stream_foldl2_io((pred(in, in, out, di, uo) is cc_multi),
         in, out, di, uo) is cc_multi.

         % Applies the given closure to each character (code point) read from the
         % input stream in turn, until eof or error, or the closure returns `no' as
         % its second argument.
         %
     :- pred io.input_stream_foldl2_io_maybe_stop(
         pred(char, bool, T, T, io, io),
         T, io.maybe_partial_res(T), io, io).
     :- mode io.input_stream_foldl2_io_maybe_stop(
         (pred(in, out, in, out, di, uo) is det),
         in, out, di, uo) is det.
     :- mode io.input_stream_foldl2_io_maybe_stop(
         (pred(in, out, in, out, di, uo) is cc_multi),
         in, out, di, uo) is cc_multi.

         % Un-reads a character (code point) from the current input stream.
         % You can put back as many characters as you like.
         % You can even put back something that you didn't actually read.
         % Note: `io.putback_char' uses the C library function ungetc().
         % On some systems only one byte of pushback is guaranteed.
         % `io.putback_char' will throw an io.error exception if ungetc() fails.
         %
     :- pred io.putback_char(char::in, io::di, io::uo) is det.

         % Reads a character (code point) from specified stream.
         %
     :- pred io.read_char(io.input_stream::in, io.result(char)::out,
         io::di, io::uo) is det.

         % Reads a character (code point) from the specified stream.
         % This interface avoids memory allocation when there is no error.
         %
     :- pred io.read_char_unboxed(io.input_stream::in, io.result::out, char::out,
         io::di, io::uo) is det.

         % Reads a whitespace delimited word from specified stream.
         %
     :- pred io.read_word(io.input_stream::in, io.result(list(char))::out,
         io::di, io::uo) is det.

         % Reads a line from specified stream, returning the result
         % as a list of characters (code point).
         %
     :- pred io.read_line(io.input_stream::in, io.result(list(char))::out,
         io::di, io::uo) is det.

         % Reads a line from specified stream, returning the
         % result as a string. See the documentation for `string.line' for
         % the definition of a line.
         %
     :- pred io.read_line_as_string(io.input_stream::in, io.result(string)::out,
         io::di, io::uo) is det.

         % Reads all the characters (code points) from the given input stream until
         % eof or error.
         %
     :- pred io.read_file(io.input_stream::in,
         io.maybe_partial_res(list(char))::out, io::di, io::uo) is det.

         % Reads all the characters from the given input stream until eof or error.
         % Returns the result as a string rather than as a list of char.
         %
         % Returns an error if the file contains a null character, because
         % null characters are not allowed in Mercury strings.
         %
     :- pred io.read_file_as_string(io.input_stream::in,
         io.maybe_partial_res(string)::out, io::di, io::uo) is det.

         % Applies the given closure to each character (code point) read from
         % the input stream in turn, until eof or error.
         %
     :- pred io.input_stream_foldl(io.input_stream, pred(char, T, T),
         T, io.maybe_partial_res(T), io, io).
     :- mode io.input_stream_foldl(in, in(pred(in, in, out) is det),
         in, out, di, uo) is det.
     :- mode io.input_stream_foldl(in, in(pred(in, in, out) is cc_multi),
         in, out, di, uo) is cc_multi.

         % Applies the given closure to each character (code point) read from
         % the input stream in turn, until eof or error.
         %
     :- pred io.input_stream_foldl_io(io.input_stream, pred(char, io, io),
         io.res, io, io).
     :- mode io.input_stream_foldl_io(in, in(pred(in, di, uo) is det),
         out, di, uo) is det.
     :- mode io.input_stream_foldl_io(in, in(pred(in, di, uo) is cc_multi),
         out, di, uo) is cc_multi.

         % Applies the given closure to each character (code point) read from
         % the input stream in turn, until eof or error.
         %
     :- pred io.input_stream_foldl2_io(io.input_stream,
         pred(char, T, T, io, io),
         T, io.maybe_partial_res(T), io, io).
     :- mode io.input_stream_foldl2_io(in,
         in(pred(in, in, out, di, uo) is det),
         in, out, di, uo) is det.
     :- mode io.input_stream_foldl2_io(in,
         in(pred(in, in, out, di, uo) is cc_multi),
         in, out, di, uo) is cc_multi.

         % Applies the given closure to each character (code point) read from the
         % input stream in turn, until eof or error, or the closure returns `no' as
         % its second argument.
         %
     :- pred io.input_stream_foldl2_io_maybe_stop(io.input_stream,
         pred(char, bool, T, T, io, io),
         T, io.maybe_partial_res(T), io, io).
     :- mode io.input_stream_foldl2_io_maybe_stop(in,
         (pred(in, out, in, out, di, uo) is det),
         in, out, di, uo) is det.
     :- mode io.input_stream_foldl2_io_maybe_stop(in,
         (pred(in, out, in, out, di, uo) is cc_multi),
         in, out, di, uo) is cc_multi.

         % Un-reads a character from specified stream.
         % You can put back as many characters as you like.
         % You can even put back something that you didn't actually read.
         % Note: `io.putback_char' uses the C library function ungetc().
         % On some systems only one byte of pushback is guaranteed.
         % `io.putback_char' will throw an io.error exception if ungetc() fails.
         %
     :- pred io.putback_char(io.input_stream::in, char::in, io::di, io::uo) is det.

         % Reads a ground term of any type, written using standard Mercury syntax,
         % from the current or specified input stream. The type of the term read
         % is determined by the context in which `io.read' is used.
         %
         % First, the input stream is read until an end-of-term token, end-of-file,
         % or I/O error is reached.  (An end-of-term token consists of a `.'
         % followed by whitespace. The trailing whitespace is left in the input
         % stream.)
         %
         % Then, the result is determined according to the tokens read. If there
         % were no non-whitespace characters before the end of file, then `io.read'
         % returns `eof'. If the tokens read formed a syntactically correct ground
         % term of the correct type, followed by an end-of-term token, then it
         % returns `ok(Term)'. If characters read from the input stream did not form
         % a syntactically correct term, or if the term read is not a ground term,
         % or if the term is not a valid term of the appropriate type, or if an
         % I/O error is encountered, then it returns `error(Message, LineNumber)'.
         %
     :- pred io.read(io.read_result(T)::out, io::di, io::uo) is det.
     :- pred io.read(io.input_stream::in, io.read_result(T)::out,
         io::di, io::uo) is det.

         % The type `posn' represents a position within a string.
         %
     :- type posn
         --->    posn(int, int, int).
                 % line number, offset of start of line, current offset (the first
                 % two are used only for the purposes of computing term_contexts,
                 % for use e.g. in error messages). Offsets start at zero.

         % io.read_from_string(FileName, String, MaxPos, Result, Posn0, Posn):
         % Same as io.read/4 except that it reads from a string rather than
         % from a stream.
         % FileName is the name of the source (for use in error messages).
         % String is the string to be parsed.
         % Posn0 is the position to start parsing from.
         % Posn is the position one past where the term read in ends.
         % MaxPos is the offset in the string which should be considered the
         % end-of-stream -- this is the upper bound for Posn. (In the usual case,
         % MaxPos is just the length of the String.)
         % WARNING: if MaxPos > length of String then the behaviour is UNDEFINED.
         %
     :- pred io.read_from_string(string::in, string::in, int::in,
         io.read_result(T)::out, posn::in, posn::out) is det.

         % Discards all the whitespace from the current stream.
         %
     :- pred io.ignore_whitespace(io.result::out, io::di, io::uo) is det.

         % Discards all the whitespace from the specified stream.
         %
     :- pred io.ignore_whitespace(io.input_stream::in, io.result::out,
         io::di, io::uo) is det.

     %--------------------------------------------------%
     %
     % Text output predicates
     %

     % These will all throw an io.error exception if an I/O error occurs.

         % io.print/3 writes its argument to the standard output stream.
         % io.print/4 writes its second argument to the output stream specified
         % in its first argument. In all cases, the argument to output can be
         % of any type. It is output in a format that is intended to be human
         % readable.
         %
         % If the argument is just a single string or character, it will be printed
         % out exactly as is (unquoted). If the argument is of type univ, then
         % it will print out the value stored in the univ, but not the type.
         %
         % io.print/5 is the same as io.print/4 except that it allows the caller
         % to specify how non-canonical types should be handled. io.print/3 and
         % io.print/4 implicitly specify `canonicalize' as the method for handling
         % non-canonical types. This means that for higher-order types, or types
         % with user-defined equality axioms, or types defined using the foreign
         % language interface (i.e. pragma foreign_type), the text output will
         % only describe the type that is being printed, not the value.
         %
         % io.print_cc/3 is the same as io.print/3 except that it specifies
         % `include_details_cc' rather than `canonicalize'. This means that it will
         % print the details of non-canonical types. However, it has determinism
         % `cc_multi'.
         %
         % Note that even if `include_details_cc' is specified, some implementations
         % may not be able to print all the details for higher-order types or types
         % defined using the foreign language interface.
         %
     :- pred io.print(T::in, io::di, io::uo) is det.

     :- pred io.print(io.output_stream::in, T::in, io::di, io::uo) is det.

     :- pred io.print(io.output_stream, deconstruct.noncanon_handling, T, io, io).
     :- mode io.print(in, in(do_not_allow), in, di, uo) is det.
     :- mode io.print(in, in(canonicalize), in, di, uo) is det.
     :- mode io.print(in, in(include_details_cc), in, di, uo) is cc_multi.
     :- mode io.print(in, in, in, di, uo) is cc_multi.

     :- pred io.print_cc(T::in, io::di, io::uo) is cc_multi.

         % io.write/3 writes its argument to the current output stream.
         % io.write/4 writes its second argument to the output stream specified
         % in its first argument. In all cases, the argument to output may be
         % of any type. The argument is written in a format that is intended to
         % be valid Mercury syntax whenever possible.
         %
         % Strings and characters are always printed out in quotes, using backslash
         % escapes if necessary. For higher-order types, or for types defined
         % using the foreign language interface (pragma foreign_code), the text
         % output will only describe the type that is being printed, not the value,
         % and the result may not be parsable by `io.read'. For the types
         % containing existential quantifiers, the type `type_desc' and closure
         % types, the result may not be parsable by `io.read', either. But in all
         % other cases the format used is standard Mercury syntax, and if you append
         % a period and newline (".\n"), then the results can be read in again
         % using `io.read'.
         %
         % io.write/5 is the same as io.write/4 except that it allows the caller
         % to specify how non-canonical types should be handled. io.write_cc/3
         % is the same as io.write/3 except that it specifies `include_details_cc'
         % rather than `canonicalize'.
         %
     :- pred io.write(T::in, io::di, io::uo) is det.

     :- pred io.write(io.output_stream::in, T::in, io::di, io::uo) is det.

     :- pred io.write(io.output_stream, deconstruct.noncanon_handling, T, io, io).
     :- mode io.write(in, in(do_not_allow), in, di, uo) is det.
     :- mode io.write(in, in(canonicalize), in, di, uo) is det.
     :- mode io.write(in, in(include_details_cc), in, di, uo) is cc_multi.
     :- mode io.write(in, in, in, di, uo) is cc_multi.

     :- pred io.write_cc(T::in, io::di, io::uo) is cc_multi.

         % Writes a newline character to the current output stream.
         %
     :- pred io.nl(io::di, io::uo) is det.

         % Writes a newline character to the specified output stream.
         %
     :- pred io.nl(io.output_stream::in, io::di, io::uo) is det.

         % Writes a string to the current output stream.
         %
     :- pred io.write_string(string::in, io::di, io::uo) is det.

         % Writes a string to the specified output stream.
         %
     :- pred io.write_string(io.output_stream::in, string::in, io::di, io::uo)
         is det.

         % Writes a list of strings to the current output stream.
         %
     :- pred io.write_strings(list(string)::in, io::di, io::uo) is det.

         % Writes a list of strings to the specified output stream.
         %
     :- pred io.write_strings(io.output_stream::in, list(string)::in,
         io::di, io::uo) is det.

         % Writes a character to the current output stream.
         %
     :- pred io.write_char(char::in, io::di, io::uo) is det.

         % Writes a character to the specified output stream.
         %
     :- pred io.write_char(io.output_stream::in, char::in, io::di, io::uo) is det.

         % Writes an integer to the current output stream.
         %
     :- pred io.write_int(int::in, io::di, io::uo) is det.

         % Writes an integer to the specified output stream.
         %
     :- pred io.write_int(io.output_stream::in, int::in, io::di, io::uo) is det.

         % Writes a floating point number to the current output stream.
         %
     :- pred io.write_float(float::in, io::di, io::uo) is det.

         % Writes a floating point number to the specified output stream.
         %
     :- pred io.write_float(io.output_stream::in, float::in, io::di, io::uo)
         is det.

         % Formats the specified arguments according to the format string,
         % using string.format, and then writes the result to the current
         % output stream. (See the documentation of string.format for details.)
         %
     :- pred io.format(string::in, list(io.poly_type)::in, io::di, io::uo) is det.

         % Formats the specified argument list according to the format string,
         % using string.format, and then writes the result to the specified
         % output stream. (See the documentation of string.format for details.)
         %
     :- pred io.format(io.output_stream::in, string::in, list(io.poly_type)::in,
         io::di, io::uo) is det.

         % Writes the specified arguments to the current output stream.
         %
     :- pred io.write_many(list(io.poly_type)::in, io::di, io::uo) is det.

         % Writes the specified arguments to the specified output stream.
         %
     :- pred io.write_many(io.output_stream::in, list(io.poly_type)::in,
         io::di, io::uo) is det.

         % io.write_list(List, Separator, OutputPred, !IO):
         % applies OutputPred to each element of List, printing Separator
         % between each element. Outputs to the current output stream.
         %
     :- pred io.write_list(list(T), string, pred(T, io, io), io, io).
     :- mode io.write_list(in, in, pred(in, di, uo) is det, di, uo) is det.
     :- mode io.write_list(in, in, pred(in, di, uo) is cc_multi, di, uo)
         is cc_multi.

         % io.write_list(Stream, List, Separator, OutputPred, !IO):
         % applies OutputPred to each element of List, printing Separator
         % between each element. Outputs to Stream.
         %
     :- pred io.write_list(io.output_stream, list(T), string,
         pred(T, io, io), io, io).
     :- mode io.write_list(in, in, in, pred(in, di, uo) is det, di, uo) is det.
     :- mode io.write_list(in, in, in, pred(in, di, uo) is cc_multi, di, uo)
         is cc_multi.

         % Flush the output buffer of the current output stream.
         %
     :- pred io.flush_output(io::di, io::uo) is det.

         % Flush the output buffer of the specified output stream.
         %
     :- pred io.flush_output(io.output_stream::in, io::di, io::uo) is det.

     %--------------------------------------------------%
     %
     % Input text stream predicates
     %

         % io.see(File, Result, !IO).
         % Attempts to open a file for input, and if successful,
         % sets the current input stream to the newly opened stream.
         % Result is either 'ok' or 'error(ErrorCode)'.
         %
     :- pred io.see(string::in, io.res::out, io::di, io::uo) is det.

         % Closes the current input stream.
         % The current input stream reverts to standard input.
         % This will throw an io.error exception if an I/O error occurs.
         %
     :- pred io.seen(io::di, io::uo) is det.

         % Attempts to open a file for input.
         % Result is either 'ok(Stream)' or 'error(ErrorCode)'.
         %
     :- pred io.open_input(string::in, io.res(io.input_stream)::out,
         io::di, io::uo) is det.

         % Closes an open input stream.
         % Throw an io.error exception if an I/O error occurs.
         %
     :- pred io.close_input(io.input_stream::in, io::di, io::uo) is det.

         % Retrieves the current input stream.
         % Does not modify the I/O state.
         %
     :- pred io.input_stream(io.input_stream::out, io::di, io::uo) is det.

         % io.set_input_stream(NewStream, OldStream, !IO):
         % Changes the current input stream to the stream specified.
         % Returns the previous stream.
         %
     :- pred io.set_input_stream(io.input_stream::in, io.input_stream::out,
         io::di, io::uo) is det.

         % Retrieves the standard input stream.
         %
     :- func io.stdin_stream = io.input_stream.

         % Retrieves the standard input stream.
         % Does not modify the I/O state.
         %
     :- pred io.stdin_stream(io.input_stream::out, io::di, io::uo) is det.

         % Retrieves the human-readable name associated with the current input
         % stream. For file streams, this is the filename. For stdin,
         % this is the string "<standard input>".
         %
     :- pred io.input_stream_name(string::out, io::di, io::uo) is det.

         % Retrieves the human-readable name associated with the specified input
         % stream. For file streams, this is the filename. For stdin,
         % this is the string "<standard input>".
         %
     :- pred io.input_stream_name(io.input_stream::in, string::out,
         io::di, io::uo) is det.

         % Return the line number of the current input stream. Lines are normally
         % numbered starting at 1, but this can be overridden by calling
         % io.set_line_number.
         %
     :- pred io.get_line_number(int::out, io::di, io::uo) is det.

         % Return the line number of the specified input stream. Lines are normally
         % numbered starting at 1, but this can be overridden by calling
         % io.set_line_number.
         %
     :- pred io.get_line_number(io.input_stream::in, int::out, io::di, io::uo)
         is det.

         % Set the line number of the current input stream.
         %
     :- pred io.set_line_number(int::in, io::di, io::uo) is det.

         % Set the line number of the specified input stream.
         %
     :- pred io.set_line_number(io.input_stream::in, int::in, io::di, io::uo)
         is det.

     %--------------------------------------------------%
     %
     % Output text stream predicates
     %

         % Attempts to open a file for output, and if successful sets the current
         % output stream to the newly opened stream. As per Prolog tell/1.
         % Result is either 'ok' or 'error(ErrCode)'.
         %
     :- pred io.tell(string::in, io.res::out, io::di, io::uo) is det.

         % Closes the current output stream; the default output stream reverts
         % to standard output. As per Prolog told/0. This will throw an
         % io.error exception if an I/O error occurs.
         %
     :- pred io.told(io::di, io::uo) is det.

         % Attempts to open a file for output.
         % Result is either 'ok(Stream)' or 'error(ErrorCode)'.
         %
     :- pred io.open_output(string::in, io.res(io.output_stream)::out,
         io::di, io::uo) is det.

         % Attempts to open a file for appending.
         % Result is either 'ok(Stream)' or 'error(ErrorCode)'.
         %
     :- pred io.open_append(string::in, io.res(io.output_stream)::out,
         io::di, io::uo) is det.

         % Closes an open output stream.
         % This will throw an io.error exception if an I/O error occurs.
         %
     :- pred io.close_output(io.output_stream::in, io::di, io::uo) is det.

         % Retrieves the current output stream.
         % Does not modify the I/O state.
         %
     :- pred io.output_stream(io.output_stream::out, io::di, io::uo) is det.

         % Changes the current output stream to the stream specified.
         % Returns the previous stream.
         %
     :- pred io.set_output_stream(io.output_stream::in, io.output_stream::out,
         io::di, io::uo) is det.

         % Retrieves the standard output stream.
         %
     :- func io.stdout_stream = io.output_stream.

         % Retrieves the standard output stream.
         % Does not modify the I/O state.
         %
     :- pred io.stdout_stream(io.output_stream::out, io::di, io::uo) is det.

         % Retrieves the standard error stream.
         %
     :- func io.stderr_stream = io.output_stream.

         % Retrieves the standard error stream.
         % Does not modify the I/O state.
         %
     :- pred io.stderr_stream(io.output_stream::out, io::di, io::uo) is det.

         % Retrieves the human-readable name associated with the current
         % output stream.
         % For file streams, this is the filename.
         % For stdout this is the string "<standard output>".
         % For stderr this is the string "<standard error>".
         %
     :- pred io.output_stream_name(string::out, io::di, io::uo) is det.

         % Retrieves the human-readable name associated with the specified stream.
         % For file streams, this is the filename.
         % For stdout this is the string "<standard output>".
         % For stderr this is the string "<standard error>".
         %
     :- pred io.output_stream_name(io.output_stream::in, string::out,
         io::di, io::uo) is det.

         % Return the line number of the current output stream. Lines are normally
         % numbered starting at 1, but this can be overridden by calling
         % io.set_output_line_number.
         %
     :- pred io.get_output_line_number(int::out, io::di, io::uo) is det.

         % Return the line number of the specified output stream. Lines are normally
         % numbered starting at 1, but this can be overridden by calling
         % io.set_output_line_number.
         %
     :- pred io.get_output_line_number(io.output_stream::in, int::out,
         io::di, io::uo) is det.

         % Set the line number of the current output stream.
         %
     :- pred io.set_output_line_number(int::in, io::di, io::uo) is det.

         % Set the line number of the specified output stream.
         %
     :- pred io.set_output_line_number(io.output_stream::in, int::in,
         io::di, io::uo) is det.

     %--------------------------------------------------%
     %
     % Binary input predicates
     %

         % Reads a binary representation of a term of type T from the current
         % binary input stream.
         %
     :- pred io.read_binary(io.result(T)::out, io::di, io::uo) is det.

         % Reads a binary representation of a term of type T from the specified
         % binary input stream.
         %
         % Note: if you attempt to read a binary representation written by a
         % different program, or a different version of the same program,
         % then the results are not guaranteed to be meaningful. Another caveat
         % is that higher-order types cannot be read. (If you try, you will get
         % a runtime error.)
         %
         % XXX Note also that due to the current implementation,
         % io.read_binary will not work for the Java back-end.
         %
     :- pred io.read_binary(io.binary_input_stream::in, io.result(T)::out,
         io::di, io::uo) is det.

         % Reads a single 8-bit byte from the current binary input stream.
         %
     :- pred io.read_byte(io.result(int)::out, io::di, io::uo) is det.

         % Reads a single 8-bit byte from the specified binary input stream.
         %
     :- pred io.read_byte(io.binary_input_stream::in, io.result(int)::out,
         io::di, io::uo) is det.

         % Fill a bitmap from the current binary input stream.
         % Returns the number of bytes read.
         % On end-of-file, the number of bytes read will be less than the size
         % of the bitmap, and the result will be `ok'.
         %
     :- pred io.read_bitmap(bitmap::bitmap_di, bitmap::bitmap_uo,
         int::out, io.res::out, io::di, io::uo) is det.

         % Fill a bitmap from the specified binary input stream.
         % Returns the number of bytes read.
         % On end-of-file, the number of bytes read will be less than the size
         % of the bitmap, and the result will be `ok'.
         %
     :- pred io.read_bitmap(io.binary_input_stream::in,
         bitmap::bitmap_di, bitmap::bitmap_uo, int::out, io.res::out,
         io::di, io::uo) is det.

         % io.read_bitmap(StartByte, NumBytes, !Bitmap, BytesRead, Result, !IO)
         %
         % Read NumBytes bytes into a bitmap starting at StartByte
         % from the current binary input stream.
         % Returns the number of bytes read.
         % On end-of-file, the number of bytes read will be less than NumBytes,
         % and the result will be `ok'.
         %
     :- pred io.read_bitmap(byte_index::in, num_bytes::in,
         bitmap::bitmap_di, bitmap::bitmap_uo, num_bytes::out,
         io.res::out, io::di, io::uo) is det.

         % io.read_bitmap(Stream, !Bitmap, StartByte, NumBytes,
         %       BytesRead, Result, !IO)
         %
         % Read NumBytes bytes into a bitmap starting at StartByte
         % from the specified binary input stream.
         % Returns the number of bytes read.
         % On end-of-file, the number of bytes read will be less than NumBytes,
         % and the result will be `ok'.
         %
     :- pred io.read_bitmap(io.binary_input_stream::in,
         byte_index::in, num_bytes::in, bitmap::bitmap_di, bitmap::bitmap_uo,
         num_bytes::out, io.res::out, io::di, io::uo) is det.

         % Reads all the bytes from the current binary input stream
         % until eof or error into a bitmap.
         %
     :- pred io.read_binary_file_as_bitmap(io.res(bitmap)::out,
         io::di, io::uo) is det.

         % Reads all the bytes from the given binary input stream into a bitmap
         % until eof or error.
         %
     :- pred io.read_binary_file_as_bitmap(io.binary_input_stream::in,
         io.res(bitmap)::out, io::di, io::uo) is det.

         % Reads all the bytes from the current binary input stream
         % until eof or error.
         %
     :- pred io.read_binary_file(io.result(list(int))::out, io::di, io::uo) is det.

         % Reads all the bytes from the given binary input stream until
         % eof or error.
         %
     :- pred io.read_binary_file(io.binary_input_stream::in,
         io.result(list(int))::out, io::di, io::uo) is det.

         % Applies the given closure to each byte read from the current binary
         % input stream in turn, until eof or error.
         %
     :- pred io.binary_input_stream_foldl(pred(int, T, T),
         T, io.maybe_partial_res(T), io, io).
     :- mode io.binary_input_stream_foldl((pred(in, in, out) is det),
         in, out, di, uo) is det.
     :- mode io.binary_input_stream_foldl((pred(in, in, out) is cc_multi),
         in, out, di, uo) is cc_multi.

         % Applies the given closure to each byte read from the current binary
         % input stream in turn, until eof or error.
         %
     :- pred io.binary_input_stream_foldl_io(pred(int, io, io),
         io.res, io, io).
     :- mode io.binary_input_stream_foldl_io((pred(in, di, uo) is det),
         out, di, uo) is det.
     :- mode io.binary_input_stream_foldl_io((pred(in, di, uo) is cc_multi),
         out, di, uo) is cc_multi.

         % Applies the given closure to each byte read from the current binary
         % input stream in turn, until eof or error.
         %
     :- pred io.binary_input_stream_foldl2_io(
         pred(int, T, T, io, io), T, io.maybe_partial_res(T), io, io).
     :- mode io.binary_input_stream_foldl2_io(
         in(pred(in, in, out, di, uo) is det), in, out, di, uo) is det.
     :- mode io.binary_input_stream_foldl2_io(
         in(pred(in, in, out, di, uo) is cc_multi), in, out, di, uo) is cc_multi.

         % Applies the given closure to each byte read from the current binary
         % input stream in turn, until eof or error, or the closure returns `no'
         % as its second argument.
         %
     :- pred io.binary_input_stream_foldl2_io_maybe_stop(
         pred(int, bool, T, T, io, io), T, io.maybe_partial_res(T), io, io).
     :- mode io.binary_input_stream_foldl2_io_maybe_stop(
         (pred(in, out, in, out, di, uo) is det), in, out, di, uo) is det.
     :- mode io.binary_input_stream_foldl2_io_maybe_stop(
         (pred(in, out, in, out, di, uo) is cc_multi), in, out, di, uo) is cc_multi.

         % Applies the given closure to each byte read from the given binary
         % input stream in turn, until eof or error.
         %
     :- pred io.binary_input_stream_foldl(io.binary_input_stream,
         pred(int, T, T), T, io.maybe_partial_res(T), io, io).
     :- mode io.binary_input_stream_foldl(in, in(pred(in, in, out) is det),
         in, out, di, uo) is det.
     :- mode io.binary_input_stream_foldl(in, in(pred(in, in, out) is cc_multi),
         in, out, di, uo) is cc_multi.

         % Applies the given closure to each byte read from the given binary
         % input stream in turn, until eof or error.
         %
     :- pred io.binary_input_stream_foldl_io(io.binary_input_stream,
         pred(int, io, io), io.res, io, io).
     :- mode io.binary_input_stream_foldl_io(in, in(pred(in, di, uo) is det),
         out, di, uo) is det.
     :- mode io.binary_input_stream_foldl_io(in, in(pred(in, di, uo) is cc_multi),
         out, di, uo) is cc_multi.

         % Applies the given closure to each byte read from the given binary
         % input stream in turn, until eof or error.
         %
     :- pred io.binary_input_stream_foldl2_io(io.binary_input_stream,
         pred(int, T, T, io, io), T, io.maybe_partial_res(T), io, io).
     :- mode io.binary_input_stream_foldl2_io(in,
         (pred(in, in, out, di, uo) is det), in, out, di, uo) is det.
     :- mode io.binary_input_stream_foldl2_io(in,
         (pred(in, in, out, di, uo) is cc_multi), in, out, di, uo) is cc_multi.

         % Applies the given closure to each byte read from the
         % given binary input stream in turn, until eof or error,
         % or the closure returns `no' as its second argument.
         %
     :- pred io.binary_input_stream_foldl2_io_maybe_stop(io.binary_input_stream,
         pred(int, bool, T, T, io, io), T, io.maybe_partial_res(T), io, io).
     :- mode io.binary_input_stream_foldl2_io_maybe_stop(in,
         (pred(in, out, in, out, di, uo) is det), in, out, di, uo) is det.
     :- mode io.binary_input_stream_foldl2_io_maybe_stop(in,
         (pred(in, out, in, out, di, uo) is cc_multi), in, out, di, uo) is cc_multi.

         % Un-reads a byte from the current binary input stream.
         % You can put back as many bytes as you like.
         % You can even put back something that you didn't actually read.
         % The byte is taken from the bottom 8 bits of an integer.
         % Note: `io.putback_byte' uses the C library function ungetc().
         % On some systems only one byte of pushback is guaranteed.
         % `io.putback_byte' will throw an io.error exception if ungetc() fails.
         %
         % Pushing back a byte decrements the file position by one, except when
         % the file position is already zero, in which case the new file position
         % is unspecified.
         %
     :- pred io.putback_byte(int::in, io::di, io::uo) is det.

         % Un-reads a byte from specified binary input stream.
         % You can put back as many bytes as you like.
         % You can even put back something that you didn't actually read.
         % The byte is returned in the bottom 8 bits of an integer.
         % Note: `io.putback_byte' uses the C library function ungetc().
         % On some systems only one byte of pushback is guaranteed.
         % `io.putback_byte' will throw an io.error exception if ungetc() fails.
         %
         % Pushing back a byte decrements the file position by one, except when
         % the file position is already zero, in which case the new file position
         % is unspecified.
         %
     :- pred io.putback_byte(io.binary_input_stream::in, int::in,
         io::di, io::uo) is det.

     %--------------------------------------------------%
     %
     % Binary output predicates
     %

     % These will all throw an io.error exception if an I/O error occurs.
     % XXX what about wide characters?

         % Writes a binary representation of a term to the current binary output
         % stream, in a format suitable for reading in again with io.read_binary.
         %
     :- pred io.write_binary(T::in, io::di, io::uo) is det.

         % Writes a binary representation of a term to the specified binary output
         % stream, in a format suitable for reading in again with io.read_binary.
         %
         % XXX Note that due to the current implementation, io.write_binary
         % will not work for the Java back-end.
         %
     :- pred io.write_binary(io.binary_output_stream::in, T::in, io::di, io::uo)
         is det.

         % Writes a single byte to the current binary output stream.
         % The byte is taken from the bottom 8 bits of an int.
         %
     :- pred io.write_byte(int::in, io::di, io::uo) is det.

         % Writes a single byte to the specified binary output stream.
         % The byte is taken from the bottom 8 bits of an int.
         %
     :- pred io.write_byte(io.binary_output_stream::in, int::in, io::di, io::uo)
         is det.

         % Write a bitmap to the current binary output stream.
         % The bitmap must not contain a partial final byte.
         %
     :- pred io.write_bitmap(bitmap, io, io).
     %:- mode io.write_bitmap(bitmap_ui, di, uo) is det.
     :- mode io.write_bitmap(in, di, uo) is det.

         % io.write_bitmap(BM, StartByte, NumBytes, !IO).
         % Write part of a bitmap to the current binary output stream.
         %
     :- pred io.write_bitmap(bitmap, int, int, io, io).
     %:- mode io.write_bitmap(bitmap_ui, in, in, di, uo) is det.
     :- mode io.write_bitmap(in, in, in, di, uo) is det.

         % Write a bitmap to the specified binary output stream.
         % The bitmap must not contain a partial final byte.
         %
     :- pred io.write_bitmap(io.binary_output_stream, bitmap, io, io).
     %:- mode io.write_bitmap(in, bitmap_ui, di, uo) is det.
     :- mode io.write_bitmap(in, in, di, uo) is det.

         % io.write_bitmap(Stream, BM, StartByte, NumBytes, !IO).
         % Write part of a bitmap to the specified binary output stream.
         %
     :- pred io.write_bitmap(io.binary_output_stream, bitmap, int, int, io, io).
     %:- mode io.write_bitmap(in, bitmap_ui, in, in, di, uo) is det.
     :- mode io.write_bitmap(in, in, in, in, di, uo) is det.

         % Flush the output buffer of the current binary output stream.
         %
     :- pred io.flush_binary_output(io::di, io::uo) is det.

         % Flush the output buffer of the specified binary output stream.
         %
     :- pred io.flush_binary_output(io.binary_output_stream::in,
         io::di, io::uo) is det.

         % Seek to an offset relative to Whence (documented above)
         % on a specified binary input stream. Attempting to seek on a pipe
         % or tty results in implementation dependent behaviour.
         %
         % A successful seek undoes any effects of io.putback_byte on the stream.
         %
     :- pred io.seek_binary_input(io.binary_input_stream::in, io.whence::in,
         int::in, io::di, io::uo) is det.

         % Seek to an offset relative to Whence (documented above)
         % on a specified binary output stream. Attempting to seek on a pipe
         % or tty results in implementation dependent behaviour.
         %
     :- pred io.seek_binary_output(io.binary_output_stream::in, io.whence::in,
         int::in, io::di, io::uo) is det.

         % Returns the offset (in bytes) into the specified binary input stream.
         %
     :- pred io.binary_input_stream_offset(io.binary_input_stream::in, int::out,
         io::di, io::uo) is det.

         % Returns the offset (in bytes) into the specified binary output stream.
         %
     :- pred io.binary_output_stream_offset(io.binary_output_stream::in, int::out,
         io::di, io::uo) is det.

     %--------------------------------------------------%
     %
     % Binary input stream predicates
     %

         % Attempts to open a file for binary input, and if successful sets
         % the current binary input stream to the newly opened stream.
         % Result is either 'ok' or 'error(ErrorCode)'.
         %
     :- pred io.see_binary(string::in, io.res::out, io::di, io::uo) is det.

         % Closes the current input stream. The current input stream reverts
         % to standard input. This will throw an io.error exception if
         % an I/O error occurs.
         %
     :- pred io.seen_binary(io::di, io::uo) is det.

         % Attempts to open a binary file for input.
         % Result is either 'ok(Stream)' or 'error(ErrorCode)'.
         %
     :- pred io.open_binary_input(string::in,
         io.res(io.binary_input_stream)::out, io::di, io::uo) is det.

         % Closes an open binary input stream. This will throw an io.error
         % exception if an I/O error occurs.
         %
     :- pred io.close_binary_input(io.binary_input_stream::in,
         io::di, io::uo) is det.

         % Retrieves the current binary input stream.
         % Does not modify the I/O state.
         %
     :- pred io.binary_input_stream(io.binary_input_stream::out,
         io::di, io::uo) is det.

         % Changes the current input stream to the stream specified.
         % Returns the previous stream.
         %
     :- pred io.set_binary_input_stream(io.binary_input_stream::in,
         io.binary_input_stream::out, io::di, io::uo) is det.

         % Retrieves the standard binary input stream.
         % Does not modify the I/O state.
         %
     :- pred io.stdin_binary_stream(io.binary_input_stream::out,
         io::di, io::uo) is det.

         % Retrieves the human-readable name associated with the current binary
         % input stream. For file streams, this is the filename.
         %
     :- pred io.binary_input_stream_name(string::out, io::di, io::uo) is det.

         % Retrieves the human-readable name associated with the specified
         % binary input stream. For file streams, this is the filename.
         %
     :- pred io.binary_input_stream_name(io.binary_input_stream::in, string::out,
         io::di, io::uo) is det.

     %--------------------------------------------------%
     %
     % Binary output stream predicates
     %

         % Attempts to open a file for binary output, and if successful sets
         % the current binary output stream to the newly opened stream.
         % As per Prolog tell/1. Result is either 'ok' or 'error(ErrCode)'.
         %
     :- pred io.tell_binary(string::in, io.res::out, io::di, io::uo) is det.

         % Closes the current binary output stream. The default binary output
         % stream reverts to standard output. As per Prolog told/0. This will
         % throw an io.error exception if an I/O error occurs.
         %
     :- pred io.told_binary(io::di, io::uo) is det.

         % Attempts to open a file for binary output.
         % Result is either 'ok(Stream)' or 'error(ErrorCode)'.
         %
     :- pred io.open_binary_output(string::in,
         io.res(io.binary_output_stream)::out, io::di, io::uo) is det.

         % Attempts to open a file for binary appending.
         % Result is either 'ok(Stream)' or 'error(ErrorCode)'.
         %
     :- pred io.open_binary_append(string::in,
         io.res(io.binary_output_stream)::out, io::di, io::uo) is det.

         % Closes an open binary output stream.
         % This will throw an io.error exception if an I/O error occurs.
         %
     :- pred io.close_binary_output(io.binary_output_stream::in,
         io::di, io::uo) is det.

         % Retrieves the current binary output stream.
         % Does not modify the I/O state.
         %
     :- pred io.binary_output_stream(io.binary_output_stream::out,
         io::di, io::uo) is det.

         % Retrieves the standard binary output stream.
         % Does not modify the I/O state.
         %
     :- pred io.stdout_binary_stream(io.binary_output_stream::out,
         io::di, io::uo) is det.

         % Changes the current binary output stream to the stream specified.
         % Returns the previous stream.
         %
     :- pred io.set_binary_output_stream(io.binary_output_stream::in,
         io.binary_output_stream::out, io::di, io::uo) is det.

         % Retrieves the human-readable name associated with the current
         % binary output stream. For file streams, this is the filename.
         %
     :- pred io.binary_output_stream_name(string::out, io::di, io::uo) is det.

         % Retrieves the human-readable name associated with the specified
         % output stream. For file streams, this is the filename.
         %
     :- pred io.binary_output_stream_name(io.binary_output_stream::in,
         string::out, io::di, io::uo) is det.

     %--------------------------------------------------%
     %
     % Global state predicates
     %

         % io.progname(DefaultProgname, Progname).
         %
         % Returns the name that the program was invoked with, if available,
         % or DefaultProgname if the name is not available.
         % Does not modify the I/O state.
         %
     :- pred io.progname(string::in, string::out, io::di, io::uo) is det.

         % io.progname_base(DefaultProgname, Progname).
         %
         % Like `io.progname', except that it strips off any path name
         % preceding the program name.  Useful for error messages.
         %
     :- pred io.progname_base(string::in, string::out, io::di, io::uo) is det.

         % Returns the arguments that the program was invoked with,
         % if available, otherwise an empty list. Does not modify the I/O state.
         %
     :- pred io.command_line_arguments(list(string)::out, io::di, io::uo) is det.

         % The I/O state contains an integer used to record the program's exit
         % status. When the program finishes, it will return this exit status
         % to the operating system. The following predicates can be used to get
         % and set the exit status.
         %
     :- pred io.get_exit_status(int::out, io::di, io::uo) is det.
     :- pred io.set_exit_status(int::in, io::di, io::uo) is det.

         % The I/O state includes a `globals' field which is not used by the
         % standard library, but can be used by the application. The globals field
         % is of type `univ' so that the application can store any data it wants
         % there.  The following predicates can be used to access this global state.
         %
         % Does not modify the I/O state.
         %
     :- pred io.get_globals(univ::out, io::di, io::uo) is det.
     :- pred io.set_globals(univ::in, io::di, io::uo) is det.

         % io.update_globals(UpdatePred, !IO).
         % Update the `globals' field in the I/O state based upon its current
         % value.  This is equivalent to the following:
         %
         %   io.get_globals(Globals0, !IO),
         %   UpdatePred(Globals0, Globals),
         %   io.set_globals(Globals, !IO)
         %
         % In parallel grades calls to io.update_globals/3 are atomic.
         % If `UpdatePred' throws an exception then the `globals' field is
         % left unchanged.
         %
     :- pred io.update_globals(pred(univ, univ)::in(pred(in, out) is det),
         io::di, io::uo) is det.

         % The following predicates provide an interface to the environment list.
         % Do not attempt to put spaces or '=' signs in the names of environment
         % variables, or bad things may result!
         %
         % First argument is the name of the environment variable. Returns
         % yes(Value) if the variable was set (Value will be set to the value
         % of the variable) and no if the variable was not set.
         %
     :- pred io.get_environment_var(string::in, maybe(string)::out,
         io::di, io::uo) is det.

         % First argument is the name of the environment variable, second argument
         % is the value to be assigned to that variable. Will throw an exception
         % if the system runs out of environment space.
         %
         % Note: this predicate is not supported on Java.
         %
     :- pred io.set_environment_var(string::in, string::in, io::di, io::uo) is det.

     %--------------------------------------------------%
     %
     % File handling predicates
     %

         % io.make_temp(Name, !IO) creates an empty file whose name is different
         % to the name of any existing file. Name is bound to the name of the file.
         % It is the responsibility of the program to delete the file when it is
         % no longer needed.
         %
         % The file will reside in an implementation-dependent directory.
         % For current Mercury implementations, it is determined as follows:
         % 1. For the non-Java back-ends:
         %    - On Microsoft Windows systems, the file will reside in
         %      the current directory if the TMP environment variable
         %      is not set, or in the directory specified by TMP if it is set.
         %    - On Unix systems, the file will reside in /tmp if the TMPDIR
         %      environment variable is not set, or in the directory specified
         %      by TMPDIR if it is set.
         % 2. For the Java back-end, the system-dependent default
         %    temporary-file directory will be used, specified by the Java
         %    system property java.io.tmpdir. On UNIX systems the default
         %    value of this property is typically "/tmp" or "/var/tmp";
         %    on Microsoft Windows systems it is typically "c:\\temp".
         %
     :- pred io.make_temp(string::out, io::di, io::uo) is det.

         % io.make_temp(Dir, Prefix, Name, !IO) creates an empty file whose
         % name is different to the name of any existing file. The file will reside
         % in the directory specified by `Dir' and will have a prefix using up to
         % the first 5 characters of `Prefix'. Name is bound to the name of the
         % file. It is the responsibility of the program to delete the file
         % when it is no longer needed.
         %
     :- pred io.make_temp(string::in, string::in, string::out, io::di, io::uo)
         is det.

         % io.remove_file(FileName, Result, !IO) attempts to remove the file
         % `FileName', binding Result to ok/0 if it succeeds, or error/1 if it
         % fails. If `FileName' names a file that is currently open, the behaviour
         % is implementation-dependent.
         %
     :- pred io.remove_file(string::in, io.res::out, io::di, io::uo) is det.

         % io.remove_file_recursively(FileName, Result, !IO) attempts to remove
         % the file `FileName', binding Result to ok/0 if it succeeds, or error/1
         % if it fails. If `FileName' names a file that is currently open, the
         % behaviour is implementation-dependent.
         %
         % Unlike `io.remove_file', this predicate will attempt to remove non-empty
         % directories (recursively). If it fails, some of the directory elements
         % may already have been removed.
         %
     :- pred remove_file_recursively(string::in, io.res::out, io::di, io::uo)
         is det.

         % io.rename_file(OldFileName, NewFileName, Result, !IO).
         %
         % Attempts to rename the file `OldFileName' as `NewFileName', binding
         % Result to ok/0 if it succeeds, or error/1 if it fails. If `OldFileName'
         % names a file that is currently open, the behaviour is
         % implementation-dependent. If `NewFileName' names a file that already
         % exists the behaviour is also implementation-dependent; on some systems,
         % the file previously named `NewFileName' will be deleted and replaced
         % with the file previously named `OldFileName'.
         %
     :- pred io.rename_file(string::in, string::in, io.res::out, io::di, io::uo)
         is det.

         % Succeeds if this platform can read and create symbolic links.
         %
     :- pred io.have_symlinks is semidet.

         % io.make_symlink(FileName, LinkFileName, Result, !IO).
         %
         % Attempts to make `LinkFileName' be a symbolic link to `FileName'.
         % If `FileName' is a relative path, it is interpreted relative
         % to the directory containing `LinkFileName'.
         %
     :- pred io.make_symlink(string::in, string::in, io.res::out, io::di, io::uo)
         is det.

         % io.read_symlink(FileName, Result, !IO) returns `ok(LinkTarget)'
         % if `FileName' is a symbolic link pointing to `LinkTarget', and
         % `error(Error)' otherwise. If `LinkTarget' is a relative path,
         % it should be interpreted relative the directory containing `FileName',
         % not the current directory.
         %
     :- pred io.read_symlink(string::in, io.res(string)::out, io::di, io::uo)
         is det.

     :- type io.access_type
         --->    read
         ;       write
         ;       execute.

         % io.check_file_accessibility(FileName, AccessTypes, Result):
         %
         % Check whether the current process can perform the operations given
         % in `AccessTypes' on `FileName'.
         % XXX When using the .NET CLI, this predicate will sometimes report
         % that a directory is writable when in fact it is not.
         % XXX On the Erlang backend, or on Windows with some compilers, `execute'
         % access is not checked.
         %
     :- pred io.check_file_accessibility(string::in, list(access_type)::in,
         io.res::out, io::di, io::uo) is det.

     :- type io.file_type
         --->    regular_file
         ;       directory
         ;       symbolic_link
         ;       named_pipe
         ;       socket
         ;       character_device
         ;       block_device
         ;       message_queue
         ;       semaphore
         ;       shared_memory
         ;       unknown.

         % io.file_type(FollowSymLinks, FileName, TypeResult)
         % finds the type of the given file.
         %
     :- pred io.file_type(bool::in, string::in, io.res(file_type)::out,
         io::di, io::uo) is det.

         % io.file_modification_time(FileName, TimeResult)
         % finds the last modification time of the given file.
         %
     :- pred io.file_modification_time(string::in, io.res(time_t)::out,
         io::di, io::uo) is det.

     %--------------------------------------------------%
     %
     % Memory management predicates
     %

         % Write memory/time usage statistics to stderr.
         %
     :- pred io.report_stats(io::di, io::uo) is det.

         % Write statistics to stderr; what statistics will be written
         % is controlled by the first argument, which acts a selector.
         % What selector values cause what statistics to be printed
         % is implementation defined.
         %
         % The Melbourne implementation supports the following selectors:
         %
         % "standard"
         %   Writes memory/time usage statistics.
         %
         % "full_memory_stats"
         %   Writes complete memory usage statistics, including information
         %   about all procedures and types. Requires compilation with memory
         %   profiling enabled.
         %
         % "tabling"
         %   Writes statistics about the internals of the tabling system.
         %   Requires the runtime to have been compiled with the macro
         %   MR_TABLE_STATISTICS defined.
         %
     :- pred io.report_stats(string::in, io::di, io::uo) is det.

     %--------------------------------------------------%
     %
     % Miscellaneous predicates
     %

         % Invokes the operating system shell with the specified Command.
         % Result is either `ok(ExitStatus)', if it was possible to invoke
         % the command, or `error(ErrorCode)' if not. The ExitStatus will be 0
         % if the command completed successfully or the return value of the system
         % call. If a signal kills the system call, then Result will be an error
         % indicating which signal occurred.
         %
     :- pred io.call_system(string::in, io.res(int)::out, io::di, io::uo) is det.

     :- type io.system_result
         --->    exited(int)
         ;       signalled(int).

         % call_system_return_signal(Command, Result, !IO):
         %
         % Invokes the operating system shell with the specified Command.
         % Result is either `ok(ExitStatus)' if it was possible to invoke
         % the command or `error(Error)' if the command could not be executed.
         % If the command could be executed then ExitStatus is either
         % `exited(ExitCode)' if the command ran to completion or
         % `signalled(SignalNum)' if the command was killed by a signal.
         % If the command ran to completion then ExitCode will be 0 if the command
         % ran successfully and the return value of the command otherwise.
         %
     :- pred io.call_system_return_signal(string::in,
         io.res(io.system_result)::out, io::di, io::uo) is det.

         % Construct an error code including the specified error message.
         %
     :- func io.make_io_error(string) = io.error.

         % Look up the error message corresponding to a particular error code.
         %
     :- func io.error_message(io.error) = string.
     :- pred io.error_message(io.error::in, string::out) is det.

     %--------------------------------------------------%
     %
     % Instances of the stream typeclass
     %

     :- instance stream.error(io.error).

     :- instance stream.stream(io.output_stream, io).
     :- instance stream.output(io.output_stream, io).
     :- instance stream.writer(io.output_stream, char,   io).
     :- instance stream.writer(io.output_stream, float,  io).
     :- instance stream.writer(io.output_stream, int,    io).
     :- instance stream.writer(io.output_stream, string, io).
     :- instance stream.writer(io.output_stream, univ,   io).
     :- instance stream.line_oriented(io.output_stream, io).

     :- instance stream.stream(io.input_stream, io).
     :- instance stream.input(io.input_stream, io).
     :- instance stream.reader(io.input_stream, char, io, io.error).
     :- instance stream.reader(io.input_stream, line, io, io.error).
     :- instance stream.reader(io.input_stream, text_file, io, io.error).

     :- instance stream.line_oriented(io.input_stream, io).
     :- instance stream.putback(io.input_stream, char, io, io.error).

     :- instance stream.stream(io.binary_output_stream, io).
     :- instance stream.output(io.binary_output_stream, io).
     :- instance stream.writer(io.binary_output_stream, byte, io).
     :- instance stream.writer(io.binary_output_stream, bitmap.slice, io).
     :- instance stream.seekable(io.binary_output_stream, io).

     :- instance stream.stream(io.binary_input_stream,  io).
     :- instance stream.input(io.binary_input_stream, io).
     :- instance stream.reader(io.binary_input_stream, int, io, io.error).
     :- instance stream.bulk_reader(io.binary_input_stream, int,
             bitmap, io, io.error).
     :- instance stream.putback(io.binary_input_stream, int, io, io.error).
     :- instance stream.seekable(io.binary_input_stream, io).

     %--------------------------------------------------%
     %--------------------------------------------------%


File: mercury_library.info,  Node: lazy,  Next: lexer,  Prev: io,  Up: Top

37 lazy
*******

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 1999, 2006, 2009-2010 The University of Melbourne.
     % This file may only be copied under the terms of the GNU Library General
     % Public License - see the file COPYING.LIB in the Mercury distribution.
     %--------------------------------------------------%
     %
     % lazy.m - provides support for optional explicit lazy evaluation.
     %
     % Author: fjh, pbone.
     % Stability: medium.
     %
     % This module provides the data type `lazy(T)' and the functions `val',
     % `delay', and `force', which can be used to emulate lazy evaluation.
     %
     % A field within a data structure can be made lazy by wrapping it within a lazy
     % type.  Or a lazy data-structure can be implemented, for example:
     %
     % :- type lazy_list(T)
     %     --->    lazy_list(
     %                 lazy(list_cell(T))
     %             ).
     %
     % :- type list_cell(T)
     %     --->    cons(T, lazy_list(T))
     %     ;       nil.
     %
     % Note that this makes every list cell lazy, whereas:
     %
     %   lazy(list(T))
     %
     % uses only one thunk for the entire list. And:
     %
     %   list(lazy(T))
     %
     % uses one thunk for every element, but the list's structure is not lazy.
     %
     %--------------------------------------------------%

     :- module lazy.
     :- interface.

         % A lazy(T) is a value of type T which will only be evaluated on
         % demand.
         %
     :- type lazy(T).

         % Convert a value from type T to lazy(T)
         %
     :- func val(T) = lazy(T).

         % Construct a lazily-evaluated lazy(T) from a closure
         %
     :- func delay((func) = T) = lazy(T).

         % Force the evaluation of a lazy(T), and return the result as type T.
         % Note that if the type T may itself contains subterms of type lazy(T),
         % as is the case when T is a recursive type like the lazy_list(T) type
         % defined in lazy_list.m, those subterms will not be evaluated --
         % force/1 only forces evaluation of the lazy/1 term at the top level.
         %
         % A second call to force will not re-evaluate the lazy expression, it will
         % simply return T.
         %
     :- func force(lazy(T)) = T.

         % Get the value of a lazy expression if it has already been made available
         % with force/1 This is useful as it can provide information without
         % incurring (much) cost.
         %
     :- pred read_if_val(lazy(T)::in, T::out) is semidet.

         % Test lazy values for equality.
         %
     :- pred equal_values(lazy(T)::in, lazy(T)::in) is semidet.

     :- pred compare_values(comparison_result::uo, lazy(T)::in, lazy(T)::in) is det.

     %--------------------------------------------------%
     %
     % The declarative semantics of the above constructs are given by the
     % following equations:
     %
     %   val(X) = delay((func) = X).
     %
     %   force(delay(F)) = apply(F).
     %
     % The operational semantics satisfy the following:
     %
     % - val/1 and delay/1 both take O(1) time and use O(1) additional space.
     %   In particular, delay/1 does not evaluate its argument using apply/1.
     %
     % - When force/1 is first called for a given term, it uses apply/1 to
     %   evaluate the term, and then saves the result computed by destructively
     %   modifying its argument; subsequent calls to force/1 on the same term
     %   will return the same result.  So the time to evaluate force(X), where
     %   X = delay(F), is O(the time to evaluate apply(F)) for the first call,
     %   and O(1) time for subsequent calls.
     %
     % - Equality on values of type lazy(T) is implemented by calling force/1
     %   on both arguments and comparing the results.  So if X and Y have type
     %   lazy(T), and both X and Y are ground, then the time to evaluate X = Y
     %   is O(the time to evaluate (X1 = force(X)) + the time to evaluate
     %   (Y1 = force(Y)) + the time to unify X1 and Y1).
     %
     %--------------------------------------------------%
     %--------------------------------------------------%


File: mercury_library.info,  Node: lexer,  Next: library,  Prev: lazy,  Up: Top

38 lexer
********

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et
     %--------------------------------------------------%
     % Copyright (C) 1993-2000, 2003-2008, 2011 The University of Melbourne.
     % This file may only be copied under the terms of the GNU Library General
     % Public License - see the file COPYING.LIB in the Mercury distribution.
     %--------------------------------------------------%
     %
     % File: lexer.m.
     % Main author: fjh.
     % Stability: high.
     %
     % Lexical analysis.  This module defines the representation of tokens
     % and exports predicates for reading in tokens from an input stream.
     %
     % See ISO Prolog 6.4.  Also see the comments at the top of parser.m.
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module lexer.
     :- interface.

     :- import_module char.
     :- import_module io.

     %--------------------------------------------------%

     :- type token
         --->    name(string)
         ;       variable(string)
         ;       integer(int)
         ;       float(float)
         ;       string(string)      % "...."
         ;       implementation_defined(string) % $name
         ;       open                % '('
         ;       open_ct             % '(' without any preceding whitespace
         ;       close               % ')'
         ;       open_list           % '['
         ;       close_list          % ']'
         ;       open_curly          % '{'
         ;       close_curly         % '}'
         ;       ht_sep              % '|'
         ;       comma               % ','
         ;       end                 % '.'
         ;       junk(char)          % junk character in the input stream
         ;       error(string)       % some other invalid token
         ;       io_error(io.error) % error reading from the input stream
         ;       eof                 % end-of-file
         ;       integer_dot(int).   % the lexer will never return this.
                                     % The integer_dot/1 token is used
                                     % internally in the lexer, to keep
                                     % the grammar LL(1) so that only one
                                     % character of pushback is needed.
                                     % But the lexer will convert
                                     % integer_dot/1 tokens to integer/1
                                     % tokens before returning them.

         % For every token, we record the line number of the line on
         % which the token occurred.
         %
     :- type token_context == int.   % line number

         % This "fat list" representation is more efficient than a list of pairs.
         %
     :- type token_list
         --->    token_cons(token, token_context, token_list)
         ;       token_nil.

         % Read a list of tokens from the current input stream.
         % Keep reading until we encounter either an `end' token
         % (i.e. a full stop followed by whitespace) or the end-of-file.
         %
     :- pred get_token_list(token_list::out, io::di, io::uo) is det.

         % The type `offset' represents a (zero-based) offset into a string.
         %
     :- type offset == int.

         % string_get_token_list_max(String, MaxOffset, Tokens,
         %   InitialPos, FinalPos):
         %
         % Scan a list of tokens from a string, starting at the current offset
         % specified by InitialPos. Keep scanning until either we encounter either
         % an `end' token (i.e. a full stop followed by whitespace) or until we
         % reach MaxOffset. (MaxOffset must be =< the length of the string.)
         % Return the tokens scanned in Tokens, and return the position one
         % character past the end of the last token in FinalPos.
         %
     :- pred string_get_token_list_max(string::in, offset::in, token_list::out,
         posn::in, posn::out) is det.

         % string_get_token_list(String, Tokens, InitialPos, FinalPos):
         %
         % calls string_get_token_list_max above with MaxPos = length of String.
         %
     :- pred string_get_token_list(string::in, token_list::out,
         posn::in, posn::out) is det.

         % Convert a token to a human-readable string describing the token.
         %
     :- pred token_to_string(token::in, string::out) is det.

     %--------------------------------------------------%
     %--------------------------------------------------%


File: mercury_library.info,  Node: library,  Next: list,  Prev: lexer,  Up: Top

39 library
**********

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 1993-2007, 2009-2011 The University of Melbourne.
     % This file may only be copied under the terms of the GNU Library General
     % Public License - see the file COPYING.LIB in the Mercury distribution.
     %--------------------------------------------------%
     %
     % This module imports all the modules in the Mercury library.
     %
     % It is used as a way for the Makefiles to know which library interface
     % files, objects, etc., need to be installed.
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module library.
     :- interface.

     :- pred library.version(string::out) is det.


File: mercury_library.info,  Node: list,  Next: map,  Prev: library,  Up: Top

40 list
*******

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 1993-2011 The University of Melbourne.
     % This file may only be copied under the terms of the GNU Library General
     % Public License - see the file COPYING.LIB in the Mercury distribution.
     %--------------------------------------------------%
     %
     % File: list.m.
     % Authors: fjh, conway, trd, zs, philip, warwick, ...
     % Stability: medium to high.
     %
     % This module defines the list type, and various utility predicates that
     % operate on lists.
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module list.
     :- interface.

     :- import_module pretty_printer.

     %--------------------------------------------------%

         % The definition of the type `list(T)':
         % A list is either an empty list, denoted `[]',
         % or an element `Head' of type `T' followed by a tail `Tail'
         % of type `list(T)', denoted `[Head | Tail]'.
         %
     :- type list(T)
         --->    []
         ;       [T | list(T)].

     %--------------------------------------------------%

         % Some declarations for complicated modes using lists.
         % (Note that partial instantiation is not currently supported.)

     :- inst list_skel(I) ---> [] ; [I | list_skel(I)].
     :- inst list_skel == list_skel(free).
     :- inst list(I) == list_skel(I).

     :- inst non_empty_list ---> [ground | ground].

     :- mode in_list_skel  == list_skel >> list_skel.
     :- mode out_list_skel == free >> list_skel.
     :- mode list_skel_out == list_skel >> ground.

         % These more verbose versions are deprecated.
         % They exist only for backwards compatibility,
         % and will be removed in a future release.
     :- mode input_list_skel  == in_list_skel.
     :- mode output_list_skel == out_list_skel.
     :- mode list_skel_output == list_skel_out.

         % These modes are particularly useful for passing around lists
         % of higher order terms, since they have complicated insts
         % which are not correctly approximated by "ground".
     :- mode list_skel_in(I)  == list_skel(I) >> list_skel(I).
     :- mode list_skel_out(I) == free >> list_skel(I).

     %--------------------------------------------------%

     :- pred list.is_empty(list(T)::in) is semidet.

     :- pred list.is_not_empty(list(T)::in) is semidet.

         % list.cons(X, Y, Z) <=> Z = [X | Y].
         %
     :- pred list.cons(T::in, list(T)::in, list(T)::out) is det.
     :- func list.cons(T, list(T)) = list(T).

         % Standard append predicate:
         % list.append(Start, End, List) is true iff
         % `List' is the result of concatenating `Start' and `End'.
         %
     :- pred list.append(list(T), list(T), list(T)).
     :- mode list.append(di, di, uo) is det.
     :- mode list.append(in, in, out) is det.
     :- mode list.append(in, in, in) is semidet.    % implied
     :- mode list.append(in, out, in) is semidet.
     :- mode list.append(out, out, in) is multi.
     %   The following mode is semidet in the sense that it doesn't
     %   succeed more than once - but it does create a choice-point,
     %   which means it's inefficient and that the compiler can't deduce
     %   that it is semidet.  Use list.remove_suffix instead.
     % :- mode list.append(out, in, in) is semidet.

     :- func list.append(list(T), list(T)) = list(T).

         % associativity of append
     :- promise all [A, B, C, ABC]
         (
             ( some [AB] (list.append(A, B, AB), list.append(AB, C, ABC)) )
         <=>
             ( some [BC] (list.append(B, C, BC), list.append(A, BC, ABC)) )
         ).
         % construction equivalence law.
         % XXX when we implement rewrite rules, we should change this law
         % to a rewrite rule.
     :- promise all [L, H, T] ( append([H], T, L) <=> L = [H | T] ).

         % L1 ++ L2 = L :- list.append(L1, L2, L).
         %
     :- func list(T) ++ list(T) = list(T).

         % list.remove_suffix(List, Suffix, Prefix):
         %
         % The same as list.append(Prefix, Suffix, List) except that
         % this is semidet whereas list.append(out, in, in) is nondet.
         %
     :- pred list.remove_suffix(list(T)::in, list(T)::in, list(T)::out) is semidet.

         % list.merge(L1, L2, L):
         %
         % L is the result of merging the elements of L1 and L2, in ascending order.
         % L1 and L2 must be sorted.
         %
     :- pred list.merge(list(T)::in, list(T)::in, list(T)::out) is det.
     :- func list.merge(list(T), list(T)) = list(T).

         % list.merge_and_remove_dups(L1, L2, L):
         %
         % L is the result of merging the elements of L1 and L2, in ascending order,
         % and eliminating any duplicates. L1 and L2 must be sorted and must each
         % not contain any duplicates.
         %
     :- pred list.merge_and_remove_dups(list(T)::in, list(T)::in, list(T)::out)
         is det.
     :- func list.merge_and_remove_dups(list(T), list(T)) = list(T).

         % list.remove_adjacent_dups(L0, L):
         %
         % L is the result of replacing every sequence of duplicate elements in L0
         % with a single such element.
         %
     :- pred list.remove_adjacent_dups(list(T)::in, list(T)::out) is det.
     :- func list.remove_adjacent_dups(list(T)) = list(T).

         % list.remove_dups(L0, L):
         %
         % L is the result of deleting the second and subsequent occurrences
         % of every element that occurs twice in L0.
         %
     :- pred list.remove_dups(list(T)::in, list(T)::out) is det.
     :- func list.remove_dups(list(T)) = list(T).

         % list.member(Elem, List):
         %
         % True iff `List' contains `Elem'.
         %
     :- pred list.member(T, list(T)).
     :- mode list.member(in, in) is semidet.
     :- mode list.member(out, in) is nondet.

         % list.member(Elem, List, SubList):
         %
         % True iff `List' contains `Elem', and `SubList' is a suffix of `List'
         % beginning with `Elem'.
         % Same as `SubList = [Elem | _], list.append(_, SubList, List)'.
         %
     :- pred list.member(T::out, list(T)::in, list(T)::out) is nondet.

         % list.member_index0(Elem, List, Index).
         %
         % True iff `List' contains `Elem' at the zero-based index `Index'.
         %
     :- pred list.member_index0(T, list(T), int).
     :- mode list.member_index0(in, in, in) is semidet.
     :- mode list.member_index0(in, in, out) is nondet.
     :- mode list.member_index0(out, in, out) is nondet.

         % list.contains(List, Elem) iff list.member(Elem, List).
         % Sometimes you need the arguments in this order, because you want to
         % construct a closure with only the list.
         %
     :- pred list.contains(list(T)::in, T::in) is semidet.

         % list.length(List, Length):
         %
         % True iff `Length' is the length of `List', i.e. if `List' contains
         % `Length' elements.
         %
     :- pred list.length(list(_T), int).
     :- mode list.length(in, out) is det.
         % XXX The current mode checker can't handle this mode
     % :- mode list.length(input_list_skel, out) is det.

     :- func list.length(list(T)) = int.

         % list.same_length(ListA, ListB):
         %
         % True iff `ListA' and `ListB' have the same length,
         % i.e. iff they both contain the same number of elements.
         %
     :- pred list.same_length(list(T1), list(T2)).
         % XXX The current mode checker can't handle these modes.
     % :- mode list.same_length(in, output_list_skel) is det.
     % :- mode list.same_length(output_list_skel, in) is det.
     :- mode list.same_length(in, in) is semidet.
     % XXX The current mode checker can't handle these modes
     % :- mode list.same_length(input_list_skel, output_list_skel) is det.
     % :- mode list.same_length(output_list_skel, input_list_skel) is det.

         % list.split_list(Len, List, Start, End):
         %
         % splits `List' into a prefix `Start' of length `Len', and a remainder
         % `End'. See also: list.take, list.drop and list.split_upto.
         %
     :- pred list.split_list(int::in, list(T)::in, list(T)::out, list(T)::out)
         is semidet.

         % list.det_split_list(Len, List, Start, End):
         %
         % A deterministic version of list.split_list, which aborts instead
         % of failing if Len > list.length(List).
         %
     :- pred list.det_split_list(int::in, list(T)::in, list(T)::out, list(T)::out)
         is det.

         % list.split_upto(Len, List, Start, End):
         %
         % splits `List' into a prefix `Start' of length `min(Len, length(List))',
         % and a remainder `End'. See also: list.split_list, list.take, list.drop.
         %
     :- pred list.split_upto(int::in, list(T)::in, list(T)::out, list(T)::out)
         is det.

         % list.take(Len, List, Start):
         %
         % `Start' is the first `Len' elements of `List'. Fails if `List' has
         % less than `Len' elements. See also: list.split_list.
         %
     :- pred list.take(int::in, list(T)::in, list(T)::out) is semidet.

         % list.take_upto(Len, List, Start):
         %
         % `Start' is the first `Len' elements of `List'. If `List' has less than
         % `Len' elements, return the entire list.
         %
     :- pred list.take_upto(int::in, list(T)::in, list(T)::out) is det.
     :- func list.take_upto(int, list(T)) = list(T).

         % list.drop(Len, List, End):
         %
         % `End' is the remainder of `List' after removing the first `Len' elements.
         % Fails if `List' does not have at least `Len' elements.
         % See also: list.split_list.
         %
     :- pred list.drop(int::in, list(T)::in, list(T)::out) is semidet.

         % list.det_drop(Len, List, End):
         %
         % `End' is the remainder of `List' after removing the first `Len' elements.
         % Aborts if `List' does not have at least `Len' elements.
         % See also: list.split_list.
         %
     :- pred list.det_drop(int::in, list(T)::in, list(T)::out) is det.

         % list.insert(Elem, List0, List):
         %
         % `List' is the result of inserting `Elem' somewhere in `List0'.
         % Same as `list.delete(List, Elem, List0)'.
         %
     :- pred list.insert(T, list(T), list(T)).
     :- mode list.insert(in, in, in) is semidet.
     :- mode list.insert(in, out, in) is nondet.
     :- mode list.insert(out, out, in) is nondet.
     :- mode list.insert(in, in, out) is multi.

         % list.delete(List, Elem, Remainder):
         %
         % True iff `Elem' occurs in `List', and `Remainder' is the result of
         % deleting one occurrence of `Elem' from `List'.
         %
     :- pred list.delete(list(T), T, list(T)).
     :- mode list.delete(in, in, in) is semidet.
     :- mode list.delete(in, in, out) is nondet.
     :- mode list.delete(in, out, out) is nondet.
     :- mode list.delete(out, in, in) is multi.

     :- func list.delete_all(list(T), T) = list(T).

         % list.delete_first(List0, Elem, List) is true iff Elem occurs in List0
         % and List is List0 with the first occurrence of Elem removed.
         %
     :- pred list.delete_first(list(T)::in, T::in, list(T)::out) is semidet.

         % list.delete_all(List0, Elem, List) is true iff List is List0 with
         % all occurrences of Elem removed.
         %
     :- pred list.delete_all(list(T), T, list(T)).
     :- mode list.delete_all(di, in, uo) is det.
     :- mode list.delete_all(in, in, out) is det.

         % list.delete_elems(List0, Elems, List) is true iff List is List0 with
         % all occurrences of all elements of Elems removed.
         %
     :- pred list.delete_elems(list(T)::in, list(T)::in, list(T)::out) is det.
     :- func list.delete_elems(list(T), list(T)) = list(T).

         % list.replace(List0, D, R, List) is true iff List is List0
         % with an occurrence of D replaced with R.
         %
     :- pred list.replace(list(T), T, T, list(T)).
     :- mode list.replace(in, in, in, in) is semidet.
     :- mode list.replace(in, in, in, out) is nondet.

         % list.replace_first(List0, D, R, List) is true iff List is List0
         % with the first occurrence of D replaced with R.
         %
     :- pred list.replace_first(list(T)::in, T::in, T::in, list(T)::out)
         is semidet.

         % list.replace_all(List0, D, R, List) is true iff List is List0
         % with all occurrences of D replaced with R.
         %
     :- pred list.replace_all(list(T)::in, T::in, T::in, list(T)::out) is det.
     :- func list.replace_all(list(T), T, T) = list(T).

         % list.replace_nth(List0, N, R, List) is true iff List is List0
         % with Nth element replaced with R.
         % Fails if N < 1 or if length of List0 < N.
         % (Position numbers start from 1.)
         %
     :- pred list.replace_nth(list(T)::in, int::in, T::in, list(T)::out)
         is semidet.

         % list.det_replace_nth(List0, N, R, List) is true iff List is List0
         % with Nth element replaced with R.
         % Aborts if N < 1 or if length of List0 < N.
         % (Position numbers start from 1.)
         %
     :- pred list.det_replace_nth(list(T)::in, int::in, T::in, list(T)::out) is det.
     :- func list.det_replace_nth(list(T), int, T) = list(T).

     :- pragma obsolete(list.replace_nth_det/4).
     :- pred list.replace_nth_det(list(T)::in, int::in, T::in, list(T)::out)
         is det.
     :- pragma obsolete(list.replace_nth_det/3).
     :- func list.replace_nth_det(list(T), int, T) = list(T).

         % list.sort_and_remove_dups(List0, List):
         %
         % List is List0 sorted with the second and subsequent occurrence of
         % any duplicates removed.
         %
     :- pred list.sort_and_remove_dups(list(T)::in, list(T)::out) is det.
     :- func list.sort_and_remove_dups(list(T)) = list(T).

         % list.sort(List0, List):
         %
         % List is List0 sorted.
         %
     :- pred list.sort(list(T)::in, list(T)::out) is det.
     :- func list.sort(list(T)) = list(T).

         % list.reverse(List, Reverse):
         %
         % `Reverse' is a list containing the same elements as `List'
         % but in reverse order.
         %
     :- pred list.reverse(list(T), list(T)).
     :- mode list.reverse(in, out) is det.
     :- mode list.reverse(out, in) is det.

     :- func list.reverse(list(T)) = list(T).

         % list.perm(List0, List):
         %
         % True iff `List' is a permutation of `List0'.
         %
     :- pred list.perm(list(T)::in, list(T)::out) is multi.

         % list.nth_member_search(List, Elem, Position):
         %
         % Elem is the Position'th member of List.
         % (Position numbers start from 1.)
         %
     :- pred list.nth_member_search(list(T)::in, T::in, int::out) is semidet.

         % A deterministic version of list.nth_member_search, which aborts
         % instead of failing if the element is not found in the list.
         %
     :- pred list.nth_member_lookup(list(T)::in, T::in, int::out) is det.

         % list.index*(List, Position, Elem):
         %
         % These predicates select an element in a list from it's position.
         % The `index0' preds consider the first element to be element
         % number zero, whereas the `index1' preds consider the first element
         % to be element number one. The `det_' preds call error/1 if the index
         % is out of range, whereas the semidet preds fail if the index is out of
         % range.
         %
     :- pred list.index0(list(T)::in, int::in, T::out) is semidet.
     :- pred list.index1(list(T)::in, int::in, T::out) is semidet.
     :- pred list.det_index0(list(T)::in, int::in, T::out) is det.
     :- pred list.det_index1(list(T)::in, int::in, T::out) is det.

     :- pragma obsolete(list.index0_det/3).
     :- pred list.index0_det(list(T)::in, int::in, T::out) is det.
     :- pragma obsolete(list.index1_det/3).
     :- pred list.index1_det(list(T)::in, int::in, T::out) is det.

     :- pragma obsolete(list.index0_det/2).
     :- func list.index0_det(list(T), int) = T.
     :- pragma obsolete(list.index1_det/2).
     :- func list.index1_det(list(T), int) = T.
     :- func list.det_index0(list(T), int) = T.
     :- func list.det_index1(list(T), int) = T.

         % list.index*_of_first_occurrence(List, Elem, Position):
         %
         % Computes the least value of Position such that
         % list_index*(List, Position, Elem). The `det_' funcs call error/1
         % if Elem is not a member of List.
         %
     :- pred list.index0_of_first_occurrence(list(T)::in, T::in, int::out)
         is semidet.
     :- pred list.index1_of_first_occurrence(list(T)::in, T::in, int::out)
         is semidet.
     :- func list.det_index0_of_first_occurrence(list(T), T) = int.
     :- func list.det_index1_of_first_occurrence(list(T), T) = int.

         % list.zip(ListA, ListB, List):
         %
         % List is the result of alternating the elements of ListA and ListB,
         % starting with the first element of ListA (followed by the first element
         % of ListB, then the second element of listA, then the second element
         % of ListB, etc.). When there are no more elements remaining in one of
         % the lists, the remainder of the nonempty list is appended.
         %
     :- pred list.zip(list(T)::in, list(T)::in, list(T)::out) is det.
     :- func list.zip(list(T), list(T)) = list(T).

         % list.duplicate(Count, Elem, List) is true iff List is a list
         % containing Count duplicate copies of Elem.
         %
     :- pred list.duplicate(int::in, T::in, list(T)::out) is det.
     :- func list.duplicate(int, T) = list(T).

         % list.condense(ListOfLists, List):
         %
         % `List' is the result of concatenating all the elements of `ListOfLists'.
         %
     :- pred list.condense(list(list(T))::in, list(T)::out) is det.
     :- func list.condense(list(list(T))) = list(T).

         % list.chunk(List, ChunkSize, Chunks):
         %
         % Takes a list `List' and breaks it into a list of lists `Chunks',
         % such that the length of each list in `Chunks' is at most `ChunkSize.
         % (More precisely, the length of each list in `Chunks' other than the
         % last one is exactly `ChunkSize', and the length of the last list in
         % `Chunks' is between one and `ChunkSize'.)
         %
     :- pred list.chunk(list(T)::in, int::in, list(list(T))::out) is det.
     :- func list.chunk(list(T), int) = list(list(T)).

         % list.sublist(SubList, FullList) is true if one can obtain SubList
         % by starting with FullList and deleting some of its elements.
         %
     :- pred list.sublist(list(T)::in, list(T)::in) is semidet.

         % list.all_same(List) is true if all elements of the list are the same.
         %
     :- pred list.all_same(list(T)::in) is semidet.

         % list.last(List, Last) is true if Last is the last element of List.
         %
     :- pred list.last(list(T)::in, T::out) is semidet.

         % A deterministic version of list.last, which aborts instead of
         % failing if the input list is empty.
         %
     :- pred list.det_last(list(T)::in, T::out) is det.
     :- func list.det_last(list(T)) = T.

     :- pragma obsolete(list.last_det/2).
     :- pred list.last_det(list(T)::in, T::out) is det.

         % list.split_last(List, AllButLast, Last) is true if Last is the
         % last element of List and AllButLast is the list of elements before it.
         %
     :- pred list.split_last(list(T)::in, list(T)::out, T::out) is semidet.

         % A deterministic version of list.split_last, which aborts instead of
         % failing if the input list is empty.
         %
     :- pred list.split_last_det(list(T)::in, list(T)::out, T::out) is det.
     :- pred list.det_split_last(list(T)::in, list(T)::out, T::out) is det.

     %--------------------------------------------------%
     %
     % The following group of predicates use higher-order terms to simplify
     % various list processing tasks. They implement pretty much standard
     % sorts of operations provided by standard libraries for functional languages.
     %
     %--------------------------------------------------%

         % list.map(T, L, M) uses the closure T
         % to transform the elements of L into the elements of M.
         %
     :- pred list.map(pred(X, Y), list(X), list(Y)).
     :- mode list.map(pred(in, out) is det, in, out) is det.
     :- mode list.map(pred(in, out) is cc_multi, in, out) is cc_multi.
     :- mode list.map(pred(in, out) is semidet, in, out) is semidet.
     :- mode list.map(pred(in, out) is multi, in, out) is multi.
     :- mode list.map(pred(in, out) is nondet, in, out) is nondet.
     :- mode list.map(pred(in, in) is semidet, in, in) is semidet.

     :- func list.map(func(X) = Y, list(X)) = list(Y).

         % list.map2(T, L, M1, M2) uses the closure T
         % to transform the elements of L into the elements of M1 and M2.
         %
     :- pred list.map2(pred(A, B, C), list(A), list(B), list(C)).
     :- mode list.map2(pred(in, out, out) is det, in, out, out) is det.
     :- mode list.map2(pred(in, out, out) is cc_multi, in, out, out) is cc_multi.
     :- mode list.map2(pred(in, out, out) is semidet, in, out, out) is semidet.
     :- mode list.map2(pred(in, out, out) is multi, in, out, out) is multi.
     :- mode list.map2(pred(in, out, out) is nondet, in, out, out) is nondet.
     :- mode list.map2(pred(in, in, in) is semidet, in, in, in) is semidet.

         % list.map3(T, L, M1, M2, M3) uses the closure T
         % to transform the elements of L into the elements of M1, M2 and M3.
         %
     :- pred list.map3(pred(A, B, C, D), list(A), list(B), list(C), list(D)).
     :- mode list.map3(pred(in, out, out, out) is det, in, out, out, out) is det.
     :- mode list.map3(pred(in, out, out, out) is cc_multi, in, out, out, out)
         is cc_multi.
     :- mode list.map3(pred(in, out, out, out) is semidet, in, out, out, out)
         is semidet.
     :- mode list.map3(pred(in, out, out, out) is multi, in, out, out, out)
         is multi.
     :- mode list.map3(pred(in, out, out, out) is nondet, in, out, out, out)
         is nondet.
     :- mode list.map3(pred(in, in, in, in) is semidet, in, in, in, in) is semidet.

         % list.map4(T, L, M1, M2, M3, M4) uses the closure T
         % to transform the elements of L into the elements of M1, M2, M3 and M4.
         %
     :- pred list.map4(pred(A, B, C, D, E), list(A), list(B), list(C), list(D),
         list(E)).
     :- mode list.map4(pred(in, out, out, out, out) is det, in, out, out, out, out)
         is det.
     :- mode list.map4(pred(in, out, out, out, out) is cc_multi, in, out, out, out,
         out) is cc_multi.
     :- mode list.map4(pred(in, out, out, out, out) is semidet, in, out, out, out,
         out) is semidet.
     :- mode list.map4(pred(in, out, out, out, out) is multi, in, out, out, out,
         out) is multi.
     :- mode list.map4(pred(in, out, out, out, out) is nondet, in, out, out, out,
         out) is nondet.
     :- mode list.map4(pred(in, in, in, in, in) is semidet, in, in, in, in, in)
         is semidet.

         % list.map5(T, L, M1, M2, M3, M4, M5) uses the closure T
         % to transform the elements of L into the elements of M1, M2, M3, M4
         % and M5.
         %
     :- pred list.map5(pred(A, B, C, D, E, F), list(A), list(B), list(C), list(D),
         list(E), list(F)).
     :- mode list.map5(pred(in, out, out, out, out, out) is det, in, out, out, out,
         out, out) is det.
     :- mode list.map5(pred(in, out, out, out, out, out) is cc_multi, in, out, out,
         out, out, out) is cc_multi.
     :- mode list.map5(pred(in, out, out, out, out, out) is semidet, in, out, out,
         out, out, out) is semidet.
     :- mode list.map5(pred(in, out, out, out, out, out) is multi, in, out, out,
         out, out, out) is multi.
     :- mode list.map5(pred(in, out, out, out, out, out) is nondet, in, out, out,
         out, out, out) is nondet.
     :- mode list.map5(pred(in, in, in, in, in, in) is semidet, in, in, in, in, in,
         in) is semidet.

         % list.map6(T, L, M1, M2, M3, M4, M5, M6) uses the closure T
         % to transform the elements of L into the elements of M1, M2, M3, M4,
         % M5 and M6.
         %
     :- pred list.map6(pred(A, B, C, D, E, F, G), list(A), list(B), list(C),
         list(D), list(E), list(F), list(G)).
     :- mode list.map6(pred(in, out, out, out, out, out, out) is det, in, out, out,
         out, out, out, out) is det.
     :- mode list.map6(pred(in, out, out, out, out, out, out) is cc_multi, in, out,
         out, out, out, out, out) is cc_multi.
     :- mode list.map6(pred(in, out, out, out, out, out, out) is semidet, in, out,
         out, out, out, out, out) is semidet.
     :- mode list.map6(pred(in, out, out, out, out, out, out) is multi, in, out,
         out, out, out, out, out) is multi.
     :- mode list.map6(pred(in, out, out, out, out, out, out) is nondet, in, out,
         out, out, out, out, out) is nondet.
     :- mode list.map6(pred(in, in, in, in, in, in, in) is semidet, in, in, in, in,
         in, in, in) is semidet.

         % list.map7(T, L, M1, M2, M3, M4, M5, M6, M7) uses the closure T
         % to transform the elements of L into the elements of M1, M2, M3, M4,
         % M5, M6 and M7.
         %
     :- pred list.map7(pred(A, B, C, D, E, F, G, H), list(A), list(B), list(C),
         list(D), list(E), list(F), list(G), list(H)).
     :- mode list.map7(pred(in, out, out, out, out, out, out, out) is det,
         in, out, out, out, out, out, out, out) is det.
     :- mode list.map7(pred(in, out, out, out, out, out, out, out) is cc_multi,
         in, out, out, out, out, out, out, out) is cc_multi.
     :- mode list.map7(pred(in, out, out, out, out, out, out, out) is semidet,
         in, out, out, out, out, out, out, out) is semidet.
     :- mode list.map7(pred(in, out, out, out, out, out, out, out) is multi,
         in, out, out, out, out, out, out, out) is multi.
     :- mode list.map7(pred(in, out, out, out, out, out, out, out) is nondet,
         in, out, out, out, out, out, out, out) is nondet.
     :- mode list.map7(pred(in, in, in, in, in, in, in, in) is semidet,
         in, in, in, in, in, in, in, in) is semidet.

         % list.map8(T, L, M1, M2, M3, M4, M5, M6, M7) uses the closure T
         % to transform the elements of L into the elements of M1, M2, M3, M4,
         % M5, M6, M7 and M8.
         %
     :- pred list.map8(pred(A, B, C, D, E, F, G, H, I), list(A), list(B), list(C),
         list(D), list(E), list(F), list(G), list(H), list(I)).
     :- mode list.map8(pred(in, out, out, out, out, out, out, out, out) is det,
         in, out, out, out, out, out, out, out, out) is det.
     :- mode list.map8(pred(in, out, out, out, out, out, out, out, out) is cc_multi,
         in, out, out, out, out, out, out, out, out) is cc_multi.
     :- mode list.map8(pred(in, out, out, out, out, out, out, out, out) is semidet,
         in, out, out, out, out, out, out, out, out) is semidet.
     :- mode list.map8(pred(in, out, out, out, out, out, out, out, out) is multi,
         in, out, out, out, out, out, out, out, out) is multi.
     :- mode list.map8(pred(in, out, out, out, out, out, out, out, out) is nondet,
         in, out, out, out, out, out, out, out, out) is nondet.
     :- mode list.map8(pred(in, in, in, in, in, in, in, in, in) is semidet,
         in, in, in, in, in, in, in, in, in) is semidet.

         % list.map_corresponding(F, [A1, .. An], [B1, .. Bn]) =
         %   [F(A1, B1), .., F(An, Bn)].
         %
         % An exception is raised if the list arguments differ in length.
         %
     :- func list.map_corresponding(func(A, B) = C, list(A), list(B)) = list(C).
     :- pred list.map_corresponding(pred(A, B, C), list(A), list(B), list(C)).
     :- mode list.map_corresponding(in(pred(in, in, out) is det), in, in, out)
         is det.
     :- mode list.map_corresponding(in(pred(in, in, out) is semidet), in, in, out)
         is semidet.

         % list.map_corresponding3(F, [A1, .. An], [B1, .. Bn], [C1, .. Cn]) =
         %   [F(A1, B1, C1), .., F(An, Bn, Cn)].
         %
         % An exception is raised if the list arguments differ in length.
         %
     :- func list.map_corresponding3(func(A, B, C) = D, list(A), list(B), list(C))
         = list(D).

         % list.filter_map_corresponding/3 is like list.map_corresponding/3
         % except the function argument is semidet and the output list
         % consists of only those applications of the function argument that
         % succeeded.
         %
     :- func list.filter_map_corresponding(func(A, B) = C, list(A), list(B))
         = list(C).
     :- mode list.filter_map_corresponding(func(in, in) = out is semidet, in, in)
         = out is det.

         % list.filter_map_corresponding3/4 is like list.map_corresponding3/4
         % except the function argument is semidet and the output list
         % consists of only those applications of the function argument that
         % succeeded.
         %
     :- func list.filter_map_corresponding3(func(A, B, C) = D,
         list(A), list(B), list(C)) = list(D).
     :- mode list.filter_map_corresponding3(func(in, in, in) = out is semidet,
         in, in, in) = out is det.

         % list.map_corresponding_foldl/6 is like list.map_corresponding except
         % that it has an accumulator threaded through it.
         %
     :- pred list.map_corresponding_foldl(pred(A, B, C, D, D),
         list(A), list(B), list(C), D, D).
     :- mode list.map_corresponding_foldl(pred(in, in, out, in, out) is det,
         in, in, out, in, out) is det.
     :- mode list.map_corresponding_foldl(pred(in, in, out, mdi, muo) is det,
         in, in, out, mdi, muo) is det.
     :- mode list.map_corresponding_foldl(pred(in, in, out, di, uo) is det,
         in, in, out, di, uo) is det.
     :- mode list.map_corresponding_foldl(pred(in, in, out, in, out) is semidet,
         in, in, out, in, out) is semidet.
     :- mode list.map_corresponding_foldl(pred(in, in, out, mdi, muo) is semidet,
         in, in, out, mdi, muo) is semidet.
     :- mode list.map_corresponding_foldl(pred(in, in, out, di, uo) is semidet,
         in, in, out, di, uo) is semidet.

         % Like list.map_corresponding_foldl/6 except that it has two
         % accumulators.
         %
     :- pred list.map_corresponding_foldl2(pred(A, B, C, D, D, E, E),
         list(A), list(B), list(C), D, D, E, E).
     :- mode list.map_corresponding_foldl2(
         pred(in, in, out, in, out, in, out) is det, in, in, out, in, out,
         in, out) is det.
     :- mode list.map_corresponding_foldl2(
         pred(in, in, out, in, out, mdi, muo) is det, in, in, out, in, out,
         mdi, muo) is det.
     :- mode list.map_corresponding_foldl2(
         pred(in, in, out, in, out, di, uo) is det, in, in, out, in, out,
         di, uo) is det.
     :- mode list.map_corresponding_foldl2(
         pred(in, in, out, in, out, in, out) is semidet, in, in, out, in, out,
         in, out) is semidet.
     :- mode list.map_corresponding_foldl2(
         pred(in, in, out, in, out, mdi, muo) is semidet, in, in, out, in, out,
         mdi, muo) is semidet.
     :- mode list.map_corresponding_foldl2(
         pred(in, in, out, in, out, di, uo) is semidet, in, in, out, in, out,
         di, uo) is semidet.

         % Like list.map_corresponding_foldl/6 except that it has three
         % accumulators.
         %
     :- pred list.map_corresponding_foldl3(pred(A, B, C, D, D, E, E, F, F),
         list(A), list(B), list(C), D, D, E, E, F, F).
     :- mode list.map_corresponding_foldl3(
         pred(in, in, out, in, out, in, out, in, out) is det, in, in, out, in, out,
         in, out, in, out) is det.
     :- mode list.map_corresponding_foldl3(
         pred(in, in, out, in, out, in, out, mdi, muo) is det, in, in, out, in, out,
         in, out, mdi, muo) is det.
     :- mode list.map_corresponding_foldl3(
         pred(in, in, out, in, out, in, out, di, uo) is det, in, in, out, in, out,
         in, out, di, uo) is det.
     :- mode list.map_corresponding_foldl3(
         pred(in, in, out, in, out, in, out, in, out) is semidet, in, in, out,
         in, out, in, out, in, out) is semidet.
     :- mode list.map_corresponding_foldl3(
         pred(in, in, out, in, out, in, out, mdi, muo) is semidet, in, in, out,
         in, out, in, out, mdi, muo) is semidet.
     :- mode list.map_corresponding_foldl3(
         pred(in, in, out, in, out, in, out, di, uo) is semidet, in, in, out,
         in, out, in, out, di, uo) is semidet.

         % list.map_corresponding3_foldl/7 is like list.map_corresponding3 except
         % that it has an accumulator threaded through it.
         %
     :- pred list.map_corresponding3_foldl(pred(A, B, C, D, E, E),
         list(A), list(B), list(C), list(D), E, E).
     :- mode list.map_corresponding3_foldl(pred(in, in, in, out, in, out) is det,
         in, in, in, out, in, out) is det.
     :- mode list.map_corresponding3_foldl(pred(in, in, in, out, mdi, muo) is det,
         in, in, in, out, mdi, muo) is det.
     :- mode list.map_corresponding3_foldl(pred(in, in, in, out, di, uo) is det,
         in, in, in, out, di, uo) is det.
     :- mode list.map_corresponding3_foldl(
         pred(in, in, in, out, in, out) is semidet,
         in, in, in, out, in, out) is semidet.
     :- mode list.map_corresponding3_foldl(
         pred(in, in, in, out, mdi, muo) is semidet,
         in, in, in, out, mdi, muo) is semidet.
     :- mode list.map_corresponding3_foldl(
         pred(in, in, in, out, di, uo) is semidet,
         in, in, in, out, di, uo) is semidet.

         % list.foldl(Pred, List, Start, End) calls Pred with each
         % element of List (working left-to-right) and an accumulator
         % (with the initial value of Start), and returns the final
         % value in End.
         %
     :- pred list.foldl(pred(L, A, A), list(L), A, A).
     :- mode list.foldl(pred(in, in, out) is det, in, in, out) is det.
     :- mode list.foldl(pred(in, mdi, muo) is det, in, mdi, muo) is det.
     :- mode list.foldl(pred(in, di, uo) is det, in, di, uo) is det.
     :- mode list.foldl(pred(in, in, out) is semidet, in, in, out) is semidet.
     :- mode list.foldl(pred(in, mdi, muo) is semidet, in, mdi, muo) is semidet.
     :- mode list.foldl(pred(in, di, uo) is semidet, in, di, uo) is semidet.
     :- mode list.foldl(pred(in, in, out) is multi, in, in, out) is multi.
     :- mode list.foldl(pred(in, in, out) is nondet, in, in, out) is nondet.
     :- mode list.foldl(pred(in, mdi, muo) is nondet, in, mdi, muo) is nondet.
     :- mode list.foldl(pred(in, in, out) is cc_multi, in, in, out) is cc_multi.
     :- mode list.foldl(pred(in, di, uo) is cc_multi, in, di, uo) is cc_multi.

     :- func list.foldl(func(L, A) = A, list(L), A) = A.

         % list.foldr(Pred, List, Start, End) calls Pred with each
         % element of List (working right-to-left) and an accumulator
         % (with the initial value of Start), and returns the final
         % value in End.
         %
     :- pred list.foldr(pred(L, A, A), list(L), A, A).
     :- mode list.foldr(pred(in, in, out) is det, in, in, out) is det.
     :- mode list.foldr(pred(in, mdi, muo) is det, in, mdi, muo) is det.
     :- mode list.foldr(pred(in, di, uo) is det, in, di, uo) is det.
     :- mode list.foldr(pred(in, in, out) is semidet, in, in, out) is semidet.
     :- mode list.foldr(pred(in, mdi, muo) is semidet, in, mdi, muo) is semidet.
     :- mode list.foldr(pred(in, di, uo) is semidet, in, di, uo) is semidet.
     :- mode list.foldr(pred(in, in, out) is multi, in, in, out) is multi.
     :- mode list.foldr(pred(in, in, out) is nondet, in, in, out) is nondet.
     :- mode list.foldr(pred(in, mdi, muo) is nondet, in, mdi, muo) is nondet.
     :- mode list.foldr(pred(in, di, uo) is cc_multi, in, di, uo) is cc_multi.
     :- mode list.foldr(pred(in, in, out) is cc_multi, in, in, out) is cc_multi.

     :- func list.foldr(func(L, A) = A, list(L), A) = A.

         % list.foldl2(Pred, List, !Acc1, !Acc2)
         % Does the same job as list.foldl, but with two accumulators.
         % (Although no more expressive than list.foldl, this is often
         % a more convenient format, and a little more efficient).
         %
     :- pred list.foldl2(pred(L, A, A, Z, Z), list(L), A, A, Z, Z).
     :- mode list.foldl2(pred(in, in, out, in, out) is det,
         in, in, out, in, out) is det.
     :- mode list.foldl2(pred(in, in, out, mdi, muo) is det,
         in, in, out, mdi, muo) is det.
     :- mode list.foldl2(pred(in, in, out, di, uo) is det,
         in, in, out, di, uo) is det.
     :- mode list.foldl2(pred(in, di, uo, di, uo) is det,
         in, di, uo, di, uo) is det.
     :- mode list.foldl2(pred(in, in, out, in, out) is semidet,
         in, in, out, in, out) is semidet.
     :- mode list.foldl2(pred(in, in, out, mdi, muo) is semidet,
         in, in, out, mdi, muo) is semidet.
     :- mode list.foldl2(pred(in, in, out, di, uo) is semidet,
         in, in, out, di, uo) is semidet.
     :- mode list.foldl2(pred(in, in, out, in, out) is nondet,
         in, in, out, in, out) is nondet.
     :- mode list.foldl2(pred(in, in, out, mdi, muo) is nondet,
         in, in, out, mdi, muo) is nondet.
     :- mode list.foldl2(pred(in, in, out, in, out) is cc_multi,
         in, in, out, in, out) is cc_multi.
     :- mode list.foldl2(pred(in, in, out, mdi, muo) is cc_multi,
         in, in, out, mdi, muo) is cc_multi.
     :- mode list.foldl2(pred(in, in, out, di, uo) is cc_multi,
         in, in, out, di, uo) is cc_multi.
     :- mode list.foldl2(pred(in, di, uo, di, uo) is cc_multi,
         in, di, uo, di, uo) is cc_multi.

         % list.foldl3(Pred, List, !Acc1, !Acc2, !Acc3)
         % Does the same job as list.foldl, but with three accumulators.
         % (Although no more expressive than list.foldl, this is often
         % a more convenient format, and a little more efficient).
         %
     :- pred list.foldl3(pred(L, A, A, B, B, C, C), list(L),
         A, A, B, B, C, C).
     :- mode list.foldl3(pred(in, in, out, in, out, in, out) is det,
         in, in, out, in, out, in, out) is det.
     :- mode list.foldl3(pred(in, in, out, in, out, mdi, muo) is det,
         in, in, out, in, out, mdi, muo) is det.
     :- mode list.foldl3(pred(in, in, out, in, out, di, uo) is det,
         in, in, out, in, out, di, uo) is det.
     :- mode list.foldl3(pred(in, in, out, in, out, in, out) is semidet,
         in, in, out, in, out, in, out) is semidet.
     :- mode list.foldl3(pred(in, in, out, in, out, mdi, muo) is semidet,
         in, in, out, in, out, mdi, muo) is semidet.
     :- mode list.foldl3(pred(in, in, out, in, out, di, uo) is semidet,
         in, in, out, in, out, di, uo) is semidet.
     :- mode list.foldl3(pred(in, in, out, in, out, in, out) is nondet,
         in, in, out, in, out, in, out) is nondet.
     :- mode list.foldl3(pred(in, in, out, in, out, mdi, muo) is nondet,
         in, in, out, in, out, mdi, muo) is nondet.
     :- mode list.foldl3(pred(in, in, out, in, out, in, out) is cc_multi,
         in, in, out, in, out, in, out) is cc_multi.
     :- mode list.foldl3(pred(in, in, out, in, out, di, uo) is cc_multi,
         in, in, out, in, out, di, uo) is cc_multi.

         % list.foldl4(Pred, List, !Acc1, !Acc2, !Acc3, !Acc4)
         % Does the same job as list.foldl, but with four accumulators.
         % (Although no more expressive than list.foldl, this is often
         % a more convenient format, and a little more efficient).
         %
     :- pred list.foldl4(pred(L, A, A, B, B, C, C, D, D), list(L),
         A, A, B, B, C, C, D, D).
     :- mode list.foldl4(pred(in, in, out, in, out, in, out, in, out) is det,
         in, in, out, in, out, in, out, in, out) is det.
     :- mode list.foldl4(pred(in, in, out, in, out, in, out, mdi, muo) is det,
         in, in, out, in, out, in, out, mdi, muo) is det.
     :- mode list.foldl4(pred(in, in, out, in, out, in, out, di, uo) is det,
         in, in, out, in, out, in, out, di, uo) is det.
     :- mode list.foldl4(pred(in, in, out, in, out, in, out, in, out) is cc_multi,
         in, in, out, in, out, in, out, in, out) is cc_multi.
     :- mode list.foldl4(pred(in, in, out, in, out, in, out, di, uo) is cc_multi,
         in, in, out, in, out, in, out, di, uo) is cc_multi.
     :- mode list.foldl4(pred(in, in, out, in, out, in, out, in, out) is semidet,
         in, in, out, in, out, in, out, in, out) is semidet.
     :- mode list.foldl4(pred(in, in, out, in, out, in, out, mdi, muo) is semidet,
         in, in, out, in, out, in, out, mdi, muo) is semidet.
     :- mode list.foldl4(pred(in, in, out, in, out, in, out, di, uo) is semidet,
         in, in, out, in, out, in, out, di, uo) is semidet.
     :- mode list.foldl4(pred(in, in, out, in, out, in, out, in, out) is nondet,
         in, in, out, in, out, in, out, in, out) is nondet.
     :- mode list.foldl4(pred(in, in, out, in, out, in, out, mdi, muo) is nondet,
         in, in, out, in, out, in, out, mdi, muo) is nondet.

         % list.foldl5(Pred, List, !Acc1, !Acc2, !Acc3, !Acc4, !Acc5)
         % Does the same job as list.foldl, but with five accumulators.
         % (Although no more expressive than list.foldl, this is often
         % a more convenient format, and a little more efficient).
         %
     :- pred list.foldl5(pred(L, A, A, B, B, C, C, D, D, E, E), list(L),
         A, A, B, B, C, C, D, D, E, E).
     :- mode list.foldl5(pred(in, in, out, in, out, in, out, in, out, in, out)
         is det,
         in, in, out, in, out, in, out, in, out, in, out) is det.
     :- mode list.foldl5(pred(in, in, out, in, out, in, out, in, out, mdi, muo)
         is det,
         in, in, out, in, out, in, out, in, out, mdi, muo) is det.
     :- mode list.foldl5(pred(in, in, out, in, out, in, out, in, out, di, uo)
         is det,
         in, in, out, in, out, in, out, in, out, di, uo) is det.
     :- mode list.foldl5(pred(in, in, out, in, out, in, out, in, out, in, out)
         is semidet,
         in, in, out, in, out, in, out, in, out, in, out) is semidet.
     :- mode list.foldl5(pred(in, in, out, in, out, in, out, in, out, mdi, muo)
         is semidet,
         in, in, out, in, out, in, out, in, out, mdi, muo) is semidet.
     :- mode list.foldl5(pred(in, in, out, in, out, in, out, in, out, di, uo)
         is semidet,
         in, in, out, in, out, in, out, in, out, di, uo) is semidet.
     :- mode list.foldl5(pred(in, in, out, in, out, in, out, in, out, in, out)
         is nondet,
         in, in, out, in, out, in, out, in, out, in, out) is nondet.
     :- mode list.foldl5(pred(in, in, out, in, out, in, out, in, out, mdi, muo)
         is nondet,
         in, in, out, in, out, in, out, in, out, mdi, muo) is nondet.
     :- mode list.foldl5(pred(in, in, out, in, out, in, out, in, out, in, out)
         is cc_multi,
         in, in, out, in, out, in, out, in, out, in, out) is cc_multi.
     :- mode list.foldl5(pred(in, in, out, in, out, in, out, in, out, di, uo)
         is cc_multi,
         in, in, out, in, out, in, out, in, out, di, uo) is cc_multi.

         % list.foldl6(Pred, List, !Acc1, !Acc2, !Acc3, !Acc4, !Acc5, !Acc6)
         % Does the same job as list.foldl, but with six accumulators.
         % (Although no more expressive than list.foldl, this is often
         % a more convenient format, and a little more efficient).
         %
     :- pred list.foldl6(pred(L, A, A, B, B, C, C, D, D, E, E, F, F), list(L),
         A, A, B, B, C, C, D, D, E, E, F, F).
     :- mode list.foldl6(pred(in, in, out, in, out, in, out, in, out, in, out,
         in, out) is det,
         in, in, out, in, out, in, out, in, out, in, out, in, out) is det.
     :- mode list.foldl6(pred(in, in, out, in, out, in, out, in, out, in, out,
         mdi, muo) is det,
         in, in, out, in, out, in, out, in, out, in, out, mdi, muo) is det.
     :- mode list.foldl6(pred(in, in, out, in, out, in, out, in, out, in, out,
         di, uo) is det,
         in, in, out, in, out, in, out, in, out, in, out, di, uo) is det.
     :- mode list.foldl6(pred(in, in, out, in, out, in, out, in, out, in, out,
         in, out) is cc_multi,
         in, in, out, in, out, in, out, in, out, in, out, in, out) is cc_multi.
     :- mode list.foldl6(pred(in, in, out, in, out, in, out, in, out, in, out,
         di, uo) is cc_multi,
         in, in, out, in, out, in, out, in, out, in, out, di, uo) is cc_multi.
     :- mode list.foldl6(pred(in, in, out, in, out, in, out, in, out, in, out,
         in, out) is semidet,
         in, in, out, in, out, in, out, in, out, in, out, in, out) is semidet.
     :- mode list.foldl6(pred(in, in, out, in, out, in, out, in, out, in, out,
         mdi, muo) is semidet,
         in, in, out, in, out, in, out, in, out, in, out, mdi, muo) is semidet.
     :- mode list.foldl6(pred(in, in, out, in, out, in, out, in, out, in, out,
         di, uo) is semidet,
         in, in, out, in, out, in, out, in, out, in, out, di, uo) is semidet.
     :- mode list.foldl6(pred(in, in, out, in, out, in, out, in, out, in, out,
         in, out) is nondet,
         in, in, out, in, out, in, out, in, out, in, out, in, out) is nondet.

         % list.foldl_corresponding(F, As, Bs, !Acc):
         % Does the same job as list.foldl, but works on two lists in
         % parallel.  An exception is raised if the list arguments differ
         % in length.
         %
     :- pred list.foldl_corresponding(pred(A, B, C, C), list(A), list(B), C, C).
     :- mode list.foldl_corresponding(pred(in, in, in, out) is det,
         in, in, in, out) is det.
     :- mode list.foldl_corresponding(pred(in, in, mdi, muo) is det,
         in, in, mdi, muo) is det.
     :- mode list.foldl_corresponding(pred(in, in, di, uo) is det,
         in, in, di, uo) is det.
     :- mode list.foldl_corresponding(pred(in, in, in, out) is semidet,
         in, in, in, out) is semidet.
     :- mode list.foldl_corresponding(pred(in, in, mdi, muo) is semidet,
         in, in, mdi, muo) is semidet.
     :- mode list.foldl_corresponding(pred(in, in, di, uo) is semidet,
         in, in, di, uo) is semidet.
     :- mode list.foldl_corresponding(pred(in, in, in, out) is nondet,
         in, in, in, out) is nondet.
     :- mode list.foldl_corresponding(pred(in, in, mdi, muo) is nondet,
         in, in, mdi, muo) is nondet.
     :- mode list.foldl_corresponding(pred(in, in, in, out) is cc_multi,
         in, in, in, out) is cc_multi.
     :- mode list.foldl_corresponding(pred(in, in, di, uo) is cc_multi,
         in, in, di, uo) is cc_multi.

         % list.foldl2_corresponding(F, As, Bs, !Acc1, !Acc2):
         % Does the same job as list.foldl_corresponding, but has two
         % accumulators.
         %
     :- pred list.foldl2_corresponding(pred(A, B, C, C, D, D), list(A), list(B),
         C, C, D, D).
     :- mode list.foldl2_corresponding(pred(in, in, in, out, in, out) is det,
         in, in, in, out, in, out) is det.
     :- mode list.foldl2_corresponding(pred(in, in, in, out, mdi, muo) is det,
         in, in, in, out, mdi, muo) is det.
     :- mode list.foldl2_corresponding(pred(in, in, in, out, di, uo) is det,
         in, in, in, out, di, uo) is det.
     :- mode list.foldl2_corresponding(pred(in, in, in, out, in, out) is semidet,
         in, in, in, out, in, out) is semidet.
     :- mode list.foldl2_corresponding(pred(in, in, in, out, mdi, muo) is semidet,
         in, in, in, out, mdi, muo) is semidet.
     :- mode list.foldl2_corresponding(pred(in, in, in, out, di, uo) is semidet,
         in, in, in, out, di, uo) is semidet.
     :- mode list.foldl2_corresponding(pred(in, in, in, out, in, out) is nondet,
         in, in, in, out, in, out) is nondet.
     :- mode list.foldl2_corresponding(pred(in, in, in, out, mdi, muo) is nondet,
         in, in, in, out, mdi, muo) is nondet.
     :- mode list.foldl2_corresponding(pred(in, in, in, out, in, out) is cc_multi,
         in, in, in, out, in, out) is cc_multi.
     :- mode list.foldl2_corresponding(pred(in, in, in, out, di, uo) is cc_multi,
         in, in, in, out, di, uo) is cc_multi.

         % list.foldl3_corresponding(F, As, Bs, !Acc1, !Acc2, !Acc3):
         % Does the same job as list.foldl_corresponding, but has three
         % accumulators.
         %
     :- pred list.foldl3_corresponding(pred(A, B, C, C, D, D, E, E),
         list(A), list(B), C, C, D, D, E, E).
     :- mode list.foldl3_corresponding(
         pred(in, in, in, out, in, out, in, out) is det, in, in, in, out,
         in, out, in, out) is det.
     :- mode list.foldl3_corresponding(
         pred(in, in, in, out, in, out, mdi, muo) is det, in, in, in, out,
         in, out, mdi, muo) is det.
     :- mode list.foldl3_corresponding(
         pred(in, in, in, out, in, out, di, uo) is det, in, in, in, out,
         in, out, di, uo) is det.
     :- mode list.foldl3_corresponding(
         pred(in, in, in, out, in, out, in, out) is semidet, in, in, in, out,
         in, out, in, out) is semidet.
     :- mode list.foldl3_corresponding(
         pred(in, in, in, out, in, out, mdi, muo) is semidet, in, in, in, out,
         in, out, mdi, muo) is semidet.
     :- mode list.foldl3_corresponding(
         pred(in, in, in, out, in, out, di, uo) is semidet, in, in, in, out,
         in, out, di, uo) is semidet.

         % list.foldl_corresponding3(P, As, Bs, Cs, !Acc):
         % Like list.foldl_corresponding but folds over three corresponding
         % lists.
         %
     :- pred list.foldl_corresponding3(pred(A, B, C, D, D),
         list(A), list(B), list(C), D, D).
     :- mode list.foldl_corresponding3(pred(in, in, in, in, out) is det,
         in, in, in, in, out) is det.
     :- mode list.foldl_corresponding3(pred(in, in, in, mdi, muo) is det,
         in, in, in, mdi, muo) is det.
     :- mode list.foldl_corresponding3(pred(in, in, in, di, uo) is det,
         in, in, in, di, uo) is det.
     :- mode list.foldl_corresponding3(pred(in, in, in, in, out) is semidet,
         in, in, in, in, out) is semidet.
     :- mode list.foldl_corresponding3(pred(in, in, in, mdi, muo) is semidet,
         in, in, in, mdi, muo) is semidet.
     :- mode list.foldl_corresponding3(pred(in, in, in, di, uo) is semidet,
         in, in, in, di, uo) is semidet.

         % list.foldl2_corresponding3(P, As, Bs, Cs, !Acc1, !Acc2):
         % like list.foldl_corresponding3 but with two accumulators.
         %
     :- pred list.foldl2_corresponding3(pred(A, B, C, D, D, E, E),
         list(A), list(B), list(C), D, D, E, E).
     :- mode list.foldl2_corresponding3(pred(in, in, in, in, out, in, out) is det,
         in, in, in, in, out, in, out) is det.
     :- mode list.foldl2_corresponding3(pred(in, in, in, in, out, di, uo) is det,
         in, in, in, in, out, di, uo) is det.
     :- mode list.foldl2_corresponding3(
         pred(in, in, in, in, out, in, out) is semidet,
         in, in, in, in, out, in, out) is semidet.

         % list.foldl3_corresponding3(P, As, Bs, Cs, !Acc1, !Acc2, !Acc3):
         % like list.foldl_corresponding3 but with three accumulators.
         %
     :- pred list.foldl3_corresponding3(pred(A, B, C, D, D, E, E, F, F),
         list(A), list(B), list(C), D, D, E, E, F, F).
     :- mode list.foldl3_corresponding3(
         pred(in, in, in, in, out, in, out, in, out) is det,
         in, in, in, in, out, in, out, in, out) is det.
     :- mode list.foldl3_corresponding3(
         pred(in, in, in, in, out, in, out, di, uo) is det,
         in, in, in, in, out, in, out, di, uo) is det.
     :- mode list.foldl3_corresponding3(
         pred(in, in, in, in, out, in, out, in, out) is semidet,
         in, in, in, in, out, in, out, in, out) is semidet.

         % list.foldl4_corresponding3(P, As, Bs, Cs, !Acc1, !Acc2, !Acc3, !Acc4):
         % like list.foldl_corresponding3 but with four accumulators.
         %
     :- pred list.foldl4_corresponding3(pred(A, B, C, D, D, E, E, F, F, G, G),
         list(A), list(B), list(C), D, D, E, E, F, F, G, G).
     :- mode list.foldl4_corresponding3(
         pred(in, in, in, in, out, in, out, in, out, in, out) is det,
         in, in, in, in, out, in, out, in, out, in, out) is det.
     :- mode list.foldl4_corresponding3(
         pred(in, in, in, in, out, in, out, in, out, di, uo) is det,
         in, in, in, in, out, in, out, in, out, di, uo) is det.
     :- mode list.foldl4_corresponding3(
         pred(in, in, in, in, out, in, out, in, out, in, out) is semidet,
         in, in, in, in, out, in, out, in, out, in, out) is semidet.

         % list.map_foldl(Pred, InList, OutList, Start, End) calls Pred
         % with an accumulator (with the initial value of Start) on
         % each element of InList (working left-to-right) to transform
         % InList into OutList.  The final value of the accumulator is
         % returned in End.
         %
     :- pred list.map_foldl(pred(L, M, A, A), list(L), list(M), A, A).
     :- mode list.map_foldl(pred(in, out, di, uo) is det, in, out, di, uo)
         is det.
     :- mode list.map_foldl(pred(in, out, in, out) is det, in, out, in, out)
         is det.
     :- mode list.map_foldl(pred(in, out, mdi, muo) is det, in, out, mdi, muo)
         is det.
     :- mode list.map_foldl(pred(in, out, in, out) is semidet, in, out, in, out)
         is semidet.
     :- mode list.map_foldl(pred(in, out, mdi, muo) is semidet, in, out, mdi, muo)
         is semidet.
     :- mode list.map_foldl(pred(in, out, di, uo) is semidet, in, out, di, uo)
         is semidet.
     :- mode list.map_foldl(pred(in, in, di, uo) is semidet, in, in, di, uo)
         is semidet.
     :- mode list.map_foldl(pred(in, out, in, out) is nondet, in, out, in, out)
         is nondet.
     :- mode list.map_foldl(pred(in, out, mdi, muo) is nondet, in, out, mdi, muo)
         is nondet.
     :- mode list.map_foldl(pred(in, out, in, out) is cc_multi, in, out, in, out)
         is cc_multi.
     :- mode list.map_foldl(pred(in, out, mdi, muo) is cc_multi, in, out, mdi, muo)
         is cc_multi.
     :- mode list.map_foldl(pred(in, out, di, uo) is cc_multi, in, out, di, uo)
         is cc_multi.

         % Same as list.map_foldl, but with two accumulators.
         %
     :- pred list.map_foldl2(pred(L, M, A, A, B, B), list(L), list(M), A, A, B, B).
     :- mode list.map_foldl2(pred(in, out, in, out, in, out) is det,
         in, out, in, out, in, out) is det.
     :- mode list.map_foldl2(pred(in, out, in, out, mdi, muo) is det,
         in, out, in, out, mdi, muo) is det.
     :- mode list.map_foldl2(pred(in, out, in, out, di, uo) is det,
         in, out, in, out, di, uo) is det.
     :- mode list.map_foldl2(pred(in, out, in, out, in, out) is semidet,
         in, out, in, out, in, out) is semidet.
     :- mode list.map_foldl2(pred(in, out, in, out, mdi, muo) is semidet,
         in, out, in, out, mdi, muo) is semidet.
     :- mode list.map_foldl2(pred(in, out, in, out, di, uo) is semidet,
         in, out, in, out, di, uo) is semidet.
     :- mode list.map_foldl2(pred(in, in, in, out, di, uo) is semidet,
         in, in, in, out, di, uo) is semidet.
     :- mode list.map_foldl2(pred(in, out, in, out, in, out) is cc_multi,
         in, out, in, out, in, out) is cc_multi.
     :- mode list.map_foldl2(pred(in, out, in, out, mdi, muo) is cc_multi,
         in, out, in, out, mdi, muo) is cc_multi.
     :- mode list.map_foldl2(pred(in, out, in, out, di, uo) is cc_multi,
         in, out, in, out, di, uo) is cc_multi.
     :- mode list.map_foldl2(pred(in, out, in, out, in, out) is nondet,
         in, out, in, out, in, out) is nondet.

         % Same as list.map_foldl, but with three accumulators.
         %
     :- pred list.map_foldl3(pred(L, M, A, A, B, B, C, C), list(L), list(M),
         A, A, B, B, C, C).
     :- mode list.map_foldl3(pred(in, out, in, out, in, out, di, uo) is det,
         in, out, in, out, in, out, di, uo) is det.
     :- mode list.map_foldl3(pred(in, out, in, out, in, out, in, out) is det,
         in, out, in, out, in, out, in, out) is det.
     :- mode list.map_foldl3(pred(in, out, in, out, in, out, di, uo) is cc_multi,
         in, out, in, out, in, out, di, uo) is cc_multi.
     :- mode list.map_foldl3(pred(in, out, in, out, in, out, in, out) is cc_multi,
         in, out, in, out, in, out, in, out) is cc_multi.
     :- mode list.map_foldl3(pred(in, out, in, out, in, out, in, out) is semidet,
         in, out, in, out, in, out, in, out) is semidet.
     :- mode list.map_foldl3(pred(in, out, in, out, in, out, in, out) is nondet,
         in, out, in, out, in, out, in, out) is nondet.

         % Same as list.map_foldl, but with four accumulators.
         %
     :- pred list.map_foldl4(pred(L, M, A, A, B, B, C, C, D, D), list(L), list(M),
         A, A, B, B, C, C, D, D).
     :- mode list.map_foldl4(pred(in, out, in, out, in, out, in, out, di, uo)
         is det,
         in, out, in, out, in, out, in, out, di, uo) is det.
     :- mode list.map_foldl4(pred(in, out, in, out, in, out, in, out, in, out)
         is det,
         in, out, in, out, in, out, in, out, in, out) is det.
     :- mode list.map_foldl4(pred(in, out, in, out, in, out, in, out, di, uo)
         is cc_multi,
         in, out, in, out, in, out, in, out, di, uo) is cc_multi.
     :- mode list.map_foldl4(pred(in, out, in, out, in, out, in, out, in, out)
         is cc_multi,
         in, out, in, out, in, out, in, out, in, out) is cc_multi.
     :- mode list.map_foldl4(pred(in, out, in, out, in, out, in, out, in, out)
         is semidet,
         in, out, in, out, in, out, in, out, in, out) is semidet.
     :- mode list.map_foldl4(pred(in, out, in, out, in, out, in, out, in, out)
         is nondet,
         in, out, in, out, in, out, in, out, in, out) is nondet.

         % Same as list.map_foldl, but with five accumulators.
         %
     :- pred list.map_foldl5(pred(L, M, A, A, B, B, C, C, D, D, E, E),
         list(L), list(M), A, A, B, B, C, C, D, D, E, E).
     :- mode list.map_foldl5(pred(in, out, in, out, in, out, in, out, in, out,
         di, uo) is det,
         in, out, in, out, in, out, in, out, in, out, di, uo) is det.
     :- mode list.map_foldl5(pred(in, out, in, out, in, out, in, out, in, out,
         in, out) is det,
         in, out, in, out, in, out, in, out, in, out, in, out) is det.
     :- mode list.map_foldl5(pred(in, out, in, out, in, out, in, out, in, out,
         di, uo) is cc_multi,
         in, out, in, out, in, out, in, out, in, out, di, uo) is cc_multi.
     :- mode list.map_foldl5(pred(in, out, in, out, in, out, in, out, in, out,
         in, out) is cc_multi,
         in, out, in, out, in, out, in, out, in, out, in, out) is cc_multi.
     :- mode list.map_foldl5(pred(in, out, in, out, in, out, in, out, in, out,
         in, out) is semidet,
         in, out, in, out, in, out, in, out, in, out, in, out) is semidet.
     :- mode list.map_foldl5(pred(in, out, in, out, in, out, in, out, in, out,
         in, out) is nondet,
         in, out, in, out, in, out, in, out, in, out, in, out) is nondet.

         % Same as list.map_foldl, but with six accumulators.
         %
     :- pred list.map_foldl6(pred(L, M, A, A, B, B, C, C, D, D, E, E, F, F),
         list(L), list(M), A, A, B, B, C, C, D, D, E, E, F, F).
     :- mode list.map_foldl6(pred(in, out, in, out, in, out, in, out, in, out,
         in, out, di, uo) is det,
         in, out, in, out, in, out, in, out, in, out, in, out, di, uo) is det.
     :- mode list.map_foldl6(pred(in, out, in, out, in, out, in, out, in, out,
         in, out, in, out) is det,
         in, out, in, out, in, out, in, out, in, out, in, out, in, out) is det.
     :- mode list.map_foldl6(pred(in, out, in, out, in, out, in, out, in, out,
         in, out, di, uo) is cc_multi,
         in, out, in, out, in, out, in, out, in, out, in, out, di, uo)
         is cc_multi.
     :- mode list.map_foldl6(pred(in, out, in, out, in, out, in, out, in, out,
         in, out, in, out) is cc_multi,
         in, out, in, out, in, out, in, out, in, out, in, out, in, out)
         is cc_multi.
     :- mode list.map_foldl6(pred(in, out, in, out, in, out, in, out, in, out,
         in, out, in, out) is semidet,
         in, out, in, out, in, out, in, out, in, out, in, out, in, out)
         is semidet.
     :- mode list.map_foldl6(pred(in, out, in, out, in, out, in, out, in, out,
         in, out, in, out) is nondet,
         in, out, in, out, in, out, in, out, in, out, in, out, in, out)
         is nondet.

         % Same as list.map_foldl, but with two mapped outputs.
         %
     :- pred list.map2_foldl(pred(L, M, N, A, A), list(L), list(M), list(N),
         A, A).
     :- mode list.map2_foldl(pred(in, out, out, in, out) is det, in, out, out,
         in, out) is det.
     :- mode list.map2_foldl(pred(in, out, out, mdi, muo) is det, in, out, out,
         mdi, muo) is det.
     :- mode list.map2_foldl(pred(in, out, out, di, uo) is det, in, out, out,
         di, uo) is det.
     :- mode list.map2_foldl(pred(in, out, out, in, out) is semidet, in, out, out,
         in, out) is semidet.
     :- mode list.map2_foldl(pred(in, out, out, mdi, muo) is semidet, in, out, out,
         mdi, muo) is semidet.
     :- mode list.map2_foldl(pred(in, out, out, di, uo) is semidet, in, out, out,
         di, uo) is semidet.
     :- mode list.map2_foldl(pred(in, out, out, in, out) is nondet, in, out, out,
         in, out) is nondet.
     :- mode list.map2_foldl(pred(in, out, out, mdi, muo) is nondet, in, out, out,
         mdi, muo) is nondet.
     :- mode list.map2_foldl(pred(in, out, out, in, out) is cc_multi, in, out, out,
         in, out) is cc_multi.
     :- mode list.map2_foldl(pred(in, out, out, di, uo) is cc_multi, in, out, out,
         di, uo) is cc_multi.

         % Same as list.map_foldl, but with two mapped outputs and two
         % accumulators.
         %
     :- pred list.map2_foldl2(pred(L, M, N, A, A, B, B), list(L), list(M), list(N),
         A, A, B, B).
     :- mode list.map2_foldl2(pred(in, out, out, in, out, di, uo) is det,
         in, out, out, in, out, di, uo) is det.
     :- mode list.map2_foldl2(pred(in, out, out, in, out, in, out) is det,
         in, out, out, in, out, in, out) is det.
     :- mode list.map2_foldl2(pred(in, out, out, in, out, di, uo) is cc_multi,
         in, out, out, in, out, di, uo) is cc_multi.
     :- mode list.map2_foldl2(pred(in, out, out, in, out, in, out) is cc_multi,
         in, out, out, in, out, in, out) is cc_multi.
     :- mode list.map2_foldl2(pred(in, out, out, in, out, in, out) is semidet,
         in, out, out, in, out, in, out) is semidet.
     :- mode list.map2_foldl2(pred(in, out, out, in, out, in, out) is nondet,
         in, out, out, in, out, in, out) is nondet.

         % Same as list.map_foldl, but with two mapped outputs and three
         % accumulators.
         %
     :- pred list.map2_foldl3(pred(L, M, N, A, A, B, B, C, C),
         list(L), list(M), list(N), A, A, B, B, C, C).
     :- mode list.map2_foldl3(
         pred(in, out, out, in, out, in, out, in, out) is det,
         in, out, out, in, out, in, out, in, out) is det.
     :- mode list.map2_foldl3(
         pred(in, out, out, in, out, in, out, di, uo) is det,
         in, out, out, in, out, in, out, di, uo) is det.
     :- mode list.map2_foldl3(
         pred(in, out, out, in, out, in, out, in, out) is cc_multi,
         in, out, out, in, out, in, out, in, out) is cc_multi.
     :- mode list.map2_foldl3(
         pred(in, out, out, in, out, in, out, di, uo) is cc_multi,
         in, out, out, in, out, in, out, di, uo) is cc_multi.
     :- mode list.map2_foldl3(
         pred(in, out, out, in, out, in, out, in, out) is semidet,
         in, out, out, in, out, in, out, in, out) is semidet.
     :- mode list.map2_foldl3(
         pred(in, out, out, in, out, in, out, in, out) is nondet,
         in, out, out, in, out, in, out, in, out) is nondet.

         % Same as list.map_foldl, but with two mapped outputs and four
         % accumulators.
         %
     :- pred list.map2_foldl4(pred(L, M, N, A, A, B, B, C, C, D, D),
         list(L), list(M), list(N), A, A, B, B, C, C, D, D).
     :- mode list.map2_foldl4(
         pred(in, out, out, in, out, in, out, in, out, in, out) is det,
         in, out, out, in, out, in, out, in, out, in, out) is det.
     :- mode list.map2_foldl4(
         pred(in, out, out, in, out, in, out, in, out, di, uo) is det,
         in, out, out, in, out, in, out, in, out, di, uo) is det.
     :- mode list.map2_foldl4(
         pred(in, out, out, in, out, in, out, in, out, in, out) is cc_multi,
         in, out, out, in, out, in, out, in, out, in, out) is cc_multi.
     :- mode list.map2_foldl4(
         pred(in, out, out, in, out, in, out, in, out, di, uo) is cc_multi,
         in, out, out, in, out, in, out, in, out, di, uo) is cc_multi.
     :- mode list.map2_foldl4(
         pred(in, out, out, in, out, in, out, in, out, in, out) is semidet,
         in, out, out, in, out, in, out, in, out, in, out) is semidet.
     :- mode list.map2_foldl4(
         pred(in, out, out, in, out, in, out, in, out, in, out) is nondet,
         in, out, out, in, out, in, out, in, out, in, out) is nondet.

         % Same as list.map_foldl, but with three mapped outputs.
         %
     :- pred list.map3_foldl(pred(L, M, N, O, A, A), list(L), list(M), list(N),
         list(O), A, A).
     :- mode list.map3_foldl(pred(in, out, out, out, in, out) is det, in, out, out,
         out, in, out) is det.
     :- mode list.map3_foldl(pred(in, out, out, out, mdi, muo) is det, in, out, out,
         out, mdi, muo) is det.
     :- mode list.map3_foldl(pred(in, out, out, out, di, uo) is det, in, out, out,
         out, di, uo) is det.
     :- mode list.map3_foldl(pred(in, out, out, out, in, out) is semidet, in, out,
         out, out, in, out) is semidet.
     :- mode list.map3_foldl(pred(in, out, out, out, mdi, muo) is semidet, in, out,
         out, out, mdi, muo) is semidet.
     :- mode list.map3_foldl(pred(in, out, out, out, di, uo) is semidet, in, out,
         out, out, di, uo) is semidet.
     :- mode list.map3_foldl(pred(in, out, out, out, in, out) is nondet, in, out,
         out, out, in, out) is nondet.
     :- mode list.map3_foldl(pred(in, out, out, out, mdi, muo) is nondet, in, out,
         out, out, mdi, muo) is nondet.
     :- mode list.map3_foldl(pred(in, out, out, out, in, out) is cc_multi, in, out,
         out, out, in, out) is cc_multi.
     :- mode list.map3_foldl(pred(in, out, out, out, di, uo) is cc_multi, in, out,
         out, out, di, uo) is cc_multi.

         % Same as list.map_foldl, but with three mapped outputs and two
         % accumulators.
         %
     :- pred list.map3_foldl2(pred(L, M, N, O, A, A, B, B), list(L),
         list(M), list(N), list(O), A, A, B, B).
     :- mode list.map3_foldl2(pred(in, out, out, out, in, out, di, uo) is det,
         in, out, out, out, in, out, di, uo) is det.
     :- mode list.map3_foldl2(pred(in, out, out, out, in, out, in, out) is det,
         in, out, out, out, in, out, in, out) is det.
     :- mode list.map3_foldl2(pred(in, out, out, out, in, out, di, uo) is cc_multi,
         in, out, out, out, in, out, di, uo) is cc_multi.
     :- mode list.map3_foldl2(pred(in, out, out, out, in, out, in, out) is cc_multi,
         in, out, out, out, in, out, in, out) is cc_multi.
     :- mode list.map3_foldl2(pred(in, out, out, out, in, out, in, out) is semidet,
         in, out, out, out, in, out, in, out) is semidet.
     :- mode list.map3_foldl2(pred(in, out, out, out, in, out, in, out) is nondet,
         in, out, out, out, in, out, in, out) is nondet.

         % Same as list.map_foldl, but with four mapped outputs.
         %
     :- pred list.map4_foldl(pred(L, M, N, O, P, A, A), list(L), list(M), list(N),
         list(O), list(P), A, A).
     :- mode list.map4_foldl(pred(in, out, out, out, out, in, out) is det,
         in, out, out, out, out, in, out) is det.
     :- mode list.map4_foldl(pred(in, out, out, out, out, mdi, muo) is det,
         in, out, out, out, out, mdi, muo) is det.
     :- mode list.map4_foldl(pred(in, out, out, out, out, di, uo) is det,
         in, out, out, out, out, di, uo) is det.
     :- mode list.map4_foldl(pred(in, out, out, out, out, in, out) is semidet,
         in, out, out, out, out, in, out) is semidet.
     :- mode list.map4_foldl(pred(in, out, out, out, out, mdi, muo) is semidet,
         in, out, out, out, out, mdi, muo) is semidet.
     :- mode list.map4_foldl(pred(in, out, out, out, out, di, uo) is semidet,
         in, out, out, out, out, di, uo) is semidet.
     :- mode list.map4_foldl(pred(in, out, out, out, out, in, out) is nondet,
         in, out, out, out, out, in, out) is nondet.
     :- mode list.map4_foldl(pred(in, out, out, out, out, mdi, muo) is nondet,
         in, out, out, out, out, mdi, muo) is nondet.
     :- mode list.map4_foldl(pred(in, out, out, out, out, in, out) is cc_multi,
         in, out, out, out, out, in, out) is cc_multi.
     :- mode list.map4_foldl(pred(in, out, out, out, out, di, uo) is cc_multi,
         in, out, out, out, out, di, uo) is cc_multi.

         % list.filter_map_foldl(Transformer, List, TrueList, Start, End):
         % Takes a predicate with one input argument, one output argument and an
         % accumulator. It is called with each element of List. If a call succeeds,
         % then the output is included in TrueList and the accumulator is updated.
         %
     :- pred list.filter_map_foldl(pred(X, Y, A, A)::in(pred(in, out, in, out)
         is semidet), list(X)::in, list(Y)::out, A::in, A::out) is det.

         % list.all_true(Pred, List) takes a closure with one input argument.
         % If Pred succeeds for every member of List, all_true succeeds.
         % If Pred fails for any member of List, all_true fails.
         %
     :- pred list.all_true(pred(X)::in(pred(in) is semidet), list(X)::in)
         is semidet.

         % list.all_false(Pred, List) takes a closure with one input argument.
         % If Pred fails for every member of List, all_false succeeds.
         % If Pred succeeds for any member of List, all_false fails.
         %
     :- pred list.all_false(pred(X)::in(pred(in) is semidet), list(X)::in)
         is semidet.

         % list.find_first_match(Pred, List, FirstMatch) takes a closure with one
         % input argument. It returns the element X of the list (if any) for which
         % Pred(X) is true.
         %
     :- pred list.find_first_match(pred(X)::in(pred(in) is semidet), list(X)::in,
         X::out) is semidet.

         % list.filter(Pred, List, TrueList) takes a closure with one
         % input argument and for each member X of List, calls the closure.
         % X is included in TrueList iff Pred(X) is true.
         %
     :- pred list.filter(pred(X)::in(pred(in) is semidet), list(X)::in,
         list(X)::out) is det.
     :- func list.filter(pred(X)::in(pred(in) is semidet), list(X)::in)
         = (list(X)::out) is det.

         % list.negated_filter(Pred, List, FalseList) takes a closure with one
         % input argument and for each member of List `X', calls the closure.
         % X is included in FalseList iff Pred(X) is true.
         %
     :- pred list.negated_filter(pred(X)::in(pred(in) is semidet), list(X)::in,
         list(X)::out) is det.
     :- func list.negated_filter(pred(X)::in(pred(in) is semidet), list(X)::in)
         = (list(X)::out) is det.

         % list.filter(Pred, List, TrueList, FalseList) takes a closure with one
         % input argument and for each member X of List, calls the closure.
         % X is included in TrueList iff Pred(X) is true.
         % X is included in FalseList iff Pred(X) is true.
         %
     :- pred list.filter(pred(X)::in(pred(in) is semidet), list(X)::in,
         list(X)::out, list(X)::out) is det.

         % list.filter_map(Transformer, List, TrueList) takes a predicate
         % with one input argument and one output argument. It is called
         % with each element of List. If a call succeeds, then the output is
         % included in TrueList.
         %
     :- pred list.filter_map(pred(X, Y)::in(pred(in, out) is semidet),
         list(X)::in, list(Y)::out) is det.

     :- func list.filter_map(func(X) = Y, list(X)) = list(Y).
     :- mode list.filter_map(func(in) = out is semidet, in) = out is det.

         % list.filter_map(Transformer, List, TrueList, FalseList) takes
         % a predicate with one input argument and one output argument.
         % It is called with each element of List. If a call succeeds,
         % then the output is included in TrueList; otherwise, the failing
         % input is included in FalseList.
         %
     :- pred list.filter_map(pred(X, Y)::in(pred(in, out) is semidet),
         list(X)::in, list(Y)::out, list(X)::out) is det.

         % Same as list.filter_map/3 except that it only returns the first
         % match:
         %   find_first_map(X, Y, Z) <=> list.filter_map(X, Y, [Z | _])
         %
     :- pred list.find_first_map(pred(X, Y)::in(pred(in, out) is semidet),
         list(X)::in, Y::out) is semidet.

         % Same as list.find_first_map, except with two outputs.
         %
     :- pred list.find_first_map2(pred(X, A, B)::in(pred(in, out, out) is semidet),
         list(X)::in, A::out, B::out) is semidet.

         % Same as list.find_first_map, except with three outputs.
         %
     :- pred list.find_first_map3(
         pred(X, A, B, C)::in(pred(in, out, out, out) is semidet),
         list(X)::in, A::out, B::out, C::out) is semidet.

         % find_index_of_match(Match, List, Index0, Index)
         %
         % Find the index of an item in the list for which Match is true where the
         % first element in the list has the index Index0.
         %
     :- pred list.find_index_of_match(pred(T), list(T), int, int).
     :- mode list.find_index_of_match(pred(in) is semidet, in, in, out) is semidet.

         % list.takewhile(Predicate, List, UptoList, AfterList) takes a
         % closure with one input argument, and calls it on successive members
         % of List as long as the calls succeed. The elements for which
         % the call succeeds are placed in UptoList and the first element for
         % which the call fails, and all the remaining elements of List are
         % placed in AfterList.
         %
     :- pred list.takewhile(pred(T)::in(pred(in) is semidet), list(T)::in,
         list(T)::out, list(T)::out) is det.

     %--------------------------------------------------%

         % list.sort(Compare, Unsorted, Sorted) is true iff Sorted is a
         % list containing the same elements as Unsorted, where Sorted is
         % sorted with respect to the ordering defined by the predicate
         % term Compare, and the elements that are equivalent in this ordering
         % appear in the same sequence in Sorted as they do in Unsorted
         % (that is, the sort is stable).
         %
     :- pred list.sort(comparison_pred(X)::in(comparison_pred), list(X)::in,
         list(X)::out) is det.
     :- func list.sort(comparison_func(X), list(X)) = list(X).

         % list.sort_and_remove_dups(Compare, Unsorted, Sorted) is true iff
         % Sorted is a list containing the same elements as Unsorted, where
         % Sorted is sorted with respect to the ordering defined by the
         % predicate term Compare, except that if two elements in Unsorted
         % are equivalent with respect to this ordering only the one which
         % occurs first will be in Sorted.
         %
     :- pred list.sort_and_remove_dups(comparison_pred(X)::in(comparison_pred),
         list(X)::in, list(X)::out) is det.

         % list.remove_adjacent_dups(P, L0, L) is true iff L is the result
         % of replacing every sequence of elements in L0 which are equivalent
         % with respect to the ordering, with the first occurrence in L0 of
         % such an element.
         %
     :- pred list.remove_adjacent_dups(comparison_pred(X)::in(comparison_pred),
         list(X)::in, list(X)::out) is det.

         % list.merge(Compare, As, Bs, Sorted) is true iff, assuming As and
         % Bs are sorted with respect to the ordering defined by Compare,
         % Sorted is a list containing the elements of As and Bs which is
         % also sorted.  For elements which are equivalent in the ordering,
         % if they come from the same list then they appear in the same
         % sequence in Sorted as they do in that list, otherwise the elements
         % from As appear before the elements from Bs.
         %
     :- pred list.merge(comparison_pred(X)::in(comparison_pred),
         list(X)::in, list(X)::in, list(X)::out) is det.

     :- func list.merge(comparison_func(X), list(X), list(X)) = list(X).

         % list.merge_and_remove_dups(P, As, Bs, Sorted) is true iff, assuming
         % As and Bs are sorted with respect to the ordering defined by
         % Compare and neither contains any duplicates, Sorted is a list
         % containing the elements of As and Bs which is also sorted and
         % contains no duplicates.  If an element from As is duplicated in
         % Bs (that is, they are equivalent in the ordering), then the element
         % from As is the one that appears in Sorted.
         %
     :- pred list.merge_and_remove_dups(comparison_pred(X)::in(comparison_pred),
         list(X)::in, list(X)::in, list(X)::out) is det.

     :- func list.merge_and_remove_dups(comparison_func(X), list(X), list(X))
         = list(X).

     %--------------------------------------------------%

         % list.series(X, OK, Succ) = [X0, X1, ..., Xn]
         %   where X0 = X and successive elements Xj, Xk
         %   are computed as Xk = Succ(Xj).  The series
         %   terminates as soon as an element Xi is
         %   generated such that OK(Xi) fails; Xi is not
         %   included in the output.
         %
     :- func list.series(T, pred(T), func(T) = T) = list(T).
     :- mode list.series(in, pred(in) is semidet, func(in) = out is det) = out
         is det.

     %--------------------------------------------------%

         % Lo `..` Hi = [Lo, Lo + 1, ..., Hi] if Lo =< Hi
         %            =                    [] otherwise
         %
     :- func int `..` int = list(int).

     %--------------------------------------------------%

     :- func list.head(list(T)) = T is semidet.

     :- func list.tail(list(T)) = list(T) is semidet.

         % list.det_head(List) returns the first element of List,
         % calling error/1 if List is empty.
         %
     :- func list.det_head(list(T)) = T.

         % list.det_tail(List) returns the tail of List,
         % calling error/1 if List is empty.
         %
     :- func list.det_tail(list(T)) = list(T).

     %--------------------------------------------------%

         % Convert a list to a pretty_printer.doc for formatting.
         %
     :- func list_to_doc(list(T)) = pretty_printer.doc.

     %--------------------------------------------------%
     %--------------------------------------------------%


File: mercury_library.info,  Node: map,  Next: math,  Prev: list,  Up: Top

41 map
******

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et
     %--------------------------------------------------%
     % Copyright (C) 1993-2011 The University of Melbourne.
     % This file may only be copied under the terms of the GNU Library General
     % Public License - see the file COPYING.LIB in the Mercury distribution.
     %--------------------------------------------------%
     %
     % File: map.m.
     % Main author: fjh, conway.
     % Stability: high.
     %
     % This file provides the 'map' ADT.
     % A map (also known as a dictionary or an associative array) is a collection
     % of (Key, Data) pairs which allows you to look up any Data item given the
     % Key.
     %
     % The implementation is using balanced binary trees, as provided by
     % tree234.m.  Virtually all the predicates in this file just
     % forward the work to the corresponding predicate in tree234.m.
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module map.
     :- interface.

     :- import_module assoc_list.
     :- import_module list.
     :- import_module set.

     %--------------------------------------------------%

     :- type map(_K, _V).

     %--------------------------------------------------%

         % Initialize an empty map.
         %
     :- pred map.init(map(_, _)::uo) is det.
     :- func map.init = (map(K, V)::uo) is det.

         % Initialize a map containing the given key-value pair.
         %
     :- func map.singleton(K, V) = map(K, V).

         % Check whether a map is empty.
         %
     :- pred map.is_empty(map(_, _)::in) is semidet.

         % Check whether map contains key
         %
     :- pred map.contains(map(K, _V)::in, K::in) is semidet.

     :- pred map.member(map(K, V)::in, K::out, V::out) is nondet.

         % Search map for key.
         %
     :- func map.search(map(K, V), K) = V is semidet.
     :- pred map.search(map(K, V)::in, K::in, V::out) is semidet.

         % Search map for key, but abort if search fails.
         %
     :- func map.lookup(map(K, V), K) = V.
     :- pred map.lookup(map(K, V)::in, K::in, V::out) is det.

         % Search for a key-value pair using the key.  If there is no entry
         % for the given key, returns the pair for the next lower key instead.
         % Fails if there is no key with the given or lower value.
         %
     :- pred map.lower_bound_search(map(K, V)::in, K::in, K::out, V::out)
         is semidet.

         % Search for a key-value pair using the key.  If there is no entry
         % for the given key, returns the pair for the next lower key instead.
         % Aborts if there is no key with the given or lower value.
         %
     :- pred map.lower_bound_lookup(map(K, V)::in, K::in, K::out, V::out) is det.

         % Search for a key-value pair using the key.  If there is no entry
         % for the given key, returns the pair for the next higher key instead.
         % Fails if there is no key with the given or higher value.
         %
     :- pred map.upper_bound_search(map(K, V)::in, K::in, K::out, V::out)
         is semidet.

         % Search for a key-value pair using the key.  If there is no entry
         % for the given key, returns the pair for the next higher key instead.
         % Aborts if there is no key with the given or higher value.
         %
     :- pred map.upper_bound_lookup(map(K, V)::in, K::in, K::out, V::out) is det.

         % Return the largest key in the map, if there is one.
         %
     :- func map.max_key(map(K,V)) = K is semidet.

         % Return the smallest key in the map, if there is one.
         %
     :- func map.min_key(map(K,V)) = K is semidet.

         % Search map for data.
         %
     :- pred map.inverse_search(map(K, V)::in, V::in, K::out) is nondet.

         % Insert a new key and corresponding value into a map.
         % Fail if the key already exists.
         %
     :- func map.insert(map(K, V), K, V) = map(K, V) is semidet.
     :- pred map.insert(K::in, V::in, map(K, V)::in, map(K, V)::out) is semidet.

         % Insert a new key and corresponding value into a map.
         % Abort if the key already exists.
         %
     :- func map.det_insert(map(K, V), K, V) = map(K, V).
     :- pred map.det_insert(K::in, V::in, map(K, V)::in, map(K, V)::out) is det.

         % Apply map.det_insert to key - value pairs from corresponding lists.
         %
     :- func map.det_insert_from_corresponding_lists(map(K, V), list(K), list(V))
         = map(K, V).
     :- pred map.det_insert_from_corresponding_lists(list(K)::in,
         list(V)::in, map(K, V)::in, map(K, V)::out) is det.

         % Apply map.det_insert to key - value pairs from the assoc_lists.
         %
     :- func map.det_insert_from_assoc_list(map(K, V), assoc_list(K, V))
         = map(K, V).
     :- pred map.det_insert_from_assoc_list(assoc_list(K, V)::in,
         map(K, V)::in, map(K, V)::out) is det.

         % Apply map.set to key - value pairs from corresponding lists.
         %
     :- func map.set_from_corresponding_lists(map(K, V), list(K), list(V))
         = map(K, V).
     :- pred map.set_from_corresponding_lists(list(K)::in, list(V)::in,
         map(K, V)::in, map(K, V)::out) is det.

     :- func map.set_from_assoc_list(map(K, V), assoc_list(K, V)) = map(K, V).
     :- pred map.set_from_assoc_list(assoc_list(K, V)::in,
         map(K, V)::in, map(K, V)::out) is det.

         % Update the value corresponding to a given key
         % Fail if the key doesn't already exist.
         %
     :- func map.update(map(K, V), K, V) = map(K, V) is semidet.
     :- pred map.update(K::in, V::in, map(K, V)::in, map(K, V)::out) is semidet.

         % Update the value corresponding to a given key
         % Abort if the key doesn't already exist.
         %
     :- func map.det_update(map(K, V), K, V) = map(K, V).
     :- pred map.det_update(K::in, V::in, map(K, V)::in, map(K, V)::out) is det.

         % Update the value at the given key by applying the supplied
         % transformation to it.  Fails if the key is not found.  This is faster
         % than first searching for the value and then updating it.
         %
     :- pred map.transform_value(pred(V, V)::in(pred(in, out) is det), K::in,
         map(K, V)::in, map(K, V)::out) is semidet.

         % Same as transform_value/4, but aborts instead of failing if the
         % key is not found.
         %
     :- func map.det_transform_value(func(V) = V, K, map(K, V)) = map(K, V).
     :- pred map.det_transform_value(pred(V, V)::in(pred(in, out) is det), K::in,
         map(K, V)::in, map(K, V)::out) is det.

         % Update value if the key is already present, otherwise
         % insert new key and value.
         %
     :- func map.set(map(K, V), K, V) = map(K, V).
     :- pred map.set(K::in, V::in, map(K, V)::in, map(K, V)::out) is det.

         % Given a map, return a list of all the keys in the map.
         %
     :- func map.keys(map(K, _V)) = list(K).
     :- pred map.keys(map(K, _V)::in, list(K)::out) is det.

         % Given a map, return a list of all the keys in the map,
         % in sorted order.
         %
     :- func map.sorted_keys(map(K, _V)) = list(K).
     :- pred map.sorted_keys(map(K, _V)::in, list(K)::out) is det.

         % Given a map, return a list of all the data values in the map.
         %
     :- func map.values(map(_K, V)) = list(V).
     :- pred map.values(map(_K, V)::in, list(V)::out) is det.

         % Convert a map to an association list.
         %
     :- func map.to_assoc_list(map(K, V)) = assoc_list(K, V).
     :- pred map.to_assoc_list(map(K, V)::in, assoc_list(K, V)::out) is det.

         % Convert a map to an association list which is sorted on the keys.
         %
     :- func map.to_sorted_assoc_list(map(K, V)) = assoc_list(K, V).
     :- pred map.to_sorted_assoc_list(map(K, V)::in, assoc_list(K, V)::out) is det.

         % Convert an association list to a map.
         %
     :- func map.from_assoc_list(assoc_list(K, V)) = map(K, V).
     :- pred map.from_assoc_list(assoc_list(K, V)::in, map(K, V)::out) is det.

         % Convert a sorted association list with no duplicated keys to a map.
         %
     :- func map.from_sorted_assoc_list(assoc_list(K, V)) = map(K, V).
     :- pred map.from_sorted_assoc_list(assoc_list(K, V)::in, map(K, V)::out)
         is det.

         % Convert a reverse sorted association list with no duplicated keys
         % to a map.
         %
     :- func map.from_rev_sorted_assoc_list(assoc_list(K, V)) = map(K, V).
     :- pred map.from_rev_sorted_assoc_list(assoc_list(K, V)::in, map(K, V)::out)
         is det.

         % Delete a key-value pair from a map.
         % If the key is not present, leave the map unchanged.
         %
     :- func map.delete(map(K, V), K) = map(K, V).
     :- pred map.delete(K::in, map(K, V)::in, map(K, V)::out) is det.

         % Apply map.delete/3 to a list of keys.
         %
     :- func map.delete_list(map(K, V), list(K)) = map(K, V).
     :- pred map.delete_list(list(K)::in, map(K, V)::in, map(K, V)::out) is det.

         % Delete a key-value pair from a map and return the value.
         % Fail if the key is not present.
         %
     :- pred map.remove(K::in, V::out, map(K, V)::in, map(K, V)::out) is semidet.

         % Delete a key-value pair from a map and return the value.
         % Abort if the key is not present.
         %
     :- pred map.det_remove(K::in, V::out, map(K, V)::in, map(K, V)::out) is det.

         % Count the number of elements in the map.
         %
     :- func map.count(map(K, V)) = int.
     :- pred map.count(map(K, V)::in, int::out) is det.

         % Convert a pair of lists (which must be of the same length) to a map.
         %
     :- func map.from_corresponding_lists(list(K), list(V)) = map(K, V).
     :- pred map.from_corresponding_lists(list(K)::in, list(V)::in, map(K, V)::out)
         is det.

         % Merge the contents of the two maps.
         % Throws an exception if both sets of keys are not disjoint.
         %
         % The cost of this predicate is proportional to the number of elements
         % in the second map, so for efficiency, you want to put the bigger map
         % first and the smaller map second.
         %
     :- func map.merge(map(K, V), map(K, V)) = map(K, V).
     :- pred map.merge(map(K, V)::in, map(K, V)::in, map(K, V)::out) is det.

         % For map.overlay(MapA, MapB, Map), if MapA and MapB both contain the
         % same key, then Map will map that key to the value from MapB.
         % In other words, MapB takes precedence over MapA.
         %
     :- func map.overlay(map(K, V), map(K, V)) = map(K, V).
     :- pred map.overlay(map(K, V)::in, map(K, V)::in, map(K, V)::out) is det.

         % map.overlay_large_map(MapA, MapB, Map) performs the same task as
         % map.overlay(MapA, MapB, Map). However, while map.overlay takes time
         % proportional to the size of MapB, map.overlay_large_map takes time
         % proportional to the size of MapA. In other words, it preferable when
         % MapB is a large map.
         %
     :- func map.overlay_large_map(map(K, V), map(K, V)) = map(K, V).
     :- pred map.overlay_large_map(map(K, V)::in, map(K, V)::in, map(K, V)::out)
         is det.

         % map.select takes a map and a set of keys, and returns a map
         % containing the keys in the set and their corresponding values.
         %
     :- func map.select(map(K, V), set(K)) = map(K, V).
     :- pred map.select(map(K, V)::in, set(K)::in, map(K, V)::out) is det.

         % map.select_sorted_list takes a map and a sorted list of keys, and returns
         % a map containing the keys in the list and their corresponding values.
         %
     :- func map.select_sorted_list(map(K, V), list(K)) = map(K, V).
     :- pred map.select_sorted_list(map(K, V)::in, list(K)::in, map(K, V)::out)
         is det.

         % Given a list of keys, produce a list of their corresponding
         % values in a specified map.
         %
     :- func map.apply_to_list(list(K), map(K, V)) = list(V).
     :- pred map.apply_to_list(list(K)::in, map(K, V)::in, list(V)::out) is det.

         % Declaratively, a NOP.
         % Operationally, a suggestion that the implementation
         % optimize the representation of the map in the expectation
         % of a number of lookups but few or no modifications.
         %
     :- func map.optimize(map(K, V)) = map(K, V).
     :- pred map.optimize(map(K, V)::in, map(K, V)::out) is det.

         % Remove the smallest item from the map, fail if the map is empty.
         %
     :- pred map.remove_smallest(K::out, V::out, map(K, V)::in, map(K, V)::out)
         is semidet.

         % Perform an inorder traversal of the map, applying
         % an accumulator predicate for each key-value pair.
         %
     :- func map.foldl(func(K, V, A) = A, map(K, V), A) = A.
     :- pred map.foldl(pred(K, V, A, A), map(K, V), A, A).
     :- mode map.foldl(pred(in, in, in, out) is det, in, in, out) is det.
     :- mode map.foldl(pred(in, in, mdi, muo) is det, in, mdi, muo) is det.
     :- mode map.foldl(pred(in, in, di, uo) is det, in, di, uo) is det.
     :- mode map.foldl(pred(in, in, in, out) is semidet, in, in, out) is semidet.
     :- mode map.foldl(pred(in, in, mdi, muo) is semidet, in, mdi, muo) is semidet.
     :- mode map.foldl(pred(in, in, di, uo) is semidet, in, di, uo) is semidet.
     :- mode map.foldl(pred(in, in, in, out) is cc_multi, in, in, out) is cc_multi.
     :- mode map.foldl(pred(in, in, di, uo) is cc_multi, in, di, uo) is cc_multi.
     :- mode map.foldl(pred(in, in, mdi, muo) is cc_multi, in, mdi, muo)
         is cc_multi.

         % Perform an inorder traversal of the map, applying an accumulator
         % predicate with two accumulators for each key-value pair.
         % (Although no more expressive than map.foldl, this is often
         % a more convenient format, and a little more efficient).
         %
     :- pred map.foldl2(pred(K, V, A, A, B, B), map(K, V), A, A, B, B).
     :- mode map.foldl2(pred(in, in, in, out, in, out) is det,
         in, in, out, in, out) is det.
     :- mode map.foldl2(pred(in, in, in, out, mdi, muo) is det,
         in, in, out, mdi, muo) is det.
     :- mode map.foldl2(pred(in, in, in, out, di, uo) is det,
         in, in, out, di, uo) is det.
     :- mode map.foldl2(pred(in, in, di, uo, di, uo) is det,
         in, di, uo, di, uo) is det.
     :- mode map.foldl2(pred(in, in, in, out, in, out) is semidet,
         in, in, out, in, out) is semidet.
     :- mode map.foldl2(pred(in, in, in, out, mdi, muo) is semidet,
         in, in, out, mdi, muo) is semidet.
     :- mode map.foldl2(pred(in, in, in, out, di, uo) is semidet,
         in, in, out, di, uo) is semidet.
     :- mode map.foldl2(pred(in, in, in, out, in, out) is cc_multi,
         in, in, out, in, out) is cc_multi.
     :- mode map.foldl2(pred(in, in, in, out, mdi, muo) is cc_multi,
         in, in, out, mdi, muo) is cc_multi.
     :- mode map.foldl2(pred(in, in, in, out, di, uo) is cc_multi,
         in, in, out, di, uo) is cc_multi.
     :- mode map.foldl2(pred(in, in, di, uo, di, uo) is cc_multi,
         in, di, uo, di, uo) is cc_multi.

         % Perform an inorder traversal of the map, applying an accumulator
         % predicate with three accumulators for each key-value pair.
         % (Although no more expressive than map.foldl, this is often
         % a more convenient format, and a little more efficient).
         %
     :- pred map.foldl3(pred(K, V, A, A, B, B, C, C), map(K, V), A, A, B, B, C, C).
     :- mode map.foldl3(pred(in, in, in, out, in, out, in, out) is det,
         in, in, out, in, out, in, out) is det.
     :- mode map.foldl3(pred(in, in, in, out, in, out, mdi, muo) is det,
         in, in, out, in, out, mdi, muo) is det.
     :- mode map.foldl3(pred(in, in, in, out, in, out, di, uo) is det,
         in, in, out, in, out, di, uo) is det.
     :- mode map.foldl3(pred(in, in, in, out, di, uo, di, uo) is det,
         in, in, out, di, uo, di, uo) is det.
     :- mode map.foldl3(pred(in, in, di, uo, di, uo, di, uo) is det,
         in, di, uo, di, uo, di, uo) is det.
     :- mode map.foldl3(pred(in, in, in, out, in, out, in, out) is semidet,
         in, in, out, in, out, in, out) is semidet.
     :- mode map.foldl3(pred(in, in, in, out, in, out, mdi, muo) is semidet,
         in, in, out, in, out, mdi, muo) is semidet.
     :- mode map.foldl3(pred(in, in, in, out, in, out, di, uo) is semidet,
         in, in, out, in, out, di, uo) is semidet.

         % Perform an inorder traversal of the map, applying an accumulator
         % predicate with four accumulators for each key-value pair.
         % (Although no more expressive than map.foldl, this is often
         % a more convenient format, and a little more efficient).
         %
     :- pred map.foldl4(pred(K, V, A, A, B, B, C, C, D, D), map(K, V),
         A, A, B, B, C, C, D, D).
     :- mode map.foldl4(pred(in, in, in, out, in, out, in, out, in, out) is det,
         in, in, out, in, out, in, out, in, out) is det.
     :- mode map.foldl4(pred(in, in, in, out, in, out, in, out, in, out) is semidet,
         in, in, out, in, out, in, out, in, out) is semidet.
     :- mode map.foldl4(pred(in, in, in, out, in, out, in, out, di, uo) is det,
         in, in, out, in, out, in, out, di, uo) is det.
     :- mode map.foldl4(pred(in, in, in, out, in, out, di, uo, di, uo) is det,
         in, in, out, in, out, di, uo, di, uo) is det.
     :- mode map.foldl4(pred(in, in, in, out, di, uo, di, uo, di, uo) is det,
         in, in, out, di, uo, di, uo, di, uo) is det.
     :- mode map.foldl4(pred(in, in, di, uo, di, uo, di, uo, di, uo) is det,
         in, di, uo, di, uo, di, uo, di, uo) is det.

         % Perform an inorder traversal of the map, applying
         % an accumulator predicate for value.
         %
     :- pred map.foldl_values(pred(V, A, A), map(K, V), A, A).
     :- mode map.foldl_values(pred(in, in, out) is det, in, in, out) is det.
     :- mode map.foldl_values(pred(in, mdi, muo) is det, in, mdi, muo) is det.
     :- mode map.foldl_values(pred(in, di, uo) is det, in, di, uo) is det.
     :- mode map.foldl_values(pred(in, in, out) is semidet, in, in, out) is semidet.
     :- mode map.foldl_values(pred(in, mdi, muo) is semidet, in, mdi, muo)
         is semidet.
     :- mode map.foldl_values(pred(in, di, uo) is semidet, in, di, uo) is semidet.
     :- mode map.foldl_values(pred(in, in, out) is cc_multi, in, in, out)
         is cc_multi.
     :- mode map.foldl_values(pred(in, di, uo) is cc_multi, in, di, uo) is cc_multi.
     :- mode map.foldl_values(pred(in, mdi, muo) is cc_multi, in, mdi, muo)
         is cc_multi.

     :- func map.foldr(func(K, V, A) = A, map(K, V), A) = A.
     :- pred map.foldr(pred(K, V, A, A), map(K, V), A, A).
     :- mode map.foldr(pred(in, in, in, out) is det, in, in, out) is det.
     :- mode map.foldr(pred(in, in, mdi, muo) is det, in, mdi, muo) is det.
     :- mode map.foldr(pred(in, in, di, uo) is det, in, di, uo) is det.
     :- mode map.foldr(pred(in, in, in, out) is semidet, in, in, out) is semidet.
     :- mode map.foldr(pred(in, in, mdi, muo) is semidet, in, mdi, muo) is semidet.
     :- mode map.foldr(pred(in, in, di, uo) is semidet, in, di, uo) is semidet.
     :- mode map.foldr(pred(in, in, in, out) is cc_multi, in, in, out) is cc_multi.
     :- mode map.foldr(pred(in, in, di, uo) is cc_multi, in, di, uo) is cc_multi.
     :- mode map.foldr(pred(in, in, mdi, muo) is cc_multi, in, mdi, muo)
         is cc_multi.

     :- pred map.foldr2(pred(K, V, A, A, B, B), map(K, V), A, A, B, B).
     :- mode map.foldr2(pred(in, in, in, out, in, out) is det,
         in, in, out, in, out) is det.
     :- mode map.foldr2(pred(in, in, in, out, in, out) is semidet,
         in, in, out, in, out) is semidet.
     :- mode map.foldr2(pred(in, in, in, out, di, uo) is det,
         in, in, out, di, uo) is det.
     :- mode map.foldr2(pred(in, in, di, uo, di, uo) is det,
         in, di, uo, di, uo) is det.

     :- pred map.foldr3(pred(K, V, A, A, B, B, C, C), map(K, V), A, A, B, B, C, C).
     :- mode map.foldr3(pred(in, in, in, out, in, out, in, out) is det,
         in, in, out, in, out, in, out) is det.
     :- mode map.foldr3(pred(in, in, in, out, in, out, in, out) is semidet,
         in, in, out, in, out, in, out) is semidet.
     :- mode map.foldr3(pred(in, in, in, out, in, out, di, uo) is det,
         in, in, out, in, out, di, uo) is det.
     :- mode map.foldr3(pred(in, in, in, out, di, uo, di, uo) is det,
         in, in, out, di, uo, di, uo) is det.
     :- mode map.foldr3(pred(in, in, di, uo, di, uo, di, uo) is det,
         in, di, uo, di, uo, di, uo) is det.

     :- pred map.foldr4(pred(K, V, A, A, B, B, C, C, D, D), map(K, V),
         A, A, B, B, C, C, D, D).
     :- mode map.foldr4(pred(in, in, in, out, in, out, in, out, in, out) is det,
         in, in, out, in, out, in, out, in, out) is det.
     :- mode map.foldr4(pred(in, in, in, out, in, out, in, out, in, out) is semidet,
         in, in, out, in, out, in, out, in, out) is semidet.
     :- mode map.foldr4(pred(in, in, in, out, in, out, in, out, di, uo) is det,
         in, in, out, in, out, in, out, di, uo) is det.
     :- mode map.foldr4(pred(in, in, in, out, in, out, di, uo, di, uo) is det,
         in, in, out, in, out, di, uo, di, uo) is det.
     :- mode map.foldr4(pred(in, in, in, out, di, uo, di, uo, di, uo) is det,
         in, in, out, di, uo, di, uo, di, uo) is det.
     :- mode map.foldr4(pred(in, in, di, uo, di, uo, di, uo, di, uo) is det,
         in, di, uo, di, uo, di, uo, di, uo) is det.

         % Apply a transformation predicate to all the values in a map.
         %
     :- func map.map_values(func(K, V) = W, map(K, V)) = map(K, W).
     :- pred map.map_values(pred(K, V, W), map(K, V), map(K, W)).
     :- mode map.map_values(pred(in, in, out) is det, in, out) is det.
     :- mode map.map_values(pred(in, in, out) is semidet, in, out) is semidet.

         % Same as map.map_values, but do not pass the key to the given predicate.
         %
     :- func map.map_values_only(func(V) = W, map(K, V)) = map(K, W).
     :- pred map.map_values_only(pred(V, W), map(K, V), map(K, W)).
     :- mode map.map_values_only(pred(in, out) is det, in, out) is det.
     :- mode map.map_values_only(pred(in, out) is semidet, in, out) is semidet.

         % Apply a transformation predicate to all the values in a map,
         % while continuously updating an accumulator.
         %
     :- pred map.map_foldl(pred(K, V, W, A, A), map(K, V), map(K, W), A, A).
     :- mode map.map_foldl(pred(in, in, out, di, uo) is det, in, out, di, uo)
         is det.
     :- mode map.map_foldl(pred(in, in, out, in, out) is det, in, out, in, out)
         is det.
     :- mode map.map_foldl(pred(in, in, out, in, out) is semidet, in, out, in, out)
         is semidet.

         % As map.map_foldl, but with two accumulators.
         %
     :- pred map.map_foldl2(pred(K, V, W, A, A, B, B), map(K, V), map(K, W),
         A, A, B, B).
     :- mode map.map_foldl2(pred(in, in, out, di, uo, di, uo) is det,
         in, out, di, uo, di, uo) is det.
     :- mode map.map_foldl2(pred(in, in, out, in, out, di, uo) is det,
         in, out, in, out, di, uo) is det.
     :- mode map.map_foldl2(pred(in, in, out, in, out, in, out) is det,
         in, out, in, out, in, out) is det.
     :- mode map.map_foldl2(pred(in, in, out, in, out, in, out) is semidet,
         in, out, in, out, in, out) is semidet.

         % As map.map_foldl, but with three accumulators.
         %
     :- pred map.map_foldl3(pred(K, V, W, A, A, B, B, C, C), map(K, V), map(K, W),
         A, A, B, B, C, C).
     :- mode map.map_foldl3(pred(in, in, out, di, uo, di, uo, di, uo) is det,
         in, out, di, uo, di, uo, di, uo) is det.
     :- mode map.map_foldl3(pred(in, in, out, in, out, di, uo, di, uo) is det,
         in, out, in, out, di, uo, di, uo) is det.
     :- mode map.map_foldl3(pred(in, in, out, in, out, in, out, di, uo) is det,
         in, out, in, out, in, out, di, uo) is det.
     :- mode map.map_foldl3(pred(in, in, out, in, out, in, out, in, out) is det,
         in, out, in, out, in, out, in, out) is det.
     :- mode map.map_foldl3(pred(in, in, out, in, out, in, out, in, out) is semidet,
         in, out, in, out, in, out, in, out) is semidet.

         % As map.map_foldl, but without passing the key to the predicate.
         %
     :- pred map.map_values_foldl(pred(V, W, A, A), map(K, V), map(K, W), A, A).
     :- mode map.map_values_foldl(pred(in, out, di, uo) is det,
         in, out, di, uo) is det.
     :- mode map.map_values_foldl(pred(in, out, in, out) is det,
         in, out, in, out) is det.
     :- mode map.map_values_foldl(pred(in, out, in, out) is semidet,
         in, out, in, out) is semidet.

         % As map.map_values_foldl, but with two accumulators.
         %
     :- pred map.map_values_foldl2(pred(V, W, A, A, B, B), map(K, V), map(K, W),
         A, A, B, B).
     :- mode map.map_values_foldl2(pred(in, out, di, uo, di, uo) is det,
         in, out, di, uo, di, uo) is det.
     :- mode map.map_values_foldl2(pred(in, out, in, out, di, uo) is det,
         in, out, in, out, di, uo) is det.
     :- mode map.map_values_foldl2(pred(in, out, in, out, in, out) is det,
         in, out, in, out, in, out) is det.
     :- mode map.map_values_foldl2(pred(in, out, in, out, in, out) is semidet,
         in, out, in, out, in, out) is semidet.

         % As map.map_values_foldl, but with three accumulators.
         %
     :- pred map.map_values_foldl3(pred(V, W, A, A, B, B, C, C),
         map(K, V), map(K, W), A, A, B, B, C, C).
     :- mode map.map_values_foldl3(pred(in, out, di, uo, di, uo, di, uo) is det,
         in, out, di, uo, di, uo, di, uo) is det.
     :- mode map.map_values_foldl3(pred(in, out, in, out, di, uo, di, uo) is det,
         in, out, in, out, di, uo, di, uo) is det.
     :- mode map.map_values_foldl3(pred(in, out, in, out, in, out, di, uo) is det,
         in, out, in, out, in, out, di, uo) is det.
     :- mode map.map_values_foldl3(pred(in, out, in, out, in, out, in, out) is det,
         in, out, in, out, in, out, in, out) is det.
     :- mode map.map_values_foldl3(
         pred(in, out, in, out, in, out, in, out) is semidet,
         in, out, in, out, in, out, in, out) is semidet.

         % Given two maps M1 and M2, create a third map M3 that has only the
         % keys that occur in both M1 and M2. For keys that occur in both M1
         % and M2, compute the value in the final map by applying the supplied
         % predicate to the values associated with the key in M1 and M2.
         % Fail if and only if this predicate fails on the values associated
         % with some common key.
         %
     :- pred map.intersect(pred(V, V, V), map(K, V), map(K, V), map(K, V)).
     :- mode map.intersect(pred(in, in, out) is semidet, in, in, out) is semidet.
     :- mode map.intersect(pred(in, in, out) is det, in, in, out) is det.

     :- func map.intersect(func(V, V) = V, map(K, V), map(K, V)) = map(K, V).

         % Calls map.intersect. Aborts if map.intersect fails.
         %
     :- pred map.det_intersect(pred(V, V, V), map(K, V), map(K, V), map(K, V)).
     :- mode map.det_intersect(pred(in, in, out) is semidet, in, in, out) is det.

     :- func map.det_intersect(func(V, V) = V, map(K, V), map(K, V)) = map(K, V).
     :- mode map.det_intersect(func(in, in) = out is semidet, in, in) = out is det.

         % Given two maps M1 and M2, create a third map M3 that has only the
         % keys that occur in both M1 and M2. For keys that occur in both M1
         % and M2, compute the corresponding values. If they are the same,
         % include the key/value pair in M3. If they differ, do not include the
         % key in M3.
         %
         % This predicate effectively considers the input maps to be sets of
         % key/value pairs, computes the intersection of those two sets, and
         % returns the map corresponding to the intersection.
         %
         % map.common_subset is very similar to map.intersect, but can succeed
         % even with an output map that does not contain an entry for a key
         % value that occurs in both input maps.
         %
     :- func map.common_subset(map(K, V), map(K, V)) = map(K, V).

         % Given two maps M1 and M2, create a third map M3 that all the keys
         % that occur in either M1 and M2. For keys that occur in both M1
         % and M2, compute the value in the final map by applying the supplied
         % predicate to the values associated with the key in M1 and M2.
         % Fail if and only if this predicate fails on the values associated
         % with some common key.
         %
     :- func map.union(func(V, V) = V, map(K, V), map(K, V)) = map(K, V).
     :- pred map.union(pred(V, V, V), map(K, V), map(K, V), map(K, V)).
     :- mode map.union(pred(in, in, out) is semidet, in, in, out) is semidet.
     :- mode map.union(pred(in, in, out) is det, in, in, out) is det.

         % Calls map.union. Aborts if map.union fails.
         %
     :- pred map.det_union(pred(V, V, V), map(K, V), map(K, V), map(K, V)).
     :- mode map.det_union(pred(in, in, out) is semidet, in, in, out) is det.

     :- func map.det_union(func(V, V) = V, map(K, V), map(K, V)) = map(K, V).
     :- mode map.det_union(func(in, in) = out is semidet, in, in) = out is det.

         % Consider the original map a set of key-value pairs. This predicate
         % returns a map that maps each value to the set of keys it is paired
         % with in the original map.
         %
     :- func map.reverse_map(map(K, V)) = map(V, set(K)).

         % Field selection for maps.

         % Map ^ elem(Key) = map.search(Map, Key).
         %
     :- func map.elem(K, map(K, V)) = V is semidet.

         % Map ^ det_elem(Key) = map.lookup(Map, Key).
         %
     :- func map.det_elem(K, map(K, V)) = V.

         % Field update for maps.

         % (Map ^ elem(Key) := Value) = map.set(Map, Key, Value).
         %
     :- func 'elem :='(K, map(K, V), V) = map(K, V).

         % (Map ^ det_elem(Key) := Value) = map.det_update(Map, Key, Value).
         %
     :- func 'det_elem :='(K, map(K, V), V) = map(K, V).

     %--------------------------------------------------%
     %--------------------------------------------------%


File: mercury_library.info,  Node: math,  Next: maybe,  Prev: map,  Up: Top

42 math
*******

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 1995-2007, 2011 The University of Melbourne.
     % This file may only be copied under the terms of the GNU Library General
     % Public License - see the file COPYING.LIB in the Mercury distribution.
     %--------------------------------------------------%
     %
     % File: math.m.
     % Main author: bromage.
     % Stability: high.
     %
     % Higher mathematical operations.  (The basics are in float.m.)
     %
     % By default, domain errors are currently handled by throwing an exception.
     %
     % For better performance, it is possible to disable the Mercury domain
     % checking by compiling with `--intermodule-optimization' and the C macro
     % symbol `ML_OMIT_MATH_DOMAIN_CHECKS' defined, e.g. by using
     % `MCFLAGS=--intermodule-optimization' and
     % `MGNUCFLAGS=-DML_OMIT_MATH_DOMAIN_CHECKS' in your Mmakefile,
     % or by compiling with the command
     % `mmc --intermodule-optimization --cflags -DML_OMIT_MATH_DOMAIN_CHECKS'.
     %
     % For maximum performance, all Mercury domain checking can be disabled by
     % recompiling this module using `MGNUCFLAGS=-DML_OMIT_MATH_DOMAIN_CHECKS'
     % or `mmc --cflags -DML_OMIT_MATH_DOMAIN_CHECKS' as above. You can
     % either recompile the entire library, or just copy `math.m' to your
     % application's source directory and link with it directly instead of as
     % part of the library.
     %
     % Note that the above performance improvements are semantically safe,
     % since the C math library and/or floating point hardware perform these
     % checks for you.  The benefit of having the Mercury library perform the
     % checks instead is that Mercury will tell you in which function or
     % predicate the error occurred, as well as giving you a stack trace if
     % that is enabled; with the checks disabled you only have the information
     % that the floating-point exception signal handler gives you.
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module math.
     :- interface.

         % A domain error exception, indicates that the inputs to a function
         % were outside the domain of the function.  The string indicates
         % where the error occurred.
         %
         % It is possible to switch domain checking off, in which case,
         % depending on the backend, a domain error may cause a program
         % abort.
         %
     :- type domain_error ---> domain_error(string).

     %--------------------------------------------------%
     %
     % Mathematical constants
     %

         % Pythagoras' number.
         %
     :- func math.pi = float.

         % Base of natural logarithms.
         %
     :- func math.e = float.

     %--------------------------------------------------%
     %
     % "Next integer" operations
     %

         % math.ceiling(X) = Ceil is true if Ceil is the smallest integer
         % not less than X.
         %
     :- func math.ceiling(float) = float.

         % math.floor(X) = Floor is true if Floor is the largest integer
         % not greater than X.
         %
     :- func math.floor(float) = float.

         % math.round(X) = Round is true if Round is the integer closest to X.
         % If X has a fractional value of 0.5, it is rounded up.
         %
     :- func math.round(float) = float.

         % math.truncate(X) = Trunc is true if Trunc is the integer closest to X
         % such that |Trunc| =< |X|.
         %
     :- func math.truncate(float) = float.

     %--------------------------------------------------%
     %
     % Polynomial roots
     %

         % math.sqrt(X) = Sqrt is true if Sqrt is the positive square root of X.
         %
         % Domain restriction: X >= 0
         %
     :- func math.sqrt(float) = float.

         % As above, but the behaviour is undefined if the argument is less
         % than zero.
         %
     :- func math.unchecked_sqrt(float) = float.

     :- type math.quadratic_roots
         --->    no_roots
         ;       one_root(float)
         ;       two_roots(float, float).

         % math.solve_quadratic(A, B, C) = Roots is true if Roots are
         % the solutions to the equation Ax^2 + Bx + C.
         %
         % Domain restriction: A \= 0
         %
     :- func math.solve_quadratic(float, float, float) = quadratic_roots.

     %--------------------------------------------------%
     %
     % Power/logarithm operations
     %

         % math.pow(X, Y) = Res is true if Res is X raised to the power of Y.
         %
         % Domain restriction: X >= 0 and (X = 0 implies Y > 0)
         %
     :- func math.pow(float, float) = float.

         % math.exp(X) = Exp is true if Exp is e raised to the power of X.
         %
     :- func math.exp(float) = float.

         % math.ln(X) = Log is true if Log is the natural logarithm of X.
         %
         % Domain restriction: X > 0
         %
     :- func math.ln(float) = float.

         % math.log10(X) = Log is true if Log is the logarithm to base 10 of X.
         %
         % Domain restriction: X > 0
         %
     :- func math.log10(float) = float.

         % math.log2(X) = Log is true if Log is the logarithm to base 2 of X.
         %
         % Domain restriction: X > 0
         %
     :- func math.log2(float) = float.

         % math.log(B, X) = Log is true if Log is the logarithm to base B of X.
         %
         % Domain restriction: X > 0 and B > 0 and B \= 1
         %
     :- func math.log(float, float) = float.

     %--------------------------------------------------%
     %
     % Trigonometric operations
     %

         % math.sin(X) = Sin is true if Sin is the sine of X.
         %
     :- func math.sin(float) = float.

         % math.cos(X) = Cos is true if Cos is the cosine of X.
         %
     :- func math.cos(float) = float.

         % math.tan(X) = Tan is true if Tan is the tangent of X.
         %
     :- func math.tan(float) = float.

         % math.asin(X) = ASin is true if ASin is the inverse sine of X,
         % where ASin is in the range [-pi/2,pi/2].
         %
         % Domain restriction: X must be in the range [-1,1]
         %
     :- func math.asin(float) = float.

         % math.acos(X) = ACos is true if ACos is the inverse cosine of X,
         % where ACos is in the range [0, pi].
         %
         % Domain restriction: X must be in the range [-1,1]
         %
     :- func math.acos(float) = float.

         % math.atan(X) = ATan is true if ATan is the inverse tangent of X,
         % where ATan is in the range [-pi/2,pi/2].
         %
     :- func math.atan(float) = float.

         % math.atan2(Y, X) = ATan is true if ATan is the inverse tangent of Y/X,
         % where ATan is in the range [-pi,pi].
         %
     :- func math.atan2(float, float) = float.

     %--------------------------------------------------%
     %
     % Hyperbolic functions
     %

         % math.sinh(X) = Sinh is true if Sinh is the hyperbolic sine of X.
         %
     :- func math.sinh(float) = float.

         % math.cosh(X) = Cosh is true if Cosh is the hyperbolic cosine of X.
         %
     :- func math.cosh(float) = float.

         % math.tanh(X) = Tanh is true if Tanh is the hyperbolic tangent of X.
         %
     :- func math.tanh(float) = float.

     %--------------------------------------------------%
     %--------------------------------------------------%


File: mercury_library.info,  Node: maybe,  Next: multi_map,  Prev: math,  Up: Top

43 maybe
********

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 1994-2006, 2010-2011 The University of Melbourne.
     % This file may only be copied under the terms of the GNU Library General
     % Public License - see the file COPYING.LIB in the Mercury distribution.
     %--------------------------------------------------%
     %
     % File: maybe.m.
     % Main author: fjh.
     % Stability: high.
     %
     % This module defines the "maybe" type.
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module maybe.
     :- interface.

     %--------------------------------------------------%

     :- type maybe(T)
     	--->	no
         ;       yes(T).

     :- inst maybe(I)
         --->    no
         ;       yes(I).

     :- inst maybe_yes(I)
         --->    yes(I).

     :- type maybe_error
         --->    ok
         ;       error(string).

     :- type maybe_error(T)
         --->    ok(T)
         ;       error(string).

     :- inst maybe_error(I)
         --->    ok(I)
         ;       error(ground).

     :- inst maybe_error_ok(I)
         --->    ok(I).

         % map_maybe(P, yes(Value0), yes(Value)) :- P(Value, Value).
         % map_maybe(_, no, no).
         %
     :- pred map_maybe(pred(T, U), maybe(T), maybe(U)).
     :- mode map_maybe(pred(in, out) is det, in, out) is det.
     :- mode map_maybe(pred(in, out) is semidet, in, out) is semidet.
     :- mode map_maybe(pred(in, out) is multi, in, out) is multi.
     :- mode map_maybe(pred(in, out) is nondet, in, out) is nondet.

         % map_maybe(_, no) = no.
         % map_maybe(F, yes(Value)) = yes(F(Value)).
         %
     :- func map_maybe(func(T) = U, maybe(T)) = maybe(U).

         % fold_maybe(_, no, !Acc).
         % fold_maybe(P, yes(Value), !Acc) :- P(Value, !Acc).
         %
     :- pred fold_maybe(pred(T, U, U), maybe(T), U, U).
     :- mode fold_maybe(pred(in, in, out) is det, in, in, out) is det.
     :- mode fold_maybe(pred(in, mdi, muo) is det, in, mdi, muo) is det.
     :- mode fold_maybe(pred(in, di, uo) is det, in, di, uo) is det.
     :- mode fold_maybe(pred(in, in, out) is semidet, in, in, out) is semidet.
     :- mode fold_maybe(pred(in, mdi, muo) is semidet, in, mdi, muo) is semidet.
     :- mode fold_maybe(pred(in, di, uo) is semidet, in, di, uo) is semidet.

         % fold_maybe(_, no, Acc) = Acc.
         % fold_maybe(F, yes(Value), Acc0) = F(Acc0).
         %
     :- func fold_maybe(func(T, U) = U, maybe(T), U) = U.

         % map_fold_maybe(_, no, no, !Acc).
         % map_fold_maybe(P, yes(Value0), yes(Value), !Acc) :-
         %      P(Value, Value, !Acc).
         %
     :- pred map_fold_maybe(pred(T, U, Acc, Acc), maybe(T), maybe(U), Acc, Acc).
     :- mode map_fold_maybe(pred(in, out, in, out) is det, in, out,
         in, out) is det.
     :- mode map_fold_maybe(pred(in, out, mdi, muo) is det, in, out,
         mdi, muo) is det.
     :- mode map_fold_maybe(pred(in, out, di, uo) is det, in, out,
         di, uo) is det.
     :- mode map_fold_maybe(pred(in, out, in, out) is semidet, in, out,
         in, out) is semidet.
     :- mode map_fold_maybe(pred(in, out, mdi, muo) is semidet, in, out,
         mdi, muo) is semidet.
     :- mode map_fold_maybe(pred(in, out, di, uo) is semidet, in, out,
         di, uo) is semidet.

         % As above, but with two accumulators.
         %
     :- pred map_fold2_maybe(pred(T, U, Acc1, Acc1, Acc2, Acc2),
         maybe(T), maybe(U), Acc1, Acc1, Acc2, Acc2).
     :- mode map_fold2_maybe(pred(in, out, in, out, in, out) is det,
         in, out, in, out, in, out) is det.
     :- mode map_fold2_maybe(pred(in, out, in, out, mdi, muo) is det,
         in, out, in, out, mdi, muo) is det.
     :- mode map_fold2_maybe(pred(in, out, in, out, di, uo) is det,
         in, out, in, out, di, uo) is det.
     :- mode map_fold2_maybe(pred(in, out, in, out, in, out) is semidet,
         in, out, in, out, in, out) is semidet.
     :- mode map_fold2_maybe(pred(in, out, in, out, mdi, muo) is semidet,
         in, out, in, out, mdi, muo) is semidet.
     :- mode map_fold2_maybe(pred(in, out, in, out, di, uo) is semidet,
         in, out, in, out, di, uo) is semidet.

         % As above, but with three accumulators.
         %
     :- pred map_fold3_maybe(pred(T, U, Acc1, Acc1, Acc2, Acc2, Acc3, Acc3),
         maybe(T), maybe(U), Acc1, Acc1, Acc2, Acc2, Acc3, Acc3).
     :- mode map_fold3_maybe(pred(in, out, in, out, in, out, in, out) is det,
         in, out, in, out, in, out, in, out) is det.
     :- mode map_fold3_maybe(pred(in, out, in, out, in, out, mdi, muo) is det,
         in, out, in, out, in, out, mdi, muo) is det.
     :- mode map_fold3_maybe(pred(in, out, in, out, in, out, di, uo) is det,
         in, out, in, out, in, out, di, uo) is det.
     :- mode map_fold3_maybe(pred(in, out, in, out, in, out, in, out) is semidet,
         in, out, in, out, in, out, in, out) is semidet.
     :- mode map_fold3_maybe(pred(in, out, in, out, in, out, mdi, muo) is semidet,
         in, out, in, out, in, out, mdi, muo) is semidet.
     :- mode map_fold3_maybe(pred(in, out, in, out, in, out, di, uo) is semidet,
         in, out, in, out, in, out, di, uo) is semidet.

         % maybe_is_yes(yes(X), X).
         %
         % This is useful as an argument to list.filter_map
         %
     :- pred maybe_is_yes(maybe(T)::in, T::out) is semidet.

     %--------------------------------------------------%
     %--------------------------------------------------%


File: mercury_library.info,  Node: multi_map,  Next: ops,  Prev: maybe,  Up: Top

44 multi_map
************

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 1995, 1997, 2000, 2002-2006, 2011 The University of Melbourne.
     % This file may only be copied under the terms of the GNU Library General
     % Public License - see the file COPYING.LIB in the Mercury distribution.
     %--------------------------------------------------%
     %
     % File: multi_map.m.
     % Main author: dylan.  Based on map.m, by fjh, conway.
     % Stability: low.
     %
     % This file provides the 'multi_map' ADT.
     % A map (also known as a dictionary or an associative array) is a collection
     % of (Key, Data) pairs which allows you to look up any Data item given the
     % Key.  A multi_map is similar, though allows a one to many relationship
     % between keys and data.
     %
     % This is implemented almost as a special case of map.m.
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module multi_map.
     :- interface.

     :- import_module assoc_list.
     :- import_module list.
     :- import_module map.
     :- import_module set.

     %--------------------------------------------------%

     :- type multi_map(Key, Data) == map(Key, list(Data)).

     %--------------------------------------------------%

         % Initialize an empty multi_map.
         %
     :- func multi_map.init = multi_map(_, _).
     :- pred multi_map.init(multi_map(_, _)::uo) is det.

         % Check whether a multi_map is empty.
         %
     :- pred multi_map.is_empty(multi_map(_, _)::in) is semidet.

         % Check whether multi_map contains key.
         %
     :- pred multi_map.contains(multi_map(K, _V)::in, K::in) is semidet.

     :- pred multi_map.member(multi_map(K, V)::in, K::out, V::out) is nondet.

         % Search multi_map for given key.
         %
     :- pred multi_map.search(multi_map(K, V)::in, K::in, list(V)::out) is semidet.

         % Search multi_map for given key.
         %
     :- pred multi_map.nondet_search(multi_map(K, V)::in, K::in, V::out) is nondet.

         % Search multi_map for key, but abort if search fails.
         %
     :- func multi_map.lookup(multi_map(K, V), K) = list(V).
     :- pred multi_map.lookup(multi_map(K, V)::in, K::in, list(V)::out) is det.

         % Search multi_map for key.
         %
     :- pred multi_map.nondet_lookup(multi_map(K, V)::in, K::in, V::out) is nondet.

         % Search multi_map for data.
         %
     :- pred multi_map.inverse_search(multi_map(K, V)::in, V::in, K::out) is nondet.

         % Insert a new key and corresponding value into a multi_map.
         % Fail if the key already exists.
         %
     :- pred multi_map.insert(K::in, V::in,
         multi_map(K, V)::in, multi_map(K, V)::out) is semidet.

         % Insert a new key and corresponding value into a multi_map.
         % Aborts if the key already exists.
         %
     :- func multi_map.det_insert(multi_map(K, V), K, V) = multi_map(K, V).
     :- pred multi_map.det_insert(K::in, V::in,
         multi_map(K, V)::in, multi_map(K, V)::out) is det.

         % Update (add) the value corresponding to a given key.
         % Fails if the key does not already exist.
         %
     :- pred multi_map.update(K::in, V::in,
         multi_map(K, V)::in, multi_map(K, V)::out) is semidet.

         % Update (add) the value corresponding to a given key.
         % Aborts if the key does not already exist.
         %
     :- func multi_map.det_update(multi_map(K, V), K, V) = multi_map(K, V).
     :- pred multi_map.det_update(K::in, V::in,
         multi_map(K, V)::in, multi_map(K, V)::out) is det.

         % Update (replace) the value corresponding to a given key.
         % Fails if the key does not already exist.
         %
     :- pred multi_map.replace(K::in, list(V)::in,
         multi_map(K, V)::in, multi_map(K, V)::out) is semidet.

         % Update (replace) the value corresponding to a given key.
         % Aborts if the key does not already exist.
         %
     :- func multi_map.det_replace(multi_map(K, V), K, list(V)) = multi_map(K, V).
     :- pred multi_map.det_replace(K::in, list(V)::in,
         multi_map(K, V)::in, multi_map(K, V)::out) is det.

         % Update (add) value if the key is already present, otherwise
         % insert the new key and value.
         %
     :- func multi_map.set(multi_map(K, V), K, V) = multi_map(K, V).
     :- pred multi_map.set(K::in, V::in,
         multi_map(K, V)::in, multi_map(K, V)::out) is det.

     :- func multi_map.add(multi_map(K, V), K, V) = multi_map(K, V).
     :- pred multi_map.add(K::in, V::in,
         multi_map(K, V)::in, multi_map(K, V)::out) is det.

         % Given a multi_map, return a list of all the keys in the multi_map.
         %
     :- func multi_map.keys(multi_map(K, _V)) = list(K).
     :- pred multi_map.keys(multi_map(K, _V)::in, list(K)::out) is det.

         % Given a multi_map, return a list of all the data values in the
         % multi_map.
         %
     :- func multi_map.values(multi_map(_K, V)) = list(V).
     :- pred multi_map.values(multi_map(_K, V)::in, list(V)::out) is det.

         % Convert a multi_map to an association list.
         %
     :- func multi_map.to_flat_assoc_list(multi_map(K, V)) = assoc_list(K, V).
     :- pred multi_map.to_flat_assoc_list(multi_map(K, V)::in,
         assoc_list(K, V)::out) is det.

         % Convert an association list to a multi_map.
         %
     :- func multi_map.from_flat_assoc_list(assoc_list(K, V)) = multi_map(K, V).
     :- pred multi_map.from_flat_assoc_list(assoc_list(K, V)::in,
         multi_map(K, V)::out) is det.

         % Convert a multi_map to an association list, with all the
         % values for each key in one element of the association list.
         %
     :- func multi_map.to_assoc_list(multi_map(K, V)) = assoc_list(K, list(V)).
     :- pred multi_map.to_assoc_list(multi_map(K, V)::in,
         assoc_list(K, list(V))::out) is det.

         % Convert an association list with all the values for each
         % key in one element of the list to a multi_map.
         %
     :- func multi_map.from_assoc_list(assoc_list(K, list(V))) = multi_map(K, V).
     :- pred multi_map.from_assoc_list(assoc_list(K, list(V))::in,
         multi_map(K, V)::out) is det.

         % Convert a sorted association list to a multi_map.
         %
     :- func multi_map.from_sorted_assoc_list(assoc_list(K, list(V)))
         = multi_map(K, V).
     :- pred multi_map.from_sorted_assoc_list(assoc_list(K, list(V))::in,
         multi_map(K, V)::out) is det.

         % Delete a key and data from a multi_map
         % if the key is not present, leave the multi_map unchanged.
         %
     :- func multi_map.delete(multi_map(K, V), K) = multi_map(K, V).
     :- pred multi_map.delete(K::in,
         multi_map(K, V)::in, multi_map(K, V)::out) is det.

         % Delete a data value from a key in a multi_map
         % if the key is not present, leave the multi_map unchanged.
         %
     :- func multi_map.delete(multi_map(K, V), K, V) = multi_map(K, V).
     :- pred multi_map.delete(K::in, V::in,
         multi_map(K, V)::in, multi_map(K, V)::out) is det.

         % Delete a key-value pair from a multi_map and return the value.
         % Fails if the key is not present.
         %
     :- pred multi_map.remove(K::in, list(V)::out,
         multi_map(K, V)::in, multi_map(K, V)::out) is semidet.

         % Delete a key-value pair from a multi_map and return the value.
         % Aborts if the key is not present.
         %
     :- pred multi_map.det_remove(K::in, list(V)::out,
         multi_map(K, V)::in, multi_map(K, V)::out) is det.

         % Count the number of elements (keys) in the multi_map.
         %
     :- func multi_map.count(multi_map(K, V)) = int.
     :- pred multi_map.count(multi_map(K, V)::in, int::out) is det.

         % Count the number of data elements in the multi_map.
         %
     :- func multi_map.all_count(multi_map(K, V)) = int.
     :- pred multi_map.all_count(multi_map(K, V)::in, int::out) is det.

         % Convert a pair of lists (which must be of the same length)
         % to a multi_map.
         %
     :- func multi_map.from_corresponding_lists(list(K), list(V))
         = multi_map(K, V).
     :- pred multi_map.from_corresponding_lists(list(K)::in, list(V)::in,
         multi_map(K, V)::out) is det.

         % Convert a pair of lists (which must be of the same length)
         % to a multi_map.
         %
     :- func multi_map.from_corresponding_list_lists(list(K), list(list(V)))
         = multi_map(K, V).
     :- pred multi_map.from_corresponding_list_lists(list(K)::in, list(list(V))::in,
         multi_map(K, V)::out) is det.

         % multi_map.merge(MultiMapA, MultiMapB, MultiMap).
         % Merge `MultiMapA' and `MultiMapB' so that if a key occurs in
         % both `MultiMapA' and `MultiMapB' then the values corresponding
         % to that key in `MultiMap' will be the concatenation of
         % the values corresponding to that key from `MultiMapA' and
         % `MultiMapB'.
         %
     :- func multi_map.merge(multi_map(K, V), multi_map(K, V))
         = multi_map(K, V).
     :- pred multi_map.merge(multi_map(K, V)::in, multi_map(K, V)::in,
         multi_map(K, V)::out) is det.

         % multi_map.select takes a multi_map and a set of keys and returns
         % a multi_map containing the keys in the set and their corresponding
         % values.
         %
     :- func multi_map.select(multi_map(K, V), set(K)) = multi_map(K, V).
     :- pred multi_map.select(multi_map(K, V)::in, set(K)::in,
         multi_map(K, V)::out) is det.

         % Given a list of keys, produce a list of their values in a
         % specified multi_map.
         %
     :- func multi_map.apply_to_list(list(K), multi_map(K, V)) = list(V).
     :- pred multi_map.apply_to_list(list(K)::in, multi_map(K, V)::in,
         list(V)::out) is det.

         % Declaratively, a NOP.
         % Operationally, a suggestion that the implementation
         % optimize the representation of the multi_map in the expectation
         % of a number of lookups but few or no modifications.
         %
     :- func multi_map.optimize(multi_map(K, V)) = multi_map(K, V).
     :- pred multi_map.optimize(multi_map(K, V)::in, multi_map(K, V)::out) is det.

         % Remove the smallest item from the multi_map.
         % Fails if the multi_map is empty.
         %
     :- pred multi_map.remove_smallest(K::out, list(V)::out,
         multi_map(K, V)::in, multi_map(K, V)::out) is semidet.

     %--------------------------------------------------%
     %--------------------------------------------------%


File: mercury_library.info,  Node: ops,  Next: pair,  Prev: multi_map,  Up: Top

45 ops
******

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 1995-2008, 2010 The University of Melbourne.
     % This file may only be copied under the terms of the GNU Library General
     % Public License - see the file COPYING.LIB in the Mercury distribution.
     %--------------------------------------------------%
     %
     % File: ops.m.
     % Main author: fjh.
     % Stability: low.
     %
     % This module exports a typeclass `ops.op_table' which is used to define
     % operator precedence tables for use by `parser.read_term_with_op_table'
     % and `term_io.write_term_with_op_table'.
     %
     % It also exports an instance `ops.mercury_op_table' that implements the
     % Mercury operator table defined in the Mercury Language Reference Manual.
     %
     % See samples/calculator2.m for an example program.
     %
     % XXX In the current implementation the table of Mercury operators
     % is fixed and cannot be modified at run-time.
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module ops.
     :- interface.

     :- import_module list.

     %--------------------------------------------------%

         % An ops.class describes what structure terms constructed with an operator
         % of that class are allowed to take.
     :- type ops.class
         --->    infix(ops.assoc, ops.assoc)             % term Op term
         ;       prefix(ops.assoc)                       % Op term
         ;       binary_prefix(ops.assoc, ops.assoc)     % Op term term
         ;       postfix(ops.assoc).                     % term Op

         % `x' represents an argument whose priority must be
         % strictly lower than the priority of the operator.
         % `y' represents an argument whose priority must be
         % lower than or equal to the priority of the operator.
     :- type ops.assoc
         --->    x
         ;       y.

         % Operators with a low "priority" bind more tightly than those
         % with a high "priority". For example, given that `+' has
         % priority 500 and `*' has priority 400, the term `2 * X + Y'
         % would parse as `(2 * X) + Y'.
         %
         % The lowest priority is 0.
         %
     :- type ops.priority == int.

     :- type ops.op_info
         --->    op_info(
                     ops.class,
                     ops.priority
                 ).

     %--------------------------------------------------%

     :- typeclass ops.op_table(Table) where [

             % Check whether a string is the name of an infix operator,
             % and if it is, return its precedence and associativity.
             %
         pred lookup_infix_op(Table::in, string::in, ops.priority::out,
             ops.assoc::out, ops.assoc::out) is semidet,

             % Check whether a string is the name of a prefix operator,
             % and if it is, return its precedence and associativity.
             %
         pred ops.lookup_prefix_op(Table::in, string::in,
             ops.priority::out, ops.assoc::out) is semidet,

             % Check whether a string is the name of a binary prefix operator,
             % and if it is, return its precedence and associativity.
             %
         pred ops.lookup_binary_prefix_op(Table::in, string::in,
             ops.priority::out, ops.assoc::out, ops.assoc::out) is semidet,

             % Check whether a string is the name of a postfix operator,
             % and if it is, return its precedence and associativity.
             %
         pred ops.lookup_postfix_op(Table::in, string::in, ops.priority::out,
             ops.assoc::out) is semidet,

             % Check whether a string is the name of an operator.
             %
         pred ops.lookup_op(Table::in, string::in) is semidet,

             % Check whether a string is the name of an operator, and if it is,
             % return the op_info describing that operator in the third argument.
             % If the string is the name of more than one operator, return
             % information about its other guises in the last argument.
             %
         pred ops.lookup_op_infos(Table::in, string::in,
             op_info::out, list(op_info)::out) is semidet,

             % Operator terms are terms of the form `X `Op` Y', where `Op' is
             % a variable or a name and `X' and `Y' are terms. If operator terms
             % are included in `Table', return their precedence and associativity.
             %
         pred ops.lookup_operator_term(Table::in, ops.priority::out,
             ops.assoc::out, ops.assoc::out) is semidet,

             % Returns the highest priority number (the lowest is zero).
             %
         func ops.max_priority(Table) = ops.priority,

             % The maximum priority of an operator appearing as the top-level
             % functor of an argument of a compound term.
             %
             % This will generally be the precedence of `,/2' less one.
             % If `,/2' does not appear in the op_table, `ops.max_priority' plus one
             % may be a reasonable value.
             %
         func ops.arg_priority(Table) = ops.priority
     ].

     %--------------------------------------------------%

         % The table of Mercury operators.
         % See the "Builtin Operators" section of the "Syntax" chapter
         % of the Mercury Language Reference Manual for details.
         %
     :- type ops.mercury_op_table.
     :- instance ops.op_table(ops.mercury_op_table).

     :- func ops.init_mercury_op_table = (ops.mercury_op_table::uo) is det.

     %--------------------------------------------------%
     %--------------------------------------------------%


File: mercury_library.info,  Node: pair,  Next: parser,  Prev: ops,  Up: Top

46 pair
*******

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 1994-2006 The University of Melbourne.
     % This file may only be copied under the terms of the GNU Library General
     % Public License - see the file COPYING.LIB in the Mercury distribution.
     %--------------------------------------------------%
     %
     % File: pair.m.
     % Main author: fjh.
     % Stability: high.
     %
     % The "pair" type.  Useful for many purposes.
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module pair.
     :- interface.

     :- type pair(T1, T2)
         --->    (T1 - T2).
     :- type pair(T) ==  pair(T, T).

     :- inst pair(I1, I2)
         --->    (I1 - I2).
     :- inst pair(I) ==  pair(I, I).

         % Return the first element of the pair.
         %
     :- func fst(pair(X, Y)) = X.
     :- pred fst(pair(X, Y)::in, X::out) is det.

         % Return the second element of the pair.
         %
     :- func snd(pair(X, Y)) = Y.
     :- pred snd(pair(X, Y)::in, Y::out) is det.

     :- func pair(T1, T2) = pair(T1, T2).

     %--------------------------------------------------%
     %--------------------------------------------------%


File: mercury_library.info,  Node: parser,  Next: parsing_utils,  Prev: pair,  Up: Top

47 parser
*********

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 1995-2001, 2003-2008, 2011 The University of Melbourne.
     % This file may only be copied under the terms of the GNU Library General
     % Public License - see the file COPYING.LIB in the Mercury distribution.
     %--------------------------------------------------%
     %
     % File: parser.m.
     % Main author: fjh.
     % Stability: high.
     %
     % This file exports the predicate read_term, which reads
     % a term from the current input stream.
     % The read_term_from_string predicates are the same as the
     % read_term predicates, except that the term is read from
     % a string rather than from the current input stream.
     % The parse_token_list predicate is similar,
     % but it takes a list of tokens rather than a string.
     %
     % The parser and lexer are intended to exactly follow ISO Prolog
     % syntax, but there are some departures from that for three reasons:
     %
     %   (1) I wrote some of the code at home when the ISO Prolog draft
     %       was at uni - so in some places I just guessed.
     %   (2) In some places the lexer reports an error when it shouldn't.
     %   (3) There are a couple of hacks to make it compatible with NU-Prolog
     %       syntax.
     %
     % The parser is a relatively straight-forward top-down recursive descent
     % parser, made somewhat complicated by the need to handle operator
     % precedences.  It uses `lexer.get_token_list' to read a list of tokens.
     % It uses the routines in module `ops' to look up operator precedences.
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module parser.
     :- interface.

     :- import_module io.
     :- import_module lexer.
     :- import_module ops.
     :- import_module term_io.

     %--------------------------------------------------%

         % read_term(Result):
         %
         % Reads a Mercury term from the current input stream.
         %
     :- pred read_term(read_term(T)::out, io::di, io::uo) is det.

         % read_term_with_op_table(Result):
         %
         % Reads a term from the current input stream, using the given op_table
         % to interpret the operators.
         %
     :- pred read_term_with_op_table(Ops::in, read_term(T)::out, io::di, io::uo)
         is det <= op_table(Ops).

         % read_term_filename(FileName, Result, !IO):
         %
         % Reads a term from the current input stream. The string is the filename
         % to use for the current input stream; this is used in constructing the
         % term.contexts in the read term. This interface is used to support
         % the `:- pragma source_file' directive.
         %
     :- pred read_term_filename(string::in, read_term(T)::out, io::di, io::uo)
         is det.

         % read_term_filename_with_op_table(Ops, FileName, Result, !IO):
         %
         % As above but using the given op_table.
         %
     :- pred read_term_filename_with_op_table(Ops::in, string::in,
         read_term(T)::out, io::di, io::uo) is det <= op_table(Ops).

     %--------------------------------------------------%

         % The read_term_from_string predicates are the same as the read_term
         % predicates, except that the term is read from a string rather than from
         % the current input stream. The returned value `EndPos' is the position
         % one character past the end of the term read. The arguments `MaxOffset'
         % and `StartPos' in the six-argument version specify the length of the
         % string and the position within the string at which to start parsing.

         % read_term_from_string(FileName, String, EndPos, Term).
         %
     :- pred read_term_from_string(string::in, string::in, posn::out,
         read_term(T)::out) is det.

         % read_term_from_string_with_op_table(Ops, FileName,
         %   String, EndPos, Term).
         %
     :- pred read_term_from_string_with_op_table(Ops::in, string::in,
         string::in, posn::out, read_term(T)::out) is det <= op_table(Ops).

         % read_term_from_string(FileName, String, MaxOffset, StartPos,
         %   EndPos, Term).
         %
     :- pred read_term_from_substring(string::in, string::in, int::in,
         posn::in, posn::out, read_term(T)::out) is det.

         % read_term_from_string_with_op_table(Ops, FileName, String,
         %   MaxOffset, StartPos, EndPos, Term).
         %
     :- pred read_term_from_substring_with_op_table(Ops::in, string::in,
         string::in, int::in, posn::in, posn::out, read_term(T)::out) is det
         <= op_table(Ops).

     %--------------------------------------------------%

         % parse_tokens(FileName, TokenList, Result):
         %
     :- pred parse_tokens(string::in, token_list::in, read_term(T)::out) is det.

         % parse_tokens(FileName, TokenList, Result):
         %
     :- pred parse_tokens_with_op_table(Ops::in, string::in, token_list::in,
         read_term(T)::out) is det <= op_table(Ops).

     %--------------------------------------------------%
     %--------------------------------------------------%


File: mercury_library.info,  Node: parsing_utils,  Next: pprint,  Prev: parser,  Up: Top

48 parsing_utils
****************

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 2009-2011 The University of Melbourne.
     % This file may only be copied under the terms of the GNU Library General
     % Public License - see the file COPYING.LIB in the Mercury distribution.
     %--------------------------------------------------%
     %
     % File: parsing_utils.m
     % Authors: Ralph Becket <rafe@csse.unimelb.edu.au>, maclarty
     % Stability: low
     %
     % Utilities for recursive descent parsers.  Parsers take at least three
     % arguments: a source (src) containing the input string and a parser state (ps)
     % input/output pair tracking the current offset into the input.
     %
     % Call parse(InputString, SkipWS, Parser, Result) to parse an input string
     % and return an error context and message if parsing failed.
     % The SkipWS predicate is used by the primitive parsers to skip over any
     % following whitespace (providing a skipping predicate allows users to define
     % comments as whitespace).
     % Alternatively a new src and ps can be constructed by calling
     % new_src_and_ps(InputString, SkipWS, Src, !:PS).
     % Parsing predicates are semidet and typically take the form
     % p(...parameters..., Src, Result, !PS).  A parser matching variable
     % assignments of the form `x = 42' might be defined like this:
     %
     %   var_assignment(Src, {Var, Value}, !PS) :-
     %       var(Src, Var, !PS),
     %       punct(Src, "=", !PS),
     %       expr(Src, Expr, !PS).
     %
     % where var/4 and expr/4 are parsers for variables and expressions
     % respectively and punct/4 is provided by this module for matching
     % punctuation.
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module parsing_utils.
     :- interface.

     :- import_module char.
     :- import_module list.
     :- import_module maybe.
     :- import_module unit.

     %--------------------------------------------------%

         % The parser source (input string).
         %
     :- type src.

         % The parser "state", passed around in DCG arguments.
         %
     :- type ps.

         % These types and insts are useful for specifying "standard" parser
         % signatures.
         %
     :- type parser(T) == pred(src, T, ps, ps).
     :- inst parser == ( pred(in, out, in, out) is semidet ).

         % The following are for parsers that also transform a separate state value.
         %
     :- type parser_with_state(T, S) == pred(src, T, S, S, ps, ps).
     :- inst parser_with_state == ( pred(in, out, in, out, in, out) is semidet ).

         % Predicates of this type are used to skip whitespace in the primitive
         % parsers provided by this module.
         %
     :- type skip_whitespace_pred == parser(unit).

     :- type parse_result(T)
         --->    ok(T)
         ;       error(
                     error_message :: maybe(string),
                     error_line    :: int,
                     error_col     :: int
                 ).

         % parse(Input, SkipWS, Parser, Result).
         % Try to parse Input using Parser and SkipWS to consume whitespace.
         % If Parser succeeds then return ok with the parsed value,
         % otherwise return error.  If there were any calls to fail_with_message
         % without any subsequent progress being made, then the error message
         % passed to the last call to fail_with_message will be returned in the
         % error result.  Otherwise no message is returned and the furthest
         % position the parser got in the input string is returned.
         %
     :- pred parse(string::in, skip_whitespace_pred::in(parser),
         parser(T)::in(parser), parse_result(T)::out) is cc_multi.

         % As above but using the default whitespace parser.
         %
     :- pred parse(string::in, parser(T)::in(parser), parse_result(T)::out)
         is cc_multi.

         % Construct a new parser source and state from a string, also specifying
         % a predicate for skipping over whitespace (several primitive parsers
         % use this predicate to consume whitespace after a token; this argument
         % allows the user to specify a predicate for, say, skipping over comments
         % as well).
         %
     :- pred new_src_and_ps(string::in,
         skip_whitespace_pred::in(parser),
         src::out, ps::out) is det.

         % Construct a new parser source and state from a string (the default
         % whitespace parser is used).
         %
     :- pred new_src_and_ps(string::in, src::out, ps::out) is det.

         % Obtain the current offset from the start of the input string
         % (the first character in the input has offset 0).
         %
     :- pred current_offset(src::in, int::out, ps::in, ps::out) is det.

         % Compute a structure from the parser source which can be used to
         % convert offsets into line numbers and positions in the file (this
         % is useful for error reporting).
         %
     :- type line_numbers.

     :- func src_to_line_numbers(src) = line_numbers.

         % Convert an offset into a line number and position within the line
         % (the first line is number 1; the first character in a line is
         % position 1).
         %
     :- pred offset_to_line_number_and_position(line_numbers::in, int::in,
         int::out, int::out) is det.

         % input_substring(Src, StartOffset, EndOffsetPlusOne, Substring):
         % Copy the substring from the input occupying the offsets
         % [StartOffset, EndOffsetPlusOne).
         %
     :- pred input_substring(src::in, int::in, int::in, string::out) is semidet.

         % Read the next char.
         %
     :- pred next_char(src::in, char::out, ps::in, ps::out) is semidet.

         % Match a char from the given string.
         %
     :- pred char_in_class(string::in, src::in, char::out,
         ps::in, ps::out) is semidet.

         % Match a string exactly and any subsequent whitespace.
         %
     :- pred punct(string::in, src::in, unit::out, ps::in, ps::out) is semidet.

         % keyword(IdChars, Keyword, Src, _, !PS) matches Keyword exactly (i.e., it
         % must not be followed by any character in IdChars) and any subsequent
         % whitespace.
         %
     :- pred keyword(string::in, string::in, src::in, unit::out,
         ps::in, ps::out) is semidet.

         % ikeyword(IdChars, Keyword, Src, _, !PS)
         % Case-insensitive version of keyword/6.
         % Only upper and lowercase unaccented Latin letters are treated specially.
         %
     :- pred ikeyword(string::in, string::in, src::in, unit::out,
         ps::in, ps::out) is semidet.

         % identifier(InitIdChars, IdChars, Src, Identifier, !PS) matches the next
         % identifier (result in Identifier) comprising a char from InitIdChars
         % followed by zero or more chars from IdChars.  Any subsequent whitespace
         % is consumed.
         %
     :- pred identifier(string::in, string::in, src::in, string::out,
         ps::in, ps::out) is semidet.

         % Consume any whitespace (defined as a sequence of characters
         % satisfying char.is_whitespace).
         %
     :- pred whitespace(src::in, unit::out,
         ps::in, ps::out) is semidet.

         % Consume any input up to, and including, the next newline character
         % marking the end of the current line.
         %
     :- pred skip_to_eol(src::in, unit::out,
         ps::in, ps::out) is semidet.

         % Succeed if we have reached the end of the input.
         %
     :- pred eof(src::in, unit::out, ps::in, ps::out) is semidet.

         % Parse a float literal matching [-][0-9]+[.][0-9]+([Ee][-][0-9]+)?
         % followed by any whitespace.  The float_literal_as_string version simply
         % returns the matched string.  The float_literal version uses
         % string.to_float to convert the output of float_literal_as_string; this
         % may return an approximate answer since not all floating point numbers
         % can be perfectly represented as Mercury floats.
         %
     :- pred float_literal_as_string(src::in, string::out,
         ps::in, ps::out) is semidet.
     :- pred float_literal(src::in, float::out,
         ps::in, ps::out) is semidet.

         % Parse an int literal matching [-][0-9]+, not followed by [.][0-9]+,
         % followed by any whitespace.  The int_literal_as_string version simply
         % returns the matched string.  The int_literal version uses string.to_int
         % to convert the output of int_literal_as_string; this may fail if the
         % number in question cannot be represented as a Mercury int.
         %
     :- pred int_literal_as_string(src::in, string::out,
         ps::in, ps::out) is semidet.
     :- pred int_literal(src::in, int::out,
         ps::in, ps::out) is semidet.

         % Parse an string literal.  The string argument is the quote character.
         % A backslash (\) character in the string makes the next character
         % literal (e.g., for embedding quotes).  These 'escaped' characters
         % are included as-is in the result, along with the preceding backslash.
         % Any following whitespace is also consumed.
         %
     :- pred string_literal(char::in, src::in, string::out,
         ps::in, ps::out) is semidet.

         % optional(P, Src, Result, !PS) returns Result = yes(X), if P(Src, X, !PS),
         % or Result = no if P does not succeed.
         %
     :- pred optional(parser(T)::in(parser), src::in, maybe(T)::out,
         ps::in, ps::out) is semidet.

         % zero_or_more(P, Src, Xs, !PS) returns the list of results Xs obtained
         % by repeatedly applying P until P fails.  The nth item in Xs is
         % the result from the nth application of P.
         %
     :- pred zero_or_more(parser(T)::in(parser), src::in, list(T)::out,
         ps::in, ps::out) is semidet.

         % one_or_more(P, Src, Xs, !PS) returns the list of results Xs obtained
         % by repeatedly applying P until P fails.  The nth item in Xs is
         % the result from the nth application of P.  P must succeed at
         % least once.
         %
     :- pred one_or_more(parser(T)::in(parser), src::in, list(T)::out,
         ps::in, ps::out) is semidet.

         % brackets(L, R, P, Src, X, !PS) is equivalent to
         %   punct(L, Src, _, !PS), P(Src, X, !PS), punct(R, Src, _, !PS).
         %
     :- pred brackets(string::in, string::in, parser(T)::in(parser), src::in,
         T::out, ps::in, ps::out) is semidet.

         % separated_list(Separator, P, Src, Xs, !PS) is like
         % zero_or_more(P, Src, Xs, !PS) except that successive applications of
         % P must be separated by punct(Separator, Src, _, !PS).
         %
     :- pred separated_list(string::in, parser(T)::in(parser), src::in,
         list(T)::out, ps::in, ps::out) is semidet.

         % comma_separated_list(P, Src, Xs) is the same as
         %   separated_list(",", P, Src, Xs).
         %
     :- pred comma_separated_list(parser(T)::in(parser), src::in, list(T)::out,
         ps::in, ps::out) is semidet.

         % Declaratively this predicate is equivalent to false.  Operationally
         % it will record an error message that will be returned by parse/4
         % if no further progress is made and then fail.
         %
     :- pred fail_with_message(string::in, src::in, T::out, ps::in, ps::out)
         is semidet.

         % As above, but use the given offset for the context of the message.
         %
     :- pred fail_with_message(string::in, int::in, src::in, T::out,
         ps::in, ps::out) is semidet.

     % The following parser combinators are equivalent to the above, except that
     % a separate state argument is threaded through the computation (e.g., for
     % parsers that incrementally construct a symbol table).

         % optional(P, Src, Result, !S, !PS) returns Result = yes(X),
         % if P(Src, X, !S, !PS), or Result = no if P does not succeed.
         %
     :- pred optional(parser_with_state(T, S)::in(parser_with_state), src::in,
         maybe(T)::out, S::in, S::out, ps::in, ps::out) is semidet.

         % zero_or_more(P, Src, Xs, !S, !PS) returns the list of results Xs obtained
         % by repeatedly applying P until P fails.  The nth item in Xs is
         % the result from the nth application of P.
         %
     :- pred zero_or_more(parser_with_state(T, S)::in(parser_with_state), src::in,
         list(T)::out, S::in, S::out, ps::in, ps::out) is semidet.

         % one_or_more(P, Src, Xs, !S, !PS) returns the list of results Xs obtained
         % by repeatedly applying P until P fails.  The nth item in Xs is
         % the result from the nth application of P.  P must succeed at
         % least once.
         %
     :- pred one_or_more(parser_with_state(T, S)::in(parser_with_state), src::in,
         list(T)::out, S::in, S::out, ps::in, ps::out) is semidet.

         % brackets(L, R, P, Src, X, !S, !PS) is equivalent to
         %   punct(L, Src, _, !PS), P(Src, X, !S, !PS), punct(R, Src, _, !PS).
         %
     :- pred brackets(string::in, string::in,
         parser_with_state(T, S)::in(parser_with_state), src::in,
         T::out, S::in, S::out, ps::in, ps::out) is semidet.

         % separated_list(Separator, P, Src, Xs, !S, !PS) is like
         % zero_or_more(P, Src, Xs, !S, !PS) except that successive applications of
         % P must be separated by punct(Separator, Src, _, !PS).
         %
     :- pred separated_list(string::in,
         parser_with_state(T, S)::in(parser_with_state),
         src::in, list(T)::out, S::in, S::out, ps::in, ps::out) is semidet.

         % comma_separated_list(P, Src, Xs, !S, !PS) is the same as
         %   separated_list(",", P, Src, Xs, !S, !PS).
         %
     :- pred comma_separated_list(parser_with_state(T, S)::in(parser_with_state),
         src::in, list(T)::out, S::in, S::out, ps::in, ps::out) is semidet.

     %--------------------------------------------------%
     %--------------------------------------------------%


File: mercury_library.info,  Node: pprint,  Next: pqueue,  Prev: parsing_utils,  Up: Top

49 pprint
*********

     %--------------------------------------------------%
     % vim:ts=4 sw=4 expandtab tw=0 wm=0 ft=mercury
     %--------------------------------------------------%
     % Copyright (C) 2000-2007, 2010-2011 The University of Melbourne
     % This file may only be copied under the terms of the GNU Library General
     % Public License - see the file COPYING.LIB in the Mercury distribution.
     %--------------------------------------------------%
     %
     % File: pprint.m
     % Main author: rafe
     % Stability: medium
     %
     % NOTE: this module has now been superceded by pretty_printer.m which is
     % more economical, produces better output, has better control over
     % the amount of output produced, and supports user-specifiable formatting
     % for arbitrary types.
     %
     % ABOUT
     % -----
     %
     % This started off as pretty much a direct transliteration of Philip Wadler's
     % Haskell pretty printer described in "A Prettier Printer", available at
     % http://cm.bell-labs.com/cm/cs/who/wadler/topics/recent.html
     %
     % Several changes have been made to the algorithm to preserve linear running
     % time under a strict language and to ensure scalability to extremely large
     % terms without thrashing the VM system.
     %
     % Wadler's approach has three main advantages:
     % 1. the layout algebra is small and quite intuitive (more so than Hughes');
     % 2. the pretty printer is optimal in the sense that it will never generate
     %    output that over-runs the specified width unless that is unavoidable; and
     % 3. the pretty printer is bounded in that it never needs to look more than
     %    k characters ahead to make a formatting decision.
     %
     % I have made the following changes:
     %
     % (a) rather than having group/1 as a non-primitive function (for
     % allowing line-breaks to be converted into spaces at the pretty
     % printer's discretion) over docs, I have extended the doc type to
     % include a `GROUP' constructor and made the appropriate algorithmic
     % changes.  Because `UNION' only arises as a consequence of processing
     % a 'GROUP' it turns out to be simpler to do away with `UNION'
     % altogether and convert clauses that process `UNION' terms to
     % processing `GROUP's.
     %
     % (b) Flattened `line' breaks become empty strings rather than spaces.
     %
     % (c) The third change is the introduction of the `LABEL' constructor,
     % which acts much like `NEST', except that indentation is defined
     % using a string rather than a number of spaces.  This is useful for,
     % e.g., multi-line compiler errors and warnings that should be
     % prefixed with the offending source file and line number.
     %
     % (d) The formatting decision procedure has been altered to preserve
     % linear runtime behaviour in a strict language.
     %
     % (e) Naively marking up a term as a doc has the drawback that the
     % resulting doc is significantly larger than the original term.
     % Worse, any sharing structure in the original term leads to
     % duplicated sub-docs, which can cause an exponential blow-up in the
     % size of the doc w.r.t. the source term.  To get around this problem
     % I have introduced the 'DOC' constructor which causes on-demand
     % conversion of arguments.
     %
     % [This is not true laziness in the sense that the 'DOC', once
     % evaluated, will be overwritten with its value.  This approach would
     % lead to garbage retention and not solve the page thrashing behaviour
     % otherwise experienced when converting extremely large terms.
     % Instead, each 'DOC' is reevaluated each time it is examined.  This
     % trades off computation time for space.]
     %
     % I have added several obvious general purpose formatting functions.
     %
     %
     % USAGE
     % -----
     %
     % There are two stages in pretty printing an object of some type T:
     % 1. convert the object to a pprint.doc using the constructor functions
     %    described below or by simply calling pprint.to_doc/[1,2];
     % 2. call pprint.write/[4,5] or pprint.to_string/2 passing the display width
     %    and the doc.
     %
     %
     % EXAMPLES
     % --------
     %
     % The doc/1 type class has types string, char, int, float and doc as instances.
     % Hence these types can all be converted to docs by applying doc/1.
     % This happens automatically to the arguments of ++/2. Users may find it
     % convenient to add other types as instances of the doc/1 type class.
     %
     % Below are some docs followed by the ways they might be displayed by the
     % pretty printer given various line widths.
     %
     % 1. "Hello " ++ line ++ "world"
     %
     %   Hello
     %   world
     %
     % 2. group("Hello " ++ line ++ "world")
     %
     %   Hello world
     %
     %   Hello
     %   world
     %
     % 3. group("Hello " ++ nest(3, line ++ "world"))
     %
     %   Hello world
     %
     %   Hello
     %      world
     %
     % 4. group("Goodbye " ++ nest(3, line ++ "cruel " ++ line ++ "world")
     %
     %   Goodbye cruel world
     %
     %   Goodbye
     %      cruel
     %      world
     %
     % 5. group("Goodbye " ++ nest(3, line ++ group("cruel " ++ line ++ "world")))
     %
     %   Goodbye cruel world
     %
     %   Goodbye
     %      cruel world
     %
     %   Goodbye
     %      cruel
     %      world
     %
     % 6. label("Look! ", line ++
     %                    group("Goodbye " ++
     %                          nest(3, line ++ group("cruel " ++ line ++ "world"))))
     %
     %   Look! Goodbye cruel world
     %
     %   Look! Goodbye
     %   Look!    cruel world
     %
     %   Look! Goodbye
     %   Look!    cruel
     %   Look!    world
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module pprint.
     :- interface.

     :- import_module char.
     :- import_module io.
     :- import_module list.
     :- import_module stream.
     :- import_module string.
     :- import_module univ.

     %--------------------------------------------------%

         % Clients must translate data structures into docs for
         % the pretty printer to display.
         %
     :- type doc.

         % This typeclass can be used to simplify the construction of docs.
         %
     :- typeclass doc(T) where [
         % Convert a T to a doc, placing a limit on how much of the term
         % will be fully converted as follows:
         %
         % doc(_, f         ) = f
         % doc(N, f(A, B, C)) = f/3 if N =< 0
         % doc(N, f(A, B, C)) = some representation of the term whereby
         %   A is converted as doc(N - 1, A),
         %   B is converted as doc(N - 2, B), and
         %   C is converted as doc(N - 3, C)
         %   - if there are more than N arguments, the N+1th and subsequent
         %     arguments should be replaced with a single ellipsis.
         %
         func doc(int, T) = doc
     ].

     :- instance doc(doc).
     :- instance doc(string).
     :- instance doc(int).
     :- instance doc(float).
     :- instance doc(char).

         % Fully convert an instance of doc/1.
         %
     :- func doc(T) = doc <= (doc(T)).

         % An alternative to the <>/2 concatenation operator that works
         % on members of the doc/1 typeclass.
         %
     :- func T1 ++ T2 = doc <= (doc(T1), doc(T2)).

         % The empty document corresponding to the null string.
         %
     :- func nil                 = doc.

         % The document consisting of a single string.
         %
         % NOTE: since string is now an instance of the doc/1
         % type class, it is simpler to just apply the doc/1
         % method.
         %
     :- func text(string)        = doc.

         % The composition of two docs with no intervening space.
         %
         % NOTE: with the addition of the doc/1 type class, it is
         % simpler to construct compound docs using ++/2.
         %
     :- func doc `<>` doc        = doc.

         % The newline document. In a group doc (see below) the pretty printer
         % may choose to instead `flatten' all line docs into nil docs in order
         % to fit a doc on a single line.
         %
     :- func line                = doc.

         % Any `line' docs in the body that are not flattened out by the
         % pretty printer are followed by the given number of spaces
         % (nested `nest's add up).
         %
     :- func nest(int, T)        = doc <= (doc(T)).

         % Identical to a nest doc except that indentation is extended with
         % a string label rather than some number of spaces.
         %
     :- func label(string, T)    = doc <= (doc(T)).

         % A group doc gives the pretty printer a choice: if the doc can be printed
         % without line wrapping then it does so (all line, label, nest and group
         % directives within the group are ignored); otherwise the pretty printer
         % treats the group body literally, although nested group docs remain as
         % choice points.
         %
     :- func group(T)            = doc <= (doc(T)).

         % This function can be used to convert strings, chars, ints and floats
         % to their text doc equivalents.
         %
         % NOTE: since these types are now instances of the doc/1 type class,
         % it is simpler to just apply the doc/1 method to these types.
         %
     :- func poly(string.poly_type) = doc.

         % Shorthand for doc ++ line ++ doc.
         %
     :- func doc `</>` doc       = doc.

         % Various bracketing functions.
         %
         %   bracketed(L, R, Doc) = L ++ Doc ++ R
         %       parentheses(Doc) = bracketed("(", ")", Doc)
         %          brackets(Doc) = bracketed("[", "]", Doc)
         %            braces(Doc) = bracketed("{", "}", Doc)
         %
     :- func bracketed(T1, T2, T3)  = doc <= (doc(T1), doc(T2), doc(T3)).
     :- func parentheses(T)         = doc <= (doc(T)).
     :- func brackets(T)            = doc <= (doc(T)).
     :- func braces(T)              = doc <= (doc(T)).

         % packed(Sep, [X1, X2, .., Xn]) = G1 `<>` G2 `<>` .. `<>` Gn where
         % Gi = group(line `<>` Xi `<>` Sep), except for Gn where
         % Gn = group(line `<>` Xn).
         %
         % For the singleton list case, packed(Sep, [X]) = group(line `<>` X).
         %
         % The resulting doc tries to pack as many items on a line as possible.
         %
     :- func packed(T1, list(T2)) = doc <= (doc(T1), doc(T2)).

         % A variant of the above whereby only the first N elements of the list
         % are formatted and the rest are replaced by a single ellipsis.
         %
     :- func packed(int, T1, list(T2)) = doc <= (doc(T1), doc(T2)).

         % packed_cs(Xs) = packed(comma_space, Xs).
         %
         % For example, to pretty print a Mercury list of docs one might use
         %
         %   brackets(nest(2, packed_cs(Xs)))
         %
     :- func packed_cs(list(T)) = doc <= (doc(T)).

         % A variant of the above whereby only the first N elements of the list
         % are formatted and the rest are replaced by a single ellipsis.
         %
     :- func packed_cs(int, list(T)) = doc <= (doc(T)).

         % This is like a depth-limited version of packed_cs/1 that first calls
         % to_doc/2 on each member of the argument list.
         %
     :- func packed_cs_to_depth(int, list(T)) = doc.

         % This is like a version of packed_cs_to_depth/1 that first calls
         % univ_value/1 for each member of the argument list.
         %
     :- func packed_cs_univ_args(int, list(univ)) = doc.

         % separated(PP, Sep, [X1,...,Xn]) =
         %   PP(X1) `<>` Sep `<>` ... Sep `<>` PP(Xn)
         %
     :- func separated(func(T1) = doc, T2, list(T1)) = doc <= (doc(T2)).

         % Handy punctuation docs and versions with following
         % spaces and/or line breaks.
         %
     :- func comma               = doc.
     :- func semic               = doc.      % Semicolon.
     :- func colon               = doc.
     :- func space               = doc.
     :- func comma_space         = doc.
     :- func semic_space         = doc.
     :- func colon_space         = doc.
     :- func comma_line          = doc.
     :- func semic_line          = doc.
     :- func colon_line          = doc.
     :- func space_line          = doc.
     :- func comma_space_line    = doc.
     :- func semic_space_line    = doc.
     :- func colon_space_line    = doc.
     :- func ellipsis            = doc.      % "...".

         % Performs word wrapping at the end of line, taking whitespace sequences
         % as delimiters separating words.
         %
     :- func word_wrapped(string) = doc.

         % Convert arbitrary terms to docs. This requires std_util.functor/3 to work
         % on all components of the object being converted. The second version
         % places a maximum depth on terms which are otherwise truncated in the
         % manner described in the documentation for the doc/2 method of the doc/1
         % type class.
         %
         % This may throw an exception or cause a runtime abort if the term
         % in question has user-defined equality.
         %
     :- func to_doc(T)           = doc.
     :- func to_doc(int, T)      = doc.

         % Convert docs to pretty printed strings. The int argument specifies
         % a line width in characters.
         %
     :- func to_string(int, doc) = string.

         % Write docs out in pretty printed format. The int argument specifies
         % a page width in characters.
         %
     :- pred write(int::in, T::in, io::di, io::uo) is det <= doc(T).

         % Write docs to the specified string writer stream in pretty printed
         % format. The int argument specifies a page width in characters.
         %
     :- pred write(Stream::in, int::in, T::in, State::di, State::uo) is det
         <= ( doc(T), stream.writer(Stream, string, State) ).

     %--------------------------------------------------%
     %--------------------------------------------------%


File: mercury_library.info,  Node: pqueue,  Next: pretty_printer,  Prev: pprint,  Up: Top

50 pqueue
*********

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 1994-1995, 1997, 1999, 2003-2007, 2009 The University of
     % Melbourne.
     %
     % This file may only be copied under the terms of the GNU Library General
     % Public License - see the file COPYING.LIB in the Mercury distribution.
     %--------------------------------------------------%
     %
     % File: pqueue.m.
     % Main author: conway.
     % Stability: high.
     %
     % This module implements a priority queue ADT.
     %
     % A pqueue is a priority queue.  A priority queue holds a collection
     % of key-value pairs; the interface provides operations to create
     % an empty priority queue, to insert a key-value pair into a priority
     % queue, and to remove the element with the lowest key.
     %
     % Insertion/removal is not guaranteed to be "stable"; that is,
     % if you insert two values with the same key, the order in which
     % they will be removed is unspecified.
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module pqueue.
     :- interface.

     :- import_module assoc_list.

     %--------------------------------------------------%

     :- type pqueue(K, V).

         % Create an empty priority queue.
         %
     :- func pqueue.init = pqueue(K, V).
     :- pred pqueue.init(pqueue(K, V)::out) is det.

         % Insert a value V with key K into a priority queue
         % and return the new priority queue.
         %
     :- func pqueue.insert(pqueue(K, V), K, V) = pqueue(K, V).
     :- pred pqueue.insert(pqueue(K, V)::in, K::in, V::in, pqueue(K, V)::out)
         is det.

         % Remove the smallest item from the priority queue.
         % Fails if the priority queue is empty.
         %
     :- pred pqueue.remove(pqueue(K, V)::in, K::out, V::out, pqueue(K, V)::out)
         is semidet.

         % As above, but calls error/1 if the priority queue is empty.
         %
     :- pred pqueue.det_remove(K::out, V::out, pqueue(K, V)::in, pqueue(K, V)::out)
         is det.

         % Extract all the items from a priority queue by repeated
         % removal, and place them in an association list.
         %
     :- func pqueue.to_assoc_list(pqueue(K, V)) = assoc_list(K, V).
     :- pred pqueue.to_assoc_list(pqueue(K, V)::in, assoc_list(K, V)::out) is det.

         % Insert all the key-value pairs in an association list
         % into a priority queue.
         %
     :- func pqueue.assoc_list_to_pqueue(assoc_list(K, V)) = pqueue(K, V).
     :- pred pqueue.assoc_list_to_pqueue(assoc_list(K, V)::in, pqueue(K, V)::out)
         is det.

         % A synonym for pqueue.assoc_list_to_pqueue/1.
         %
     :- func pqueue.from_assoc_list(assoc_list(K, V)) = pqueue(K, V).

         % length(PQueue) = Length.
         %
         % Length is the number of items in PQueue
         %
     :- func pqueue.length(pqueue(K, V)) = int.

     %--------------------------------------------------%
     %--------------------------------------------------%


File: mercury_library.info,  Node: pretty_printer,  Next: prolog,  Prev: pqueue,  Up: Top

51 pretty_printer
*****************

     %--------------------------------------------------%
     % vim: ts=4 sw=4 expandtab tw=0 wm=0 ft=mercury
     %--------------------------------------------------%
     % Copyright (C) 2007, 2009-2011 The University of Melbourne
     % This file may only be copied under the terms of the GNU Library General
     % Public License - see the file COPYING.LIB in the Mercury distribution.
     %--------------------------------------------------%
     %
     % File: pretty_printer.m
     % Main author: rafe
     % Stability: medium
     %
     % This module defines a doc type for formatting and a pretty printer for
     % displaying docs.
     %
     % The doc type includes data constructors for outputting strings, newlines,
     % forming groups, indented blocks, and arbitrary values.
     %
     % The key feature of the algorithm is this: newlines in a group are ignored if
     % the group can fit on the remainder of the current line.  [The algorithm is
     % similar to those of Oppen and Wadler, although it uses neither coroutines or
     % laziness.]
     %
     % When a newline is printed, indentation is also output according to the
     % current indentation level.
     %
     % The pretty printer includes special support for formatting Mercury style
     % terms in a way that respects Mercury's operator precedence and
     % bracketing rules.
     %
     % The pretty printer takes a parameter specifying a collection of user-defined
     % formatting functions for handling certain types rather than using the
     % default built-in mechanism.  This allows one to, say, format maps as
     % sequences of (key -> value) pairs rather than exposing the underlying
     % 234-tree structure.
     %
     % The amount of output produced is controlled via limit parameters.  Three
     % kinds of limits are supported: the output line width, the maximum number of
     % lines to be output, and a limit on the depth for formatting arbitrary terms.
     % Output is replaced with ellipsis ("...") when limits are exceeded.
     %
     %--------------------------------------------------%

     :- module pretty_printer.
     :- interface.

     :- import_module deconstruct.
     :- import_module list.
     :- import_module io.
     :- import_module stream.
     :- import_module type_desc.
     :- import_module univ.

     %--------------------------------------------------%

     :- type doc
         --->    str(string)
                 % Output a literal string. Strings containing newlines, hard tabs,
                 % etc. will lead to strange output.

         ;       nl
                 % Output a newline, followed by indentation, iff the enclosing
                 % group does not fit on the current line and starting a new line
                 % adds more space.

         ;       hard_nl
                 % Always outputs a newline, followed by indentation.

         ;       docs(docs)
                 % An embedded sequence of docs.

         ;       format_univ(univ)
                 % Use a specialised formatter if available, otherwise use the
                 % generic formatter.

         ;       format_list(list(univ), doc)
                 % Pretty print a list of items using the given doc as a separator
                 % between items.

         ;       format_term(string, list(univ))
                 % Pretty print a term with zero or more arguments. If the term
                 % corresponds to a Mercury operator it will be printed with
                 % appropriate fixity and, if necessary, in parentheses. The term
                 % name will be quoted and escaped if necessary.

         ;       format_susp((func) = doc)
                 % The argument is a suspended computation used to lazily produce a
                 % doc. If the formatting limit has been reached then just "..." is
                 % output, otherwise the suspension is evaluated and the resulting
                 % doc is used. This is useful for formatting large structures
                 % without using more resources than required. Expanding a
                 % suspended computation reduces the formatting limit by one.

         ;       pp_internal(pp_internal).
                 % pp_internal docs are used in the implementation and cannot
                 % be exploited by user code.

     :- type docs == list(doc).

         % This type is private to the implementation. It cannot be exploited by
         % user code.
         %
     :- type pp_internal.

         % indent(IndentString, Docs):
         %
         % Append IndentString to the current indentation while printing Docs.
         % Indentation is printed after each newline that is output.
         %
     :- func indent(string, docs) = doc.

         % indent(Docs) = indent("  ", Docs).
         %   A convenient abbreviation.
         %
     :- func indent(docs) = doc.

         % group(Docs):
         %
         % If Docs can be output on the remainder of the current line by ignoring
         % any nls in Docs, then do so. Otherwise nls in Docs are printed
         % (followed by any indentation). The formatting test is applied recursively
         % for any subgroups in Docs.
         %
     :- func group(docs) = doc.

         % format(X) = format_univ(univ(X)):
         % A convenient abbreviation.
         %
     :- func format(T) = doc.

         % format_arg(Doc) has the effect of formatting any term in Doc as though
         % it were an argument in a Mercury term by enclosing it in parentheses if
         % necessary.
         %
     :- func format_arg(doc) = doc.

         % The pretty-printer limit type, used to control conversion by
         % format_univ, format_list, and format_term.
         %
         % A limit of linear(N) formats the first N functors before truncating
         % output to "...".
         %
         % A limit of triangular(N) formats a term t(X1, ..., Xn) by applying a
         % limit of triangular(N - 1) when formatting X1, triangular(N - 2) when
         % formatting X2, ..., and triangular(N - n) when formatting Xn.
         % The cost of formatting the term t(X1, ..., Xn) as a whole is just one,
         % so a sequence of terms T1, T2, ... is formatted with limits
         % triangular(N), triangular(N - 1), ... respectively.  When the
         % limit is exhausted, terms are output as just "...".
         %
     :- type formatting_limit
         --->    linear(int)                 % Print this many functors.
         ;       triangular(int).            % Print first arg with limit N-1,
                                             % second arg with limit N-2, ...

         % The type of generic formatting functions.
         % The first argument is the univ of the value to be formatted.
         % The second argument is the list of argument type_descs for
         % the type of the first argument.
         %
     :- type formatter == ( func(univ, list(type_desc)) = doc ).

         % A formatter_map maps types to pps.  Types are identified by module name,
         % type name, and type arity.
         %
     :- type formatter_map.

         % Construct a new formatter_map.
         %
     :- func new_formatter_map = formatter_map.

         % set_formatter(ModuleName, TypeName, TypeArity, Formatter, FMap):
         %
         % Update FMap to use Formatter to format the type
         % ModuleName.TypeName/TypeArity.
         %
     :- func set_formatter(string, string, int, formatter, formatter_map) =
         formatter_map.



         % format(Stream, FMap, LineWidth, MaxLines, Limit, Doc, !State):
         %
         % Format Doc to fit on lines of LineWidth chars, truncating after
         % MaxLines lines, fomatting format_univ(_) docs using specialised
         % formatters Formatters starting with pretty-printer limits Limit.
         %
     :- pred write_doc_to_stream(Stream, noncanon_handling, formatter_map, int, int,
         formatting_limit, doc, State, State)
         <= stream.writer(Stream, string, State).
     :- mode write_doc_to_stream(in, in(canonicalize), in, in, in, in, in,
         di, uo) is det.
     :- mode write_doc_to_stream(in, in(include_details_cc), in, in, in, in, in,
         di, uo) is cc_multi.

         % Convenience predicates.  A user-configurable set of type-specific
         % formatters and formatting parameters are attached to the I/O state.
         % The I/O state-specific format predicate below uses this settings.
         %
     :- type pp_params
         --->    pp_params(
                     pp_line_width   :: int,             % Line width in characters.
                     pp_max_lines    :: int,             % Max lines to output.
                     pp_limit        :: formatting_limit % Term formatting limit.
                 ).

         % An initial default formatter_map is provided for the most commonly
         % used types in the Mercury standard library (array, char, float,
         % int, map, string, etc.)
         %
         % The default formatter_map may also be updated by users' modules
         % (e.g., in initialisation goals).
         %
         % These defaults are thread local (i.e., changes made by one thread to
         % the default formatter_map will not be visible in another thread).
         %
     :- pred get_default_formatter_map(formatter_map::out, io::di, io::uo) is det.
     :- pred set_default_formatter_map(formatter_map::in, io::di, io::uo) is det.
     :- pred set_default_formatter(string::in, string::in, int::in, formatter::in,
         io::di, io::uo) is det.

         % The initial default pp_params are pp_params(78, 100, triangular(100)).
         % These defaults are thread local (i.e., changes made by one thread to
         % the default pp_params will not be visible in another thread).
         %
     :- pred get_default_params(pp_params::out, io::di, io::uo) is det.
     :- pred set_default_params(pp_params::in, io::di, io::uo) is det.

         % write_doc(Doc, !IO):
         % write_doc(FileStream, Doc, !IO):
         %
         % Format Doc to io.stdout_stream or FileStream respectively, using
         % write_doc_to stream, with include_details_cc, the default formatter_map,
         % and the default pp_params.
         %
     :- pred write_doc(doc::in, io::di, io::uo) is det.
     :- pred write_doc(io.output_stream::in, doc::in, io::di, io::uo) is det.

     %--------------------------------------------------%
     %--------------------------------------------------%


File: mercury_library.info,  Node: prolog,  Next: queue,  Prev: pretty_printer,  Up: Top

52 prolog
*********

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 1997-2003, 2005-2006 The University of Melbourne.
     % This file may only be copied under the terms of the GNU Library General
     % Public License - see the file COPYING.LIB in the Mercury distribution.
     %--------------------------------------------------%
     %
     % File: prolog.m.
     % Main author: fjh.
     % Stability: high.
     %
     % This file contains predicates that are intended to help people
     % porting Prolog programs, or writing programs in the intersection
     % of Mercury and Prolog.
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module prolog.
     :- interface.

     :- import_module list.
     :- import_module pair.
     :- import_module univ.

     %--------------------------------------------------%
     %
     % Prolog arithmetic operators
     %

     :- pred T =:= T.            % In Mercury, just use =
     :- mode in =:= in is semidet.

     :- pred T =\= T.            % In Mercury, just use \=
     :- mode in =\= in is semidet.

     /*******
     is/2 is currently defined in int.m, for historical reasons.

     :- pred is(T, T) is det.        % In Mercury, just use =
     :- mode is(uo, di) is det.
     :- mode is(out, in) is det.
     ******/

     %--------------------------------------------------%
     %
     % Prolog term comparison operators
     %

     :- pred T == T.             % In Mercury, just use =
     :- mode in == in is semidet.

     :- pred T \== T.            % In Mercury, just use \=
     :- mode in \== in is semidet.

     % Prolog's so-called "univ" operator, `=..'.
     % Note: this is not related to Mercury's "univ" type!
     % In Mercury, use `deconstruct.deconstruct' instead.

     :- pred T =.. univ_result.
     :- mode in =.. out is det.
         %
         % Note that the Mercury =.. is a bit different to the Prolog
         % one.  We could make it slightly more similar by overloading '.'/2,
         % but that would cause ambiguities that might prevent type
         % inference in a lot of cases.
         %
     % :- type univ_result ---> '.'(string, list(univ)).
     :- type univ_result == pair(string, list(univ)).

         % arg/3.  In Mercury, use argument/3 (defined in module std_util)
         % instead:
         %      arg(ArgNum, Term, Data) :- argument(Term, ArgNum - 1, Data).
         %
     :- pred arg(int::in, T::in, univ::out) is semidet.

         % det_arg/3: like arg/3, but calls error/1 rather than failing
         % if the index is out of range.
         %
     :- pred det_arg(int::in, T::in, univ::out) is det.

     %--------------------------------------------------%
     %--------------------------------------------------%


File: mercury_library.info,  Node: queue,  Next: random,  Prev: prolog,  Up: Top

53 queue
********

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 1994-1995, 1997-1999, 2003-2006, 2011 The University of Melbourne.
     % This file may only be copied under the terms of the GNU Library General
     % Public License - see the file COPYING.LIB in the Mercury distribution.
     %--------------------------------------------------%
     %
     % File: queue.m.
     % Main author: fjh.
     % Stability: high.
     %
     % This file contains a `queue' ADT.
     % A queue holds a sequence of values, and provides operations
     % to insert values at the end of the queue (queue.put) and remove them from
     % the front of the queue (queue.get).
     %
     % This implementation is in terms of a pair of lists.
     % The put and get operations are amortized constant-time.
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module queue.
     :- interface.

     :- import_module list.

     %--------------------------------------------------%

     :- type queue(T).

         % `queue.init(Queue)' is true iff `Queue' is an empty queue.
         %
     :- func queue.init = queue(T).
     :- pred queue.init(queue(T)::out) is det.

         % 'queue_equal(Q1, Q2)' is true iff Q1 and Q2 contain the same
         % elements in the same order.
         %
     :- pred queue.equal(queue(T)::in, queue(T)::in) is semidet.

         % `queue.is_empty(Queue)' is true iff `Queue' is an empty queue.
         %
     :- pred queue.is_empty(queue(T)::in) is semidet.

         % `queue.is_full(Queue)' is intended to be true iff `Queue' is a queue
         % whose capacity is exhausted. This implementation allows arbitrary-sized
         % queues, so queue.is_full always fails.
         %
     :- pred queue.is_full(queue(T)::in) is semidet.

         % `queue.put(Elem, Queue0, Queue)' is true iff `Queue' is the queue
         % which results from appending `Elem' onto the end of `Queue0'.
         %
     :- func queue.put(queue(T), T) = queue(T).
     :- pred queue.put(T::in, queue(T)::in, queue(T)::out) is det.

         % `queue.put_list(Elems, Queue0, Queue)' is true iff `Queue' is the queue
         % which results from inserting the items in the list `Elems' into `Queue0'.
         %
     :- func queue.put_list(queue(T), list(T)) = queue(T).
     :- pred queue.put_list(list(T)::in, queue(T)::in, queue(T)::out) is det.

         % `queue.first(Queue, Elem)' is true iff `Queue' is a non-empty queue
         % whose first element is `Elem'.
         %
     :- pred queue.first(queue(T)::in, T::out) is semidet.

         % `queue.get(Elem, Queue0, Queue)' is true iff `Queue0' is a non-empty
         % queue whose first element is `Elem', and `Queue' the queue which results
         % from removing that element from the front of `Queue0'.
         %
     :- pred queue.get(T::out, queue(T)::in, queue(T)::out) is semidet.

         % `queue.length(Queue, Length)' is true iff `Queue' is a queue
         % containing `Length' elements.
         %
     :- func queue.length(queue(T)) = int.
     :- pred queue.length(queue(T)::in, int::out) is det.

         % `queue.list_to_queue(List, Queue)' is true iff `Queue' is a queue
         % containing the elements of List, with the first element of List at
         % the head of the queue.
         %
     :- func queue.list_to_queue(list(T)) = queue(T).
     :- pred queue.list_to_queue(list(T)::in, queue(T)::out) is det.

         % A synonym for queue.list_to_queue/1.
         %
     :- func queue.from_list(list(T)) = queue(T).

         % `queue.to_list(Queue) = List' is the inverse of queue.from_list/1.
         %
     :- func queue.to_list(queue(T)) = list(T).

         % `queue.delete_all(Elem, Queue0, Queue)' is true iff `Queue' is the same
         % queue as `Queue0' with all occurrences of `Elem' removed from it.
         %
     :- func queue.delete_all(queue(T), T) = queue(T).
     :- pred queue.delete_all(T::in, queue(T)::in, queue(T)::out) is det.

         % `queue.put_on_front(Queue0, Elem) = Queue' pushes `Elem' on to
         % the front of `Queue0', giving `Queue'.
         %
     :- func queue.put_on_front(queue(T), T) = queue(T).
     :- pred queue.put_on_front(T::in, queue(T)::in, queue(T)::out) is det.

         % `queue.put_list_on_front(Queue0, Elems) = Queue' pushes `Elems'
         % on to the front of `Queue0', giving `Queue' (the Nth member
         % of `Elems' becomes the Nth member from the front of `Queue').
         %
     :- func queue.put_list_on_front(queue(T), list(T)) = queue(T).
     :- pred queue.put_list_on_front(list(T)::in, queue(T)::in, queue(T)::out)
         is det.

         % `queue.get_from_back(Elem, Queue0, Queue)' removes `Elem' from
         % the back of `Queue0', giving `Queue'.
         %
     :- pred queue.get_from_back(T::out, queue(T)::in, queue(T)::out) is semidet.

     %--------------------------------------------------%
     %--------------------------------------------------%


File: mercury_library.info,  Node: random,  Next: rational,  Prev: queue,  Up: Top

54 random
*********

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 1994-1998,2001-2006, 2011 The University of Melbourne.
     % This file may only be copied under the terms of the GNU Library General
     % Public License - see the file COPYING.LIB in the Mercury distribution.
     %--------------------------------------------------%
     %
     % File: random.m
     % Main author: conway
     % Stability: low
     %
     % Define a set of random number generator predicates. This implementation
     % uses a threaded random-number supply.  The supply can be used in a
     % non-unique way, which means that each thread returns the same list of
     % random numbers.  However, this may not be desired so in the interests
     % of safety it is also declared with (backtrackable) unique modes.
     %
     % The coefficients used in the implementation were taken from Numerical
     % Recipes in C (Press et al), and are originally due to Knuth.  These
     % coefficients are described as producing a "Quick and Dirty" random number
     % generator, which generates the numbers very quickly but not necessarily
     % with a high degree of quality.  As with all random number generators,
     % the user is advised to consider carefully whether this generator meets
     % their requirements in terms of "randomness".  For applications which have
     % special needs (e.g. cryptographic key generation), a generator such as
     % this is unlikely to be suitable.
     %
     % Note that random number generators of this type have several known
     % pitfalls which the user may need to avoid:
     %
     %	1) The high bits tend to be more random than the low bits.  If
     %	you wish to generate a random integer within a given range, you
     %	should something like 'div' to reduce the random numbers to the
     %	required range rather than something like 'mod' (or just use
     %	random.random/5).
     %
     %	2) Similarly, you should not try to break a random number up into
     %	components.  Instead, you should generate each number with a
     %	separate call to this module.
     %
     %	3) There can be sequential correlation between successive calls,
     %	so you shouldn't try to generate tuples of random numbers, for
     %	example, by generating each component of the tuple in sequential
     %	order.  If you do, it is likely that the resulting sequence will
     %	not cover the full range of possible tuples.
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module random.
     :- interface.

     :- import_module list.

     %--------------------------------------------------%

     	% The type `random.supply' represents a supply of random numbers.
         %
     :- type random.supply.

     	% random.init(Seed, RS): creates a supply of random numbers RS
     	% using the specified Seed.
     	%
     :- pred random.init(int::in, random.supply::uo) is det.

     	% random.random(Num, RS0, RS): extracts a number Num in the
     	% range 0 .. RandMax from the random number supply RS0, and
     	% binds RS to the new state of the random number supply.
         %
     :- pred random.random(int, random.supply, random.supply).
     :- mode random.random(out, mdi, muo) is det.
     :- mode random.random(out, in, out) is det.

     	% random.random(Low, Range, Num, RS0, RS): extracts a number Num
     	% in the range Low .. (Low + Range - 1) from the random number
     	% supply RS0, and binds RS to the new state of the random number
     	% supply.  For best results, the value of Range should be no greater
     	% than about 100.
     	%
     :- pred random.random(int, int, int, random.supply, random.supply).
     :- mode random.random(in, in, out, mdi, muo) is det.
     :- mode random.random(in, in, out, in, out) is det.

     	% random.randmax(RandMax, RS0, RS): binds RandMax to the maximum
     	% random number that can be returned from the random number
     	% supply RS0, and returns RS = RS0.
     	%
     :- pred random.randmax(int, random.supply, random.supply).
     :- mode random.randmax(out, mdi, muo) is det.
     :- mode random.randmax(out, in, out) is det.

     	% random.randcount(RandCount, RS0, RS): binds RandCount to the
     	% number of distinct random numbers that can be returned from the
     	% random number supply RS0, and returns RS = RS0.  This will be one
     	% more than the number returned by randmax/3.
     	%
     :- pred random.randcount(int, random.supply, random.supply).
     :- mode random.randcount(out, mdi, muo) is det.
     :- mode random.randcount(out, in, out) is det.

     	% random.permutation(List0, List, RS0, RS):
     	% binds List to a random permutation of List0,
     	% and binds RS to the new state of the random number supply.
     	%
     :- pred random.permutation(list(T), list(T), random.supply, random.supply).
     :- mode random.permutation(in, out, mdi, muo) is det.
     :- mode random.permutation(in, out, in, out) is det.

     %--------------------------------------------------%
     %--------------------------------------------------%


File: mercury_library.info,  Node: rational,  Next: rbtree,  Prev: random,  Up: Top

55 rational
***********

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 1997-1998, 2003-2006 The University of Melbourne.
     % This file may only be copied under the terms of the GNU Library General
     % Public License - see the file COPYING.LIB in the Mercury distribution.
     %--------------------------------------------------%
     %
     % File: rational.m.
     % Authors: aet Apr 1998. (with plagiarism from rat.m)
     % Stability: high.
     %
     % Implements a rational number type and a set of basic operations on
     % rational numbers.
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module rational.
     :- interface.

     :- import_module integer.

     %--------------------------------------------------%

     :- type rational.

     :- pred '<'(rational::in, rational::in) is semidet.

     :- pred '>'(rational::in, rational::in) is semidet.

     :- pred '=<'(rational::in, rational::in) is semidet.

     :- pred '>='(rational::in, rational::in) is semidet.

     :- func rational.rational(int) = rational.

     :- func rational.rational(int, int) = rational.

     :- func rational.from_integer(integer) = rational.

     :- func rational.from_integers(integer, integer) = rational.

     % :- func float(rational) = float.

     :- func '+'(rational) = rational.

     :- func '-'(rational) = rational.

     :- func rational + rational = rational.

     :- func rational - rational = rational.

     :- func rational * rational = rational.

     :- func rational / rational = rational.

     :- func rational.numer(rational) = integer.

     :- func rational.denom(rational) = integer.

     :- func rational.abs(rational) = rational.

     :- func rational.reciprocal(rational) = rational.

     :- func rational.one = rational.

     :- func rational.zero = rational.

     %--------------------------------------------------%
     %--------------------------------------------------%

