home *** CD-ROM | disk | FTP | other *** search
/ ftp.uni-stuttgart.de/pub/systems/acorn/ / Acorn.tar / Acorn / acornet / dev / gofer.spk / docsrc / doc230 < prev   
Text File  |  1994-06-27  |  23KB  |  585 lines

  1. .co This is the source form of the release notes for Gofer 2.30
  2. .co
  3. .co Mark P Jones June 1994
  4. .co-------------------------------------------------------------------|
  5. .>release.230
  6. -----------------------------------------------------------------------
  7.        __________   __________   __________   __________   ________
  8.       /  _______/  /  ____   /  /  _______/  /  _______/  /  ____  \
  9.      /  / _____   /  /   /  /  /  /______   /  /______   /  /___/  /
  10.     /  / /_   /  /  /   /  /  /  _______/  /  _______/  /  __   __/
  11.    /  /___/  /  /  /___/  /  /  /         /  /______   /  /  \  \ 
  12.   /_________/  /_________/  /__/         /_________/  /__/    \__\
  13.  
  14.   Functional programming environment, Version 2.30
  15.  
  16.   Copyright Mark P Jones 1994.  This release is subject to the same
  17.   conditions of use and distribution as previous versions, documented
  18.   in src/goferite.h and in the main user manual.
  19.  
  20.   Release notes
  21. -----------------------------------------------------------------------
  22.  
  23. This document is intended to be used as a supplement to the original
  24. user manual ``An introduction to Gofer version 2.20'' and release
  25. notes for Gofer 2.21 and Gofer 2.28.  These notes replace the
  26. preliminary version distributed with Gofer 2.30.
  27.   
  28.   ACKNOWLEDGMENTS:
  29. A lot of people have contributed to the development of Gofer 2.30a
  30. with their support, encouragement, suggestions, comments and bug
  31. reports.  There are a lot of people to thank:
  32.   
  33.         Jim Blandy        Jonathan Bowen           Rodney Brown
  34.        Nick Chapman          Derek Charleston      Stuart Clayman
  35.       Terry Dineen             Luc Duponcheel        Dirk Dussart
  36.   Sebastian Egner          Stephen Eldridge        Jeroen Fokker
  37.        Jeff Fried             Andy Gill           Michial Gunter
  38.       Kevin Hammond         Daniel Harris          Barney Hilken
  39.       Steve Hill               Ian Holyer         Richard Jones
  40.     Fumiaki Kamiya             Eak Khoon         Hiroyuki Matsuda
  41.        Sava Mintchev        Torben Mogensen          Dirk Nehring
  42.        Chin Wei Ngan          Kurt Olender          Palle Nielsen
  43.         Ian Poole          Bambang Prastowo          Jaan Priisalu
  44.    Giuliano Procida          Jerry Prothero       Laurenz Pruessner
  45.      Niklas R\"ojemo    Kristoffer Rose          Bernhard Rumpe
  46.       David Rushall        Carsten Schultz          Viren Shah
  47.        Dave Sherratt           Guy Steele Jr.      Donald Smith
  48.     Matthew Smith          Michael Stout          Bernard Sufrin
  49.       Peter Thiemann       Stephen Thomas            Bert Thompson
  50.     Ignacio Trejos-Zelaya   Goeran Uddeborg         Robin Watts
  51.       Gavin Wraith           David Wright            Isii Yuuitirou
  52.   
  53. This also includes the names of people who sent comments and bug
  54. reports after the release of version 2.28 and who may not have been
  55. credited in previous release notes.  The list probably isn't complete,
  56. and I apologize if I have inadvertently left your name out.
  57.   
  58.   Enjoy!            jones-mark@cs.yale.edu   (Until mid-July 1994)
  59.   Mark              mpj@cs.nott.ac.uk        (From  Sept/Oct 1994)
  60. .pa
  61. .ti Release Notes v2.30
  62. .co-------------------------------------------------------------------|
  63. .ST 1. MINOR ENHANCEMENTS AND BUGFIXES
  64.  
  65. The following sections list the minor enhancements and bugfixes that
  66. have been made to Gofer since the release of version 2.28.  More
  67. significant changes are described in Section 2.
  68.  
  69.  
  70. .ST 1.1  Enhancements
  71. -----------------
  72.   o  A new command, :gc, has been added, making it possible to force the
  73.      interpreter to carry out a garbage collection.
  74.  
  75.   o  The infamous `too many variables in type checker' message that has
  76.      caused problems with some programs, particularly machine generated
  77.      Gofer scripts like the parsers produced by Ratatosk, should now be
  78.      a thing of the past.  The message may still appear when running
  79.      such programs on smaller machines where the amount of free memory
  80.      available for such things is very limited.
  81.  
  82.   o  It is now possible to compile Gofer without support for old style
  83.      Dialogue based I/O and, independently, without support for (n+k)
  84.      and (c*n) patterns.  You may take this as a hint that these
  85.      features may not be supported in future versions, although no firm
  86.      decisions have been made just yet.
  87.  
  88.   o  As a convenience, the parser allows constructor expressions of
  89.      the form (t ->) as an abbreviation for ((->) t).
  90.  
  91.   o  Tuple patterns (with irrefutable components) are now treated as
  92.      irrefutable patterns, but without changing the previous lifted
  93.      semantics.  This is marginallly more efficient.  It also means
  94.      that it is no longer necessary to use ~ for generators of the form
  95.      (x,y) <- expr in monad comprehensions, too avoid restricting the
  96.      enclosing comprehension to monads with a zero.
  97.  
  98.   o  Type expressions appearing in primitive declarations may now
  99.      include synonyms, classes etc. defined in the same script.
  100.  
  101.   o  Other minor tweaks and improvements.
  102.  
  103.  
  104. .ST 1.2  Bug fixes
  105. --------------
  106. Nobody really likes to dwell on bugs, especially when they have been
  107. eliminated.  But for those of you who want to know, here is a summary of
  108. the bugs discovered and fixed in Gofer 2.30:
  109.  
  110.   o  Test programs apr*.gs that were included in previous distributions
  111.      are no longer included in the src directory.  These programs were
  112.      intended only for quick tests, not for public distribution.  The
  113.      fact that some of the test programs (intentionally) caused errors,
  114.      was a source of unnecessary concern for some since the expected
  115.      behaviour was not documented.
  116.  
  117.   o  Some minor fixes to the parser/grammar to give better error
  118.      messages.
  119.  
  120.   o  Fixed problems with the :edit command on some machines,
  121.      particularly noticeable on the RISCOS version.
  122.  
  123.   o  Large integer constants that are outside the range for Int
  124.      values are no longer implicitly coerced to type Float.
  125.  
  126.   o  The implementations of assignment in the LAMBDAVAR and LAMBDANU
  127.      extensions, and the implementation of the system primitive for
  128.      LAMBDANU contained subtle bugs that have now been fixed.  Note
  129.      however that these extensions are now regarded as obsolete, and
  130.      will probably not be supported in future versions.  (LAMBDAVAR and
  131.      LAMBDANU where never formally included as an official feature of
  132.      Gofer anyway.)
  133.  
  134.   o  Infix data constructors can now be used in a datatype definition
  135.      such as:
  136.  
  137.          data  Tree a  =   Empty  |  Tree a `Fork` Tree a
  138.  
  139.   o  A very subtle bug in the unification algorithm has been fixed.
  140.  
  141.   o  Some bugs in mildly complicated examples involving pattern
  142.      matching of integer constants and singleton lists have been
  143.      fixed.
  144.  
  145.   o  Fixed some small problems with a couple of the demonstration
  146.      programs.
  147.  
  148.   o  Modified prelude definitions of the index function (in class Ix)
  149.      to include a bounds check.
  150.  
  151.   o  Other minor bug fixes and tweaks.
  152.  
  153. Someone is bound to find a new one within hours of the release of 2.30,
  154. if past experience is anything to go by.  If that someone is you,
  155. please let me know!
  156.  
  157.  
  158. .co-------------------------------------------------------------------|
  159. .ST 2. LANGUAGE DIFFERENCES
  160.  
  161. This section outlines a number of more substantial extensions that are
  162. supported in Gofer 2.30.  One of the most important motivations for
  163. some of these extensions, and part of an ongoing process, is to provide
  164. greater compatibility with standard Haskell.
  165.  
  166.  
  167. .ST 2.1  Contexts in datatype definitions
  168. -------------------------------------
  169. For greater compatibility with Haskell, it is now possible to include
  170. contexts in datatype definitions.  These are treated in exactly the
  171. same way as in Haskell.  For example, the only effect of using a
  172. context in the datatype definition:
  173.  
  174.     data Eq a => Set a = NilSet | ConsSet a (Set a)
  175.  
  176.  is to treat the ConsSet constructor function as having type:
  177.  
  178.     ConsSet :: Eq a => a -> Set a -> Set a
  179.  
  180.  See Section 4.2.1 of the Haskell report, version 1.2, for further
  181.  details.
  182.  
  183.  
  184. .ST 2.2  Contexts in member function types
  185. --------------------------------------
  186. For greater compatibility with Haskell, it is now possible to include
  187. contexts in the type of member function definitions in a class
  188. specification.  For example, you can now try out the class definition
  189. for pseudo monads given in the Yale Research Report YALEU/DCS/RR-1004
  190. entitled `Composing Monads' by myself and Luc Duponcheel:
  191.  
  192.     class Premonad m => Pseudomonad m where
  193.       pbind :: Monad m => p a -> (a -> m (p b)) -> m (p b)
  194.  
  195. Unlike Haskell, Gofer does not make the restriction that the additional
  196. constraints on the types of the member functions should not mention any
  197. of the types in the first line of the class declaration.  This appears
  198. to have been a consequence of the formal system underlying the original
  199. theoretical work on type classes by Blott.  For the qualified type
  200. system that is used as a basis for Gofer, such restrictions are
  201. unnecessary, although one might argue that they should be retained on
  202. stylistic grounds ...
  203.  
  204. See Section 4.3.1 of the Haskell report, version 1.2, for further
  205. details.
  206.  
  207.  
  208. .ST 2.3  Haskell arrays
  209. -------------------
  210. For closer compatibility with Haskell, Gofer now supports a built-in
  211. implementation of Haskell style arrays.  To include support for these
  212. arrays, Gofer must be compiled with the HASKELL_ARRAYS flag set to 1.
  213. This is the default for all but the very smallest PC version of Gofer.
  214.  
  215. The implementation includes is based on new primitive datatype:
  216.  
  217.     data Array a b
  218.  
  219. The array primitives are not currently incorporated into any of the
  220. preludes supplied with Gofer.  However a separate script file,
  221. array.gs, is included in the same directory with the following
  222. interface:
  223.  
  224.     data Assoc a b =  a := b  deriving (Eq, Ord, Text)
  225.  
  226.     array      :: Ix a => (a,a) -> [Assoc a b] -> Array a b
  227.     listArray  :: Ix a => (a,a) -> [b] -> Array a b
  228.     (!)        :: Ix a => Array a b -> a -> b
  229.     bounds     :: Ix a => Array a b -> (a,a)
  230.     indices    :: Ix a => Array a b -> [a]
  231.     elems      :: Ix a => Array a b -> [b]
  232.     assocs     :: Ix a => Array a b -> [Assoc a b]
  233.     accumArray :: Ix a => (b -> c -> b) -> b -> (a,a)
  234.                             -> [Assoc a c] -> Array a b
  235.     (//)       :: Ix a => Array a b -> [Assoc a b] -> Array a b
  236.     accum      :: Ix a => (b -> c -> b) -> Array a b
  237.                             -> [Assoc a c] -> Array a b
  238.     amap       :: Ix a => (b -> c) -> Array a b -> Array a c
  239.     ixmap      :: (Ix a, Ix b) => (a,a) -> (a -> b)
  240.                                     -> Array b c -> Array a c
  241.  
  242.     instance (Ix a, Eq [Assoc a b]) => Eq (Array a b)
  243.     instance (Ix a, Ord [Assoc a b]) => Ord (Array a b)
  244.     instance (Ix a, Text (a,a), Text [Assoc a b])
  245.                => Text (Array a b)
  246.  
  247.     instance (Ix a, Ix b) => Ix (a,b)
  248.     rangeSize :: (Ix a) => (a,a) -> Int
  249.  
  250. For example, to use these primitives in a Gofer session, just include
  251. array.gs as the first file that you load, or as the one of the first
  252. file names in a project file.
  253.  
  254. Arrays, and the primitives above are supported in both the interpreter
  255. and the compiler.  Because of restrictions in memory management, the
  256. current implementation does not provide true O(1) lookup/indexing in
  257. the interpreter or the compiler using the markscan garbage collector.
  258. True O(1) access is supported when the twospace collector is used for
  259. compiled programs.
  260.  
  261. See Section 6.9 of the Haskell report, version 1.2, for further details
  262. about the use of arrays and the primitives described above.  Please
  263. bear in mind that the current implementation is still preliminary, and
  264. may contain bugs.  Please let me know if you encounter any problems
  265. with it!  A few short demo programs are included in demos/arrayEx.gs.
  266.  
  267.  
  268. .ST 2.4  Monadic I/O
  269. ----------------
  270. A preliminary implementation of the monadic I/O is supported, built on
  271. top of the framework for lazy functional state threads that has been
  272. proposed by John Launchbury and Simon Peyton Jones (PLDI '94).  The
  273. details of monadic I/O can be expected to change in future releases as
  274. a new standard for monadic I/O is established.  For the time being, the
  275. primitives described here will be of most interest to those looking to
  276. experiment with simple monadic I/O and the Launchbury/Peyton Jones
  277. system.  To include support for monadic I/O, Gofer must be compiled
  278. with the IO_MONAD flag set to 1.  This is the default for all but the
  279. very smallest PC version of Gofer.
  280.  
  281. The current implementation provides several new primitive types:
  282.  
  283.     data ST s a        -- lazy state threads monad
  284.     data World         -- representation of `the world'
  285.     type IO = ST World -- the I/O monad proper
  286.     data MutVar s a    -- a mutable variable
  287.  
  288. An interface to monadic I/O can be obtained by loading the file
  289. iomonad.gs which may be found in the same directory as the prelude
  290. files.  This provides the following operations:
  291.  
  292.     returnST  :: a -> ST s a
  293.     thenST    :: ST s a -> (a -> ST s b) -> ST s b
  294.     thenST_   :: ST s () -> ST s b -> ST s b
  295.     seqST     :: [ST s ()] -> ST s ()
  296.  
  297.     newVar    :: a -> ST s (MutVar s a)
  298.     readVar   :: MutVar s a -> ST s a
  299.     writeVar  :: MutVar s a -> a -> ST s ()
  300.     mutvarEq  :: MutVar s a -> MutVar s a -> Bool
  301.  
  302.     instance Eq (MutVar s a)
  303.  
  304.     getch     :: IO Char
  305.     getchar   :: IO Char
  306.     putchar   :: Char -> IO ()
  307.     putString :: String -> IO ()
  308.     thenIO    :: ST s a -> (a -> ST s b) -> ST s b
  309.     interleaveST :: ST s a -> ST s a
  310.  
  311. There is also a built-in special form, runST expr, which is typed using
  312. the rule:
  313.  
  314.     expr :: forall s. ST s a        (s not appearing in a)
  315.     ------------------------
  316.        runST expr :: a
  317.  
  318. This special form is used for encapsulating state based computations
  319. within a purely functional program.  See references below for more
  320. details.
  321.  
  322. If the version of Gofer being used also includes support for arrays, as
  323. described above, you can also use the definitions in ioarray.gs to
  324. support monadic array operations:
  325.  
  326.     newArr    :: Ix a => (a,a) -> b -> ST s (MutArr s a b)
  327.     readArr   :: Ix a => MutArr s a b -> a -> ST s b
  328.     writeArr  :: Ix a => MutArr s a b -> a -> b -> ST s ()
  329.     freezeArr :: Ix a => MutArr s a b -> ST s (Array a b)
  330.  
  331. Some sample programs using the functions described here may be found in
  332. the demos/IO directory.  For further details about monadic I/O, please
  333. consult the papers:
  334.  
  335.     Imperative Functional Programming, S.L. Peyton Jones and
  336.     P. Wadler, POPL '93.
  337.  
  338.      Lazy Functional State Threads, J. Launchbury and S.L. Peyton
  339.     Jones, PLDI '94.
  340.  
  341. See also:
  342.  
  343.     Lazy depth-first search and linear graph algorithms in
  344.     Haskell, D. King and J. Launchbury, 1993.
  345.  
  346. for some very nice applications of lazy functional state threads.  All
  347. of these papers are currently available by anonymous ftp from the
  348. University of Glasgow, ftp.dcs.glasgow.ac.uk.
  349.  
  350. Monadic I/O as described above is supported in both the Gofer
  351. interpreter and compiler.  No special optimizations are used in the
  352. current implementation which should still be treated as preliminary,
  353. and may contain bugs.  Please let me know if you encounter any problems
  354. with it!
  355.  
  356.  
  357. .ST 2.5  Trace primitive
  358. --------------------
  359. A simple trace function, inspired by the original implementation in
  360. LML, can now be accessed by including the primitive definition:
  361.  
  362.     primitive trace "primTrace" :: String -> a -> a
  363.  
  364. in a Gofer script.  When called, trace prints the string in its first
  365. argument, then returns the second argument as its result.  The trace
  366. function is not referentially transparent, and should only be used for
  367. debugging, or monitoring execution.  That is why it is not included in
  368. any of the preludes.  Be warned also that, unless you understand
  369. something about the way that Gofer programs are actually executed,
  370. results obtained using trace may be rather confusing.
  371.  
  372. Because of it's intended use, the trace primitive is not supported
  373. by the Gofer compiler, gofc.  It is however possible to `hack' in
  374. a version of trace for gofc using the external function call
  375. mechanism described below with the following C program:
  376.   
  377.     #include <stdio.h>
  378.     #include "/usr/local/lib/Gofer/gofc.h"
  379.    
  380.     #define emptyList mkCfun(0)
  381.    
  382.     extern Cell primTrace(str,val)
  383.     Cell str, val; {
  384.         eval(str);
  385.         while (whnf!=emptyList) {
  386.             eval(pop());
  387.             putchar(charOf(whnf));
  388.             eval(pop());
  389.         }
  390.         fflush(stdout);
  391.          return val;    }
  392.  
  393. See Section 2.7 below for further details.
  394.  
  395.  
  396.  
  397. .ST 2.6  Constructor synonyms
  398. -------------------------
  399. Type synonym definitions have been generalized to allow arbitrary
  400. constructor synonyms such as:
  401.  
  402.     type List     = []
  403.     type Function = (->)
  404.     type Infer    = StateM Int Error
  405.  
  406. Previously, it was assumed that both the constructors on the left and
  407. right hand sides were types, i.e. constructors of kind *.  This
  408. restriction has now been lifted, although both sides are still required
  409. to have the same kind.  However, the restriction that all arguments to
  410. a synonym must be given is still imposed.
  411.  
  412.  
  413. .ST 2.7  External function calls
  414. ----------------------------
  415. The Gofc compiler, translating Gofer programs to C provides a simple
  416. external function calling mechanism.
  417.  
  418. External functions are specified using a primitive declaration of the
  419. form:
  420.  
  421.     primitive foo "bar" :: a1 -> a2 -> a3 -> ... -> an -> r
  422.  
  423. where foo is the Gofer name for the function, bar is the name of the
  424. corresponding C function (which must not be a string referring to one
  425. of the built in primitives ... if you avoid the `prim' prefix, this
  426. should not be a problem), the ai are the argument types, and r is the
  427. result type.  Arguments of type Int, Bool, Char and Float are evaluated
  428. before the bar function is invoked, and their results passed to bar in
  429. parameters of suitable types.  All other values are passed as
  430. unevaluated Cell values.  (Special treatment is also provided for
  431. arrays, mutable variables, and mutable arrays for versions of Gofer
  432. that support these facilities.)
  433.  
  434. Results of type Int, Bool, Char and Float returned from an external
  435. function are automatically converted to suitable representations for
  436. Gofer.  Values of any other type should be passed back as Cell values
  437. by the C code for the external function.
  438.  
  439. A result type of the form IO r should be used for external functions
  440. that may have some side effects.  A result type of the form IO () can
  441. be used to call a function that does not return any useful value and is
  442. executed only for its effect.
  443.  
  444. Here is a simple example using the external function mechanism.  It
  445. involves the following short Gofer and C programs:
  446.  
  447. (gix1.gs):    primitive howdy "sayHello" :: Int -> IO ()
  448.  
  449.               main = howdy (length (filter even [1..5]))
  450.  
  451. (cix1.c):     #include <stdio.h>
  452.               #include "gofc.h"
  453.  
  454.               Void sayHello(i)
  455.               Int i; {
  456.                   while (i-- > 0)
  457.                       printf("hello, world\n");
  458.               }
  459.  
  460. First, we compile gix1.gs to get a C program gix1.c:
  461.  
  462.     machine% gofc gix1.gs
  463.     Gofer->C Version 1.02 (2.30) ...
  464.  
  465.     Reading script file "/usr/local/lib/Gofer/standard.prelude":
  466.     Reading script file "gix1.gs":
  467.                    
  468.     Writing C output file "gix1.c":
  469.     [Leaving Gofer->C]
  470.  
  471. Now we compile the C programs, and link them into a single executable
  472. file, ix1:
  473.  
  474.     machine% cc -O -o ix1 gix1.c cix1.c runtime.o
  475.  
  476. Finally, we get to run the program:
  477.  
  478.     machine% ix1
  479.     hello, world
  480.     hello, world
  481.  
  482. Note that the external function call mechanism described here cannot be
  483. used in the Gofer interpreter.  The external function call mechanism is
  484. a prototype only.  It should also be emphasized that we do not, in
  485. general, regard the Gofc compiler as suitable for serious applications
  486. development.  If you want to do something along those lines, try one of
  487. the full Haskell systems available (e.g. the Lisp or C interfaces for
  488. Yale Haskell, or the C interface for Glasgow Haskell).
  489.  
  490.  
  491. .ST 2.8  The do notation
  492. --------------------
  493. Gofer 2.30 supports a new, experimental syntax for monad comprehensions
  494. which we will refer to as `do {...} notation'.  The do notation is only
  495. supported if the system is compiled with the DO_COMPS flag in prelude.h
  496. set to to 1, and the DO_COMPS section of parser.y included.  See the
  497. comments in these files for further details.
  498.  
  499. The do notation is useful for monadic programming, and requires the
  500. cc.prelude, and uses the following syntax:
  501.  
  502.     <expr>   ::=  do "{" <dquals> <expr> "}"  -- uses layout rule
  503.  
  504.     <dquals> ::=  {<dqual> ;}
  505.  
  506.     <dqual>  ::=  <pat> <- <expr>             -- generator
  507.               |   <expr>                      -- command
  508.               |   let "{" decls "}"           -- local definitions
  509.               |   if <expr>                   -- guard
  510.  
  511. With this notation, a guard is written as if <expr>, while a single
  512. expression of the form <expr> is treated as a command, i.e. a generator
  513. of the form _ <- <expr>.  For example, a general version of the filter
  514. function can be defined as:
  515.  
  516.     myFilter     :: Monad0 m => (a -> Bool) -> m a -> m a
  517.     myFilter p xs = do x <- xs
  518.                        if p x
  519.                        result x
  520.  
  521. If you prefer, this can be written as follows, using explicit layout:
  522.  
  523.     myFilter p xs = do { x <- xs;
  524.                          if p x;
  525.                          result x
  526.                        }
  527.  
  528. In standard comprehension notation, this would be written:
  529.  
  530.     myFilter p xs = [ x | x <- xs, p x ]
  531.  
  532. Perhaps the most significant difference between these two examples is
  533. the fact that the call to result must be written explicitly in the
  534. first case.  In fact, if the comprehension is interpreted in a monad,
  535. m, then any expression of type (m a) can be used as the final
  536. expression in a do comprehension.  This is useful for describing `tail
  537. recursive' procedures.  For example, compare:
  538.  
  539.     echo' = do c <- getchar
  540.                if c==EOF
  541.                  then result ()
  542.                  else do putchar c
  543.                          echo'
  544.  
  545. with:
  546.  
  547.     echo' = [ () | c  <- getchar,
  548.                    () <- if c==EOF then result ()
  549.                                    else [ () | _ <- putchar c,
  550.                                                () <- echo' ] ]
  551.  
  552. It is, of course, a matter of personal opinion which of these you
  553. prefer.  The intention of do notation is to provide a more attractive
  554. syntax for monadic programming, to be compared with programs using
  555. `bind` in which the example above would be written:
  556.  
  557.     echo' = getchar `bind` \c ->
  558.             if c==EOF then result ()
  559.                       else putchar c  `bind` \_ ->
  560.                            echo'
  561.  
  562. See which notation you prefer for practical programming, and let me
  563. know!
  564.  
  565. .co-------------------------------------------------------------------|
  566. .ST 3. THE IMPLEMENTATION OF GOFER
  567.  
  568. For those interested in the actual implementation of Gofer, there is
  569. a (relatively new) technical report available that describes the
  570. implementation of Gofer 2.30:
  571.  
  572.     The implementation of the Gofer functional programming system
  573.     Mark P. Jones
  574.     Research Report YALEU/DCS/RR-1030
  575.     Yale University, Department of Computer Science,
  576.     May 1994.
  577.  
  578. Copies of this report are currently available by anonymous ftp from
  579. nebula.cs.yale.edu in the directory pub/yale-fp/reports, together
  580. with a number of other recent reports by members of the Yale Haskell
  581. project.
  582.  
  583.  
  584. .co-------------------------------------------------------------------|
  585.