home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / gofer230.zip / Progs / Gofer / Docs / release.221 < prev    next >
Text File  |  1994-06-23  |  44KB  |  1,387 lines

  1.  
  2.  
  3.                                                                       
  4.  
  5.  
  6. -----------------------------------------------------------------------
  7.        __________   __________   __________   __________   ________
  8.       /  _______/  /  ____   /  /  _______/  /  _______/  /  ____  \
  9.      /  / _____   /  /   /  /  /  /______   /  /______   /  /___/  /
  10.     /  / /_   /  /  /   /  /  /  _______/  /  _______/  /  __   __/
  11.    /  /___/  /  /  /___/  /  /  /         /  /______   /  /  \  \ 
  12.   /_________/  /_________/  /__/         /_________/  /__/    \__\
  13.  
  14.   Functional programming environment, Version 2.21
  15.  
  16.   Copyright Mark P Jones 1991.
  17.  
  18.  
  19.   Release notes
  20.  
  21. -----------------------------------------------------------------------
  22.  
  23. This document is intended as a supplement to the user manual ``An
  24. introduction to Gofer'' supplied with the previous public release of
  25. Gofer, version 2.20.1.  It provides brief descriptions of the changes
  26. and new features incorporated in version 2.21.  With the exception of
  27. bug fixes, which will be distributed as soon as they become available,
  28. there are no plans to release a further update of Gofer for some time
  29. (at least six months).
  30.  
  31. If you would like to be informed when bug-fixes or further versions
  32. become available, please send email to me at mpj@prg.ox.ac.uk or
  33. jones-mark@cs.yale.edu (if you have not already done so) and I will
  34. add your name to the mailing list.
  35.  
  36. Please contact me if you have any questions about the Gofer system, or
  37. if you need some advice or help to complete a port of Gofer to a new
  38. platform.
  39.  
  40. In addition to PC and Sun workstations, I have now had reports that
  41. Gofer has been successfully compiled and used on a number of other
  42. machines including Apollo, DecStation, Mips, MicroVax and Acorn ARM
  43. machines, with little or no changes to the original source.
  44.  
  45.  
  46. ACKNOWLEDGMENTS
  47.  
  48. Many of the features described in this document were motivated by
  49. comments and suggestions from users of the previously released version
  50. of Gofer.  My thanks in particular to Julian Seward, but also to Brent
  51. Benson, Stuart Clayman, Andy Gill, Peter Hancock, Ian Holyer, Hiroyuki
  52. Matsuda, Aiden McCaughey, Tobias Nipkow, Will Partain, Ian Poole,
  53. Bernard Sufrin and Phil Wadler.
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.                                       1
  65.  
  66.  
  67.  
  68.  
  69. Release Notes                                    1. MINOR ENHANCEMENTS
  70.  
  71.  
  72. 1. MINOR ENHANCEMENTS
  73.  
  74. A number of small enhancements have been made to make the source code
  75. for Gofer a little more flexible.  In particular, this includes:
  76.  
  77.   o  Gofer can now be compiled using the Gnu C compiler gcc, for those
  78.      who prefer this to the standard cc compiler provided on their
  79.      machine.
  80.  
  81.   o  Default table sizes for the Unix version have been expanded which
  82.      makes it possible to support larger programs in Gofer (a program
  83.      of over 5000 lines has already been tested with this release).
  84.  
  85.   o  The Makefile has been made less SunOS specific and should be
  86.      usable on a wider range of machines without modification.
  87.  
  88.  
  89.  
  90.  
  91.  
  92.  
  93.  
  94.  
  95.  
  96.  
  97.  
  98.  
  99.  
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122.  
  123.  
  124.  
  125.  
  126.  
  127.  
  128.  
  129.  
  130.                                       2
  131.  
  132.  
  133.  
  134.  
  135. Release Notes                             2. USER INTERFACE EXTENSIONS
  136.  
  137.  
  138. 2. USER INTERFACE EXTENSIONS
  139.  
  140. The user interface of the previous release has been extended to support
  141. a range of new features, intended to make the Gofer environment more
  142. convenient for program development.  Further details are given in the
  143. following sections.
  144.  
  145. 2.1 Command line options
  146. ------------------------
  147. Although the previous version of Gofer accepted some command line
  148. options, these were not documented.  Those who discovered the
  149. Gofer command line options in the previous release by reading the
  150. source code should note that a different syntax is now used which is
  151. not compatible with the older system.
  152.  
  153. Options may be set when loading Gofer (on the UNIX/DOS command line)
  154. or within the interpreter itself using the :set command.  Using this
  155. command on its own with no arguments prints a menu of all of the
  156. available options and displays the current settings:
  157.  
  158.     ? :set
  159.     Groups of options begin with +/- to turn options on/off resp.
  160.  
  161.     TOGGLES:
  162.     s    Print no. reductions/cells after eval
  163.     t    Print type after evaluation
  164.     d    Show dictionary values in output exprs
  165.     f    Terminate evaluation on first error
  166.     g    Print no. cells recovered after gc
  167.     c    Test conformality for pattern bindings
  168.     l    Treat input files as literate scripts
  169.     e    Warn about errors in literate scripts
  170.     i    Apply fromInteger to integer literals
  171.     o    Optimise use of (&&) and (||)
  172.     u    Catch ambiguously typed top-level vars
  173.     a    Use any evidence, not nec. best
  174.     E    Fail silently if evidence not found
  175.  
  176.     OTHER OPTIONS: (leading + or - makes no difference)
  177.     hnum Set heap size (cannot be changed within Gofer)
  178.     pstr Set prompt string to str
  179.     xnum Set maximum depth for evidence search
  180.  
  181.     Current settings: +sdcoaE -tfgleiu -h100000 -p? -x8
  182.     ?
  183.  
  184. Most options are toggles meaning that they can either be switched on
  185. (by preceding the option with a `+' character) or off (by using a `-'
  186. character).  Several options may be grouped together so that:
  187.  
  188.   :set +std -le     is equivalent to       :set +s +t +d -l -e
  189.  
  190. In order to distinguish command line options from filenames, a leading
  191. `+' or `-' must also be used with the `h', `p' and `x' options, although
  192. the choice in each case is not significant.
  193.  
  194.  
  195.  
  196.                                       3
  197.  
  198.  
  199.  
  200.  
  201. Release Notes                                 2.1 Command line options
  202.  
  203.  
  204. Options may also be used in :a and :l commands, and within project files
  205. (see section 2.2), although it should be noted that they will be acted
  206. upon as soon as they are encountered and will not be reapplied when
  207. reloading files.
  208.  
  209. Most of the options listed above are described in more detail in the
  210. following sections.
  211.  
  212.  
  213. 2.1.1  Set Gofer prompt
  214. -----------------------
  215. The standard Gofer prompt "? " may be changed using a command line
  216. option of the form -pstr where for any string str.  The new prompt is
  217. formed from the given string, followed by a single space:
  218.  
  219.     ? :set -pGofer>
  220.     Gofer> :set -p?
  221.     ?
  222.  
  223. 2.1.2  Print statistics
  224. -----------------------
  225. In normal operation, Gofer displays the number of reductions and cells
  226. used by a particular calculation when the result has been evaluated or
  227. if the calculation is interrupted:
  228.  
  229.     ? map (\x -> x*x) [1..10]
  230.     [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
  231.     (112 reductions, 204 cells)
  232.     ? [1..]
  233.     [1, 2, 3, 4, ^C{Interrupted!}
  234.  
  235.     (18 reductions, 54 cells)
  236.     ?
  237.  
  238. Printing of these statistics can be suppressed using the -s option
  239. (and subsequently restored using +s):
  240.  
  241.     ? :set -s
  242.     ? map (\x -> x*x) [1..10]
  243.     [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
  244.     ? [1..]
  245.     [1, 2, 3, 4, ^C{Interrupted!}
  246.  
  247.     ? :set +s
  248.     ? 2 + 4
  249.     6
  250.     (2 reductions, 6 cells)
  251.     ?
  252.  
  253.  
  254. 2.1.3  Print type
  255. -----------------
  256. Before evaluating an expression entered into the interpreter, the Gofer
  257. type checker is used to determine the type of the resulting value.
  258. This is used to detect errors in the original input expression, avoid
  259. the use of runtime type checks and determine how the value should be
  260.  
  261.  
  262.                                       4
  263.  
  264.  
  265.  
  266.  
  267. Release Notes                                        2.1.3  Print type
  268.  
  269.  
  270. output.  The actual type of the term is not usually displayed unless a
  271. type error is detected.  This behaviour can be changed using the +t
  272. option which displays the type of each value as soon as evaluation is
  273. complete.
  274.  
  275.     ? :set +t
  276.     ? map (\x -> x*x) [1..10]
  277.     [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] :: [Int]
  278.     (108 reductions, 204 cells)
  279.  
  280.     ? map concat
  281.     map concat :: [[[a]]] -> [[a]]
  282.     (2 reductions, 17 cells)
  283.  
  284.     ? fix where fix f = f (fix f)
  285.     v112 :: (a -> a) -> a
  286.     (1 reduction, 7 cells)
  287.     ?
  288.  
  289. Note that values of type String and Dialogue (or equivalent forms) are
  290. displayed in a different manner to other values, and no type information
  291. is printed after such values to avoid any possibility of confusion:
  292.  
  293.     ? map                              -- the map function
  294.     map :: (a -> b) -> [a] -> [b]
  295.     (1 reduction, 6 cells)
  296.  
  297.     ? "map"                            -- a string expression
  298.     map
  299.     (0 reductions, 4 cells)
  300.  
  301.     ? print "map"                      -- a dialogue
  302.     "map"
  303.     (18 reductions, 44 cells)
  304.     ?
  305.  
  306.  
  307. 2.1.4  Show dictionaries
  308. ------------------------
  309. The implementation of overloading in Gofer uses a translation of each
  310. expression entered into the interpreter to a new expression involving
  311. dictionary variables and constants.  These additional parameters are
  312. usually included in expressions displayed by the interpreter and are
  313. often useful for understanding and resolving overloading problems:
  314.  
  315.     ? \x -> x + x
  316.     ERROR: Unresolved overloading
  317.     *** type        : Num a => a -> a
  318.     *** translation : \d125 x -> (+) d125 x x
  319.  
  320.     ? :t map (1+) [1..10]
  321.     map ((+) {dict} 1) (enumFromTo {dict} 1 10) :: [Int]
  322.     ?
  323.  
  324. If necessary (perhaps to make the output of Gofer easier for a beginner
  325. to understand), the printing of dictionary parameters may be suppressed
  326.  
  327.  
  328.                                       5
  329.  
  330.  
  331.  
  332.  
  333. Release Notes                                 2.1.4  Show dictionaries
  334.  
  335.  
  336. using the -d option:
  337.  
  338.     ? :set -d
  339.     ? \x -> x + x
  340.     ERROR: Unresolved overloading
  341.     *** type        : Num a => a -> a
  342.     *** translation : \x -> x + x
  343.  
  344.     ? :t map (1+) [1..10]
  345.     map (1 +) (enumFromTo 1 10) :: [Int]
  346.     ?
  347.  
  348. The original behaviour can be obtained using :set +d within the
  349. interpreter.
  350.  
  351.  
  352. 2.1.5  Terminate on error
  353. -------------------------
  354. When an irreducible subexpression is encountered during the evaluation
  355. of a particular expression, the irreducible redex is printed with
  356. surrounding braces and the Gofer interpreter attempts to continue the
  357. evaluation with other parts of the original expression:
  358.  
  359.     ? take (1/0) [1..]          -- value is bottom
  360.     {primDivInt 1 0}
  361.     (4 reductions, 33 cells)
  362.     ? [1/0]                     -- value is [bottom]
  363.     [{primDivInt 1 0}]
  364.     (5 reductions, 34 cells)
  365.     ? [1/0, 2]                  -- value is [bottom, 2]
  366.     [{primDivInt 1 0}, 2]
  367.     (7 reductions, 43 cells)
  368.     ?
  369.  
  370. Notice that, reading an expression enclosed in {braces} as bottom, each
  371. of the values printed by Gofer gives the correct value.  Of course, it
  372. is not possible to arrange for anything to be printed when a value of
  373. bottom is generated by a nonterminating computation:
  374.  
  375.     ? last [1..]
  376.     ^C{Interrupted!}            -- nothing printed until interrupted
  377.  
  378.     (10470 reductions, 15712 cells)
  379.     ?
  380.  
  381. An alternative behaviour is provided by the +f option, which causes the
  382. evaluation of an expression to be abandoned completely if an error
  383. occurs:
  384.  
  385.     ? :set +f
  386.     ? take (1/0) [1..]
  387.  
  388.     Aborting evaluation: {primDivInt 1 0}
  389.     (3 reductions, 55 cells)
  390.  
  391.  
  392.  
  393.  
  394.                                       6
  395.  
  396.  
  397.  
  398.  
  399. Release Notes                                2.1.5  Terminate on error
  400.  
  401.  
  402.     ? [1/0]
  403.  
  404.     Aborting evaluation: {primDivInt 1 0}
  405.     (3 reductions, 54 cells)
  406.  
  407.     ? [1/0,2]
  408.  
  409.     Aborting evaluation: {primDivInt 1 0}
  410.     (3 reductions, 56 cells)
  411.  
  412.     ?
  413.  
  414. Note that we are no longer able to distinguish between the values
  415. produced by these three terms from the output produced by Gofer -- the
  416. only differences are in the number of reductions and cells used which
  417. tells us nothing about the values of the terms.  Note that the basic
  418. method of evaluation in Gofer is unchanged -- the +f option simply
  419. modifies the printing mechanism (i.e the means by which values are
  420. displayed) to be more strict (in the technical sense of the word).
  421.  
  422. Although the use of the +f option makes the Gofer printing mechanism
  423. less accurate, it is sometimes useful during program development so
  424. that an error can be detected as soon as it occurs.  The original
  425. behaviour can of course be restored at any time using the -f
  426. option.
  427.  
  428.  
  429. 2.1.6  Heap size
  430. ----------------
  431. The -hnumber option can be used to set the heap size (i.e. total number
  432. of cells available at any one time), but cannot be used once the
  433. interpreter has been loaded.  For example, starting the interpreter
  434. with the command:
  435.  
  436.     gofer -h20000
  437.  
  438. will typically start the Gofer interpreter with a heap of 20000 cells.
  439. Note that the heap is used to hold an intermediate (parsed) form of an
  440. input file while it is being read, type checked and compiled.  It
  441. follows that, the larger the input file, the larger the heap required
  442. to enable that file to be loaded into Gofer.  In practice, most large
  443. programs are written (and loaded) as a number of separate files (see
  444. section 2.2) which means that this does not usually cause problems.
  445.  
  446.  
  447. 2.1.7  Garbage collector notification
  448. -------------------------------------
  449. It is sometimes helpful to be able to tell when the garbage collector
  450. is being used, in order to monitor the amount of time involved and the
  451. number of cells recovered with each garbage collection.  If the +g
  452. command line option is given (for example, using the command :set +g)
  453. then the garbage collector prints a message of the form {{Gc:num}} each
  454. time that the garbage collector is invoked.  The number after the colon
  455. indicates the total number of cells that have been recovered.
  456.  
  457.  
  458.  
  459.  
  460.                                       7
  461.  
  462.  
  463.  
  464.  
  465. Release Notes                    2.1.7  Garbage collector notification
  466.  
  467.  
  468. The garbage collector messages are actually printed in three sections,
  469. which indicate which stage the garbage collector has reached (this is
  470. only noticeable on slower machines of course!):
  471.  
  472.             {{Gc                :              number}}
  473.  
  474.    garbage       marking cells      preparing           garbage
  475.    collection      which are       unused cells         collection
  476.    begins         still in use      for reuse           completed
  477.  
  478. Garbage collector messages may be printed at almost any stage in a
  479. computation (or indeed whilst loading, type checking or compiling a
  480. file of definitions).  For this reason, it is often better to turn
  481. the garbage collector messages off (using :set -g for example) when
  482. they are not required.
  483.  
  484.  
  485. 2.1.8  Conformality testing
  486. ---------------------------
  487. As described briefly in section 9.11 of the documentation for Gofer
  488. version 2.20, pattern bindings of the form pat=expr are implemented
  489. using a `conformality check' to ensure that the value of expr does
  490. indeed match the pattern pat.  For example, the pattern binding:
  491.  
  492.     (x:xs) = [1..]
  493.  
  494. is actually implemented as if it had been defined by:
  495.  
  496.     (x:xs) = conformality [1..]
  497.              where conformality v@(_:_) = v
  498.  
  499. which is in turn treated as a group of bindings:
  500.  
  501.     xxs    = conformality [1..] where conformality v@(_:_) = v
  502.     x      = head xxs
  503.     xs     = tail xxs
  504.  
  505. [The variables conformality and xxs used here are given as examples
  506. only -- in practice, Gofer maintains a supply of variable names and
  507. selects new names from this supply to avoid clashes with variables
  508. which are already in use.]
  509.  
  510. The conformality check does not cause any problems in the example
  511. above because the list [1..] is always guaranteed to match the
  512. pattern (x:xs) (i.e. a non-empty list).  We can however see the
  513. conformality check in action if we try examples in which the pattern
  514. does not match:
  515.  
  516.     ? x where (x:xs) = []
  517.     {v114 []}
  518.     (3 reductions, 25 cells)
  519.  
  520.     ? xs where (0:xs) = [1..]
  521.     {v114 [1] ++ iterate (primPlusInt 1) (primPlusInt 1 1)}
  522.     (13 reductions, 94 cells)
  523.     ?
  524.  
  525.  
  526.                                       8
  527.  
  528.  
  529.  
  530.  
  531. Release Notes                              2.1.8  Conformality testing
  532.  
  533.  
  534. The variable v114 in each of these examples is the variable name
  535. representing the conformality check.  As the second example shows, the
  536. value of the expression on the right hand side of the pattern binding
  537. is evaluated as much as necessary to determine whether the pattern
  538. fits.
  539.  
  540. [ASIDE: This example also demonstrates a small problem with the printer
  541. in that, when the first element of the list is encountered, it is
  542. unable to detect that the tail of the list has not yet been evaluated.
  543. Consequently, the expression:
  544.  
  545.     [1] ++ iterate (primPlusInt 1) (primPlusInt 1 1)
  546.  
  547. is not enclosed in parentheses as it should be.  This is a little
  548. annoying, but not important because the expression only appears in an
  549. error message.  The problem cannot in general be solved unless we avoid
  550. the use of the [...] notation for enumerating the elements of a list.]
  551.  
  552. The conformality check must be used for compatibility with Haskell.
  553. However, it is sometimes useful to be able to suppress the conformality
  554. check using the -c option (for example, to use some programs written
  555. for a language without conformality checks within Gofer):
  556.  
  557.     ? :set -c
  558.     ? x where (x:xs) = []
  559.     {_SEL (:) [] 1}
  560.     (5 reductions, 36 cells)
  561.     ? xs where (0:xs) = [1..]
  562.     [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14^C{Interrupted!}
  563.  
  564.     (55 reductions, 146 cells)
  565.     ?
  566.  
  567. In the first example, the expression _SEL (:) [] 1 indicates that the
  568. first component of an object constructed using the (:) operator is to
  569. be extracted from the object [].  Clearly this is impossible, and hence
  570. the expression _SEL (:) [] 1 is irreducible.  In the second case, the
  571. value of xs is equivalent to _SEL (:) (1:[2..]) 2 which reduces to
  572. the infinite list [2..] as shown, despite the fact that [1..] does not
  573. match the pattern (0:xs).
  574.  
  575. [ASIDE: The _SEL function is used internally by Gofer and cannot be
  576. entered directly into the the interpreter.  One particular reason for
  577. this is that it is not in general possible to assign a sensible type
  578. to _SEL.  Constructor functions appearing as the first argument to _SEL
  579. are printed in the normal manner.  There is no standard syntax for
  580. writing tuple constructors in Gofer or Haskell which are therefore
  581. printed in the form (,,,) for example, where the number of commas
  582. indicates the number of components in the tuple.  In the following
  583. example the constructor (,) denotes the pairing constructor.
  584.  
  585.     ? f a b where f (n+1) y = n+y;  (a,b) = (0,1)
  586.     {v113 0 (_SEL (,) (0,1) 2)}
  587.     (10 reductions, 63 cells)
  588.     ?
  589.  
  590.  
  591.  
  592.                                       9
  593.  
  594.  
  595.  
  596.  
  597. Release Notes                              2.1.8  Conformality testing
  598.  
  599.  
  600. The same notation is sometimes used in the messages produced when type
  601. errors are detected:
  602.  
  603.     ? (1,2) 3
  604.     ERROR: Type error in application
  605.     *** expression     : (1,2) 3
  606.     *** term           : (,)
  607.     *** type           : a -> b -> (a,b)
  608.     *** does not match : c -> d -> e -> f
  609.  
  610.     ?
  611.  
  612. This syntax for tuple constructor functions cannot be used in
  613. expressions entered directly into Gofer.  It may however be a nice
  614. extension to consider for future versions, allowing definitions such
  615. as zip = zipWith (,)  and  distl x = map (x,).]
  616.  
  617.  
  618. 2.1.9  Literate scripts
  619. -----------------------
  620. In common with most programming languages, Gofer typically treats input
  621. from a file as a list definitions in which program text is the norm,
  622. and comments play a secondary role, introduced by the character
  623. sequences ``--'' and ``{- ... -}''.
  624.  
  625. An alternative approach, using an idea described by Knuth as ``literate
  626. programming'', gives more emphasis to comments and documentation, with
  627. additional characters needed to distinguish program text from comments.
  628. Gofer supports a form of literate programming based on an idea due to
  629. Richard Bird and originally implemented as part of the functional
  630. programming language Orwell.  The same idea has subsequently been
  631. adopted by several other functional language systems.
  632.  
  633. A literate script contains a sequence of lines.  Program lines are
  634. distinguished from comments by a `>' character in the first column.
  635. This makes it particularly easy to write a document which is both an
  636. executable program script and at the same time, without need for any
  637. preprocessing, suitable for use with document preparation software such
  638. as LaTeX.  Indeed, this document is itself a literate script containing
  639. the following definition of the squaring function.
  640.  
  641. > sqr x = x * x
  642.  
  643. The +l option sets Gofer to treat each input file as a literate
  644. script.  It should not be used on the command line unless the prelude
  645. file has been edited to make a literate script.
  646.  
  647. The effect of using literate scripts can be thought of as applying a
  648. preprocessor to each input file before it is loaded into Gofer.  This
  649. program has a particularly simple definition in Gofer:
  650.  
  651.    illiterate   :: String -> String
  652.    illiterate cs = unlines [ xs | ('>':xs) <- lines cs ]
  653.  
  654. The system of literate scripts used in Orwell is actually a little more
  655. complicated than this and requires that the programmer adopt two simple
  656.  
  657.  
  658.                                       10
  659.  
  660.  
  661.  
  662.  
  663. Release Notes                                  2.1.9  Literate scripts
  664.  
  665.  
  666. conventions in an attempt to try to catch simple errors in literate
  667. scripts:
  668.  
  669.   o  Every input file must contain at least one line whose first
  670.      character is `>'.  This means that programs containing no
  671.      definitions (because the programmer has forgotten to use the `>'
  672.      character to mark definitions) from being accepted.
  673.  
  674.   o  Lines containing definitions must be separated from comment lines
  675.      by one or more blank lines (i.e. lines containing only space and
  676.      tab characters).  This is useful for catching programs where the
  677.      leading `>' character has been omitted from one or more lines in
  678.      the definition of a function.  For example:
  679.  
  680.      >   map f []     = []
  681.          map f (x:xs) = f x : map f xs
  682.  
  683.      would result in an error if the `>' character appeared in the first
  684.      column of the first line.
  685.  
  686. Gofer will report on errors of this kind if the +l option is combined
  687. with the +e option (for example as +le).
  688.  
  689.  
  690. 2.1.10 Optimise (&&) and (||)
  691. -----------------------------
  692. The operator symbols (&&) and (||) are usually used to represent the
  693. boolean connectives conjunction (and) and disjunction (or).  By
  694. default, Gofer uses the following equations to produce better code for
  695. expressions involving these operators:
  696.  
  697.          x && y  =  if  x  then  y     else  False
  698.          x || y  =  if  x  then  True  else  y
  699.  
  700. This optimization is only valid if the operator symbols (&&) and (||)
  701. are indeed bound to the appropriate values at the top level (the
  702. standard full definitions are required in order to support partial
  703. applications involving these operators).  Although this optimization is
  704. in general valid (because the appropriated definitions are included in
  705. the standard prelude), it may be necessary in certain cases (for
  706. example, when working with a non-standard prelude) to suppress the
  707. optimization using the -o option.
  708.  
  709.  
  710.  
  711.  
  712.  
  713.  
  714.  
  715.  
  716.  
  717.  
  718.  
  719.  
  720.  
  721.  
  722.  
  723.  
  724.                                       11
  725.  
  726.  
  727.  
  728.  
  729. Release Notes                                       2.2  Project Files
  730.  
  731.  
  732. 2.2  Project Files
  733. ------------------
  734. Project files provide a simple way to use programs which are
  735. spread across a number of source files.  Larger programs are often
  736. written in this way, to separate the different components of the
  737. program into smaller pieces which can be developed and tested
  738. independently of other components.
  739.  
  740. A project file is a simple text file containing a list of program
  741. filenames.  The project file may also contain comments using either of
  742. the Gofer conventions for comments.  As a simple example, a simple
  743. project file, in a file named "miniProlog", suitable for the
  744. stack-based version of the mini Prolog interpreter included as a
  745. demonstration program with Gofer 2.21 is as follows:
  746.  
  747.     -- This is a project file suitable for loading the stack-based
  748.     -- version of the mini Prolog interpreter into Gofer 2.21
  749.     --
  750.     -- Load into Gofer using the command:   :p miniProlog
  751.     --        or from command line using:   gofer + miniProlog
  752.  
  753.     Parse       -- general purpose parsing library
  754.     Interact    -- general purpose library for interactive programs
  755.     PrologData  -- definition of main data structures
  756.     Subst       -- substitutions and unification
  757.     StackEngine -- inference engine
  758.     Main        -- top level program
  759.  
  760. As indicated in the comments at the top, there are two ways of using
  761. this file with Gofer.  Within the interpreter we can use the command
  762. :p miniProlog.  Once this command has been entered, Gofer reads the
  763. contents of the project file and then attempts to load each of the
  764. files named.  In general, if a particular project file "proj" contains
  765. the options op1, ..., opn and the filenames f1, ..., fm, then the
  766. command :p proj is equivalent to the sequence of commands:
  767.  
  768.     :l                -- clear any previously loaded scripts
  769.     :set op1 ... opn  -- set options
  770.     :l f1 ... fm      -- load files
  771.  
  772. The project file name may also be specified on the command line used to
  773. start the interpreter by preceding the project file name with a single
  774. `+' character.  Note that there must be at least one space on each side
  775. of the `+'.  This may be combined with standard command line options,
  776. but any additional filename arguments will be ignored.  Starting Gofer
  777. with a command of the form "gofer + proj" is equivalent to starting
  778. Gofer without the "+ project" arguments and then giving the command
  779. :p proj.
  780.  
  781. In addition, Gofer records the name of the project file and displays
  782. this with the list of files loaded.  For example:
  783.  
  784.     Gofer session for: (project: miniProlog)
  785.     /users/mpj/public/Gofer/prelude 
  786.     Parse
  787.     Interact
  788.  
  789.  
  790.                                       12
  791.  
  792.  
  793.  
  794.  
  795. Release Notes                                       2.2  Project Files
  796.  
  797.  
  798.     PrologData
  799.     Subst
  800.     StackEngine
  801.     Main
  802.     ? 
  803.  
  804. Once a project file has been selected, the command :p (without any
  805. arguments) can be used to force Gofer to reread the project file and
  806. load fresh copies of each of the files listed there.  There are two
  807. places in which this is particularly useful:
  808.  
  809.   o  If the project file itself has been modified since the last time
  810.      that it was read.
  811.  
  812.   o  To force Gofer to reload all of the files in the project,
  813.      regardless of the last time they were modified.
  814.  
  815. As usual, the :r command can be used to reload each of the files in the
  816. current project without rereading the project file itself, and avoiding
  817. the need to read certain files which have not been modified since the
  818. previous time they were loaded.
  819.  
  820. The use of project files integrates smoothly with the other parts of
  821. the Gofer environment.  As an example consider a project file proj
  822. containing the four filenames f1, f2, f3 and f4, and suppose that the
  823. file f3 contains an error of some kind.  This leads to the following
  824. sequence of commands and results:
  825.  
  826.     :p proj       -- attempt to load project proj
  827.                   -- reads filenames f1, f2, f3, f4 from proj
  828.                   -- load definitions from f1
  829.                   -- load definitions from f2
  830.                   -- load definitions from f3 -- error occurs
  831.                   -- error message printed
  832.     :e            -- starts up editor at relevant line in f3
  833.                   -- correct error
  834.                   -- exit editor
  835.                   -- load definitions from f3
  836.                   -- load definitions from f4
  837.  
  838. After just these two commands, the error in f3 has been corrected and
  839. all of the files mentioned in proj have been loaded, ready for use.
  840.  
  841.  
  842.  
  843.  
  844.  
  845.  
  846.  
  847.  
  848.  
  849.  
  850.  
  851.  
  852.  
  853.  
  854.  
  855.  
  856.                                       13
  857.  
  858.  
  859.  
  860.  
  861. Release Notes                                  2.3  Other new features
  862.  
  863.  
  864. 2.3  Other new features
  865. -----------------------
  866.  
  867. 2.3.1  :find - find definition
  868. ------------------------------
  869. The command ":f name" starts up an editor to allow you to inspect (and
  870. possibly modify) the definition of a particular name from the files
  871. currently loaded into Gofer.  If supported (using the EDITLINE
  872. variable), Gofer will attempt to initialize the editor so that the
  873. cursor is initially positioned at the first line in the definition.
  874. There are three possibilities:
  875.  
  876.   o  If the name is defined by a function or variable binding then
  877.      the cursor is positioned at the first line in the definition of
  878.      the name (ignoring any type declaration, if present).
  879.  
  880.   o  If the name is a constructor function, then the cursor is
  881.      positioned at the first line in the definition of the
  882.      corresponding data definition.
  883.  
  884.   o  If the name represents an internal Gofer function, then the
  885.      cursor will be positioned at the beginning of the standard
  886.      prelude file.
  887.  
  888. Note that names of infix operators should be given without any
  889. enclosing them in parentheses.  Thus ":f ++" starts an editor on the
  890. standard prelude at the first line in the definition of (++).
  891.  
  892.  
  893. 2.3.2  :! - shell escape
  894. ------------------------
  895. A command of the form ":! cmd" can be used to execute a specified
  896. system command without leaving the Gofer interpreter.  For example,
  897. ":! ls" (or ":! dir" on MS DOS machines) can be used to list the
  898. contents of the current directory.
  899.  
  900. The command ":!" without any arguments starts a new shell:
  901.  
  902.   o  On a unix machine, the SHELL environment variable is used to
  903.      determine which shell to use (the default is "/bin/sh").
  904.  
  905.   o  On an MS DOS machine, the COMSPEC environment variable is used
  906.      to determine which shell to use.  This is usually COMMAND.COM
  907.      and you may return to Gofer using the EXIT command.
  908.  
  909. As usual, it is not possible to use a shell escape to change the
  910. current working directory.  The :cd command described in the following
  911. section can be used for this purpose.
  912.  
  913.  
  914. 2.3.3  :cd - change directory
  915. -----------------------------
  916. The command ":cd dir" changes the current working directory to the path
  917. given by "dir".  This command is ignored if the pathname is omitted.
  918.  
  919.  
  920.  
  921.  
  922.                                       14
  923.  
  924.  
  925.  
  926.  
  927. Release Notes                               2.3.4  :names - list names
  928.  
  929.  
  930. 2.3.4  :names - list names
  931. --------------------------
  932. The :n command lists the names of variables and functions whose
  933. definitions are currently loaded into the Gofer interpreter.  Using
  934. this command without any arguments produces the list of all names
  935. known to the system.  For example, with just the standard prelude
  936. loaded we obtain:
  937.  
  938.     ? :n
  939.     !! && * + ++ - . / /= : < <= == > >= AppendChan AppendFile Echo
  940.     Failure False FormatError OtherError ReadChan ReadError ReadFile
  941.     SearchError Str Success True WriteError WriteFile [] \\ ^ abort abs
  942.     all and any appendChan appendFile asTypeOf break chr cjustify
  943.     concat const copy curry cycle div done drop dropWhile echo elem
  944.     enumFrom enumFromThen enumFromThenTo enumFromTo error even exit
  945.     filter flip foldl foldl' foldl1 foldr foldr1 fromInteger fst fst3
  946.     gcd head help id inRange index init insert interact isAlpha
  947.     isAlphanum isAscii isControl isDigit isLower isPrint isSpace
  948.     isUpper iterate last layn lcm length lines ljustify map max maximum
  949.     merge min minimum mod negate not notElem nub null odd or ord
  950.     otherwise primDivFloat primDivInt primEqFloat primEqInt
  951.     primIntToFloat primLeFloat primLeInt primMinusFloat primMinusInt
  952.     primMulFloat primMulInt primNegFloat primNegInt primPlusFloat
  953.     primPlusInt primPrint print prints product products qsort range
  954.     readChan readFile rem repeat reverse rjustify run scanl scanl'
  955.     scanl1 scanr scanr1 show show' showChar showList showString shows
  956.     showsPrec signum snd snd3 sort space span splitAt stdecho stderr
  957.     stdin stdout strDispatch strict subtract succDispatch sum sums tail
  958.     take takeUntil takeWhile thd3 toLower toUpper transpose uncurry
  959.     undefined unlines until until' unwords words writeFile zip zip3
  960.     zip4 zip5 zip6 zip7 zipWith zipWith3 zipWith4 zipWith5 zipWith6
  961.     zipWith7 ||
  962.     (201 names listed)
  963.     ?
  964.  
  965. Note that the names are listed in the standard alphabetical order.
  966.  
  967. The :n can also accept one or more pattern strings which limits the list
  968. of names printed to those names matching one or more of the given
  969. pattern strings:
  970.  
  971.     ? :n fold*
  972.     foldl foldl' foldl1 foldr foldr1
  973.     (5 names listed)
  974.     ?
  975.  
  976. Each pattern string consists of a string of characters and may use the
  977. standard wildcard characters: `*' (matches anything), `?' (matches any
  978. single character), `\c' (matches exactly the character c) and ranges of
  979. characters of the form `[a-zA-Z]' etc.  For example:
  980.  
  981.     ? :n *ap* *[Cc]han \\\\ ?
  982.     * + - . / : < > AppendChan ReadChan \\ ^ appendChan appendFile
  983.     map readChan
  984.     (16 names listed)
  985.     ?
  986.  
  987.  
  988.                                       15
  989.  
  990.  
  991.  
  992.  
  993. Release Notes                       2.3.5  $$ - recall last expression
  994.  
  995.  
  996. 2.3.5  $$ - recall last expression
  997. ----------------------------------
  998. The previously entered expression can be recalled at any stage whilst
  999. using the Gofer interpreter (even if the list of currently loaded files
  1000. has subsequently been changed) by using the operator symbol $$:
  1001.  
  1002.     ? 42
  1003.     42
  1004.     (1 reduction, 5 cells)
  1005.     ? [$$]
  1006.     [42]
  1007.     (3 reductions, 12 cells)
  1008.     ? [$$]
  1009.     [[42]]
  1010.     (5 reductions, 19 cells)
  1011.     ? ($$, length $$)
  1012.     ([[42]],1)
  1013.     (14 reductions, 43 cells)
  1014.     ?
  1015.  
  1016. The $$ symbol is bound to a new value each time that an expression is
  1017. evaluated, or its type determined using the :t command:
  1018.  
  1019.     ? :t $$
  1020.     ([[42]],length [[42]]) :: ([[Int]],Int)
  1021.     ? :t map (1+) [1..10]
  1022.     map ((+) {dict} 1) (enumFromTo {dict} 1 10) :: [Int]
  1023.     ? $$
  1024.     [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
  1025.     (100 reductions, 189 cells)
  1026.     ?
  1027.  
  1028. Note that $$ can also be used when the last expression entered used
  1029. a where clause (such expressions are simply translated into the
  1030. appropriate let expressions):
  1031.  
  1032.     ? fibs where fibs = 0:1:zipWith (+) fibs (tail fibs)
  1033.     [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55^C{Interrupted!}
  1034.  
  1035.     (41 reductions, 136 cells)
  1036.     ? :t $$
  1037.     let {...} in fibs :: [Int]
  1038.     ? take 5 $$
  1039.     [0, 1, 1, 2, 3]
  1040.     (24 reductions, 77 cells)
  1041.     ?
  1042.  
  1043. Note that $$ expands to the unevaluated form of the expression, so that
  1044. a certain amount of computation may be repeated if $$ is used more than
  1045. once in a subsequent expression:
  1046.  
  1047.     ? sum [1..10]
  1048.     55
  1049.     (92 reductions, 130 cells)
  1050.     ? $$ + $$
  1051.     110
  1052.  
  1053.  
  1054.                                       16
  1055.  
  1056.  
  1057.  
  1058.  
  1059. Release Notes                       2.3.5  $$ - recall last expression
  1060.  
  1061.  
  1062.     (176 reductions, 254 cells)
  1063.     ? x + x where x = sum [1..10]
  1064.     110
  1065.     (89 reductions, 131 cells)
  1066.     ?
  1067.  
  1068. Note that the value of $$ is updated after the expression has been parsed
  1069. but before it is type checked:
  1070.  
  1071.     ? 42
  1072.     42
  1073.     (1 reduction, 5 cells)
  1074.     ? 4)
  1075.     ERROR: Syntax error in input (unexpected `)')
  1076.     ? $$ 4
  1077.     ERROR: Type error in application
  1078.     *** expression     : 42 4
  1079.     *** term           : 42
  1080.     *** type           : Int
  1081.     *** does not match : a -> b
  1082.  
  1083.     ?
  1084.  
  1085.  
  1086. 2.3.6  Command names
  1087. --------------------
  1088. Command names of the form :X (where X represents an arbitrary capital
  1089. letter) are no longer supported.  Each command has a mnemonic full name
  1090. of the form :name which can be abbreviated to :n where `n' is the first
  1091. letter of the full name.  The complete list of commands produced by the
  1092. :? command is as follows:
  1093.  
  1094.     ? :?
  1095.     LIST OF COMMANDS:  Any command may be abbreviated to :c where
  1096.     c is the first character in the full name.
  1097.  
  1098.     :set <options>      set command line options
  1099.     :set                help on command line options
  1100.     :?                  display this list of commands
  1101.     <expr>              evaluate expression
  1102.     :type <expr>        print type of expression
  1103.     :names [pat]        list names currently in scope
  1104.     :load <filenames>   load scripts from specified files
  1105.     :load               clear all files except prelude
  1106.     :also <filenames>   read additional script files
  1107.     :reload             repeat last load command
  1108.     :project <filename> use project file
  1109.     :edit <filename>    edit file
  1110.     :edit               edit last file
  1111.     :find <name>        edit file containing definition of name
  1112.     :! command          shell escape
  1113.     :cd dir             change directory
  1114.     :quit               exit Gofer interpreter
  1115.     ?
  1116.  
  1117.  
  1118.  
  1119.  
  1120.                                       17
  1121.  
  1122.  
  1123.  
  1124.  
  1125. Release Notes                                  3. LANGUAGE DIFFERENCES
  1126.  
  1127.  
  1128. 3. LANGUAGE DIFFERENCES
  1129.  
  1130. There are very few changes to the language supported by Gofer -- most
  1131. programs that ran correctly under the previous release should run
  1132. without any changes.  The features described in the following sections
  1133. are (for the most part) extensions to the previous version.
  1134.  
  1135. 3.1 c*p and p+k patterns
  1136. ------------------------
  1137. Motivated by recent discussion on the Haskell mailing list, starting
  1138. with a posting from Tony Davie, Gofer now supports a more general form
  1139. of n+k pattern, together with a new form of pattern, c*p.  The syntax
  1140. of patterns is extended to include:
  1141.  
  1142.         pattern ::= .... | pattern + integer | integer * pattern
  1143.  
  1144. Note that, in the previous version of Gofer, only variables were
  1145. permitted for the pattern p in a p+k pattern.  Certain restrictions are
  1146. placed on the constants c and k used in c*p and p+k patterns; Gofer
  1147. currently requires c>1 and k>0.
  1148.  
  1149. The semantics of these new patterns are described by the equations
  1150. (suggested by Kent Karlsson):
  1151.  
  1152.     case e0 of {p+k -> e; _ -> e'}
  1153.       = if e0 >= k then case e0-k of {p -> e; _ -> e'} else e'
  1154.  
  1155.     case e0 of {c*p -> e; _ -> e'}
  1156.       = if e0 >= 0 then  case e0 `divRem` c of {(p, 0) -> e; _ -> e'}
  1157.                    else  e'
  1158.  
  1159. In Gofer, both forms of pattern match nonnegative integers only (there
  1160. is no possibility for overloading here as there is in Haskell).
  1161.  
  1162. These features are included in Gofer to enable experimentation with the
  1163. use of c*p patterns.  They are not currently supported by Haskell, and
  1164. are subject to change as we gain more experience using them.  To
  1165. illustrate the potential uses for these extensions, here are two
  1166. examples provided by Tony Davie in his original message which can be
  1167. used in Gofer:
  1168.  
  1169.     x^^0       = 1                     -- fast exponentiation 
  1170.     x^^(2*n)   = xn*xn where xn = x^^n -- compare with definition
  1171.     x^^(2*n+1) = x * x^^(2*n)          -- of (^) in the prelude
  1172.  
  1173.     fib 1       = 1                    -- fast fibonnacci
  1174.     fib 2       = 1
  1175.     fib (2*n)   = (fib(n+1))^^2 - (fib(n-1))^^2
  1176.     fib (2*n+1) = (fib(n+1))^^2 + (fib n   )^^2
  1177.  
  1178.  
  1179.  
  1180.  
  1181.  
  1182.  
  1183.  
  1184.  
  1185.  
  1186.                                       18
  1187.  
  1188.  
  1189.  
  1190.  
  1191. Release Notes                                 3.2 Errors during output
  1192.  
  1193.  
  1194. 3.2 Errors during output
  1195. ------------------------
  1196. If an error of the form "error str" occurs during an output request in
  1197. a program using the facilities for I/O, the IOError value passed to
  1198. the failure continuation is the (WriteError str), rather than
  1199. (WriteError "{error str}") as in the previous release.  This enables
  1200. further evaluation of the string str (for example to produce a
  1201. compound error message by concatenating several strings together).
  1202.  
  1203. You are strongly advised to consider using the standard prelude
  1204. continuation "exit" in your programs in place of the "abort" predicate;
  1205. whereas "abort" causes a program to terminate without any indication of
  1206. the problem, "exit" attempts to print a suitable error message before
  1207. the program terminates.
  1208.  
  1209.  
  1210. 3.3 Type synonyms in predicates
  1211. -------------------------------
  1212. Type synonyms may now be used in predicates (The previous release
  1213. allowed only data constructors).  This means that programs such as the
  1214. cat program described in section 14.2.6 (page 68) of the Gofer
  1215. documentation can now be written as:
  1216.  
  1217.     class    Cat a        where cat  :: a -> Dialogue
  1218.     instance Cat String   where cat n = showFile n done
  1219.     instance Cat [String] where cat   = foldr showFile done
  1220.  
  1221.     showFile name cont = readFile name abort
  1222.                              (\s->appendChan stdout s abort cont)
  1223.  
  1224. This uses the type synonym String in place of the expanded form [Char]
  1225. required by the original program.  Note that it is still not permitted
  1226. to define overlapping instances; an attempt to add an instance for Cat
  1227. [Char] to the above will not be accepted.
  1228.  
  1229.  
  1230. 3.4 Reporting on ambiguous types
  1231. --------------------------------
  1232. Class declarations whose member functions have ambiguous types are no
  1233. longer permitted.  For example, in the class declaration:
  1234.  
  1235.     class Box a where
  1236.         mem :: Int
  1237.  
  1238. The type of the member function mem is Box a => Int which is ambiguous
  1239. and produces the error message:
  1240.  
  1241.     ERROR "examp" (line 3): Ambiguous type signature in class declaration
  1242.     *** ambiguous type : Box a => Int
  1243.     *** assigned to    : mem
  1244.  
  1245.     ?
  1246.  
  1247. Similar error messages are produced when an explicit type signature
  1248. includes an ambiguous type.  For example:
  1249.  
  1250.  
  1251.  
  1252.                                       19
  1253.  
  1254.  
  1255.  
  1256.  
  1257. Release Notes                         3.4 Reporting on ambiguous types
  1258.  
  1259.  
  1260.     func   :: Eq a => Int -> Int
  1261.     func x  = 2*x+1
  1262.  
  1263. Results in an error of the form:
  1264.  
  1265.     ERROR "examp" (line 12): Ambiguous type signature in type declaration
  1266.     *** ambiguous type : Eq a => Int -> Int
  1267.     *** assigned to    : func
  1268.  
  1269.     ?
  1270.  
  1271. By default, no error is signalled if an ambiguous type is assigned to a
  1272. variable or function by the type checker.  This makes it possible to
  1273. write definitions such as:
  1274.  
  1275.     f y xs  =  if xs==[] then 0 else g y
  1276.     g y     =  f y []
  1277.  
  1278. The types obtained for each of these terms is as follows:
  1279.  
  1280.     f :: Eq [a] => b -> [a] -> Int
  1281.     g :: Eq [a] => b -> Int
  1282.  
  1283. Note that the second type is ambiguous.  Making the analogy between
  1284. these mutually recursive functions and a two state machine, we can
  1285. think of a direct call to f as initializing the machine correctly so
  1286. that there is no problem when we enter g.  On the other hand, entering
  1287. the system at g does not initialize the machine correctly, as signalled
  1288. by the ambiguity.
  1289.  
  1290. Using the +u command line flag forces Gofer to generate an error when
  1291. an attempt to assign an ambiguous type to a top-level function occurs.
  1292. For the above example this gives:
  1293.  
  1294.     ERROR "examp" (line 20): Ambiguous type signature in inferred type
  1295.     *** ambiguous type : Eq [a] => b -> Int
  1296.     *** assigned to    : g
  1297.  
  1298.     ?
  1299.  
  1300. The restriction to top-level functions means that f can still be
  1301. implemented by writing:
  1302.  
  1303.     f :: Eq [a] => b -> [a] -> Int
  1304.     f  = f'  where  f' y xs = if xs==[] then 0 else g y
  1305.                     g' y    = f y []
  1306.  
  1307. which prevents external access to g' (preventing entry to the finite
  1308. machine described above in state g).  Note that the type signature in
  1309. this example is necessary to avoid the monomorphism restriction.
  1310.  
  1311.  
  1312.  
  1313.  
  1314.  
  1315.  
  1316.  
  1317.  
  1318.                                       20
  1319.  
  1320.  
  1321.  
  1322.  
  1323. Release Notes                                         4. OTHER MATTERS
  1324.  
  1325.  
  1326. 4. OTHER MATTERS
  1327.  
  1328. 4.1 Contributions
  1329. -----------------
  1330. I would like to hear from anyone with interesting Gofer programs or
  1331. other useful items which might be included (with full credit to the
  1332. original author(s) of course!) in subsequent releases of Gofer.  There
  1333. is already one example of this in the new release; a small gnuemacs
  1334. mode for running the Gofer interpreter from within gnuemacs on Unix
  1335. machines, contributed by Stuart Clayman.  See the file gofer.el for
  1336. more details.
  1337.  
  1338. 4.2 Future directions
  1339. ---------------------
  1340. There will not be another release of Gofer for some time.  There are
  1341. however a number of areas which I would like to investigate at some
  1342. point as extensions to the Gofer system:
  1343.  
  1344.   o  The ability to use Haskell style type classes.
  1345.  
  1346.   o  Facilities for working with modules, based on the approach
  1347.      described in the Haskell report.  A particular problem here is
  1348.      in finding an elegant way to provide the full power of the
  1349.      module system from the interactive environment.
  1350.  
  1351.   o  The ability to write stand alone applications programs using
  1352.      Gofer.
  1353.  
  1354.   o  An improved user interface.  There are a number of grand ideas
  1355.      based on the use of windowing/mouse/pulldown-menus etc.  The
  1356.      current user interface is closer to this kind of approach than
  1357.      might at first be realized.  More interesting ideas include the
  1358.      design of class, data type and value browsers, along the lines
  1359.      of a Smalltalk system.
  1360.  
  1361. I would be interested to hear from anyone with comments or suggestions
  1362. on any of these (or other ideas).
  1363.  
  1364.  
  1365.  
  1366.  
  1367.  
  1368.  
  1369.  
  1370.  
  1371.  
  1372.  
  1373.  
  1374.  
  1375.  
  1376.  
  1377.  
  1378.  
  1379.  
  1380.  
  1381.  
  1382.  
  1383.  
  1384.                                       21
  1385.  
  1386.  
  1387.