diff options
Diffstat (limited to 'miralib/manual/27/4')
-rw-r--r-- | miralib/manual/27/4 | 116 |
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). + |