mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 17:33:38 +00:00
extras/lazy_evaluation/*:
Removed old code.
samples/lazy_list/README:
samples/lazy_list/lazy_list.m:
samples/lazy_list/lazy_list_test.m:
Code copied from old location.
lazy_list.m has been modified to ensure that it works with the current
version of library/lazy.m
extras/README:
Removed old description of lazy_evaluation
samples/README:
Describe the exitance of samples/lazy_list
Index: extras/README
===================================================================
RCS file: /home/mercury1/repository/mercury/extras/README,v
retrieving revision 1.29
diff -u -p -b -r1.29 README
--- extras/README 2 Aug 2011 07:55:09 -0000 1.29
+++ extras/README 29 Aug 2011 06:06:42 -0000
@@ -36,11 +36,6 @@ graphics Some packages for doing graphic
GLUT, a simplified binding to Xlib, a binding
to Allegro/AllegroGL and a Mercury binding to Cairo.
-lazy_evaluation
- Some examples of the use of the standard library's
- `lazy' module, including a module `lazy_list' that defines
- a lazy list data type.
-
lex A lexer package for Mercury that works over the I/O state,
strings, and so forth. It comes with a rich set of
standard regular expressions and the user is free to add
Index: extras/lazy_evaluation/Mmakefile
===================================================================
RCS file: extras/lazy_evaluation/Mmakefile
diff -N extras/lazy_evaluation/Mmakefile
--- extras/lazy_evaluation/Mmakefile 16 Jan 2003 10:44:17 -0000 1.2
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,11 +0,0 @@
-#-----------------------------------------------------------------------------#
-# Copyright (C) 2002-2003 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.
-#-----------------------------------------------------------------------------#
-INSTALL_PREFIX := $(INSTALL_PREFIX)/extras
--include ../Mmake.params
-default_target: all
-depend: lazy_list.depend lazy_list_test.depend
-all: liblazy_list lazy_list_test
-install: liblazy_list.install
Index: extras/lazy_evaluation/README
===================================================================
RCS file: extras/lazy_evaluation/README
diff -N extras/lazy_evaluation/README
--- extras/lazy_evaluation/README 7 Oct 2010 05:03:12 -0000 1.3
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,73 +0,0 @@
-This directory contains support for optional lazy evaluation.
-Using the modules defined here, you can write Mercury code that
-makes use of lazily evaluated data structures.
-
-Our implementation of lazy evaluation requires you to use a different
-type, lazy(T), whenever you want things to be lazily evaluated, and
-requires you to insert explicit calls to delay/1 or force/1 whenever
-lazy evaluation requires the creation or evaluation of closures.
-
-This directory contains the following files:
-
- lazy_list.m:
- This module defines a type lazy_list(T) using the lazy(T) type,
- and also defines a few functions and predicates that operate
- on lazy lists.
-
- lazy_list_test.m:
- This is just a very simple example showing the use of lazy
- lists.
-
-Mercury's standard library contains.
-
- lazy.m:
- This module defines the lazy(T) type, and the force/1
- and delay/1 functions.
-
-In comparison with lazy functional languages, the disadvantage of our
-approach is that inserting the lazy(T) types and the explicit calls to
-force/1 and delay/1 requires additional work when you are writing your
-code. Fortunately the Mercury compiler's static type checking will
-ensure that the calls to force/1 and delay/1 are consistent with the
-use of lazy(T) types. But even so, putting all the calls to force/1
-and delay/1 in the right place can still be rather tedious.
-
-In return, however, we get several important advantages.
-
-The first is that there are absolutely no efficiency costs resulting
-from lazy evaluation if you don't use it. This is in contrast to many
-implementations of lazy functional languages, where you often pay a
-significant efficiency cost simply because things *might* be lazy, even
-when in actual fact they are not. Compilers for lazy functional
-languages often try to avoid these costs by performing strictness
-analysis, but current compilers can only infer strictness of functions,
-not data types; using lazy data types rather than strict data types can
-have a very large impact on efficiency (e.g. a factor of 5). Also, in
-the presence of separate compilation, compilers may need to make
-conservative assumptions about strictness.
-
-The second advantage is that the creation and evaluation of closures is
-explicit in the source code, which makes it much easier to reason about
-the performance of your programs. Programs in languages where laziness
-is the default often suffer from space leaks or unexpectedly high
-memory usage, and these problems can be _extremely_ difficult to track
-down and understand, even for very experienced programmers.
-
-The third advantage is that supporting lazy evaluation via a library
-module keeps the language and its semantics simple. We're not really
-providing lazy evaluation per se, we just _emulating_ it by passing
-lambda expressions as arguments. So the "Semantics" chapter of the
-language reference manual does not need to be modified at all.
-Supporting lazy evaluation via a library module also keeps the
-implementation simple -- the module lazy.m requires only a very
-small amount of implementation-dependent code, and none of the
-rest of the implementation need change.
-
-Our current implementation of lazy evaluation is not very efficient.
-There are several reasons for this. One is that promise_only_solution/1,
-which is used in the implementation of force/1, is currently implemented
-rather inefficiently. Another is that the lazy(T) type currently uses
-two levels of indirection, whereas it really ought to use only one.
-Finally, for maximum efficiency, we would need to inline delay/1,
-but that is not possible in the current implementation. Solving these
-latter two issues would require a bit more compiler support.
Index: extras/lazy_evaluation/lazy_list.m
===================================================================
RCS file: extras/lazy_evaluation/lazy_list.m
diff -N extras/lazy_evaluation/lazy_list.m
--- extras/lazy_evaluation/lazy_list.m 5 Aug 2010 06:55:43 -0000 1.4
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,137 +0,0 @@
-%-----------------------------------------------------------------------------%
-% vim: ts=4 sw=4 et ft=mercury
-%-----------------------------------------------------------------------------%
-%
-% This is an example of how to use the `lazy' module to define
-% a recursive lazy data type, in this case lazy lists.
-% It also defines a small number of functions and predicates
-% that operate on lazy lists.
-%
-% See also lazy_list_test.m, which is an example program using this module.
-%
-% This source file is hereby placed in the public domain. -fjh (the author).
-
-:- module lazy_list.
-:- interface.
-:- import_module lazy, int, list.
-
-%-----------------------------------------------------------------------------%
-
- % The definition of the type `lazy_list(T)':
- % A lazy lazy_list is either an empty lazy_list, denoted `[]',
- % or an element `Head' of type `T' followed by a lazily
- % evaluated tail `Tail', of type `lazy(lazy_list(T))',
- % denoted `[Head | Tail]'.
-
-:- type lazy_list(T) ---> [] ; [T | lazy(lazy_list(T))].
-
-:- inst lazy_list(I) ---> [] ; [I | lazy(lazy_list(I))].
-:- inst lazy_list == lazy_list(ground).
-
-:- inst nonempty_lazy_list(I) ---> [I | lazy(lazy_list(I))].
-:- inst nonempty_lazy_list == nonempty_lazy_list(ground).
-
-%-----------------------------------------------------------------------------%
-
- % force evaluation of (the top level of) a lazy list
-:- func force_list(lazy(lazy_list(T))) = lazy_list(T).
-:- mode force_list(in(lazy(lazy_list))) = out(lazy_list) is det.
-
-%-----------------------------------------------------------------------------%
-
- % Convert a lazy_list to an ordinary list.
-:- func to_list(lazy_list(T)) = list(T).
-:- mode to_list(in(lazy_list)) = out is det.
-
- % Convert an ordinary list to a lazy_list.
-:- func from_list(list(T)) = lazy_list(T).
-:- mode from_list(in) = out(lazy_list) is det.
-
-%-----------------------------------------------------------------------------%
-
- % A lazy_list function version of the usual append predicate:
- % append(Start, End) = List is true iff
- % `List' is the result of concatenating `Start' and `End'.
- %
-:- func append(lazy_list(T), lazy(lazy_list(T))) = lazy_list(T).
-:- mode append(in(lazy_list), in(lazy(lazy_list))) = out(lazy_list)
- is det.
-
- % member(Elem, List) :
- % True iff `List' contains `Elem'.
-:- pred member(T, lazy_list(T)).
-:- mode member(in, in(lazy_list)) is semidet.
-:- mode member(out, in(nonempty_lazy_list)) is multi.
-:- mode member(out, in(lazy_list)) is nondet.
-
-%-----------------------------------------------------------------------------%
-
- % iterate(F, X0) = [X0, F(X0), F(F(X0)), F(F(F(X0))), ...]
-:- func iterate(func(T) = T, T) = lazy_list(T).
-:- mode iterate(func(in) = out is det, in) = out(lazy_list) is det.
-
- % take(N, L) returns the first N elements of L
-:- func take(int, lazy_list(T)) = lazy_list(T).
-:- mode take(in, in(lazy_list)) = out(lazy_list) is det.
-
- % map(F, [X0, X1, X2, ...]) = [F(X0), F(X1), F(X2), ...].
-:- func map(func(X) = Y, lazy_list(X)) = lazy_list(Y).
-:- mode map(func(in) = out is det, in(lazy_list)) = out(lazy_list) is det.
-
-%-----------------------------------------------------------------------------%
-%-----------------------------------------------------------------------------%
-
-:- implementation.
-
-force_list(Xs) = list_inst_cast(force(Xs)).
-
-% Because the Mercury mode system is not properly polymorphic,
-% it doesn't always infer the right inst. We sometimes need
-% to use inst casts (which can be implemented using `pragma foreign_proc').
-% :-(
-
-:- func list_inst_cast(lazy_list(T)) = lazy_list(T).
-:- mode list_inst_cast(in) = out(lazy_list) is det.
-
-:- pragma foreign_proc("C",
- list_inst_cast(F::in) = (F2::out(lazy_list)),
- [promise_pure, will_not_call_mercury, thread_safe],
-"
- F2 = F;
-").
-
-%-----------------------------------------------------------------------------%
-
-to_list([]) = [].
-to_list([X | Xs]) = [X | to_list(force_list(Xs))].
-
-from_list([]) = [].
-from_list([X | Xs]) =
- [X | delay((func) = R :- R = from_list(Xs))].
-
-%-----------------------------------------------------------------------------%
-
-append([], Ys) = force_list(Ys).
-append([X | Xs], Ys) =
- [X | delay((func) = R :- R = append(force_list(Xs), Ys))].
-
-member(X, [X | _]).
-member(X, [_ | Xs]) :-
- member(X, force_list(Xs)).
-
-%-----------------------------------------------------------------------------%
-
-map(_, []) = [].
-map(F, [H|T]) = [F(H) | delay((func) = R :- R = map(F, force_list(T)))].
-
-iterate(F, X0) = [X0 | delay((func) = R :- R = iterate(F, F(X0)))].
-
-take(_, []) = [].
-take(N, [X|Xs]) =
- (if N > 0 then
- [X | delay((func) = R :- R = take(N-1, force_list(Xs)))]
- else
- []
- ).
-
-%-----------------------------------------------------------------------------%
Index: extras/lazy_evaluation/lazy_list_test.m
===================================================================
RCS file: extras/lazy_evaluation/lazy_list_test.m
diff -N extras/lazy_evaluation/lazy_list_test.m
--- extras/lazy_evaluation/lazy_list_test.m 15 Mar 1999 08:56:59 -0000 1.1
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,27 +0,0 @@
-%-----------------------------------------------------------------------------%
-%
-% lazy_list_test.m:
-% This is a trivial example of the use of lazy lists.
-%
-% This source file is hereby placed in the public domain. -fjh (the author).
-
-:- module lazy_list_test.
-:- interface.
-:- import_module io.
-
-:- pred main(io__state::di, io__state::uo) is det.
-
-%-----------------------------------------------------------------------------%
-
-:- implementation.
-:- import_module lazy, lazy_list, int.
-
-:- func double(int) = int.
-double(X) = 2 * X.
-
-main -->
- { L = iterate(double, 1) }, % construct an infinite list...
- { L10 = take(10, L) }, % extract the first 10 elements
- print(to_list(L10)), nl. % print them
-
-%-----------------------------------------------------------------------------%
Index: samples/README
===================================================================
RCS file: /home/mercury1/repository/mercury/samples/README,v
retrieving revision 1.13
diff -u -p -b -r1.13 README
--- samples/README 8 Jul 2011 04:08:27 -0000 1.13
+++ samples/README 29 Aug 2011 05:47:53 -0000
@@ -72,3 +72,8 @@ muz This directory contains a syntax c
solver_types This directory contains an example solver type
implementation and some sample applications.
+
+lazy_list This directory contains an example of the lazy module
+ can be used to implement lazy data structures, in this
+ case a lazy list.
+
Index: samples/lazy_list/README
===================================================================
RCS file: samples/lazy_list/README
diff -N samples/lazy_list/README
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ samples/lazy_list/README 29 Aug 2011 05:56:20 -0000
@@ -0,0 +1,69 @@
+This directory contains support for optional lazy evaluation.
+Using the modules defined here, you can write Mercury code that
+makes use of lazily evaluated data structures.
+
+Our implementation of lazy evaluation requires you to use a different
+type, lazy(T), whenever you want things to be lazily evaluated, and
+requires you to insert explicit calls to delay/1 or force/1 whenever
+lazy evaluation requires the creation or evaluation of closures.
+
+This directory contains the following files:
+
+ lazy_list.m:
+ This module defines a type lazy_list(T) using the lazy(T) type,
+ and also defines a few functions and predicates that operate
+ on lazy lists.
+
+ lazy_list_test.m:
+ This is just a very simple example showing the use of lazy
+ lists.
+
+Mercury's standard library contains.
+
+ lazy.m:
+ This module defines the lazy(T) type, and the force/1
+ and delay/1 functions.
+
+In comparison with lazy functional languages, the disadvantage of our
+approach is that inserting the lazy(T) types and the explicit calls to
+force/1 and delay/1 requires additional work when you are writing your
+code. Fortunately the Mercury compiler's static type checking will
+ensure that the calls to force/1 and delay/1 are consistent with the
+use of lazy(T) types. But even so, putting all the calls to force/1
+and delay/1 in the right place can still be rather tedious.
+
+In return, however, we get several important advantages.
+
+The first is that there are absolutely no efficiency costs resulting
+from lazy evaluation if you don't use it. This is in contrast to many
+implementations of lazy functional languages, where you often pay a
+significant efficiency cost simply because things *might* be lazy, even
+when in actual fact they are not. Compilers for lazy functional
+languages often try to avoid these costs by performing strictness
+analysis, but current compilers can only infer strictness of functions,
+not data types; using lazy data types rather than strict data types can
+have a very large impact on efficiency (e.g. a factor of 5). Also, in
+the presence of separate compilation, compilers may need to make
+conservative assumptions about strictness.
+
+The second advantage is that the creation and evaluation of closures is
+explicit in the source code, which makes it much easier to reason about
+the performance of your programs. Programs in languages where laziness
+is the default often suffer from space leaks or unexpectedly high
+memory usage, and these problems can be _extremely_ difficult to track
+down and understand, even for very experienced programmers.
+
+The third advantage is that supporting lazy evaluation via a library
+module keeps the language and its semantics simple. We're not really
+providing lazy evaluation per se, we just _emulating_ it by passing
+lambda expressions as arguments. So the "Semantics" chapter of the
+language reference manual does not need to be modified at all.
+Supporting lazy evaluation via a library module also keeps the
+implementation simple -- the module lazy.m requires only a very
+small amount of implementation-dependent code, and none of the
+rest of the implementation need change.
+
+Our current implementation of lazy evaluation is not very efficient. This is
+because the lazy(T) type currently uses two levels of indirection, whereas it
+could be implemented with only one.
+
Index: samples/lazy_list/lazy_list.m
===================================================================
RCS file: samples/lazy_list/lazy_list.m
diff -N samples/lazy_list/lazy_list.m
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ samples/lazy_list/lazy_list.m 29 Aug 2011 05:44:52 -0000
@@ -0,0 +1,111 @@
+%-----------------------------------------------------------------------------%
+% vim: ts=4 sw=4 et ft=mercury
+%-----------------------------------------------------------------------------%
+%
+% This is an example of how to use the `lazy' module to define
+% a recursive lazy data type, in this case lazy lists.
+% It also defines a small number of functions and predicates
+% that operate on lazy lists.
+%
+% See also lazy_list_test.m, which is an example program using this module.
+%
+% This source file is hereby placed in the public domain. -fjh (the author).
+% Modified by Paul Bone (2011) for compatibilty with the lazy module in
+% Mercury's standard library.
+
+:- module lazy_list.
+:- interface.
+:- import_module lazy, int, list.
+
+%-----------------------------------------------------------------------------%
+
+ % The definition of the type `lazy_list(T)':
+ % A lazy lazy_list is either an empty lazy_list, denoted `[]',
+ % or an element `Head' of type `T' followed by a lazily
+ % evaluated tail `Tail', of type `lazy(lazy_list(T))',
+ % denoted `[Head | Tail]'.
+
+:- type lazy_list(T) ---> [] ; [T | lazy(lazy_list(T))].
+
+%-----------------------------------------------------------------------------%
+
+ % force evaluation of (the top level of) a lazy list
+:- func force_list(lazy(lazy_list(T))) = lazy_list(T).
+
+%-----------------------------------------------------------------------------%
+
+ % Convert a lazy_list to an ordinary list.
+:- func to_list(lazy_list(T)) = list(T).
+
+ % Convert an ordinary list to a lazy_list.
+:- func from_list(list(T)) = lazy_list(T).
+
+%-----------------------------------------------------------------------------%
+
+ % A lazy_list function version of the usual append predicate:
+ % append(Start, End) = List is true iff
+ % `List' is the result of concatenating `Start' and `End'.
+ %
+:- func append(lazy_list(T), lazy(lazy_list(T))) = lazy_list(T).
+
+ % member(Elem, List) :
+ % True iff `List' contains `Elem'.
+:- pred member(T, lazy_list(T)).
+:- mode member(in, in) is semidet.
+:- mode member(out, in) is nondet.
+
+%-----------------------------------------------------------------------------%
+
+ % iterate(F, X0) = [X0, F(X0), F(F(X0)), F(F(F(X0))), ...]
+:- func iterate(func(T) = T, T) = lazy_list(T).
+:- mode iterate(func(in) = out is det, in) = out is det.
+
+ % take(N, L) returns the first N elements of L
+:- func take(int, lazy_list(T)) = lazy_list(T).
+
+ % map(F, [X0, X1, X2, ...]) = [F(X0), F(X1), F(X2), ...].
+:- func map(func(X) = Y, lazy_list(X)) = lazy_list(Y).
+:- mode map(func(in) = out is det, in) = out is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+force_list(Xs) = force(Xs).
+
+%-----------------------------------------------------------------------------%
+
+to_list([]) = [].
+to_list([X | Xs]) = [X | to_list(force_list(Xs))].
+
+from_list([]) = [].
+from_list([X | Xs]) =
+ [X | val(from_list(Xs))].
+
+%-----------------------------------------------------------------------------%
+
+append([], Ys) = force_list(Ys).
+append([X | Xs], Ys) =
+ [X | delay((func) = R :- R = append(force_list(Xs), Ys))].
+
+member(X, [X | _]).
+member(X, [_ | Xs]) :-
+ member(X, force_list(Xs)).
+
+%-----------------------------------------------------------------------------%
+
+map(_, []) = [].
+map(F, [H|T]) = [F(H) | delay((func) = R :- R = map(F, force_list(T)))].
+
+iterate(F, X0) = [X0 | delay((func) = R :- R = iterate(F, F(X0)))].
+
+take(_, []) = [].
+take(N, [X|Xs]) =
+ (if N > 0 then
+ [X | delay((func) = R :- R = take(N-1, force_list(Xs)))]
+ else
+ []
+ ).
+
+%-----------------------------------------------------------------------------%
Index: samples/lazy_list/lazy_list_test.m
===================================================================
RCS file: samples/lazy_list/lazy_list_test.m
diff -N samples/lazy_list/lazy_list_test.m
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ samples/lazy_list/lazy_list_test.m 29 Aug 2011 05:35:08 -0000
@@ -0,0 +1,27 @@
+%-----------------------------------------------------------------------------%
+%
+% lazy_list_test.m:
+% This is a trivial example of the use of lazy lists.
+%
+% This source file is hereby placed in the public domain. -fjh (the author).
+
+:- module lazy_list_test.
+:- interface.
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+:- import_module lazy, lazy_list, int.
+
+:- func double(int) = int.
+double(X) = 2 * X.
+
+main -->
+ { L = iterate(double, 1) }, % construct an infinite list...
+ { L10 = take(10, L) }, % extract the first 10 elements
+ print(to_list(L10)), nl. % print them
+
+%-----------------------------------------------------------------------------%
This directory contains various additional libraries, tools, and so forth that are not part of the Mercury standard library. Most of these can be built by running the commands `mmake depend' and then `mmake' in the relevant subdirectory, and many can be installed by running `mmake install'. base64 A library for base64 encoding and decoding. cgi A couple of Mercury library modules for doing HTML forms programming using CGI (Common Gateway Interface). complex_numbers A Mercury library package containing support for complex and imaginary numbers. curs A Mercury library providing a somewhat more complete and more faithful binding to the curses and panel libraries (the latter is used to provide elementary windowing facilities, rather than doing so in Mercury). curses A Mercury library providing a (partial) binding to curses; a package that provides methods for manipulating the text screen (creating windows, placing characters, etc). dynamic_linking An interface to the C functions dlopen(), dlsym(), etc. that are supported by most modern Unix systems. fixed An implementation of fixed-point arithmetic with the COBOL semantics. graphics Some packages for doing graphics programming and GUIs in Mercury: a Mercury interface to Tcl/Tk, a Mercury binding to OpenGL, a Mercury binding to GLUT, a simplified binding to Xlib, a binding to Allegro/AllegroGL and a Mercury binding to Cairo. lex A lexer package for Mercury that works over the I/O state, strings, and so forth. It comes with a rich set of standard regular expressions and the user is free to add their own. log4m A Mercury implementation of logging, in the spirit of log4j <http://logging.apache.org/log4j/docs/>. moose A parser generator for Mercury. Moose works much like yacc or bison, it takes a grammar and generates a table driven LALR parser for it. You can add code to the grammar to handle synthesized or inherited attributes. Currently you need to write your own lexer to interface to moose. mopenssl A Mercury binding to the openssl library. morphine A trace analysis system for Mercury. net A network library which uses the standard library stream interface. odbc A Mercury interface to ODBC (Open Database Connectivity), for interfacing to standard relational database packages. posix A Mercury interface to some of the POSIX (Portable Operating System Interface) APIs. references A library package containing modules for manipulating ML-style references (mutable state). solver_types Contains versions of some standard library modules adapted to make them suitable for use with solver types. trailed_update Some library modules that make use of backtrackable destructive update, including a module which provides some support for Prolog-style unification constraints. windows_installer_generator A library for generating WiX source files. WiX is an XML language that is used to generate Microsoft Windows Installer (.msi) packages. xml An XML parsing library. xml_stylesheets Sample stylesheets that can be used with the term_to_xml module in the standard library.