summaryrefslogtreecommitdiff
path: root/miralib/manual/27/4
diff options
context:
space:
mode:
Diffstat (limited to 'miralib/manual/27/4')
-rw-r--r--miralib/manual/27/4116
1 files changed, 116 insertions, 0 deletions
diff --git a/miralib/manual/27/4 b/miralib/manual/27/4
new file mode 100644
index 0000000..f34bc3d
--- /dev/null
+++ b/miralib/manual/27/4
@@ -0,0 +1,116 @@
+_T_h_e_ _%_f_r_e_e_ _d_i_r_e_c_t_i_v_e_ _a_n_d_ _p_a_r_a_m_e_t_r_i_s_e_d_ _s_c_r_i_p_t_s
+
+It is permitted to construct a script containing definitions which are
+dependent on information which will be supplied only when the script is
+made the subject of a %_i_n_c_l_u_d_e directive. Such a script is said to be
+_p_a_r_a_m_e_t_r_i_s_e_d. This is indicated by the presence in the script of a
+directive of the form
+
+ %_f_r_e_e { signature }
+
+where `signature' is a list of specifications of the identifiers for
+which bindings will be provided at %_i_n_c_l_u_d_e time. A script may contain
+at most one %_f_r_e_e directive, which must therefore give all the
+identifiers on which the script is parametrised. The %_f_r_e_e directive
+may appear anywhere in the script, but for clarity it is recommended
+that you place it at or near the top.
+
+For example a script (called "matrices" say) defining the notion of
+matrix sum and matrix product, for matrices of as-yet-unspecified
+element type, could be written as follows:-
+
+ %_e_x_p_o_r_t matmult matadd
+
+ %_f_r_e_e { elem :: _t_y_p_e
+ zero :: elem
+ mult, add :: elem->elem->elem
+ }
+
+ matrix == [[elem]]
+
+ matadd :: matrix->matrix->matrix
+ matadd xx yy = [[add a b|(a,b)<-zip2 x y]|(x,y)<-zip2 xx yy]
+
+ matmult :: matrix->matrix->matrix
+ matmult xx yy = outerprod innerprod xx (transpose yy)
+ innerprod x y = sum [mult a b|(a,b)<-zip2 x y]
+ _w_h_e_r_e
+ sum = foldr add zero
+ outerprod f xx yy = [[f x y|y<-yy]|x<-xx]
+
+Note that the identifiers declared under %_f_r_e_e may denote types as well
+as values. When we write a %_i_n_c_l_u_d_e directive for the above script we
+must provide bindings for all of its free identifiers. The bindings are
+given in braces following the pathname (and before the aliases, if any).
+Thus:-
+
+ %_i_n_c_l_u_d_e "matrices" {elem==num; zero=0; mult=*; add=+; }
+
+In the scope of the script containing the above directive the
+identifiers `matmult' and `addmult' will be available at type
+[[num]]->[[num]]->[[num]] and will behave as if their definitions had
+been written using 0, (+), (*) in place of the identifiers zero, add,
+mult.
+
+The order in which the bindings are given is immaterial (it need not be
+the order in which the identifiers occurred in the %_f_r_e_e directive) but
+a binding must be given for each free identifier of the %included
+script. Note that the binding for a type is given using `==' and for a
+value using `='. If the types of all the bindings (taken together) are
+not consistent with the information given in the free directive of the
+%included script, or if any required binding is missing, the compiler
+will reject the %_i_n_c_l_u_d_e directive as incorrect.
+
+The main advantage of a parametrised script is that different bindings
+may be given for its free identifiers on different occasions. For
+example the same script "matrices" may be invoked with different
+bindings to provide a definition of matrix addition and multiplication
+over matrices with elements of type bool. Thus:-
+
+ %_i_n_c_l_u_d_e "matrices" {elem==bool; zero=False; mult=&; add=\/; }
+
+It is even possible to %_i_n_c_l_u_d_e the same parametrised script twice in
+the same scope (presumably with different bindings for the free
+identifiers) but in this case it will be be necessary to alias apart the
+two sets of exported identifiers to avoid a nameclash. So we might add
+`b_matadd/matadd b_matmult/matmult' to the above directive if it were
+being used in the same script as the previous one.
+
+_M_i_s_c_e_l_l_a_n_e_o_u_s_ _p_o_i_n_t_s
+
+By default the identifiers declared %_f_r_e_e in a parametrised script are
+not exported from the script. As always this can be overridden by
+explicitly listing them in an %_e_x_p_o_r_t directive.
+
+Free typenames of non-zero arity are declared in the following style.
+
+ %_f_r_e_e { stack * :: _t_y_p_e
+ table * ** :: _t_y_p_e
+ ...
+ }
+
+The corresponding bindings could be as follows
+
+ %_i_n_c_l_u_d_e ... {stack * == [*]; table * ** == [(*,**)]; ... }
+
+When a parametrised script exports a locally created typename (other
+than a synonym type), each instantiation of the script by a %_i_n_c_l_u_d_e is
+deemed to create a NEW type (this is relevant to deciding whether or not
+two types are the same for the purpose of readopting a type orphan, see
+previous manual section). This is because the compiler assumes that an
+abstract or algebraic type defined in a parametrised script will in
+general have an internal structure that depends on the free identifiers.
+
+Finally note that the bindings for the free identifiers of a
+parametrised script must always be given EXPLICITLY. For example
+suppose we wish to %_i_n_c_l_u_d_e the file "matrices" in a script already
+containing a type called `elem' over which we intend to do matrix
+multiplication. We must write
+
+ %_i_n_c_l_u_d_e "matrices" {elem==elem; etc. }
+
+The binding `elem==elem' is not redundant, nor is it cyclic, because the
+two `elem's involved refer to two different scopes (on the left of the
+binding, that of the includee, and on the right that of the script
+containing the directive).
+