.co This is the `source form' of the user documentation for Gofer, to be
.co processed using my simple prn formatter before being printed.
.co
.co Mark P. Jones  August 1991
.co-------------------------------------------------------------------|
.>ch00
.op
.ti Introduction to Gofer






         __________   __________   __________   __________   ________
        /  _______/  /  ____   /  /  _______/  /  _______/  /  ____  \
       /  / _____   /  /   /  /  /  /______   /  /______   /  /___/  /
      /  / /_   /  /  /   /  /  /  _______/  /  _______/  /  __   __/
     /  /___/  /  /  /___/  /  /  /         /  /______   /  /  \  \ 
    /_________/  /_________/  /__/         /_________/  /__/    \__\

    Functional programming environment, Version 2.20

    Copyright Mark P Jones 1991.






            A N   I N T R O D U C T I O N   T O   G O F E R


     draft version only --- please report any errors, suggestions for
    improvements, extensions (or deletions!) to jones-mark@cs.yale.edu


           This version includes a number of small corrections
                   made since the original release.

   --------------------------------------------------------------------
   Permission to use, copy, modify, and distribute this software and its
   documentation for any personal or educational use without fee is hereby
   granted, provided that:
    a) This copyright notice is retained in both source code and
       supporting documentation.
    b) Modified versions of this software are redistributed only if
       accompanied by a complete history (date, author, description) of
       modifications made; the intention here is to give appropriate
       credit to those involved, whilst simultaneously ensuring that any
       recipient can determine the origin of the software.
    c) The same conditions are also applied to any software system
       derived either in full or in part from Gofer.

   The name "Gofer" is not a trademark, registered  or  otherwise,  and
   you are free to mention this name in published material, public  and
   private correspondence, or other documents  without  restriction  or
   obligation.

   Gofer is provided "as is" without express or implied warranty.
   --------------------------------------------------------------------
.pa
.po
.pn -100
                      T A B L E   O F   C O N T E N T S 


.in contents
.pa
.pn 1
.co-------------------------------------------------------------------|
.>ch01
.ST 1. INTRODUCTION

Gofer is a functional  programming  environment  (in  other  words,  an
interpreter) that I have implemented for my own personal use as part of
my research  into  `qualified  types'.   Nevertheless,  the  system  is
sufficiently complete for me to believe that Gofer may be  of  interest
and use to others interested in the field of functional programming.

These notes give a brief introduction to the Gofer system  and  include
some examples of Gofer  programs.   They  are  not  the  notes  that  I
originally intended to write, being somewhat longer  and  perhaps  more
tutorial in nature.  Nevertheless,  you  will  not  be  able  to  learn
functional programming from this document alone.  A  number  of  useful
references are given in the reading list at the end of  this  document.
In particular, the book by Bird and Wadler [1] is particularly good  as
a general introduction to the use, techniques and theory of  functional
programming.  Although their notation is  a  little  different from the
language used by Gofer, it is  a  relatively  straightforward  task  to
translate between the two, and some suggestions for this are given in a
appendix D.  More importantly, the underlying  semantics  of  Gofer  do
correspond to those expected by the authors of [1].

Whereas the work involved in investigating and implementing  the  ideas
on which Gofer is based were motivated largely by  my  own  program  of
work, the writing of these notes has rather more to do  with  the  hope
that Gofer will be  useful  to  others.   I  would  therefore  be  very
grateful for any feedback on any aspect of the these notes (or  of  the
Gofer system itself).  Please let me know if you discover  any  errors,
or if you find particular  sections  of  these  notes  rather  hard  to
follow.  Suggestions for  improvements  or  extensions  are  more  than
welcome.
.pa
.co-------------------------------------------------------------------|
.>ch02
.ST 2. BACKGROUND AND ACKNOWLEDGEMENTS

The language supported by Gofer is both syntactically and  semantically
similar to that of the functional programming language Haskell [5].  My
principal task in the implementation of Gofer  has  therefore  been  to
decide which  features  I  should  omit  and  then  to  implement  what
remains.  Features common to both include:

  o  Non-strict semantics (lazy evaluation).
  o  Higher-order functions.
  o  Extended polymorphic type system  with  support  for  user-defined
     overloading.
  o  User-defined algebraic datatypes.
  o  Pattern matching.
  o  List comprehensions.
  o  Facilities for  I/O,  whilst  retaining  referential  transparency
     within a program.

For the  benefit  of  readers  familiar  with  Haskell,  the  following
features of Haskell are not supported in the standard version of Gofer:

  o  Modules.
  o  Arrays.
  o  Defaults for unresolved overloading.
  o  Derived instances of standard classes.
  o  Contexts in datatype definitions.
  o  Full range of numeric types and classes.

But Gofer is not just a partial  implementation  of  Haskell;  it  also
includes a number of experimental features which extend the type system
in several ways:

  o  An alternative approach to type classes which avoids the need  for
     construction  of  dictionaries  during  the   evaluation   of   an
     expression.
  o  Type classes may take multiple parameters.
  o  Instances  of  type  classes   may   be   defined   at   arbitrary
     non-overlapping types.
  o  Contexts may include arbitrary type expressions.

These extensions stem from my own research [8, 9, 10, 11, 12] and  were
among the principal motivations for the  development  of  Gofer.   Full
details of the differences between Gofer and Haskell 1.1 are  given  in
appendix C.

Gofer would not have been implemented without my original  introduction
to functional programming using  Orwell  [6],  and  I  am  particularly
grateful to Quentin Miller for answering so many of my questions  about
functional programming and about the Orwell system  in  particular.   I
should also like to mention the influence of the  Haskell  B.  compiler
from Lennart Augustsson and Thomas Johnsson and based on their  earlier
LML compiler [7].

Right from the beginning, I wanted to be able to use Gofer on  a  range
of machines - and in particular, on the humble PC that I use  at  home.
With this in mind, Gofer was actually developed on that same  PC  using
Borland's Turbo C 1.5 and a public domain version of  the  yacc  parser
generator that I picked up some time ago.  Gofer was also written  with
some degree of portability in mind and has subsequently  been  compiled
to run on Sun workstations.  I hope it will also be possible to port it
to other platforms.  It is  my  intention  that  Gofer  be  distributed
complete with source code and I hope that this will be of  interest  to
some users.

Many of the ideas used in the back-end of the Gofer  system  (i.e.  the
compiler and abstract machine) originate from  the  chapters  of  Simon
Peyton Jones textbook [2]; I very much doubt whether Gofer  would  have
been  completed  without  frequent  reference  to   that   book.    The
lambda-lifter used in Gofer is based  on  Thomas  Johnsson's  algorithm
described in [3].

On  the  theoretical  side,  I'm  grateful  to  Phil  Wadler  for   the
encouragement that he has given me with my  work  on  qualified  types.
Many of the basic ideas that I have used were inspired by his  original
paper motivating the use of type classes [4].
.pa
.co-------------------------------------------------------------------|
.>ch03
.ST 3. STARTING GOFER

The Gofer interpreter is usually entered by giving the command `gofer',
after which a display something like the  following  will  normally  be
produced:

    Gofer Version 2.20
 
    Reading script file "/gofer/prelude":
    Parsing........................................................
    Dependency analysis............................................
    Type checking..................................................
    Compiling......................................................

    Gofer session for:
    /gofer/prelude
    Type :? for help
    ?

The file name "/gofer/prelude" mentioned in the  output  above  is  the
name of a file of standard definitions which are loaded into Gofer each
time that the interpreter is started.  By default,  Gofer  reads  these
definitions from  a  file  called  "prelude"  in  the  current  working
directory.  Alternatively you can set the environment variable GOFER to
the name of the  standard  prelude  file,  which  will  then  be  used,
whatever the current working directory might be.

Most commands in Gofer take the form of a colon followed by one or more
characters which distinguish one command from another.  There  are  two
commands which are particularly worth remembering:

  o  :q  exits the  Gofer  interpreter.   On most systems, you can also
     exit from Gofer by typing the end of  file  character  (^Z  on  an
     MS-DOS machine, usually ^D on a unix based machine).

  o  :?  prints a list of all the commands,  which can be useful if you
     forget the name of the command that you want to use.

The complete range of commands supported by the  Gofer  interpreter  is
described in appendix F.

Note that the interrupt key (^C on most systems) can  be  used  at  any
time whilst using Gofer to abandon the process of reading in a file  of
function definitions or the evaluation  of  an  expression.   When  the
interrupt key is detected, Gofer prints the string "{Interrupted!}" and
prints the "? " prompt so that further commands can be entered.

.pa
.co-------------------------------------------------------------------|
.>ch04
.ST 4. USING GOFER - A BASIC INTRODUCTION

Using Gofer is rather like using a high-level programmable  calculator;
Once the interpreter is loaded, the system  prints  a  prompt  "?"  and
waits for you to enter an expression, and then press the enter (return)
key.  Once the input is complete, Gofer evaluates  the  expression  and
prints its value on the terminal,  before  returning  to  the  original
prompt and waiting for the next expression.  For example:

    ? (2+3)*8
    40
    (5 reductions, 9 cells)
    ? sum [1..10]
    55
    (91 reductions, 130 cells)
    ? 

In the first example, the user entered the expression "(2+3)*8",  which
was evaluated by Gofer and the result "40" printed on the terminal.  At
the end of any calculation, Gofer displays the number of reductions  (a
measure of the amount of work) and cells (a measure of  the  amount  of
memory) that were used during the calculation.  These  figures  can  be
useful for comparing the performance of different ways of carrying  out
the same calculation.

In the second example, the user typed  the  expression  "sum  [1..10]".
The notation "[1..10]" represents the list of integers between 1 and 10
inclusive, and "sum" is a  standard  function  which  can  be  used  to
determine the sum of a list of integers.  Thus the result  obtained  by
Gofer is:

          1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10  =  55

We could have typed this sum into Gofer directly:

    ? 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10
    55
    (10 reductions, 23 cells)
    ? 

and this calculation is certainly more efficient as it uses only  1/9th
of the number of reductions and 1/5th of the number  of  cells  as  the
original calculation.  On the other hand, the  original  expression  is
much shorter and you are much less likely to make a mistake  typing  in
the expression "sum [1..200]" than you would be if you tried  to  enter
the sum of the integers from 1 to 200 directly.

You will learn more about the kind of expressions that can  be  entered
into Gofer in the rest of this document.
.pa
.co-------------------------------------------------------------------|
.>ch05
.ST 5. STANDARD AND USER-DEFINED FUNCTIONS

The function "sum" used in the examples above, and indeed the  addition
and multiplication functions (+) and (*), are  all  standard  functions
which are included as part of a large collection  of  functions  called
the `standard prelude' which are loaded into the Gofer system each time
that you start the interpreter.  Quite a number of useful  calculations
can be carried out using these functions alone, but  for  more  general
use you can also define your own functions and store the definitions in
a file so that these functions can be loaded and used by by  the  Gofer
system.  For example, suppose that you create a file "fact"  containing
the following definition:

     fact n = product [1..n]

The "product" function is another standard function which can  be  used
to calculate the product of a list of integers, and so the  line  above
defines a  function  "fact"  which  calculates  the  factorial  of  its
argument.  In standard  mathematical notation,  fact n = n!   which  is
usually defined informally by an equation of the form:

                 n! = 1 * 2 * ... * (n-1) * n

Once you become familiar with the notation used by Gofer, you will  see
that the Gofer definition of the  factorial  function  is  really  very
similar to this informal mathematical definition.

In order to use this definition from the  Gofer  interpreter,  we  must
first load the definitions of  the  file  into  the  interpreter.   The
simplest way to do this uses the ":l" command:

    ? :l fact
    Reading script file "fact":
    Parsing......................................................
    Dependency analysis..........................................
    Type checking................................................
    Compiling....................................................

    Gofer session for:
    /gofer/prelude
    fact
    ?

Notice the list of filenames displayed after "Gofer session for:"; this
tells you which files of definitions are currently being used by Gofer,
the first of which is the  file  containing  the  definitions  for  the
standard prelude.  Since the file  containing  the  definition  of  the
factorial function has now  been  loaded,  we  can  make  use  of  this
function in expressions entered to the interpreter:

    ? fact 6
    720
    (57 reductions, 85 cells)

For another example, recall the  standard  mathematical  formula  which
tells us that  the  number  of  ways  of  choosing  r  objects  from  a
collection of n objects is given by n! / (r! * (n-r)!).  In Gofer, this
function can be defined by:

    comb n r = fact n /(fact r * fact (n-r))

In order to use this function, we can either edit the file "fact" which
contains  the  definition  of  the  factorial  function,   adding   the
definition of "comb" on a new line, or we can include the definition as
part of an expression entered whilst using Gofer:

    ? comb 5 2 where comb n r = fact n /(fact r * fact (n-r))
    10
    (110 reductions, 161 cells)
    ? 

The ability to define a function as part of an expression like this  is
often quite useful.  However, if the function "comb" were likely to  be
wanted on a number of occasions, it would be more sensible to  add  its
definition to the contents of the file "fact",  instead  of  having  to
repeat the definition each time it is used.

You will learn more about the functions defined in the standard prelude
and find out  how  to  define  your  own  functions  in  the  following
sections.
.pa
.co-------------------------------------------------------------------|
.>ch06
.ST 6. FUNCTION NAMES - IDENTIFIERS AND OPERATORS

As the examples of the previous section show, there are  two  kinds  of
name that can be used for a function; identifiers  such  as  "sum"  and
operator symbols such as "+" and "*".  Choosing the appropriate kind of
name for a particular function  can  often  help  to  make  expressions
involving that function easier to read.  If for  example  the  addition
function was represented by the name "plus" rather  than  the  operator
symbol "+" then the sum of the integers from 1 to 5 would  have  to  be
written as:

                 plus (plus (plus (plus 1 2) 3) 4) 5

In this particular case, another way of writing the same sum is:

                 plus 1 (plus 2 (plus 3 (plus 4 5)))

Not only does the use of the identifier "plus" make  these  expressions
larger and more difficult to read than the equivalent expressions using
"+"; it  also  makes  it  very  much  harder  to  see  that  these  two
expressions do actually have the same value.

Gofer distinguishes between the two types of name according to the  way
that they are written:

  o  An  identifier  begins with a  letter  of the  alphabet optionally
     followed by a sequence of characters, each of which  is  either  a
     letter,  a  digit,  an  apostrophe  (')  or   an   underbar   (_).
     Identifiers representing functions or variables must begin with  a
     lower case letter (identifiers beginning with an upper case letter
     are  used  to  denote  a  special  kind  of  function   called   a
     `constructor function' described in section 11.1).  The  following
     identifiers are examples of Gofer variable and function names:

       sum    f    f''    integerSum    african_queen    do'until'zero

     The following identifiers are reserved words in Gofer  and  cannot
     be used as the name of a function or variable:

         case      of         where      let        in         if
         then      else       data       type       infix      infixl
         infixr    primitive  class      instance

  o  An  operator symbol  is written using one or more of the following
     symbol characters:

         :  !  #  $  %  &  *  +  .  /  <  =  >  ?  @  \  ^  |  -

     In addition, the tilde character (~) is also  permitted,  although
     only in the first position of an  operator  name.   [N.B.  Haskell
     also makes the  same  restriction  for  the  minus/dash  character
     (-)].   Operator  names  beginning  with  a  colon  are  used  for
     constructor functions in the same  way  as  identifiers  beginning
     with a capital  letter  as  mentioned  above.   In  addition,  the
     following operator symbols have special uses in Gofer:

         ::    =    ..    @    \    |    <-    ->    ~    =>

     All other operator  symbols can be used as variables  or  function
     names, including each of the following examples:

         +    ++    &&    ||     <=    ==    /=    //  .
         ==>  $     @@     -*-   \/    /\    ...   ?

     [Note that each of the symbols in the first line is  used  in  the
     standard prelude.  If you are interested in using Gofer to develop
     programs for use with a Haskell compiler, you might also  want  to
     avoid using the operator symbols := ! :+ and :% which are used  to
     support features in Haskell not currently provided  by  the  Gofer
     standard prelude.]

Gofer provides two simple mechanisms which make it possible to  use  an
identifier  as  an  operator  symbol,  or  an  operator  symbol  as  an
identifier:

  o  Any  identifier  will be treated as an  operator  symbol  if it is
     enclosed in backquotes (`) -- for example, the  expressions  using
     the "plus" function above are a little easier to read  using  this
     technique:

               (((1 `plus` 2) `plus` 3) `plus` 4) `plus` 5

     In general, an expression of the form "x `op` y" is equivalent  to
     the corresponding expression "op x y", whilst an  expression  such
     as "f x y z" can also be written as "(x `f` y) z".

     [NOTE: For those using Gofer on a  PC,  you  may  find  that  your
     keyboard does not have a backquote key!  In this case  you  should
     still be able to enter a backquote by holding down the key  marked
     ALT, pressing the keys '9' and then '6' on the numeric keypad  and
     then releasing the ALT key.]

  o  Any  operator symbol  can be treated as an identifier by enclosing
     it in parentheses.  For example, the addition function denoted  by
     the operator symbol "+" is often written as "(+)".  Any expression
     of the form "x + y" can also be written in the form "(+) x y".

There are two more technical problems which have to be dealt with  when
working with operator symbols:

  o  Precedence: Given operator symbols (+) and (*), should "2 * 3 + 4"
     be treated as either "(2 * 3) + 4" or "2 * (3 + 4)"?

     This problem is solved by assigning  each  operator  a  precedence
     value (an integer in the range 0 to 9).  In a  situation  such  as
     the  above,  we  simply  compare  the  precedence  values  of  the
     operators involved,  and  carry  out  the  calculation  associated
     with  the  highest  precedence  operator  first.    The   standard
     precedence values for (+) and (*) are 6 and 7 respectively so that
     the expression above will actually be treated as "(2 * 3) + 4".

  o  Grouping: The above rule  is only useful when the operator symbols
     involved have  distinct  precedences.   For  example,  should  the
     expression "1 - 2 - 3" be treated as either "(1 - 2) - 3" giving a
     result of -4, or as "1 - (2 - 3)" giving a result of 2?

     This problem is  solved  by  giving  each  operator  a  `grouping'
     (sometimes called its associativity).  An operator symbol  (-)  is
     said to:

       o  group to the left  if "x - y - z" is treated as "(x - y) - z"

       o  group to the right if "x - y - z" is treated as "x - (y - z)"

     A third possibility is that an expression of the form "x - y -  z"
     is to be treated as ambiguous and will  be  flagged  as  a  syntax
     error.   In  this  case  we  say  that   the   operator   (-)   is
     non-associative.

     The standard approach in Gofer is to treat (-) as grouping to  the
     left so that "1 - 2 - 3" will actually be treated as "(1-2)-3".

By  default,  every  operator   symbol   in   Gofer   is   treated   as
non-associative with precedence 9.  These values can be  changed  by  a
declaration of one of the following forms:

    infixl digit ops      to declare operators which group to the left
    infixr digit ops      to declare operators which group to the right
    infix  digit ops      to declare non-associative operators

In each of these declarations ops represents a  list  of  one  or  more
operator symbols separated by commas and digit is an integer between  0
and 9 which gives the precedence value for each of the listed  operator
symbols.  The precedence digit may be omitted in which case a value  of
9 is assumed.  There are a number of restrictions on the use  of  these
declarations:

  o  Operator  declarations  can  only  appear  in  files  of  function
     definitions which are loaded into Gofer; they  cannot  be  entered
     directly whilst using the Gofer interpreter.

  o  At most one operator declaration is permitted for  any  particular
     operator symbol (even if repeated  declarations  all  specify  the
     same precedence and grouping as the original declaration).

  o  Any file containing a declaration for an operator  precedence  and
     grouping must also contain  a  (top-level)  declaration  for  that
     operator.

In theory, it is possible to use an operator declaration at  any  point
in a file of definitions.  In practice, it is sensible to  ensure  that
each operator is declared before  the  symbol  is  used.   One  way  to
guarantee this is to place all operator declarations at  the  beginning
of the file [this condition is enforced in Haskell].  Note  that  until
an operator declaration for a particular  symbol  is  encountered,  any
occurrence of that symbol will be treated as a non-associative operator
with precedence 9.

The following operator declarations are taken from the standard prelude:

    -- Operator precedence table

    infixl 9 !!
    infixr 9 .
    infixr 8 ^
    infixl 7 *
    infix  7 /, `div`, `rem`, `mod`
    infixl 6 +, -
    infix  5 \\
    infixr 5 ++, :
    infix  4 ==, /=, <, <=, >=, >
    infix  4 `elem`, `notElem`
    infixr 3 &&
    infixr 2 ||

and their use is illustrated by the following examples:

 Expression:     Equivalent to:   Reasons:
 -----------     --------------   --------
 1 + 2 - 3       (1 + 2) - 3      (+) and (-) have the same  precedence
                                  and group to the left.
 x : ys ++ zs    x : (ys ++ zs)   (:) and (++) have the same precedence
                                  and group to the right
 x == y || z     (x == y) || z    (==) has higher precedence than (||).
 3 * 4 + 5       (3 * 4) + 5      (*) has higher precedence than (+).
 y `elem` z:zs   y `elem` (z:zs)  (:) has higher precedence than elem.
 12 / 6 / 3      syntax error     ambiguous  use  of  (/);  could  mean
                                  either (12/6)/3 or 12/(6/3).

Note that function application always binds more tightly than any infix
operator symbol.  For example, the expression "f x + g y" is equivalent
to "(f x) + (g y)".  Another example which often causes problems is the
expression  "f x + 1",  which is treated as "(f x)  +  1"  and  not  as
"f (x+1)" as is sometimes expected.
.pa
.co-------------------------------------------------------------------|
.>ch07
.ST 7. BUILT-IN TYPES

An important part of Gofer is the type system which is used  to  detect
errors  in  expressions  and  function  definitions.    Starting   with
primitive expressions such as numeric constants, Gofer assigns  a  type
to each expression that describes the kind of value represented by  the
expression.

In  general  we write  object :: type  to indicate  that  a  particular
expression has the indicated type.  For example:

    42   :: Int         indicating that  42  is an  integer (Int is the
                        name for the type of integer values).

    fact :: Int -> Int  indicating  that  "fact"  is a  function  which
                        takes  an  integer  argument  and  returns   an
                        integer value (its factorial).

The most important property of the type system is that it  is  possible
to determine the type of an expression without having to  evaluate  it.
For example, the information given above  is  sufficient  to  determine
that fact 42 :: Int without needing to calculate 42! first.

Gofer has a wide range of built-in types, described  in  the  following
sections.  In addition, Gofer also includes facilities for defining new
types as well as types acting as  abbreviations  for  complicated  type
expressions as described in section 11.


.ST 7.1  Functions
--------------
If t1 and t2 are types then t1 -> t2 is the type of a  function  which,
given an argument of type t1 produces a result of type t2.  A  function
of type t1 -> t2 is said to have argument type t1 and result type t2.

In mathematics, the result of applying a function f to an argument x is
traditionally written as f(x).  In many situations,  these  parentheses
are unnecessary and may be omitted when using Gofer.

e.g. if f :: t1 -> t2 and x :: t1 then f x is the result of applying
     f to x and has type t2.


If t1, t2, ..., tn are type expressions then:

                   t1 -> t2 -> ... -> tn

can be used as an abbreviation for the type:

               t1 -> (t2 -> ( ... -> tn) ...)

In a similar way, an expression of the form f x1 x2 ... xn is simply an
abbreviation for the expression ( ... ((f x1) x2) ... xn).

These two conventions allow us to deal with functions taking more  than
one argument rather elegantly.  For example, the type of  the  addition
function (+) is:
                       Int -> Int -> Int

In other words, "(+)" is a function which takes an integer argument and
returns a value of type (Int -> Int).  For  example,  "(+)  5"  is  the
function which takes an integer value n and returns the  value  of  the
integer n plus 5.  Hence "(+) 5 4", which is equivalent  to  "5  +  4",
evaluates to the integer 9 as expected.


.ST 7.2  Booleans
-------------
Represented by the type "Bool", there are two boolean values written as
"True" and "False".   The  standard  prelude  includes  several  useful
functions for manipulating boolean values:

    (&&), (||) :: Bool -> Bool -> Bool

        The value of the expression b && d is True if and only if  both
        b and d are True.  If b is False then d is not evaluated.

        The value of the expression b || d is True if either of b or  d
        is True.  If b is True then d is not evaluated.

    not  :: Bool -> Bool

        The value of the expression not b is the opposite boolean value
        to that of b; not True = False, not False = True.

Gofer includes a special form of `conditional expression' which enables
an expression to select between two alternatives according to the value
of a boolean expression:

                     if b then t else f 

is an expression which is equivalent to t if b evaluates to True, or to
f if b evaluates to False.  Note that an expression  of  this  form  is
only acceptable if b is an expression of type Bool and if the types  of
t and f are the same, in which case the whole expression also has  that
type.


.ST 7.3  Integers
-------------
Represented by the type "Int", the integer type includes both  positive
and negative integers such as -273, 0  and  383.   Like  many  computer
systems, the range of integer values that can be used is restricted and
calculations using large positive  or  negative  numbers  may  lead  to
(undetected) overflow.

A wide range of operators and functions are  defined  in  the  standard
prelude for use with integers:

    (+)     addition.
    (*)     multiplication.
    (-)     subtraction.
    (^)     raise to power.
    negate  unary negation.  An expression of the form "-x" is treated
            as the expression "negate x".
    (/)     integer division.
    div        "        "
    rem     remainder, related to integer division by the law:
                     (x `div` y)*y + (x `rem` y) == x
    mod     modulo, like remainder except that the modulo has the same
            sign as the divisor.
    odd     returns True if argument is odd, False otherwise.
    even    returns True if argument is even, False otherwise.
    gcd     returns the greatest common divisor of its two arguments.
    lcm     returns the least common multiple of its two arguments.
    abs     returns the absolute value of its argument.
    signum  returns -1, 0 or 1 indicating that its argument is negative,
            zero or positive respectively.

The  less  familiar  operators  are  illustrated   by   the   following
identities:

     3^4 == 81,          7 `div` 3 == 2,      even 23 == False
     7 `rem` 3 == 1,    -7 `rem` 3 == -1,     7 `rem` -3 == 1
     7 `mod` 3 == 1,    -7 `mod` 3 == 2,      7 `mod` -3 == -2
     gcd 32 12 == 4,    abs (-2) == 2,        signum 12 == 1


.ST 7.4  Floating point numbers
---------------------------
Represented by the type "Float", elements of this type can be  used  to
represent fractional values  as  well  as  very  large  or  very  small
quantities.  Such values are however usually only accurate to  a  fixed
number of digits and rounding errors may  occur  in  some  calculations
making significant use of floating point quantities.  A  numeric  value
in an input expression will only be treated as a floating point  number
if it either includes a decimal point such as 3.14159, or if the number
is too large to be stored as a value of type Int.  Scientific  notation
may also be used to enter floating point quantities; for example  1.0e3
is equivalent to 1000.0, whilst 5.0e-2 is equivalent to 0.05.

[N.B. floating point numbers are not included in all implementations of
Gofer].


.ST 7.5  Characters
---------------
Represented by  the  type  "Char",  elements  of  this  type  represent
individual characters such as those entered at a  keyboard.   Character
values  are  written  as  single  characters  enclosed  by   apostrophe
characters: e.g. 'a',  '0',  'Z'.   Some  special  characters  must  be
entered using an `escape code'; each of these begins with  a  backslash
character '\', followed  by  one  or  more  characters  to  select  the
required character.  Some of the most useful escape codes are:

     '\\'             backslash
     '\''             apostrophe
     '\"'             double quote
     '\n'             newline
     '\b' or '\BS'    backspace
     '\DEL'           delete
     '\t' or '\HT'    tab
     '\a' or '\BEL'   alarm (bell)
     '\f' or '\FF'    formfeed

Additional escape characters include:

     '\^c'            control character, where c is replaced by
                      one of the characters:
                         "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
                      For example, '\^A' represents control-A

     '\number'        representing the character with ASCII value
                      specified by the given decimal 'number'.

     '\onumber'       representing the character with ASCII value
                      specified by the given octal 'number'.

     '\xnumber'       representing the character with ASCII value
                      specified by the given 'hexadecimal' number.

     '\name'          named ASCII control character, where
                      `name' is replaced by one of the standard
                      ascii names e.g. `\DC3`.

In contrast with  some  common  languages  (such  as  C,  for  example)
character values are quite distinct from integers; however the standard
prelude does include functions:

                   ord :: Char -> Int
                   chr :: Int -> Char

which enable you to map a character to its corresponding  ASCII  value,
or from an ASCII value to the corresponding character:

    ? ord 'a'
    97
    (2 reductions, 6 cells)
    ? chr 65
    'A'
    (2 reductions, 7 cells)
    ?         


.ST 7.6  Lists
----------
If a is a type then [a] is the type whose elements are lists of  values
of type a.  There are several ways of writing list expressions:

  o   The simplest list of any type is the empty list, written [].

  o   Non-empty lists  can be constructed either by  explicitly listing
      the members of the list (for example: [1,3,10]) or  by  adding  a
      single element onto the front  of  another  list  using  the  (:)
      operator (pronounced "cons").  These notations are equivalent:

       [1,3,10]  =  1 : [3,10]  =  1 : 3 : [10]  =  1 : 3 : 10 : []

      (the (:) operator groups to the right so 1 :  3  :  10  :  []  is
      equivalent to (1:(3:(10:[]))) -- a list whose first element is 1,
      second element is 3 and last element is 10).

The  standard  prelude  includes  a  wide  range   of   functions   for
calculations involving lists.  For example:

  o  length xs  returns the number of elements in the list xs.
  o  xs ++ ys   returns the list of elements in xs followed by the
                elements in ys
  o  concat xss returns the list of elements in each of the lists in
                xss
  o  map f xs   returns the list of values obtained by applying the
                function f to each of the values in the list xs in turn.

Here are some examples using these functions:

    ? length [1,3,10]
    3
    (15 reductions, 28 cells)

    ? [1,3,10] ++ [2,6,5,7]
    [1, 3, 10, 2, 6, 5, 7]
    (19 reductions, 77 cells)

    ? concat [[1], [2,3], [], [4,5,6]]
    [1, 2, 3, 4, 5, 6]
    (29 reductions, 93 cells)

    ? map ord ['H', 'e', 'l', 'l', 'o']
    [72, 101, 108, 108, 111]
    (22 reductions, 73 cells)

    ?

Note that all of the elements in a list must be of the  same  type,  so
that an expression such as ['a', 2, False] is not permitted.

[ASIDE: At this point  it  might  be  useful  to  mention  an  informal
convention that is used by a  number  of  functional  programmers  when
choosing names for variables  representing  elements  of  lists,  lists
themselves, lists of lists and  so  on.   If  for  example,  a  typical
element of a list is called x, then it is often useful to use the  name
xs for a list of such values, suggesting that a list contains a  number
of "x"s.  Similarly, a list of lists might be  called  xss.   Once  you
have understood this convention it  is  much  easier  to  remember  the
relationship between the variables in the  expression  (x:xs)  than  it
would be if different names had been used such as (a:b).]


.ST 7.7  Strings
------------
A string is treated as a list of characters  and  the  type  String  is
simply an abbreviation for the type [Char].   Strings  are  written  as
sequences of characters enclosed between  speech  marks.   All  of  the
escape codes that can be used for characters may  also  be  used  in  a
string:

    ? "hello, world"
    hello, world
    (0 reductions, 13 cells)

    ? "hello\nworld"
    hello
    world
    (0 reductions, 12 cells)
    ?

In addition, strings may contain the escape sequence "\&" which can  be
used to separate otherwise  ambiguous  pairs  of  characters  within  a
string:

    e.g.  "\123h"   represents the string ['\123', 'h']
          "\12\&3h" represents the string ['\12', '3', 'h']

A string expression may be spread over a number of lines using a gap --
a non-empty sequence of space, tab and new line characters enclosed  by
backslash characters:

    ? "hell\   \o"
    hello
    (0 reductions, 6 cells)
    ? 

Notice that strings are printed  differently from other  values,  which
gives the programmer complete control over the  format  of  the  output
produced by a program.  The only values that Gofer can in fact  display
on the terminal are strings.  If the type of an expression entered into
Gofer is equivalent to String then the expression is  printed  directly
by evaluating and printing each character  in  the  list  in  sequence.
Otherwise, the expression to  be  evaluated,  e,  is  replaced  by  the
expression show' e where show' is a built-in function (defined as  part
of the standard prelude)  which  converts  any  value  to  a  printable
representation.  The  only way of printing a  string value  in the same
way as any other value is by explicitly using the show' function:

    ? show' "hello"
    "hello"
    (7 reductions, 24 cells)
    ?

The careful reader may have been puzzled by  the  fact  the  number  of
reductions used in the first three examples above was zero.  This is in
fact quite correct since these expressions are constants and no further
evaluation can be carried out.  For constant expressions of  any  other
type there will always be at least one reduction needed  to  print  the
value since the constant  must  first  be  translated  to  a  printable
representation using the show' function.

Because strings are represented as lists  of  characters,  all  of  the
standard prelude functions for manipulating lists can also be used with
strings:

    ? length "Hello"
    5
    (22 reductions, 36 cells)

    ? "Hello, " ++ "world"
    Hello, world
    (8 reductions, 37 cells)

    ? concat ["super","cali","fragi","listic"]
    supercalifragilistic
    (29 reductions, 101 cells)

    ? map ord "Hello"
    [72, 101, 108, 108, 111]
    (22 reductions, 69 cells)

    ? 


.ST 7.8  Tuples and the unit type
-----------------------------
If t1, t2, ..., tn are types and n>=2, then there is a type of n-tuples
written (t1, t2, ..., tn) whose elements are also written in  the  form
(x1, x2, ..., xn) where the expressions x1, x2, ..., xn have types  t1,
t2, ..., tn respectively.

    e.g.  (1, [2], 3)   :: (Int, [Int], Int)
          ('a', False)  :: (Char, Bool)
          ((1,2),(3,4)) :: ((Int, Int), (Int, Int))

Note that, unlike lists, the elements in a  tuple  may  have  different
types, although the number of elements in the tuple is fixed.

The unit type is written () and has a  single  element  which  is  also
written as ().  The unit type is of particular interest in  theoretical
treatments of the type system of Gofer, although you  may  occasionally
find a use for it in practical programs.
.pa
.co-------------------------------------------------------------------|
.>ch08
.ST 8. ERRORS

.ST 8.1  Errors detected on input
-----------------------------
After an expression has been entered, but before any attempt is made to
evaluate it, Gofer carries out a number of checks to make sure that the
expression that you typed does not contain any errors.  Here  are  some
examples of the kind of problem that might occur:

  o  Syntax errors.  The most common situation in which this happens is
     when  you  make  a  typing  mistake,  either  leaving   out   some
     characters, or perhaps pressing the wrong keys  instead.   In  the
     following example, the user has missed out a `[' character:

         ? sum 1..100]
         ERROR: Syntax error in input (unexpected `..')
         ?

  o  Undefined variables.  This happens when you  enter  an  expression
     using a variable or function name that is not defined  in  any  of
     the files of definitions loaded into Gofer.  This can  often  mean
     that you have misspelt the name of a function, or that  the  files
     defining a function have not yet been loaded.  For example:

         ? sum [1..n]
         ERROR: Undefined variable "n"
         ? 

  o  Type errors.  Certain  expressions  are  sensible  only  when  the
     functions used in those expressions are applied to values  of  the
     appropriate type.  For example, whilst the factorial function  can
     be used to calculate the factorial of an integer,  it  is  clearly
     meaningless to try to  determine  the  factorial  of  a  character
     value.  This kind of problem can be detected using  the  types  of
     the components of an expression.  In the expression "fact 'A'", we
     can see that the argument 'A' has type Char which does  not  match
     the argument type Int of the factorial function.  This error  will
     be detected by Gofer if you try to evaluate the expression:

         ? fact 'A'
         ERROR: Type error in application
         *** expression     : fact 'A'
         *** term           : 'A'
         *** type           : Char
         *** does not match : Int

         ?


.ST 8.2  Errors during evaluation
-----------------------------
If no errors are detected in an input expression, Gofer then begins  to
evaluate that expression.  Despite all of the checks that  are  carried
out before the evaluation begins, it is still possible for an error  to
occur during the evaluation of an expression.   A  typical  example  of
this is an attempt to divide a number by zero.   In  this  case,  Gofer
prints the part of the  expression  being  evaluated  that  caused  the
error, surrounded by braces `{' and `}':

    ? 3/0
    {primDivInt 3 0}
    (4 reductions, 30 cells)
    ? 

[The function "primDivInt" which appears here is a  primitive  function
used to divide  one  integer  (its  first  argument)  by  another  (the
second)].  If an error occurs in just one part of  an  expression, only
the part causing the problem will be displayed:

    ? 4 + (5/0)
    {primDivInt 5 0}
    (5 reductions, 32 cells)
    ? 

A standard function called "error" is defined in the  standard  prelude
which is often useful for ensuring that appropriate error messages  are
produced when an error occurs:

    ? error "Problem has occurred"
    {error "Problem has occurred"}
    (23 reductions, 99 cells)
    ? 
.pa
.co-------------------------------------------------------------------|
.>ch09
.ST 9. MORE ABOUT VALUE DECLARATIONS

.ST 9.1  Simple pattern matching
----------------------------
Although the Gofer standard prelude includes many useful functions, you
will usually need to define a collection of new functions for  specific
problems and calculations.  The declaration of a function  "f"  usually
takes the form of a number of equations of the form:

            f <pat1> <pat2> ... <patn>  =   <rhs>

(or an equivalent expression, if "f"  is  written  as  by  an  operator
symbol).   Each  of  the  expressions  <pat1>,  <pat2>,   ...,   <patn>
represents an argument to the function "f" and is called  a  `pattern'.
The number of such arguments is called the arity of  "f".   If  "f"  is
defined by more than one equation then they must  be  entered  together
and each one must give the same arity for "f".

When a function is defined by more than one equation, it  will  usually
be necessary to evaluate one or more of the arguments to  the  function
to  determine  which  equation  applies.   This   process   is   called
`pattern-matching'.  In all of the previous examples we have used  only
the simplest kind of pattern -- a variable.  As  an  example,  consider
the factorial function defined in section 5:

    fact n = product [1..n]

If we then wish to evaluate the expression "fact 6" we first match  the
expression "6" against the pattern "n" and then evaluate the expression
obtained from "product [1..n]" by replacing the variable "n"  with  the
expression "6".  The process of matching the arguments  of  a  function
against the patterns in its definition and obtaining another expression
to be evaluated is called a `reduction'.  Using Gofer, it  is  easy  to
verify that the evaluation of "fact 6" takes one  more  reduction  than
that of "product [1..6]":

    ? fact 6
    720
    (57 reductions, 85 cells)
    ? product [1..6]
    720
    (56 reductions, 85 cells)
    ? 

Many kinds of constants such as the boolean values True and  False  can
also be used in  patterns,  as  in  the  following  definition  of  the
function "not" taken from the standard prelude:

    not True  = False
    not False = True

In order to determine the value of an expression of the form  "not  b",
we must first evaluate the expression "b".  If  the  result  is  "True"
then we use the first equation  and  the  value  of  "not  b"  will  be
"False".  If the value of "b" is "False", then the second  equation  is
used and the value of "not b" will be "True".

Other constants, including integers, characters and strings may also be
used in patterns.  For example, if we define a function "hello" by:

    hello "Mark"  =  "Howdy"
    hello name    =  "Hello " ++ name ++ ", nice to meet you!"

then:

    ? hello "Mark"
    Howdy
    (1 reduction, 12 cells)
    ? hello "Fred"
    Hello Fred, nice to meet you!
    (13 reductions, 66 cells)
    ?

Note that the  order  in  which  the  equations  are  written  is  very
important because Gofer always uses the first applicable equation.   If
instead we had defined the function with the equations:

    hello name    =  "Hello " ++ name ++ ", nice to meet you!"
    hello "Mark"  =  "Howdy"

then the results obtained using this function would have been a  little
different:

    ? hello "Mark"
    Hello Mark, nice to meet you!
    (13 reductions, 66 cells)
    ? hello "Fred"
    Hello Fred, nice to meet you!
    (13 reductions, 66 cells)
    ?

There are a number of other useful kinds of pattern, some of which  are
illustrated by the following examples:

  o  Wildcard:       _        matches  any value  at all;  it is like a
                              variable pattern, except that there is no
                              way of referring to the matched value.

  o  Tuples:         (x,y)    matches a  pair  whose  first  and second
                              elements are called x and y respectively.

  o  Lists:          [x]      matches a list with precisely one element
                              called x.
                     [_,2,_]  matches  a   list  with   precisely three
                              elements,  the  second  of  which  is the
                              integer 2.
                     []       matches the empty list.
                     (x:xs)   matches a non-empty  list with head x and
                              tail xs.

  o  As patterns:    p@(x,y)  matches a  pair  whose  first and  second
                              components  are  called  x  and  y.   The
                              complete pair can  also  be  referred  to
                              directly as p.

  o  (n+k) patterns: (m+1)    matches an integer value  greater than or
                              equal to 1.  The value referred to by the
                              variable m is one  less  than  the  value
                              matched.

A further kind of pattern (called an irrefutable pattern) is introduced
in section 9.11.

Note that no variable name can be used more than once on the left  hand
side of each equation in a function definition.  The following example:

    areTheyTheSame x x = True 
    areTheyTheSame _ _ = False 

will not be accepted by the Gofer system, but should instead be defined
using the notation of guards introduced in the next section:

    areTheyTheSame x y
            | x==y      = True
            | otherwise = False


.ST 9.2  Guarded equations
----------------------
Each of the equations in a function  definition  may  contain  `guards'
which require  certain conditions  on  the  values  of  the  function's
arguments to be met.  As an example, here is a function which uses  the
standard prelude function even :: Int -> Bool to determine whether  its
argument is an even integer or not, and returns the  string  "even"  or
"odd" as appropriate:

    oddity n | even n    = "even"
             | otherwise = "odd"

In general, an equation using guards takes the form:

    f x1 x2 ... xn | condition1  =  e1
                   | condition2  =  e2
                   .
                   . 
                   | conditionm  =  em

This equation is used by evaluating each  of  the  conditions  in  turn
until one of them evaluates to "True", in which case the value  of  the
function is given by the corresponding expression e on the  right  hand
side of the `=' sign.  In Gofer, the variable "otherwise" is defined to
be equal to "True", so that writing "otherwise" as the condition  in  a
guard means that the corresponding expression will always be used if no
previous guard has been satisfied.

[ASIDE: in the notation of [1], the above examples would be written as:

    oddity n        =  "even",   if even n
                    =  "odd",    otherwise

    f x1 x2 ... xn  = e1,     if condition1
                    = e2,     if condition2
                      .
                      .
                    = em,     if conditionm

Translation between the two notations is relatively straightforward.]


.ST 9.3  Local definitions
----------------------
Function definitions may include local definitions for variables  which
can be used both in guards and on the right hand side of  an  equation.
Consider the following function which calculates the number of distinct
real roots for a quadratic equation of the form a*x*x + b*x + c = 0:

    numberOfRoots a b c | discr>0   =  2
                        | discr==0  =  1
                        | discr<0   =  0
                          where discr = b*b - 4*a*c

[ASIDE: The operator (==) is used to test whether two values are  equal
or not.  You should take care not to confuse this with the  single  `='
sign used in function definitions].

Local definitions can also be introduced at an arbitrary  point  in  an
expression using an expression of the form:

                  let <decls> in <expr>

For example:

    ? let x = 1 + 4 in x*x + 3*x + 1
    41
    (8 reductions, 15 cells)
    ? let p x = x*x + 3*x + 1  in  p (1 + 4)
    41
    (7 reductions, 15 cells)
    ?


.ST 9.4  Recursion with integers
----------------------------
Recursion  is  a  particularly  important  and  powerful  technique  in
functional programming which is useful for defining functions involving
a wide range of datatypes.  In this section, we describe one particular
application of recursion to give  an  alternative  definition  for  the
factorial function from section 5.

Suppose that we wish to calculate the factorial of a given  integer  n.
We can split the problem up into two special cases:

  o  If n is zero then the value of n! is 1.

  o  Otherwise, n!  = 1 * 2 * ... * (n-1) * n = (n-1)! * n  and  so  we
     can calculate the value of n! by calculating the value  of  (n-1)!
     and then multiplying it by n.

This process can be expressed directly in  Gofer  using  a  conditional
expression:

    fact1 n  =  if n==0 then 1 else n * fact1 (n-1)

This definition may seem rather circular; in  order  to  calculate  the
value of n!, we must first calculate (n-1)!, and unless n  is  1,  this
requires the calculation of (n-2)! etc...  However, if  we  start  with
some positive value for the variable n, then we will  eventually  reach
the case where the value of 0! is required -- and this does not require
any further calculation.  The following diagram illustrates how  6!  is
evaluated using "fact1":

    fact1 6  ==>  6 * fact1 5
             ==>  6 * (5 * fact1 4)
             ==>  6 * (5 * (4 * fact1 3))
             ==>  6 * (5 * (4 * (3 * fact1 2)))
             ==>  6 * (5 * (4 * (3 * (2 * fact1 1))))
             ==>  6 * (5 * (4 * (3 * (2 * (1 * fact1 0)))))
             ==>  6 * (5 * (4 * (3 * (2 * (1 * 1)))))
             ==>  6 * (5 * (4 * (3 * (2 * 1))))
             ==>  6 * (5 * (4 * (3 * 2)))
             ==>  6 * (5 * (4 * 6))
             ==>  6 * (5 * 24)
             ==>  6 * 120
             ==>  720

Incidentally, there are several other ways  of  writing  the  recursive
definition of "fact1" above in Gofer.  For example, using guards:

    fact2 n
      | n==0        =  1
      | otherwise   =  n * fact2 (n-1)

or using pattern matching with an integer constant:

    fact3 0         =  1
    fact3 n         =  n * fact3 (n-1)

Which of these you use is largely a matter of personal taste.

Yet another style of definition uses the (n+k)  patterns  mentioned  in
section 9.1:

    fact4 0         =  1
    fact4 (n+1)     =  (n+1) * fact4 n

which is equivalent to:

    fact5 n | n==0  =  1
            | n>=1  =  n * fact5 (n-1)

[COMMENT: Although each of the above definitions gives the same  result
as the original "fact" function  for  each  non-negative  integer,  the
functions can still be distinguished by the values obtained  when  they
are applied to negative integers:

  o  "fact (-1)" evaluates to the integer 1.
  o  "fact1 (-1)" causes Gofer to enter an infinite loop, which is only
     eventually terminated when Gofer runs out of `stack space'.
  o  "fact4 (-1)" causes an evaluation error and prints the
      message {fact4 (-1)} on the screen.

To most people, this suggests that the definition of "fact4" is perhaps
preferable to that of either "fact" or "fact1" as it neither gives  the
wrong answer  without  allowing  this  to  be  detected  nor  causes  a
potentially non-terminating computation.]


.ST 9.5  Recursion with lists
-------------------------
The same kind of  technique  that  can  be  used  to  define  recursive
functions with integers can also be used to define recursive  functions
on lists.  As an example, suppose that we wish to define a function  to
calculate the length of  a  list.   As  the  standard  prelude  already
includes such a function called "length", we  will  call  the  function
developed here "len" to avoid any conflict.  Now suppose that  we  wish
to find the length of a given list.  There are two cases to consider:

  o  If the list is empty then it has length 0

  o  Otherwise, it is non-empty and can be written in the  form  (x:xs)
     for some element x and some list xs.  Thus the  original  list  is
     one element longer than xs, and so has length 1 + len xs.

Writing these two cases out leads directly to the following definition:

    len []      =  0
    len (x:xs)  =  1 + len xs

The following diagram illustrates the way that  this  function  can  be
used to determine the length of the list [1,2,3,4] (remember that  this
is just an abbreviation for 1 : 2 : 3 : 4 : []):

    len [1,2,3,4]  ==>  1 + len [2,3,4]
                   ==>  1 + (1 + len [3,4])
                   ==>  1 + (1 + (1 + len [4]))
                   ==>  1 + (1 + (1 + (1 + len [])))
                   ==>  1 + (1 + (1 + (1 + 0)))
                   ==>  1 + (1 + (1 + 1))
                   ==>  1 + (1 + 2)
                   ==>  1 + 3
                   ==>  4

As  further  examples,  you  might  like  to  look  at  the   following
definitions which use similar ideas to define the functions product and
map introduced in earlier sections:

    product []     = 1
    product (x:xs) = x * product xs

    map f []      =  []
    map f (x:xs)  =  f x : map f xs


.ST 9.6  Lazy evaluation
--------------------
Gofer evaluates expressions using a technique  sometimes  described  as
`lazy evaluation' which means that:

  o  No expression is evaluated until its value is needed.

  o  No  shared  expression  is  evaluated  more  than  once;  if   the
     expression is ever evaluated then the result is shared between all
     those places in which it is used.

The first of these ideas is illustrated by the following function:

    ignoreArgument x = "I didn't need to evaluate x"

Since the result of the function "ignoreArgument" doesn't depend on the
value of its argument "x", that argument will not be evaluated:

    ? ignoreArgument (1/0)
    I didn't need to evaluate x
    (1 reduction, 31 cells)
    ?

In some situations, it is useful to be able to force Gofer to  evaluate
the argument to a function before the function is applied.  This can be
achieved using the function "strict" defined in the  standard  prelude;
An expression of the form "strict f x" is evaluated by first evaluating
the argument "x" and then applying the function "f" to the result:

    ? strict ignoreArgument (1/0)
    {primDivInt 1 0}
    (4 reductions, 29 cells)
    ?

The second  basic  idea  behind  lazy  evaluation  is  that  no  shared
expression should be  evaluated  more  than  once.   For  example,  the
following two expressions can be used to calculate 3*3*3*3:

    ? square * square where square = 3 * 3
    81
    (3 reductions, 9 cells)
    ? (3 * 3) * (3 * 3)
    81
    (4 reductions, 11 cells)
    ?

Notice that the first expression requires one less reduction  than  the
second.  Excluding the single reduction step  needed  to  convert  each
integer into a string, the sequences of reductions that will be used in
each case are as follows:

.cc 5
    square * square where square = 3 * 3
       -- calculate the value of square by reducing 3 * 3 ==> 9
       -- and replace each occurrence of square with this result
       ==> 9 * 9
       ==> 81

    (3 * 3) * (3 * 3)   -- evaluate first (3 * 3)
       ==> 9 * (3 * 3)  -- evaluate second (3 * 3)
       ==> 9 * 9
       ==>

Lazy evaluation is a very powerful feature of programming in a language
like Gofer, and means that only the minimum amount  of  calculation  is
used to determine the result of an expression.  The  following  example
is often used to illustrate this point.

Consider the task  of  finding  the  smallest  element  of  a  list  of
integers.  The standard prelude includes a function "minimum" which can
be used for this very purpose:

    ? minimum [100,99..1]
    1
    (809 reductions, 1322 cells)
    ?

(The expression [100,99..1] denotes the list of integers from 1 to  100
arranged in decreasing order, as described in section 10.1).

A rather different approach involves sorting the elements of  the  list
into increasing  order  (using  the  function  "sort"  defined  in  the
standard prelude) and  then  take  the  element  at  the  head  of  the
resulting list  (using  the  standard  function  "head").   Of  course,
sorting the list in its entirety is  likely  to  require  significantly
more work than the previous approach:

    ? sort [100,99..1]
    [1, 2, 3, 4, 5, 6, 7, 8, ... etc ..., 99, 100]
    (10712 reductions, 21519 cells)
    ?

However, thanks to lazy-evaluation, calculating just the first  element
of the sorted list actually requires less work in this particular  case
than the first solution using "minimum":

    ? head (sort [100,99..1])
    1
    (713 reductions, 1227 cells)
    ?

Incidentally, it is  probably worth  pointing  out  that  this  example
depends rather heavily on the particular algorithm  used  to  "sort"  a
list of elements.  The results are rather different if we  compare  the
same two approaches used to calculate the maximum value in the list:

    ? maximum [100,99..1]
    100
    (812 reductions, 1225 cells)
    ? last (sort [100,99..1])
    100
    (10612 reductions, 20732 cells)
    ?

This difference is caused by the fact that each  element  in  the  list
produced by "sort" is  only  known  once  the  values  of  all  of  the
preceding elements are also known.  Thus  the  complete  list  must  be
sorted in order to obtain the last element.


.ST 9.7  Infinite data structures
-----------------------------
One particular benefit of lazy evaluation is that it makes it  possible
for functions  in  Gofer  to  manipulate  `infinite'  data  structures.
Obviously we cannot hope either to   construct  or  store  an  infinite
object in its entirety -- the advantage of lazy evaluation is  that  it
allows us to construct infinite objects piece  by  piece  as  necessary
(and to reuse the storage space used by parts of the object  when  they
are no longer required).

As a simple example, consider the following function which can be  used
to produce infinite lists of integer values:

    countFrom n = n : countFrom (n+1)

If we evaluate the expression "countFrom 1", Gofer just prints the list
of integer values beginning with 1 until it is interrupted.  Once  each
element in the list has been printed, the storage  used  to  hold  that
element can be reused to hold later elements in the  list.   Evaluating
this expression is equivalent to using an `infinite' loop to print  the
list of integers in an imperative programming language:

    ? countFrom 1
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,^C{Interrupted!}
    (53 reductions, 160 cells)
    ?

For practical applications, we are usually only interested in  using  a
finite portion of an infinite data  structure  (just  as  loops  in  an
imperative programming language are usually terminated  after  finitely
many iterations).  For example, using  "countFrom"  together  with  the
function "take" defined in the standard  prelude,  we  can  repeat  the
calculation from section 4 to find the sum of the integers 1 to 10:

    ? sum (take 10 (countFrom 1))
    55
    (62 reductions, 119 cells)
    ?

[ASIDE: The expression "take n xs" evaluates to a list  containing  the
first n elements of the list xs (or to xs itself if the  list  contains
fewer than n elements).  Thus "countFrom 1" generates the infinite list
of integers, "take 10" ensures that only the  first  ten  elements  are
calculated, and "sum" calculates the sum of those integers as before.]

A particular advantage of using infinite data  structures  is  that  it
enables us to describe an object without being tied to  one  particular
application of that object.  Consider the following definition for  the
infinite list of powers of two [1, 2, 4, 8, ...]:

    powersOfTwo = 1 : map double powersOfTwo 
                  where double n = 2*n

This list be used in a variety of ways; using the operator (!!) defined
in the standard prelude [xs!!n evaluates to the nth element of the list
xs], we can define a function to find the nth power of 2 for any  given
integer n:

    twoToThe n = powersOfTwo !! n 

Alternatively, we can use the list "powersOfTwo" to define  a  function
mapping lists of  bits  (represented  by  integers  0  and  1)  to  the
corresponding decimal number: simply reverse the order of  the  digits,
multiply each by the corresponding power of two and calculate the  sum.
Using functions from the standard  prelude,  this  translates  directly
into the definition:

    binToDec ds = sum (zipWith (*) (reverse ds) powersOfTwo)

For example:

    ? twoToThe 12
    4096
    (15 reductions, 21 cells)
    ? binToDec [1,0,1,1,0]
    22
    (40 reductions, 85 cells)
    ?

.ST 9.8  Polymorphism
-----------------
Given the definition of "product" in section 9.5, it  is  easy  to  see
that product takes a single argument which is a list  of  integers  and
returns a single integer value -- the product of the  elements  of  the
list.  In other words, "product" has type [Int] -> Int.  On  the  other
hand, it is not immediately clear what the type of the  function  "map"
should be.  Clearly the first argument of "map" must be a function  and
both the second argument and the result are lists, so that the type  of
"map" must be of the form:

             (a -> b)   ->      [c]      ->     [d]
             \______/          \___/           \___/
           type of 1st      type of 2nd      type of result
           argument "f"     argument "xs"    "map f xs"

But what can be said about the types a, b, c and  d?   One  possibility
would be to choose a = b = c = d = Int which would  be  acceptable  for
expressions such as  "map  fact  [1,2,3,4]",  but  this  would  not  be
suitable in an expression such as  "map  chr  [65,75,32]"  because  the
"chr" function does not have type Int -> Int.

Notice however that the argument type of "f" must be the  same  as  the
type of elements in the second argument (i.e.  a  =  c)  since  "f"  is
applied to each element in that list.  Similarly, the  result  type  of
"f" must be the same as the type of elements in the result list (i.e. b
= d) since each element in  this  list  is  obtained  as  a  result  of
applying the function "f" to some value.  It is therefore reasonable to
treat the "map" function as having any type of the form:

                  (a -> b)  ->  [a]  ->  [b]

The letters  "a"  and  "b"  used  in  this  type  expression  represent
arbitrary types and are called type variables.  An  object  whose  type
includes one or more type variables can be thought of  as  having  many
different types and is often described as having a  `polymorphic  type'
(literally: its type has `many shapes').

The ability to define and use polymorphic functions in Gofer turns  out
to be very useful.  Here are the types of some of the other polymorphic
functions which have been used in previous  examples  which  illustrate
this point:

    length :: [a] -> Int
    (++)   :: [a] -> [a] -> [a]
    concat :: [[a]] -> [a]

Thus we can use precisely the same "length" function to determine  both
the length of a list of integers as well as finding  the  length  of  a
string:

    ? length [1..10]
    10
    (98 reductions, 138 cells)
    ? length "Hello"
    5
    (22 reductions, 36 cells)
    ? 


.ST 9.9  Higher-order functions
---------------------------
In Gofer, function values are treated in much the same way as any other
kind of value; in particular, they can be used both  as  arguments  to,
and results of other functions.

.cc 5
Functions which manipulate  other  functions  in  this  way  are  often
described as `higher-order functions'.  Consider the following example,
taken from the standard prelude:

    (.)       :: (b -> c) -> (a -> b) -> (a -> c)
    (f . g) x  = f (g x)

As indicated by the type declaration, we think of the (.) operator as a
function taking two function arguments and returning  another  function
value as its result.  If f and  g  are  functions  of  the  appropriate
types, then (f . g) is a function called the composition of f  with  g.
Applying (f . g) to a value is equivalent to applying g to that  value,
and then applying f to the result [As described, far  more  eloquently,
by the second line of the declaration above!].

Many problems can often be described very elegantly as a composition of
other functions.  Consider the problem of calculating the total  number
of characters used in a list of strings.  A simple  recursive  function
provides one solution:

    countChars []     = 0
    countChars (w:ws) = length w + countChars ws 

    ? countChars ["super","cali","fragi","listic"]
    20
    (96 reductions, 152 cells)
    ?

An alternative approach is to notice that we can  calculate  the  total
number of characters by  first  combining  all  of  the  words  in  the
argument list into a single word (using concat) and  then  finding  the
length of that word:

    ? (length . concat) ["super","cali","fragi","listic"]
    20
    (113 reductions, 211 cells)
    ?

Another solution is to first find the length of each word in  the  list
(using the "map" function to apply "length"  to  each  word)  and  then
calculate the sum of these individual lengths:

    ? (sum . map length) ["super","cali","fragi","listic"]
    20
    (105 reductions, 172 cells)
    ?


.ST 9.10 Variable declarations
--------------------------
A variable declaration  is  a  special  form  of  function  definition,
almost always consisting of a single equation of the form:

                           var = rhs

(i.e. a function declaration of arity 0).  Whereas the  values  defined
by function declarations of arity>0 are guaranteed to be functions, the
values defined by variable declarations may or may not be functions:

    odd = not . even   -- if an integer is not even then it must be odd
    val = sum [1..100]

Note that variables defined like this at the top level  of  a  file  of
definitions will be evaluated using lazy evaluation.  The first time we
refer  to  the  variable  "val"  defined  above  (either  directly   or
indirectly), Gofer evaluates the sum of the integers from 1 to 100  and
overwrites the definition of "val" with this number.  This  calculation
can then be avoided for each subsequent use of "val" (unless  the  file
containing the definition of "val" is reloaded).

    ? val
    5050
    (809 reductions, 1120 cells)

    ? val
    5050
    (1 reduction, 7 cells)

    ?

Because of this behaviour,  we  should  probably  try  to  avoid  using
variable declarations where the resulting value will require a  lot  of
storage space.  If we load a file of definitions including the line:

    longList = [1..10000]

and  then  evaluate  the  expression  "length   longList"   (eventually
obtaining the expected result of 10000), then Gofer will  evaluate  the
definition of "longList" and replace  it  with  the  complete  list  of
integers from  1  upto  10000.   Unlike  other  memory  used  during  a
calculation, it will not be possible to  reuse  this  space  for  other
calculations without reloading the file defining "longList", or loading
other files instead.


.ST 9.11 Pattern bindings and irrefutable patterns
----------------------------------------------
Another useful way of defining variables uses `pattern bindings'  which
are equations of the form:

                        pat = rhs

where the expression on the left hand side is a pattern as described in
section 9.1.  As a simple example of  pattern  bindings,  here  is  one
possible definition for the function "head"  which  returns  the  first
element in a list of values:

    head xs  =  x  where  (x:ys) = xs

[The definition  "head (x:_) = x"  used  in  the  standard  prelude  is
slightly more efficient, but otherwise equivalent.]

[ASIDE: Note that pattern bindings are treated quite  differently  from
function bindings (of which the variable declarations described in  the
last section are a special case).  There are two situations in which an
ambiguity may occur; i.e. if the left hand side of  an  equation  is  a
simple variable or an (n+k) pattern of the kind  described  in  section
9.1.  In both cases, these are treated as function bindings, the former
being a variable declaration whilst the latter will  be  treated  as  a
definition for the operator symbol (+).]

Pattern bindings are often useful for defining functions which we might
think of as `returning more  than  one  value'  --  although  they  are
actually packaged up in a single value such as a tuple.  As an example,
consider the function "span" defined in the standard prelude.

    span :: (a -> Bool) -> [a] -> ([a],[a])

If xs is a list of values and p is a predicate, then span p xs  returns
the pair of lists (ys,zs) such that ys++zs == xs, all of  the  elements
in ys satisfy the predicate p and the first  element  of  zs  does  not
satisfy p.  A suitable definition, using a pattern  binding  to  obtain
the two lists resulting  from  the  recursive  call  to  "span"  is  as
follows:

    span p []               = ([],[])
    span p xs@(x:xs')
                | p x       = let (ys,zs) = span p xs' in (x:ys,zs)
                | otherwise = ([],xs)


For consistency with the lazy evaluation strategy used  in  Gofer,  the
right hand side of a pattern binding is not evaluated until  the  value
of one of the  variables  bound  by  that  pattern  is  required.   The
definition:

    (0:xs) = [1,2,3]

will not cause any errors when it is loaded into Gofer, but will  cause
an error if we attempt to evaluate the variable xs:

    ? xs
    {v120 [1, 2, 3]}
    (11 reductions, 46 cells)
    ?

The variable name "v120" appearing in this expression is the name of  a
function called a `conformality check' which is  defined  automatically
by Gofer to ensure that the value on the right hand side of the pattern
binding conforms with the pattern on the left.

Compare this  with  the  behaviour  of  pattern  matching  in  function
definitions such as:

    ? example [1] where example (0:xs) = "Hello"
    {v126 [1]}
    (4 reductions, 22 cells)
    ?

where  the  equivalent  of  the  conformality  check  is  carried   out
immediately even if none of the values of the variables in the  pattern
are actually required.  The reason for  this  difference  is  that  the
arguments supplied to a function must be evaluated to  determine  which
equation in the definition of the function should be used.   The  error
produced by the example above was caused by the fact that the  argument
[1] does not match the pattern used in the equation defining  "example"
(represented by an internal Gofer function called "v126").

A different kind of behaviour can be obtained using a  pattern  of  the
form ~pat, known as an irrefutable (or lazy) pattern.  This pattern can
initially be matched against any value, delaying the  check  that  this
value does indeed match pat until the value of  one  of  the  variables
appearing in it is required.  The basic idea (together with the  method
used to implement irrefutable patterns in Gofer) is illustrated by  the
identity:

    f ~pat = rhs     is equivalent to     f v = rhs where pat=v

The following examples, based  very  closely  on  those  given  in  the
Haskell report [5], illustrate the use of  irrefutable  patterns.   The
variable "undefined" used in these examples is included in the standard
prelude  and  causes  a  run-time  error  each  time  it  is  evaluated
(technically speaking, it represents the bottom element of the relevant
semantic domain, and is the only value having all possible types):

   (\ (x,y) -> 0) undefined = {undefined}
   (\~(x,y) -> 0) undefined = 0

   (\ [x] -> 0) [] = {v113 []}
   (\~[x] -> 0) [] = 0

   (\~[x, (a,b)] -> x) [(0,1),undefined] = {undefined}
   (\~[x,~(a,b)] -> x) [(0,1),undefined] = (0,1)

   (\ (x:xs) -> x:x:xs) undefined = {undefined}
   (\~(x:xs) -> x:x:xs) undefined = {undefined}:{undefined}:{undefined}

Irrefutable patterns are not used very frequently,  although  they  are
particularly convenient in some situations (see  section  12  for  some
examples).  Be careful not to use irrefutable patterns where  they  are
not appropriate.  An attempt to define a map function "map'" using:

    map' f ~(x:xs) = f x : map' f xs
    map' f []      = []

turns out to be equivalent to the definition:

    map' f ys  =  f x : map f xs where (x:xs) = ys

and will not behave as you might have intended:

    ? map' ord "abc"
    [97, 98, 99, {v124 []}, {v124 []}, {v^C{Interrupted!}
    (35 reductions, 159 cells)
    ?


.ST 9.12 Type declarations
-----------------------
The type system used in Gofer is sufficiently powerful to enable  Gofer
to determine the type of any function without the need to  declare  the
types of its arguments and the return  value  as  in  some  programming
languages.  Despite this, Gofer allows the use of type declarations  of
the form:

                var1, ..., varn :: type

which enable the programmer  to  declare  the  intended  types  of  the
variables var1,  ...,  varn  defined  in  either  function  or  pattern
bindings.   There  are  a  number  of  benefits   of   including   type
declarations of this kind in a program:

  o  Documentation: The  type  of  a  function  often  provides  useful
     information about the way in which a function is  to  be  used  --
     including the number and order of its arguments.

  o  Restriction: In some situations, the type of a  function  inferred
     by Gofer is  more  general  than  is  required.   As  an  example,
     consider the following function, intended to act as  the  identity
     on integer values:

         idInt x  =  x

     Without an explicit type declaration, Gofer treats  "idInt"  as  a
     polymorphic function of type a -> a and the expression "idInt 'A'"
     does not cause a type error.  This problem can be  solved by using
     an explicit type declaration  to restrict the type of "idInt" to a
     particular instance of the polymorphic type a -> a:

         idInt :: Int -> Int

     Note that a declaration such as:

         idInt :: Int -> a

     is not a valid type for the function "idInt"  (the  value  of  the
     expression "idInt 42" is an  integer  and  cannot  be  treated  as
     having an arbitrary type, depending  on  the  value  of  the  type
     variable "a"), and hence will not be accepted by Gofer.

  o  Consistency check: As illustrated above, declared types are always
     checked against the definition of a value to make sure  that  they
     are compatible.   Thus  Gofer  can  be  used  to  check  that  the
     programmer's intentions (as described by  the  types  assigned  to
     variables  in  type  declarations)   are   consistent   with   the
     definitions of those values.

  o  Overloading: Explicit type declarations can be  used  to  solve  a
     number  of  problems  associated  with  overloaded  functions  and
     values.  See section 14 for further details.
.pa
.co-------------------------------------------------------------------|
.>ch10
.ST 10. INCREASING YOUR POWER OF EXPRESSION
 
This section describes a number of useful extensions to the basic range
of expressions used in the previous sections.  None of  these  add  any
extra computational power to Gofer -- anything that can  be  done  with
these constructs  could  also  be  done  with  the  constructs  already
described.  They are however included in Gofer because they allow  many
expressions and function definitions to be  written  more  clearly  and
concisely than the equivalent expressions without these notations.

.ST 10.1 Arithmetic sequences
-------------------------
A number of useful  lists  can  be  generated  using  the  notation  of
arithmetic  sequences  (so  named  because  of  their   similarity   to
arithmetic progressions in mathematics).  The following list summarises
the four forms of sequence  expression  that  can  be  used  in  Gofer,
together with their translation using the standard functions  enumFrom,
enumFromTo, enumFromThen and enumFromThenTo:

    [ n .. ]         enumFrom n

                     Produces the (potentially infinite) list of values
                     starting with the value of  n  and  increasing  in
                     single steps.

                     e.g. [1..] = [1, 2, 3, 4, 5, 6, 7, 8, 9, etc...

    [ n .. m ]       enumFromTo n m

                     Produces the list of  elements  from  n  upto  and
                     including m in single steps.  If m is less than  n
                     then the list is empty.

                     e.g. [-3..3] = [-3, -2, -1, 0, 1, 2, 3]
                          [1..1]  = [1]
                          [9..0]  = []

    [ n, m .. ]      enumFromThen n m

                     Produces the (potentially infinite) list of values
                     whose first two elements are given by the values n
                     and m.  If m is greater than n then the  following
                     elements of the list are increasing  in  steps  of
                     the same size.  A similar result is obtained if  m
                     is less than n  in  which  case  the  elements  of
                     [n,m..] will be decreasing.  If n and m are  equal
                     then [n,m..] is an infinite  list  in  which  each
                     element is equal to n.

                     e.g. [1,3..] = [1, 3, 5, 7, 9, 11, 13, etc...
                          [0,0..] = [0, 0, 0, 0, 0, 0, 0, etc...
                          [5,4..] = [5, 4, 3, 2, 1, 0, -1, etc...

    [ n, n' .. m ]   enumFromThenTo n n' m

                     Produces the list of elements from  [n,n'..]  upto
                     the limit value m.   If  m  is  less  than  n  and
                     [n,n'..] is increasing, or m is greater than n and
                     [n,n'..] is decreasing the  resulting list will be
                     empty.

                     e.g. [1,3..12] = [1, 3, 5, 7, 9, 11]
                          [0,0..10] = [0, 0, 0, 0, 0, 0, 0, etc...
                          [5,4..1]  = [5, 4, 3, 2, 1]

In  the  standard  prelude,   the   functions   enumFrom,   enumFromTo,
enumFromThen and enumFromThenTo are overloaded and may also be used  to
enumerate lists of characters or floating point values:

    ? ['0'..'9'] ++ ['A'..'Z']
    0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
    (397 reductions, 542 cells)

    ? [1.2, 1.35 .. 2.00]
    [1.2, 1.35, 1.5, 1.65, 1.8, 1.95]
    (56 reductions, 133 cells)

    ?

Arithmetic sequences such as those described above play the  same  role
in functional programming languages as the iterative  `for'  constructs
in traditional imperative languages.  A good example  of  this  is  the
example in section 4 used to calculate the sum of the integers  from  1
upto 10 -- "sum [1..10]".   An  equivalent  program  in  an  imperative
language might look something like (especially if you think of C!):

    int i;
    int total=0;
    for (i=1; i<=10; i++)
        total = total + i;
    return total;

The advantages of the functional notation in this case are clear:

   o  It is more compact.

   o  It separates the task of  generating  the  sequence  of  integers
      [1..10] from the task of finding their sum.

   o  It does not require the declaration or use of auxiliary variables
      such as "i" and "total" in the above.


.ST 10.2 List comprehensions
-------------------------
List comprehensions provide another very powerful and compact  notation
for describing certain kinds of list expression.  The basic form  of  a
list comprehension is:

                      [ <expr> | <qualifiers> ]

There are three kinds of qualifier that can be used in Gofer:

  o  Generators: A qualifier of the form pat<-exp is  used  to  extract
     each element that matches the pattern pat from the list exp in the
     order that they elements appear in that list.  A simple example of
     this is the expression [x*x | x<-[1..10]] which denotes  the  list
     of the squares of the integers between  1  and  10  inclusive  and
     evaluates to [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] as expected.

     Formally, we can define the meaning of a list comprehension with a
     single generator by the equation:

          [ e | pat <- exp ]  =  loop exp
                                 where loop []       = []
                                       loop (pat:xs) = e : loop xs
                                       loop (_:xs)   = loop xs

     If pat is an irrefutable pattern (for example,  a  variable)  then
     this is equivalent to:

          [ e | pat <- exp ]  =  map f exp
                                 where f pat = e

     The full definition is needed for those cases  where  the  pattern
     pat may not match all of the elements in the list  exp.   This  is
     the case in expressions such as [ y | (3,y)<-[(1,2),(3,4),(5,6)] ]
     which evaluates to the singleton list [4].

  o  Filters: A boolean  valued  expression  may  also  be  used  as  a
     qualifier in which case it is  often  called  a  filter.   We  can
     define the meaning of a list comprehension with a single filter by
     the equation:

            [ e | condition ]  =  if condition then [e] else []

     Whilst this form of list comprehension is occasionally  useful  as
     it stands, it is more common to use filters  in  conjunction  with
     generators as described below.

  o  Local definitions: A qualifier of the form pat=expr can be used to
     introduce a local definition within  a  list  comprehension.   Its
     meaning can be defined formally using the equation:

         [ e | pat = exp ]  =  [ let pat=exp in e ]

     As in the case of filters, local  definitions  are  more  commonly
     used within lists of more than one qualifier as  described  below.
     Particular care should be taken to distinguish  a  filter  of  the
     form pat==expr from a local definition of the form pat=expr.

     [ASIDE: I originally suggested this form of qualifier in a message
     sent to the Haskell mailing list, only to discover that a  similar
     (and more comprehensive) suggestion had been made by Kevin Hammond
     almost a year earlier.  There was a certain amount of  controversy
     surrounding the choice of an appropriate syntax and semantics  for
     the construct and consequently, this feature is not currently part
     of the Haskell  standard.   The  syntax  and  semantics  above  is
     implemented by Gofer in the hope  that  it  will  give  functional
     programmers an opportunity to experiment  with  this  facility  in
     their own programs.]

The real power of this notation is that it is possible to  use  several
qualifiers, separated by commas on the right of the  vertical  bar  `|'
symbol in a list comprehension.  Formally, if qs1 and qs2 are two  such
lists of qualifiers,  then  we  can  define  the  meaning  of  multiple
qualifiers using:

         [ e | qs1, qs2 ]  =  concat [ [ e | qs2 ] | qs1 ]

The  following  examples  illustrate  how  this  definition  works   in
practice:

  o  Variables generated by later qualifiers  vary  more  quickly  than
     those generated by earlier qualifiers:

         ? [ (x,y) | x<-[1..3], y<-[1..2] ]
         [(1,1), (1,2), (2,1), (2,2), (3,1), (3,2)]
         (107 reductions, 246 cells)
         ?

  o  Later qualifiers may use the values generated by earlier ones:

         ? [ (x,y) | x<-[1..3], y<-[1..x]]
         [(1,1), (2,1), (2,2), (3,1), (3,2), (3,3)]
         (107 reductions, 246 cells)

         ? [ x | x<-[1..10], even x ]
         [2, 4, 6, 8, 10]
         (108 reductions, 171 cells)
         ?

  o  Variables defined in later qualifiers  hide  those  introduced  by
     earlier  ones.   The  following   expressions   are   valid   list
     comprehensions, but this style of definition in  which  names  are
     reused can result in programs which are difficult  to  understand,
     and is not recommended:

         ? [ x | x<-[[1,2],[3,4]], x<-x ]
         [1, 2, 3, 4]
         (18 reductions, 53 cells)

         ? [ x | x<-[1,2], x<-[3,4] ]
         [3, 4, 3, 4]
         (18 reductions, 53 cells)
         ?

  o  Changing  the  order  of  qualifiers  has  a  direct   effect   on
     efficiency.  The following two examples produce the  same  result,
     but the first uses more reductions and cells  because  it  repeats
     the evaluation of "even x" for each possible value of "y".

         ? [ (x,y) | x<-[1..3], y<-[1..2], even x ]
         [(2,1), (2,2)]
         (110 reductions, 186 cells)

         ? [ (x,y) | x<-[1..3], even x, y<-[1..2] ]
         [(2,1), (2,2)]
         (62 reductions, 118 cells)
         ? 

     The following example illustrates a similar kind of behaviour with
     local definitions; in the first case the expression  "fact  x"  is
     evaluated twice for each possible value of "x", whilst the  second
     expression uses a local definition to ensure that  the  evaluation
     is not repeated:

         ? [ fact x + y | x<-[1..3], y<-[1..2] ]
         [2, 3, 3, 4, 7, 8]
         (246 reductions, 398 cells)

         ? [ factx + y | x<-[1..3], factx = fact x, y<-[1..2] ]
         [2, 3, 3, 4, 7, 8]
         (173 reductions, 294 cells)
         ?


.ST 10.3 Lambda expressions
------------------------
In addition to  named  function  definitions,  Gofer  also  allows  the
definition and use of unnamed functions using a `lambda expression'  of
the form:

                  \ <atomic patterns> -> <expr>

[ASIDE:  This  is  a  slight  generalisation  of  the  form  of  lambda
expression  used  in  most   theoretical   treatments   of   functional
programming and  dating  back  to  the  pioneering  work  of  logicians
including  Alonzo Church and  Haskell Curry,  from whom the programming
language takes its name.  The `\' character used at the beginning of  a
Gofer lambda expression has been  chosen  for  its  resemblance  to the
greek letter lambda that might be used if the  standard  character  set
were  a little larger.]

This expression denotes a function taking a number of  parameters  (one
for each pattern) and producing the result specified by the  expression
to the right of the -> symbol.  For example, (\x->x*x)  represents  the
function which takes a single integer argument  `x'  and  produces  the
square of that  number as its result.   Another  example is the  lambda
expression (\x y->x+y) which takes two integer  arguments  and  outputs
their sum; this expression is in fact equivalent to the (+) operator:

    ? (\x y->x+y) 2 3
    5
    (3 reductions, 7 cells)
    ?

A lambda expression of the form illustrated above is equivalent to  the
following expression using a local definition:

      (let newName <atomic patterns> = <expr> in newName)

where "newName" is a new variable name, chosen to avoid conflicts  with
other variables that are already in use.  This name will be printed  if
you enter an expression involving a lambda expression without supplying
the full number of parameters for that function:

    ? (\x y -> x+y) 42
    v117 42
    (2 reductions, 14 cells)
    ?

Lambda expressions  are  particularly  useful  for  certain  styles  of
functional programming; an example of this  is  the  continuation-based
approach to I/O described in section 12.


.ST 10.4 Case expressions
---------------------
A case expression can be used to evaluate an expression and,  depending
on the result, return one of a number of  possible  values.   As  such,
case statements are a  straightforward  generalisation  of  conditional
expressions.  Indeed, an expression of the form "if e then t else f" is
in fact equivalent to the case expression:

                        case e of 
                          True  -> t
                          False -> f

In general, a case expression takes the form "case exp of  alts"  where
exp  is  the  expression  to  be  evaluated  and  alts  is  a  list  of
alternatives, each of which is of the form:

        pat -> rhs                    for a simple alternative

    or: pat | condition1 -> rhs1      using guard expressions as
            | condition2 -> rhs2      described in section 9.2 for
                  .                   function definitions
                  .
            | conditionn -> rhsn

In Gofer, a case expression of the form case e of alts  is  implemented
by choosing a new function name "newName" as in  the  previous  section
and  using  the  alternatives  in  alts  to  construct  an  appropriate
definition for this function (essentially by replacing each `->' symbol
with a `=' symbol).  The complete case expression is  then  treated  as
being equivalent to the expression "newName e".  A  simple  example  of
this is the "scanl" function whose definition in the standard prelude:

    scanl f q xs = q : (case xs of
                        []   -> []
                        x:xs -> scanl f (f q x) xs)

is equivalent to:

    scanl f q xs = q : scanl' xs
                   where scanl' []     = []
                         scanl' (x:xs) = scanl f (f q x) xs

This latter form is precisely the definition used in [1] (but using the
name "scan" where Gofer uses "scanl").

Evaluating a case expression in which none of  the  alternatives  match
the value  of  the  discriminant  results  in  an  error  such  as  the
following:

    ? case [1,2] of [] -> "empty list"
    {v117 [1, 2]}
    (6 reductions, 31 cells)
    ?

The function name "v117" which appears here is the name of the function
which is used internally by Gofer  to  implement  the  case  expression
whilst the expression "[1, 2]" gives the discriminant value which could
not be matched.

By combining case expressions with the lambda expressions introduced in
the previous section, any function declaration can be translated into a
single equation of the form <functionName> = <expr>.  For example,  the
standard function "map" whose definition is usually written as:

    map f []     = []
    map f (x:xs) = f x : map f xs

can also be defined by the equation:

    map = \f xs -> case xs of
                     []     -> []
                     (y:ys) -> f y : map f ys

This kind  of  translation  is  used  in  the  implementation  of  many
functional programming languages, including Gofer.   See  Simon  Peyton
Jones book [2] for more details of this.


.ST 10.5 Operator sections
----------------------
As we have seen, most functions in Gofer taking more than one  argument
are treated as a function of a  single  argument,  whose  result  is  a
function which can then be applied to the  remaining  arguments.   Thus
"(+) 1" denotes the function which takes an integer  argument  "n"  and
returns the integer value "1+n".   Functions  of  this  kind  involving
operator symbols are sufficiently common that Gofer provides a  special
syntax for them.  Using e to denote an atomic expression and the symbol
"*" to represent an arbitrary infix operator, there are functions (e *)
and (* e), known as `sections of the operator (*)' defined by:

                  (e *) x  = e * x
                  (* e) x  = x * e

or, using lambda expressions as introduced in section 10.3:

                  (e *)    =  \x -> e * x
                  (* e)    =  \x -> x * e

For example: (1+)   is the successor function which returns the value
                    of its argument plus 1,
             (1.0/) is the reciprocal function,
             (/2)   is the halving function,
             (:[])  is the function which maps any value to the
                    singleton list containing that element.

In Gofer, the expressions "(e *)" and "(* e)" are actually  treated  as
abbreviations for "(*) e" and "flip (*) e" respectively,  where  "flip"
is the function defined by:

     flip        :: (a -> b -> c) -> b -> a -> c
     flip  f x y  =  f y x

There is an important special case which occurs with an  expression  of
the form (- e); this is interpreted  as  "negate  e"  and  not  as  the
section which subtracts the value of "e" from its argument.  The latter
function can be written as the section (+ (- e))  or  as  "subtract  e"
where "subtract" is the function defined in the standard prelude using:

    subtract = flip (-)


.ST 10.6 Explicitly typed expressions
----------------------------------
As described in section 9.12, it is often useful to be able to  declare
the type of a variable defined in a function or pattern  binding.   For
much the same reasons, Gofer allows expressions of the form:

                         <expr> :: <type>

so that the type of an expression can be  specified  explicitly.   Note
that the :t command can be used  to  find  the  type  of  a  particular
expression that is inferred by Gofer:

    ? :t  \x -> [x]
    \x -> [x] :: a -> [a]

    ? :t  sum . map length
    sum . map length :: [[a]] -> Int

    ? 

The types inferred in each case can be modified by  including  explicit
types in these expressions:

    ? :t  (\x -> [x]) :: Char -> String
    \x -> [x] :: Char -> String

    ? :t  sum . map (length :: String -> Int)
    sum . map length :: [String] -> Int

    ?

Note that an error occurs if the type declared in an  explicitly  typed
expression is not compatible with the type inferred by Gofer:

    ? :t (\x -> [x]) :: Int -> a
    ERROR: Declared type too general
    *** Expression    : \x -> [x]
    *** Declared type : Int -> a
    *** Inferred type : Int -> [Int]

    ?

Explicitly typed expressions  are  most  commonly  used  together  with
overloaded functions and values as described in section 14.
.pa
.co-------------------------------------------------------------------|
.>ch11
.ST 11. USER-DEFINED DATATYPES AND TYPE SYNONYMS

.ST 11.1 Datatype definitions
-------------------------
In addition to the  wide  range  of  built-in  datatypes  described  in
section 7, Gofer also allows the  definition  of  new  datatypes  using
declarations of the form:

     data DatatypeName a1 ... an = constr1 | ... | constrm

where DatatypeName is the name of a new type constructor of arity n>=0,
a1, ..., an are distinct type variables representing the  arguments  of
DatatypeName and constr1, ..., constrm (m>=1) describe the way in which
elements of the new datatype are constructed.  Each constr can take one
of two forms:

  o  Name type1 ... typer where Name is a previously unused constructor
     function  name  (i.e.  an  identifier  beginning  with  a  capital
     letter).  This declaration introduces Name as  a  new  constructor
     function of type: type1 -> ...-> typer -> DatatypeName a1 ... an.

  o  type1 CONOP type2 where CONOP is a previously  unused  constructor
     function  operator (i.e.  an  operator  symbol  beginning  with  a
     colon).  This declaration introduces (CONOP) as a new  constructor
     function of type: type1 -> type2 -> DatatypeName a1 ... an.

[N.B. only the  type variables  a1, ..., an  may  appear  in  the  type
expressions in each constr in the definition of DatatypeName.]


As a simple example, the following definition introduces a new type Day
with elements Sun, Mon, Tue, Wed, Thu, Fri and Sat:

    data Day = Sun | Mon | Tue | Wed | Thu | Fri | Sat

Simple functions manipulating elements of type Day can be defined using
pattern matching:

    what_shall_I_do Sun = "relax"
    what_shall_I_do Sat = "go shopping"
    what_shall_I_do _   = "looks like I'll have to go to work"

Another example uses a pair of constructors to provide a representation
for temperatures which may be given using either of the  centigrade  or
fahrenheit scales:

    data Temp = Centigrade Float | Fahrenheit Float

    freezing                  :: Temp -> Bool
    freezing (Centigrade temp) = temp <= 0.0
    freezing (Fahrenheit temp) = temp <= 32.0

The following example uses a type variable on the left hand side of the
datatype  definition  to  implement  a   Set   type   constructor   for
representing sets using a list of values:

    data Set a = Set [a]

For example, Set [1,2,3] is an element of type  Set  Int,  representing
the set of integers {1, 2, 3} whilst Set ['a'] represents  a  singleton
set of type Set Char.  As this example shows, it is possible to use the
same  name  simultaneously  as  both  a  type  constructor  and  as   a
constructor function.

Datatype definitions may also be  recursive,  using  the  name  of  the
datatype  being  defined  on  the  right  hand  side  of  the  datatype
definition  (mutually   recursive   datatype   definitions   are   also
permitted).  The following example is taken from the Haskell report [5]
and  defines  a  type  representing  binary  trees  with  values  of  a
particular type at their leaves:

    data Tree a = Lf a | Tree a :^: Tree a

For example, (Lf 12 :^: (Lf 23 :^: Lf 13)) :^: Lf 10 has type Tree  Int
and represents the binary tree:

                              ,--- 12
                           ,--| 
                           |  |  ,--- 23
                           |  `--| 
                           |     `--- 13
                         --| 
                           `--- 10

As an example of a function defined on trees, here are two  definitions
using recursion and pattern matching on tree valued  expressions  which
calculate the list of elements at the leaves of a tree  traversing  the
branches of the tree from left to right.  The first definition  uses  a
simple definition, whilst the second uses an  `accumulating  parameter'
giving a more efficient algorithm:

    leaves, leaves'  :: Tree a -> [a]

    leaves (Lf l)  = [l]
    leaves (l:^:r) = leaves l ++ leaves r

    leaves' t = leavesAcc t []
                 where leavesAcc (Lf l)  = (l:)
                       leavesAcc (l:^:r) = leavesAcc l . leavesAcc r

Using the binary tree above as an example:

    ? leaves ((Lf 12 :^: (Lf 23 :^: Lf 13)) :^: Lf 10)
    [12, 23, 13, 10]
    (24 reductions, 73 cells)
    ? leaves' ((Lf 12 :^: (Lf 23 :^: Lf 13)) :^: Lf 10)
    [12, 23, 13, 10]
    (20 reductions, 58 cells)
    ?


.ST 11.2 Type synonyms
------------------
Type synonyms are used to provide  convenient  abbreviations  for  type
expressions.  A type synonym is introduced  by  a  declaration  of  the
form:

     type Name a1 ... an = expansion

where Name is the name of a new type constructor  of  arity  n>=0,  a1,
..., an are distinct type variables representing the arguments of  Name
and expansion is a type expression.  Note that the only type  variables
permitted in the expansion type are those on the left hand side of  the
synonym definition.  Using this declaration any type expression of  the
form:

                  Name type1 ... typen 

is treated as an abbreviation of  the  type  expression  obtained  from
expansion by replacing each of the type variables a1, ..., an with  the
corresponding type type1, ..., typen.

The most frequently used type synonym is almost  certainly  the  String
type which is a synonym for [Char]:

    type String = [Char]

[ASIDE: This definition is actually built in to the Gofer  system,  but
the effect is the same as if this  declaration  were  included  in  the
standard prelude.]

Note that the types of expressions inferred by Gofer will  not  usually
contain any type synonyms unless an explicit type signature  is  given,
either using an explicitly typed expression (section 10.6)  or  a  type
declaration (section 9.12):

    ? :t ['c']
    ['c'] :: [Char]
    ? :t ['c'] :: String
    ['c'] :: String
    ?

Unlike the datatype declarations described  in  the  previous  section,
recursive  (and  mutually  recursive)  synonym  declarations  are   not
permitted.  This rules out examples such as:

    type BadSynonym = [BadSynonym]

and ensures that the process of expanding all of the type synonyms used
in any particular type expression  will  always  terminate.   The  same
property does not hold for the illegal definition above, in  which  any
attempt to expand the type BadSynonym would lead to the non-terminating
sequence:

    BadSynonym ==> [BadSynonym] ==> [[BadSynonym]] ==> ....
.pa
.co-------------------------------------------------------------------|
.>ch12
.ST 12. DIALOGUES: INPUT AND OUTPUT

The Gofer system implements a subset of  the  facilities  for  programs
involving I/O described in the Haskell report [5].  In particular, this
makes it possible for Gofer programs to be run  interactively,  and  to
make limited use of  text  files  for  both  reading  and  writing.   A
significant factor in the design of the Haskell I/O facilities is  that
it allows  the  use  of  such  programs  without  loss  of  referential
transparency.

.ST 12.1 Basic description
----------------------
Programs using the I/O facilities in Gofer are modelled by functions of
type Dialogue, defined by the type synonym:

    type Dialogue    =  [Response] -> [Request]

In other words, a Gofer program produces a list of output values,  each
of which may be thought of as a request for some  particular  input  or
output action, and obtains the corresponding list of  operating  system
responses as its input.  Note that the input list of responses will  be
evaluated lazily; i.e. we can ensure that we do not attempt  to  obtain
the response to a given request until that request has been completed.

The current range of requests supported by Gofer is  described  by  the
following datatype definition, taken from the standard prelude:

    data Request  =  -- file system requests:
                    ReadFile      String         
                  | WriteFile     String String
                  | AppendFile    String String
                     -- channel system requests:
                  | ReadChan      String 
                  | AppendChan    String String
                     -- environment requests:
                  | Echo          Bool
 
Each response is an element  of  the  type  defined  by  the  following
datatype definition, using an auxiliary datatype IOError to describe  a
variety of error conditions that may occur:

    data Response = Success
                  | Str String 
                  | Failure IOError
 
    data IOError  = WriteError   String
                  | ReadError    String
                  | SearchError  String
                  | FormatError  String
                  | OtherError   String

The following list describes the kind of  I/O  behaviour  specified  by
each form of Request and indicates the possible  Response  values  that
may be obtained in each case:

  o  ReadFile  string:  Read  contents  of  file  named  by   "string".
     Possible responses to this request are:

       o  Str contents  if the request is successful,  where "contents"
          is a string (evaluated lazily) containing the contents of the
          file specified by the ReadFile request.

       o  Failure (SearchError name) occurs if file  "name"  cannot  be
          accessed.

       o  Failure (ReadError name) occurs if some  other  error  occurs
          whilst opening the file "name".

  o  WriteFile name string:  Write  the  given  "string"  to  the  file
     "name".  If the file does not already exist, it is created  before
     attempting to write the value to file.  If the file already exists
     then it will be truncated to zero length before the write  begins.
     No response is obtained until the string argument has  been  fully
     evaluated and its contents written to  file.   Possible  responses
     are:

       o  Success if the write to file was completed successfully.

       o  Failure (WriteError msg) if  an  error  was  detected  whilst
          trying to perform the output.  If the problem occurred whilst
          attempting to open the specified file,  then  "msg"  contains
          the   filename,   otherwise   it   contains    a    printable
          representation of the evaluation error which occurred.

  o  AppendFile name string: Similar to the  WriteFile  request  except
     that the value of the given "string" is  appended  onto  the  file
     "name" if that file already exists.  The  responses  that  may  be
     obtained from this request are the same as those for WriteFile.

  o  ReadChan name:  Read  from  the  input  stream  "name".  Note that
     it is an error to attempt to read from the same channel more  than
     once in the same program.  Possible responses are:

       o  Str contents if the request is successful,  where  "contents"
          is  a  string  (evaluated  lazily)  containing  the  list  of
          characters entered on the input stream.

       o  Failure (SearchError name) if the  named  channel  cannot  be
          found.  The only input channel known to Gofer is the standard
          input channel "stdin".  For convenience, the standard prelude
          defines the variable stdin bound to this string.

       o  Failure (ReadError name) if a ReadChan request for the  named
          channel has already been given by a previous request.

  o  AppendChan name string:  Output "string" on  channel  "name".   No
     response is obtained until the string has been fully evaluated and
     written to the named channel.  Possible responses are:

       o  Success if the append to channel was completed successfully.

       o  Failure (SearchError name) if the  named  channel  cannot  be
          found.  The only output channels known to Gofer are "stdout",
          "stderr" and "stdecho" (which is actually just  another  name
          for  "stdout"  in  Gofer).   For  convenience,  the  standard
          prelude defines variables stdout, stderr and stdecho bound to
          the corresponding string values.

       o  Failure (WriteError msg)  if  an  error  is  detected  whilst
          trying to perform the output.  The string  "msg"  contains  a
          printable  representation  of  the  evaluation  error   which
          occurred.

  o  Echo status: Set the echo status on  the  standard  input  channel
     stdin to the given boolean value.  If the  echo  status  is  True,
     then user input will be echoed onto the screen as it is  typed and
     the usual line editing facilities  (such a  backspace  or  delete)
     provided by the host system can be used to edit the input lines as
     they are entered.  If the echo status is  False,  then  individual
     characters may be read from the standard input channel without any
     echo or line editing features.

     Note that at most one Echo request can be used in a  program,  and
     must precede any ReadChan request for stdin.  If  not  set  by  an
     explicit Echo request, the echo status defaults to True.  Possible
     responses are:

       o  Success if the request was completed successfully.

       o  Failure  (OtherError  msg)  if  the  request  could  not   be
          completed either because a readChannel request for stdin  has
          already been processed, or because a  previous  Echo  request
          has already been given.  The  corresponding  values of  "msg"
          are   "stdin already in use"   and    "repeated Echo request"
          respectively.

A simple example of a program using these facilities to output a short
message on the standard output stream is:

    helloWorld      :: Dialogue
    helloWorld resps = [AppendChan stdout "hello, world"]
 
Any expression entered into Gofer of type "Dialogue" will be treated as
a Gofer program using I/O and will be executed accordingly:

    ? helloWorld
    hello, world
    (1 reduction, 28 cells)
    ?

Notice that without the explicit type declaration, the type that  would
be  inferred  for  helloWorld   would   be  a -> [Request],  and  hence
helloWorld would not be executed as a Dialogue program.  This point can
be illustrated using lambda expressions:

    ? \resps -> [AppendChan stdout "hello, world"]
    v128
    (1 reduction, 7 cells)

    ? (\resps -> [AppendChan stdout "hello, world"]) :: Dialogue
    hello, world
 
    (1 reduction, 28 cells)
    ? 

In many cases the  structure  of  an  expression  is  enough  to  fully
determine its type  as  Dialogue  (or  equivalently  as  [Response]  ->
[Request]), in which case no explicit types are required to ensure that
the expression is treated as a Gofer program using I/O:

    ? \~[Success] -> [AppendChan stdout "hello, world"]
    hello, world
    (1 reduction, 29 cells)
    ?

Note the use of the  irrefutable  pattern  ~[Success]  for  the  lambda
expression in the last  example;  without  this,  the  usual  rules  of
pattern matching as described in section 9 would force Gofer to try  to
match the pattern [Success] against the list of responses,  before  the
corresponding request had been produced:

    ? \ [Success] -> [AppendChan stdout "hello, world"]

    Aborting Dialogue:
          {error "Attempt to read response before request complete"}
    (50 reductions, 229 cells)
    ?

The next example takes a single string as a parameter and displays  the
contents of the corresponding file:

    showFile               :: String -> Dialogue 
    showFile name ~(read:_) = [ReadFile name, AppendChan stdout result] 
     where result = case read of Str contents -> contents 
                                 Failure _    -> "Can't open " ++ name 

With a few modifications, we can  implement  a  similar  program  which
prompts for, and reads, a filename from the  standard  input  and  then
reads and displays the contents of that file as before.   This  program
is based on a similar example in the Haskell report [5]:

    main ~(Success : ~(Str userInput : ~(r3 : _)))  
      = [ AppendChan stdout "Please type a filename: ", 
          ReadChan stdin, 
          ReadFile name, 
          AppendChan stdout (case r3 of Str contents -> contents
                                        Failure _    -> "Can't open "
                                                        ++ name)
        ] where (name : _) = lines userInput


.ST 12.2 Continuation style I/O
---------------------------
As an alternative to the `stream-based' approach to programs using  the
I/O facilities in Gofer, the  standard  prelude  defines  a  family  of
functions which enables such programs to be written in a `continuation'
style.  The basic idea is to define a function  corresponding  to  each
different kind of request, whose parameters include the values required
to make the request together with two continuations.  The continuations
are functions describing "what to do next", one of which is used if the
request is successful, the other if the request fails.

As an example, the ReadFile request  is  represented  by  the  function
"readFile" whose definition is equivalent to:

    readFile name fail succ ~(r:rs) = ReadFile name : rest rs
     where rest = case r of Str s           -> succ s
                            Failure ioerror -> fail ioerror

The first thing to happen  when  a  dialogue  expression  of  the  form
"readFile name fail  succ"  is  evaluated  is  that  the  corresponding
request "ReadFile name" is added to the list of I/O  requests.   A  new
dialogue value "rest" is chosen,  depending  on  the  response  to  the
ReadFile request, and the program continues by  passing  the  remaining
part of the response list to "rest".  The functions "succ"  and  "fail"
(called the success and failure  continuations  respectively)  describe
the way in which the new dialogue "rest" is obtained.

The following example (edited a little to fit within the margins of this
document) shows how the readFile function described above can be used to
print the contents of a file called "test" on the display:

    ? readFile "test" (\ioerror resps -> [])
                      (\s resps->[AppendChan stdout s])
    This is a test message

    (4 reductions, 52 cells)
    ?

The success continuation "(\s resps->[AppendChan stdout s])" used  here
receives the contents of the file "test" in the the parameter  "s"  and
uses an AppendChan request to output that string on  the  display.   As
this example shows, the stream based approach of the  previous  section
can be combined with the continuation based style of  I/O  without  any
difficulty.  The failure continuation "(\ioerror resps -> [])"  ignores
the error condition "ioerror" which caused  the  request  to  fail  and
gives a dialogue which terminates immediately without any action.   For
example, assuming that the file "Test" cannot be found:

    ? readFile "Test" (\ioerror resps -> [])
                      (\s resps->[AppendChan stdout s])

    (4 reductions, 24 cells)
    ?

In practice, it is  usually  a  good  idea  to  produce  some  kind  of
diagnostic message when an error occurs:

    ? readFile "Test"
         (\ioerror resps -> [AppendChan stdout (show' ioerror)])
         (\s resps       -> [AppendChan stdout s])
    SearchError "Test"
    (11 reductions, 59 cells)
    ?

In each of the  examples  above,  the  failure  continuation  has  type
"FailCont" as defined by the following type  synonym  in  the  standard
prelude:

   type FailCont  =  IOError -> Dialogue

Similarly, the success continuation, which takes a string  representing
an input string and produces a new Dialogue has type "StrCont":

    type StrCont  =  String -> Dialogue

A third kind of continuation is needed for those requests which  return
a  response  of  the  form  "Success"  if  successful   (e.g.    output
requests).  In this case the continuation is simply another dialogue:

    type SuccCont =  Dialogue

The following list  gives  the  type  of  each  of  the  six  functions
corresponding to the six different kinds of I/O  request  described  in
the previous section.  Full definitions for each of these functions are
given in appendix B:

    readFile   :: String -> FailCont -> StrCont -> Dialogue
    writeFile  :: String -> String -> FailCont -> SuccCont -> Dialogue
    appendFile :: String -> String -> FailCont -> SuccCont -> Dialogue
    readChan   :: String -> FailCont -> StrCont  -> Dialogue
    appendChan :: String -> String -> FailCont -> SuccCont -> Dialogue
    echo       :: Bool -> FailCont -> SuccCont -> Dialogue

As an illustration of the use of these functions, we show how  each  of
the example programs from the previous section can be  rewritten  using
the  continuation  based  style  of  I/O,  starting  with  the  program
"helloWorld":

    helloWorld :: Dialogue
    helloWorld  = appendChan stdout "hello, world" abort done

In this case, the explicit type declaration is  not  actually  required
since the type of the expression is completely determined by  the  type
of "appendChan".  The failure continuation "abort" is equivalent to the
function "(\ioerror resps -> [])" described above  and  terminates  the
program if an error occurs without any further action.   In  a  similar
way, "done"  is  the  trivial  dialogue  which  terminates  immediately
without any action.   Both of these values are defined in the  standard
prelude:

   done         :: Dialogue
   done resps    = []

   abort        :: FailCont
   abort ioerror = done
 
Using the same approach, the "showFile" and "main"  programs  from  the
previous section are written as:

    showFile :: String -> Dialogue
    showFile name
     = readFile name (\ioerror -> appendChan stdout
                                     ("Can't open " ++ name) abort done)
                     (\contents-> appendChan stdout contents abort done)
 
    main :: Dialogue
    main  = appendChan stdout "Please type a filename: " abort
            (readChan stdin abort
            (\userInput -> let (name : _) = lines userInput in
             readFile name
              (\ioerror  -> appendChan stdout ("Can't open " ++ name)
                                abort done)
              (\contents -> appendChan stdout contents abort done)))


.ST 12.3 Interactive programs
-------------------------
One of the principal motivations for including facilities  for  I/O  in
Gofer programs was to provide a way of using  interactive  programs  as
described in [1].  An interactive program is represented by a  function
of type String -> String mapping an input string of characters  entered
at the keyboard into an output string to be displayed on the screen.

There are two functions defined in the standard prelude  which  can  be
used to `execute' functions of this kind as interactive programs:

  o  "interact f" executes f::String->String as an interactive  program
     with echo on.  This  means  that  characters  are  read  from  the
     keyboard a line at a time.  The usual editing characters  such  as
     backspace can be used to correct mistakes which are noticed before
     the return key is pressed at the end  of  each  line.   The  input
     stream can be terminated by typing an end of file character at the
     beginning of a line:

         ? interact (map toUpper)
         This text was entered using the interact function
         THIS TEXT WAS ENTERED USING THE INTERACT FUNCTION
         ^Z
         (874 reductions, 1037 cells)
         ?

  o  "run f" behaves like "interact f" except that echo is turned  off.
     In this case, the only way of terminating the input stream without
     reaching the end of the string produced  by  "f"  is  to  use  the
     interrupt key:

         ? run (map toUpper)     
         ALTHOUGH THIS IS ENTERED IN LOWER CASE, IT STILL
         APPEARS IN UPPER CASE !
         {Interrupted!}
 
         (1227 reductions, 1463 cells)
         ?

[ASIDE: of these two functions, only "interact" is also included in the
standard prelude for Haskell, although "run" may also  be  added  to  a
Haskell system using the definition below.]

The definitions of "interact" and "run"  provide  further  examples  of
Gofer programs using simple I/O facilities:

    interact        :: (String -> String) -> Dialogue
    interact f       = readChan stdin abort
                            (\s -> appendChan stdout (f s) abort done)
 
    run             :: (String -> String) -> Dialogue
    run f            = echo False abort (interact f)
 
[EXERCISE for the interested reader:  construct alternative definitions
for these functions using the stream based approach from section 12.1.]

.pa
.co-------------------------------------------------------------------|
.>ch13
.ST 13. LAYOUT

.ST 13.1 Comments
-------------
Comments provide an informal but useful way  of  annotating  a  program
with  a  description  of  its  purpose,  structure   and   development.
Following  the  definition  of  Haskell,  two  styles  of  comment  are
supported by Gofer:

  o  A one line comment begins with the  two  characters  "--"  and  is
     terminated at the end of the same line.   Note  that  an  operator
     symbol cannot begin with "--" as  this  will  be  treated  as  the
     beginning of a comment.  It is however possible  to  use  the  two
     characters "--" at any other position within an  operator  symbol.
     Thus a line such as:

                           (xs ++ ys) -- xs

     includes a comment and will actually be treated as if the line had
     been written:
                               (xs ++ ys)

     Whereas the line:

                           xs >--> ys >--> zs

     does not contain any comments (although it  will  cause  an  error
     unless ">-->" has been defined  using  an  appropriate  infixl  or
     infixr declaration).

  o  A nested comment begins with the characters "{-",  ends  with  the
     characters "-}" and may span  any  number  of  lines.   [N.B.  the
     initial "{-" string  cannot  overlap  with  the  terminating  "-}"
     string so that the shortest possible nested comment is "{--}", and
     not "{-}"].  An unterminated nested comment will be treated as  an
     error.

     As the name suggests, comments of this kind may be nested so  that
     "{- {- ... -} ... {- ... -} -}" is treated as  a  single  comment.
     This makes nested comments particularly convenient  for  enclosing
     parts  of  a  program  which  may  already  contain  other  nested
     comments.

Both kinds of comment may be used in expressions entered directly  into
the Gofer system, or more usually, in files of definitions loaded  into
Gofer.  The two  styles  of  comment  may  be  mixed  within  the  same
expression or program, remembering that the string "--" has no  special
significance within a nested comment and that the strings "{-" and "-}"
have no special significance in a single line comment.  Thus:

            [ 2, -- {-                 [ 2, {-
              3, -- -}                   -- -} 3,
              4 ]                        4 ]

are both equivalent to the list expression [2,3,4].


.ST 13.2 The layout rule
--------------------
In a tradition dating back at least a quarter of a century to  Landin's
ISWIM family of languages,  most  Gofer  programs  use  indentation  to
indicate the structure of a program.  For example, in a definition such
as:

                    f x y = g (x + w)
                            where g u = u + v
                                        where v = u * u
                                  w   = 2 + y

it is clear from the layout that the definition of w is intended to  be
local to f rather than to g.  Another example  where  layout  plays  an
important role is in distinguishing the two definitions:

         example x y z = a + b       example x y z = a + b
               where a = f x y             where a   = f x
                     b = g z                     y b = g z

There are three situations in Gofer where indentation is typically used
to determine the structure of a program:

  o  At the top-level of a file of definitions.

  o  In a group of local declarations following either of the  keywords
     "let" or "where".

  o  In a group of alternatives in a  case  expression,  following  the
     keyword "of".

In each case, Gofer actually expects to find a list of  items  enclosed
between braces `{' and `}' with individual  items  separated  from  one
another by semicolons `;'.  However, if the leading brace is not  found
then Gofer uses the layout rule described below to arrange for `{', `}'
and `;' tokens to be  inserted  into  the  input  stream  automatically
according to the indentation of each line.

In this way, the first example above will in fact be treated as if the
user had entered:

                    f x y = g (x + w)
                            where {g u = u + v
                                         where {v = u * u
                                  }; w   = 2 + y
                    }

or, equivalently, just:

  f x y = g (x + w) where {g u = u + v where {v = u * u}; w = 2 + y}

where the additional punctuation using the `{', `}' and `;'  characters
makes the intended grouping clear, regardless of indentation.

.cc 2
The layout rule used in Gofer is the same as that of Haskell,  and  can
be described as follows:

  o  An opening brace `{' is inserted in front of the  first  token  at
     the beginning of a file or following one of the keywords  "where",
     "let" or "of", unless that token is itself an opening brace.

  o  A `;' token is inserted  in  front  of  the  first  token  in  any
     subsequent line with exactly the same indentation as the token  in
     front of which the opening brace was inserted.

  o  The layout rule ends and a `}' token is inserted in front  of  the
     first token in a subsequent line  whose  indentation  is  strictly
     less than that of the token in front of which  the  opening  brace
     was inserted.

  o  A closing brace `}' will also be inserted at any  point  where  an
     otherwise unexpected token is encountered.  This part of the rule
     makes it possible to use expressions such as:

                       let a = fact 12 in a+a

     without needing to use the layout characters explicitly as in:

                      let {a = fact 12} in a+a.

  o  Lines containing only whitespace (blanks and tabs) and comments do
     not affect the use of the layout rule.

  o  For the purposes of determining the indentation of each line in  a
     file, tab stops are assumed to be placed every 8 characters,  with
     the leftmost tab stop in column 9.  Each tab character inserts one
     or more spaces as necessary to move to the next tab stop.

  o  The indentation of the end of file token is zero.

The following (rather contrived) program, is based on an example in the
Haskell report [5], and provides an extended example of the use of  the
layout rule.  A file containing the following definitions:

    data Stack a = Empty
                 | MkStack a (Stack a)

    push    :: a -> Stack a -> Stack a
    push x s = MkStack x s

    size  :: Stack a -> Int
    size s = length (stkToList s) where
               stkToList Empty         = []
               stkToList (MkStack x s) = x:xs where xs = stkToList s

    pop :: Stack a -> (a, Stack a)
    pop (MkStack x s) = (x, case s of r -> i r where i x = x)

    top :: Stack a -> a
    top (MkStack x s) = x

will be treated by Gofer as if it has been written:

    {data Stack a = Empty
                  | MkStack a (Stack a)

    ;push    :: a -> Stack a -> Stack a
    ;push x s = MkStack x s

    ;size  :: Stack a -> Int
    ;size s = length (stkToList s) where
               {stkToList Empty = []
               ;stkToList (MkStack x s) = x:xs where {xs = stkToList s

    }};pop :: Stack a -> (a, Stack a)
    ;pop (MkStack x s) = (x, case s of {r -> i r where {i x = x}})

    ;top :: Stack a -> a
    ;top (MkStack x s) = x
    }

Note that some of the more sophisticated forms of expression cannot  be
written on a single line (and hence entered  directly  into  the  Gofer
system) without explicit use of the layout characters `{', `}' and `;':

    ? len [1..10] where len [] = 0;  len (x:xs) = 1 + len xs
    10
    (81 reductions, 108 cells)

    ? f True where f x = case x of True->n where {n=not x}; False->True
    False
    (4 reductions, 11 cells)

    ?

One situation in which the layout  rule  can  cause  problems  is  with
top-level definitions.  For example, the two lines:

   f x  = 1 + x
    g y = 1 - y

will be treated as a single line "f x = 1 + x g y = 1 - y", which  will
cause a syntax  error.   This  kind  of  problem  becomes  rather  more
difficult to spot if the two definitions are not on  subsequent  lines,
particularly if they are separated by several lines of  comments.   For
this reason, it is usually a good  idea  to  ensure  that  all  of  the
top-level definitions in a file start in the  same  column  (the  first
column is usually the most convenient).  COBOL and Fortran  programmers
are not likely to find this problem too distressing :-)
.pa
.on
.co-------------------------------------------------------------------|
.>ch14
.ST 14. OVERLOADING IN GOFER

One of the biggest differences between Gofer and most other programming
languages  (with  the  exception  of  Haskell)  is  the   approach   to
overloading; enabling the definition and use of functions in which  the
meaning of a function symbol may depend on the types of its arguments.

Like Haskell, overloading in Gofer is based around  a  system  of  type
classes which allow overloaded functions to be  grouped  together  into
related groups  of  functions.   Whilst  the  precise  details  of  the
approach to type classes used by  Gofer are quite  different from those
of Haskell,  both rely on the same basic ideas and use a similar syntax
for defining and using type classes.   It would therefore seem possible
that experience gained with the overloading system in one language  can
readily by applied to the other.

The differences embodied in the Gofer system of classes  stem  from  my
own, theoretically based investigations into `qualified types' some  of
which is detailed in references [8-12].  In my  personal  opinion,  the
Gofer system has some significant advantages over the Haskell  approach
(see [12] for details) and one of the principal motivations behind  the
implementation to Gofer was to provide a way of  testing  such  claims.
One fact which I believe has already been established  using  Gofer  is
that the use and implementation of overloaded functions need  not  have
the significant effect on performance that was anticipated  with  early
implementations of Haskell.

This section outlines  the  system  of  type  classes  used  in  Gofer,
indicating briefly how they can be used and how they are implemented.


.ST 14.1 Type classes and predicates
--------------------------------
A type class can be thought of as a family of types (or more  generally
as a family of tuples of types) whose elements are called instances  of
the class.  If C is the name of  an  n-parameter  type  class  then  an
expression of the form C t1 t2 ... tn where t1, t2, ...,  tn  are  type
expressions is called a predicate and represents the assertion that the
specified tuple of types is an instance of the class C.

Given a polymorphic function (e.g. map::(a->b)->[a]->[b]), we are  free
to use the function at any type which can be obtained  by  substituting
arbitrary types for each of the type variables in its type.  In  Gofer,
a type expression may be qualified by  one  or  more  predicates  which
restrict the range of types at which a value can be used:

e.g. a function of type C a => a -> a -> a can be treated as a function
     of type t -> t -> t for any instance t of the class C.

The predicate C a in the type expression in  the  previous  example  is
called the context of the type.  Contexts may  contain  more  than  one
predicate in which case the predicates involved must  be  separated  by
commas and the context enclosed in parentheses as in (C a, D  b).   The
empty context is written () and any type expression t is equivalent  to
the qualified type () => t.  For uniformity, a context  with  only  one
element may also be enclosed by parentheses.

For technical reasons, type synonyms are  not  currently  permitted  in
predicates.  This is consistent with the use of predicates in  Haskell,
but may be relaxed, at least in certain cases,  in  later  versions  of
Gofer.


.ST 14.2 The type class Eq
----------------------
The type class Eq is a simple and useful example, whose  instances  are
precisely those types whose elements can be tested for  equality.   The
declaration of this class given in the standard prelude is as follows:

    class Eq a where
        (==), (/=) :: a -> a -> Bool
        x /= y      = not (x == y)

There are three parts in any class declaration.   For  this  particular
example we have:

  o  The first line (called the `header') of the declaration introduces
     a name Eq for the  class  and  indicates  that  it  has  a  single
     parameter, represented by the type variable a.

  o  The  second  line  of  the  declaration  (the  `signature   part')
     indicates that there are functions denoted by the operator symbols
     (==) and (/=) of type a -> a -> Bool for each instance a of  class
     Eq.  Using the notation introduced in the previous  section,  both
     of these operators have type:

                      Eq a => a -> a -> Bool

     These functions are called the `members' (or  `member  functions')
     of the class.  [This terminology, taken from  Haskell,  is  rather
     unfortunate; thinking of a type class  as  a  set  of  types,  the
     elements of the class are called `instances', whilst the `members'
     of the class correspond more closely  to  the  instance  variables
     that are used in the terminology of object-oriented programming.]

     The intention is that the (==) function will be used to  implement
     an equality test for each instance of the  class,  with  the  (/=)
     operator providing the  corresponding  inequality  function.   The
     ability to include related groups of  functions  within  a  single
     type class in this way is a useful tool in program design.

  o  The  third  line  of   the   class   declaration   (the   `default
     definitions') provides a default definition of the  (/=)  operator
     in terms of the (==) operator.  Thus it is only necessary to  give
     a definition for the (==) operator in order to define all  of  the
     member functions for the class Eq.  It  is  possible  to  override
     default member definitions by giving an alternative definition  as
     appropriate for specific instances of the class.


.ST 14.2.1 Implicit overloading
---------------------------
Member functions are clearly marked as overloaded  functions  by  their
definition as part of a class declaration, but this is not the only way
in which overloaded  functions  occur  in  Gofer;  the  restriction  to
particular instances of a type class is also carried over into the type
of any function defined either directly or indirectly in terms  of  the
member functions of that class.  For example, the  types  inferred  for
the following two functions:

    x  `elem`   xs   =   any (x==) xs
    xs `subset` ys   =   all (`elem` ys) xs

are:

    elem   :: Eq a => a -> [a] -> Bool
    subset :: Eq a => [a] -> [a] -> Bool

[ASIDE: On the  other  hand,  if  none  of  the  functions  used  in  a
particular expression or definition are overloaded then there will  not
be any overloading in the corresponding value.  Gofer does not  support
the concept of implicit overloading used  in  some  languages  where  a
value of a particular type might automatically be coerced to a value of
some supertype.  An example of this would be the automatic  translation
of a badly typed expression "1.0 == 1" to a  well-typed  expression  of
the form "1.0 == float 1" for some  (potentially  overloaded)  coercion
function "float" mapping numeric values to elements of type Float.]

Note also that the types appearing in the context of a  qualified  type
reflect the types at which overloaded functions are used.  Thus:

    f x ys  =  [x] == ys

has type  Eq [a] => a -> [a] -> Bool, and not Eq a => a -> [a] -> Bool,
which is the type that would be assigned to "f" in a Haskell system.


.ST 14.2.2 Instances of class Eq
----------------------------
Instances of a type class are defined  using  declarations  similar  to
those used to define  the  corresponding  type  class.   The  following
examples, taken from the standard prelude, give the definitions  for  a
number of simple instances of the class Eq:

    instance Eq Int  where  (==) = primEqInt

    instance Eq Bool where
        True  == True   =  True
        False == False  =  True
        _     == _      =  False

    instance Eq Char  where  c == d  =  ord c == ord d

    instance (Eq a, Eq b) => Eq (a,b) where
        (x,y) == (u,v)  =  x==u && y==v

    instance Eq a => Eq [a] where
        []     == []     =  True
        []     == (y:ys) =  False
        (x:xs) == []     =  False
        (x:xs) == (y:ys) =  x==y && xs==ys

The interpretation of these declarations is as follows:

  o  The first declaration  makes Int an instance  of  class  Eq.   The
     function "primEqInt" is a primitive Gofer function which tests the
     equality of two integer values and has type Int -> Int -> Bool.

  o  The second declaration makes  Bool an instance of  class Eq with a
     simple definition involving pattern matching.

  o  The third declaration makes Char an instance of  class  Eq.   This
     definition indicates that a pair of characters are equal  if  they
     have the same ASCII value,  which  is  obtained  using  the  "ord"
     function.  Note that the two occurrences of the symbol (==) in the
     equation:

                       c == d  =  ord c == ord d

     have  different  meanings;  the  first  denotes  equality  between
     characters (elements of type  Char),  whilst  the  second  denotes
     equality between integers (elements of type Int).

  o  The fourth declaration provides an equality  operation  on  pairs.
     Given two elements (x,y) and (u,v) of type (a,b) for some a, b, it
     must be possible to check that both x==u and y==v before we can be
     sure that the two pairs are indeed equal.  In other words, both  a
     and b must also be instances of Eq  in  order  to  make  (a,b)  an
     instance of Eq.  This requirement is described by the  first  line
     in the instance declaration using the expression:

                       (Eq a, Eq b) => Eq (a,b)

  o  The fifth declaration makes [a] an instance of Eq, whenever  a  is
     itself an instance  of  Eq  in  a  similar  way  to  the  previous
     example.  The context Eq a is used in the  last  equation  in  the
     declaration:

                     (x:xs) == (y:ys)  =  x==y && xs==ys

     which contains three occurrences of the (==) operator;  the  first
     and third are used to compare lists of type [a], whilst the second
     is used to compare elements of type a, using the instance Eq a.

Combining these five declarations, we obtain definitions for (==) on an
infinite  family  of  types  including  Int,  Char,  Bool,  (Int,Bool),
(Char,Int), [Char], (Bool,[Int]), [(Bool,Int)], etc...:

    ? 2 == 3                            -- using Eq Int
    False
    (2 reductions, 10 cells)
    ? (["Hello"],3) == (["Hello"],3)    -- using Eq ([[Char]],Int)
    True
    (31 reductions, 65 cells)
    ?

On the other hand, any attempt to use (==) to compare elements of  some
type not covered by a suitable instance declaration will result  in  an
error.  For example, the standard prelude does not define the  equality
operation on triples of values:

    ? (1,2,3) == (1,2,3)
    ERROR: Cannot derive instance in expression
    *** Expression        : (==) d125 (1,2,3) (1,2,3)
    *** Required instance : Eq (Int,Int,Int)
    ?

This can  be  solved  by  including  an  instance  declaration  of  the
following form into a file of definitions loaded into Gofer:

    instance (Eq a, Eq b, Eq c) => Eq (a,b,c) where
        (x,y,z) == (u,v,w)  =  x==u && y==v && z==w

Giving:

    ? (1,2,3) == (1,2,3)
    True
    (6 reductions, 20 cells)
    ?

In general, an instance declaration has the form:

             instance  context => predicate  where
                 definitions of member functions

The context part of the declaration gives a list  of  predicates  which
must be satisfied for the predicate on the right hand side of the  `=>'
sign to be valid.  Constant predicates (i.e. predicates  not  involving
any type variables) required by an instance declaration  (such  as  the
predicate Eq Int  required  by  the  third  declaration)  need  not  be
included in the context.  If the resulting context is empty (as in  the
first three declarations above) then it may be omitted,  together  with
the corresponding `=>' symbol.


.ST 14.2.3 Testing equality of represented values
---------------------------------------------
Instances of  Eq  can  also  be  defined  for  other  types,  including
user-defined datatypes, and unlike the instances described  above,  the
definition of (==) need not be used to  determine  whether  the  values
being compared have the same structure; it  is  often  more  useful  to
check that they represent the same value.  As an example, suppose  that
we introduce a type constructor Set for representing  sets  of  values,
using a list to store the values held in the set:

    data Set a = Set [a]

As usual, we say that two sets are equal if they have the same members,
ignoring any repetitions or differences in the ordering of the elements
in the lists  representing  the  sets.   This  is  achieved  using  the
following instance declaration:

    instance Eq a => Eq (Set a) where
        Set xs == Set ys  =  xs `subset` ys  &&  ys `subset` xs
                             where xs `subset` ys = all (`elem` ys) xs

A couple of examples illustrate the use of this definition:

    ? Set [1,2,3] == Set [3,4,1]
    False
    (49 reductions, 89 cells)
    ? Set [1,2,3] == Set [1,2,2,2,1,3]
    True
    (157 reductions, 240 cells)
    ? 


.ST 14.2.4 Instance declarations without members
--------------------------------------------
It is possible to give an instance declaration without  specifying  any
definitions for the member functions of the class.  For example:

    instance Eq ()

In this case, the definition of  (==) for the instance  Eq ()  is  left
completely undefined, and hence so is the definition of (/=), which  is
defined in terms of (==):

    ? () == ()
    {undefined_member (==)}
    (3 reductions, 34 cells)
    ? () /= ()
    {undefined_member (==)}
    (4 reductions, 36 cells)
    ? 


.ST 14.2.5 Equality on function types
---------------------------------
If an expression requires an  instance  of  a  class  which  cannot  be
obtained using the rules in the given instance  declarations,  then  an
error message will be produced when  the  expression  is  type-checked.
For example, in general there is no sensible way to  determine  when  a
pair of functions are equal, and the standard prelude does not  include
a definition for an instance of the form Eq (a -> b) for  any  types  a
and b:

    ? (1==) == (\x->1==x)
    ERROR: Cannot derive instance in expression
    *** Expression        : (==) d148 ((==) {dict} 1) (\x->(==) {dict} 1 x)
    *** Required instance : Eq (Int -> Bool)

    ?

If for some reason, you would prefer this kind of error to  produce  an
error message when an expression is evaluated, rather than when  it  is
type-checked, you can  use  an  instance  declaration  to  specify  the
required behaviour.  For example:

    instance Eq (a -> b) where 
        (==) = error "Equality not defined between functions"

Evaluating the previous expression once this instance  declaration  has
been included now produces the following result:

    ? (1==) == (\x->1==x)
    {error "Equality not defined between functions"}
    (42 reductions, 173 cells)
    ? 

A limited form of equality can be defined for functions of type  (a->b)
if a has only finitely many elements, such as the boolean type Bool:

    instance Eq a => Eq (Bool -> a) where
        f == g   =   f False == g False   &&   f True == g True

[ASIDE: This instance declaration would not be accepted  in  a  Haskell
program which insists that the predicate  on  the  right  of  the  `=>'
symbol contains precisely one type constructor symbol.]

Using this instance declaration once for each argument, we can now test
two functions taking boolean arguments for equality (assuming of course
that their result type is also an instance of Eq).

    ? (&&) == (||)
    False
    (9 reductions, 21 cells)
    ? not == (\x -> if x then False else True)
    True
    (8 reductions, 16 cells)
    ? (&&) == (\x y-> if x then y else False)
    True
    (16 reductions, 30 cells)
    ? 


.ST 14.2.6 Non-overlapping instances
--------------------------------
Other instance declarations for types of the form a -> b can be used at
the same time, so  long  as  no  pair  of  declarations  overlap.   For
example, adding the following instance declaration

    instance Eq a => Eq (() -> a)  where  f == g  =  f () == g ()

enables us to evaluate expressions such as:

    ? (\()->"Hello") == const "Hello"
    True
    (30 reductions, 55 cells)
    ? 

If however, we try to use instance declarations for types of  the  form
(a -> b) and (Bool -> a) at the same time, then Gofer produces an error
message similar to the following:

    ERROR "file" (line 37): Overlapping instances for class "Eq"
    *** This instance   : Eq (a -> b)
    *** Overlaps with   : Eq (Bool -> a)
    *** Common instance : Eq (Bool -> a)

    ? 

indicating that, given the task of testing two values of type (Bool->a)
for equality, there are (at least) two definitions of (==)  that  could
be used, with potentially different  results  being  obtained  in  each
case.

Here is a further example of the use of non-overlapping instances of  a
class to define a function "cat" (inspired by the unix (tm) command  of
the same name) which uses the I/O facilities  of  Gofer  to  print  the
contents of one or more files on the terminal:

    class    Cat a        where cat  :: a -> Dialogue
    instance Cat [Char]   where cat n = showFile n done
    instance Cat [[Char]] where cat   = foldr showFile done

    showFile name cont = readFile name abort
                             (\s->appendChan stdout s abort cont)
 
Given these declarations, an expression of the form:

                            cat "file"

can be used to display the contents of the named file, whilst a list of
files can be printed one after the other using  an  expression  of  the
form:

               cat ["file1", "file2", ..., "filen"].


.ST 14.3 Dictionaries
-----------------
In order to understand some of the messages produced by Gofer, as  well
as  some  of  the  more  subtle  problems  associated  with  overloaded
functions, it is useful to have a  rough  idea  of  the  way  in  which
overloaded functions are implemented.

The basic idea is that a function with a qualified type context => type
where context is a non-empty list of predicates  is  implemented  by  a
function which takes an  extra  argument  for  each  predicate  in  the
context.  When the function is used, each of these parameters is filled
by a `dictionary'  which  gives  the  values  of  each  of  the  member
functions in the appropriate class.  None of these extra parameters  is
entered by the programmer.  Instead, they  are  inserted  automatically
during type-checking.

For the class Eq, each dictionary has at least two elements  containing
definitions for each of the functions (==) and (/=).  A dictionary  for
an instance of Eq can be depicted by a diagram of the form:

                     +--------+--------+---------
                     |        |        |
                     |  (==)  |  (/=)  |  .....
                     |        |        |
                     +--------+--------+---------

In order to produce useful error messages and indicate the way in which
dictionary expressions are being used, Gofer uses a number  of  special
notations for printing expressions involving dictionaries:

   (#1 d)   selects the first element of the dictionary d

   (#2 d)   selects the second element of the dictionary d

   (#n d)   selects the nth element of the dictionary d
            (note that (#0 d) is equivalent to the dictionary d).

   {dict}   denotes a specific dictionary (the contents are not
            displayed).

   dnnn     a dictionary variable representing an unknown dictionary is
            printed as a lower case letter `d' followed by an  integer;
            e.g. d231.

Note that, whilst these notations are used in output produced by  Gofer
and in the following explanations, they cannot be entered directly into
Gofer expressions or programs -- even if you use  a  variable  such  as
"d1" in an expression, Gofer will not confuse this  with  a  dictionary
variable with the same name (although Gofer might confuse you by  using
the same name in two different contexts!).

Using these notations, the member functions (==) and (/=) of the  class
Eq behave as if they were defined by the expressions:

    (==) d1  =  (#1 d1)
    (/=) d1  =  (#2 d1)

To understand how these definitions work, we need to take a look  at  a
specific dictionary.  Following the original instance declaration  used
for Eq Int, the corresponding dictionary is:

                    d :: Eq Int
                    +------------+------------+
                    |            |            |
                    | primEqInt  |  defNeq d  |
                    |            |            |
                    +------------+------------+

Note that the  dictionary  variable  d  is  used  as  a  name  for  the
dictionary in this diagram, indicating how values within  a  dictionary
can include references to the same dictionary.

[ASIDE: It turns out that predicates  play  a  very  similar  role  for
dictionaries as types play for normal values.  This motivates  our  use
of the notation d :: Eq Int to indicate that d is a dictionary for  the
instance Eq Int.  One difference between these, particularly  important
for theoretical work, is that dictionary values are uniquely determined
by predicates; if d1::p and d2::p for some predicate p, then d1 = d2.]

The value held in the first element of the dictionary is the  primitive
equality function on  integers,  "primEqInt".   The  following  diagram
shows how the dictionary is used to evaluate the expression "2  ==  3".
Note that this expression will first be translated to  "(==) d 2 3"  by
the type checker.  The evaluation then proceeds as follows:

    (==) d 2 3  ==>  (#1 d) 2 3
                ==>  primEqInt 2 3
                ==>  False

The second element of the  dictionary  is  a  little  more  interesting
because it uses the default definition for (/=) given in  the  original
class definition  which,  after  translation,  is  represented  by  the
function "defNeq" defined by:

    defNeq d1 x y = not ((==) d1 x y)

Notice the way in which the  extra  dictionary  parameter  is  used  to
obtain the appropriate overloading.  For  example,  evaluation  of  the
expression  "2 /= 3", which  becomes  "(/=) d 2 3"  after  translation,
proceeds as follows:

    (/=) d 2 3  ==>  (#2 d) 2 3
                ==>  defNeq d 2 3
                ==>  not ((==) d 2 3)
                ==>  not ((#1 d) 2 3)
                ==>  not (primEqInt 2 3)
                ==>  not False
                ==>  True

[Clearly there is some scope for optimisation here; whilst  the  actual
reduction sequences used by Gofer are equivalent to  those  illustrated
above, the precise details are a little different.]

If an  instance  is  obtained  from  an  instance  declaration  with  a
non-empty context, then the basic two element dictionary  used  in  the
examples above is extended with an  extra  dictionary  value  for  each
predicate in the context.  As an example, the diagram below  shows  the
dictionaries that will be created  from  the  instance  definitions  in
section 14.2.2  for  the  instance  Eq  (Int,  [Int]).   The  functions
"eqPair" and "eqList" which are used in these dictionaries are obtained
from the definitions of (==) given in the instance declarations for  Eq
(a,b) and Eq [a] respectively:

    eqPair d (x,y) (u,v)   = (==) (#3 d) x u && (==) (#4 d) y v

    eqList d [] []         = True
    eqList d []     (y:ys) = False
    eqList d (x:xs) []     = False
    eqList d (x:xs) (y:ys) = (==) (#3 d) x y && (==) d xs ys

The dictionary structure for Eq (Int, [Int]) is as follows.  Note  that
the Gofer system ensures that there is at most  one  dictionary  for  a
particular instance of a class, and that the dictionary d1 :: Eq Int in
this system is automatically shared between d2 and d3:

   d3 :: Eq (Int, [Int])
   +------------+------------+------------+------------+
   |            |            |            |            |
   | eqPair d3  | defNeq d3  | d1::Eq Int |d2::Eq [Int]|
   |            |            |            |            |
   +------------+------------+-----+------+-----+------+
                                   |            |
                    +--------------+            |
                    |                           |
                    |        d2 :: Eq [Int]     V 
                    |        +------------+------------+------------+
                    |        |            |            |            |
                    |        | eqList d2  | defNeq d2  | d1::Eq Int |
                    |        |            |            |            |
                    |        +------------+------------+-----+------+
                    |                                        |
       d1 :: Eq Int V                                        |
       +------------+------------+                           |
       |            |            |                           |
       | primEqInt  | defNeq d1  |<--------------------------+
       |            |            |
       +------------+------------+

Once again, it may be useful to see how these definitions are  used  to
evaluate  the  expression   "(2,[1])   ==   (2,[1,3])"   which,   after
translation, becomes "(==) d3 (2,[1]) (2,[1,3])":

    (==) d3 (2,[1]) (2,[1,3])
             ==>   (#1 d3) (2,[1]) (2,[1,3])
             ==>   eqPair d3 (2,[1]) (2,[1,3])
             ==>   (==) (#3 d3) 2 2  &&  (==) (#4 d3) [1] [1,3]
             ==>   (==) d1 2 2       &&  (==) (#4 d3) [1] [1,3]
             ==>   (#1 d1) 2 2       &&  (==) (#4 d3) [1] [1,3]
             ==>   primEqInt 2 2     &&  (==) (#4 d3) [1] [1,3]
             ==>   True              &&  (==) (#4 d3) [1] [1,3]
             ==>   (==) (#4 d3) [1] [1,3]
             ==>   (==) d2 [1] [1,3]
             ==>   (#1 d2) [1] [1,3]
             ==>   eqList d2 [1] [1,3]
             ==>   (==) (#3 d2) 1 1  &&  (==) d2 [] [3]
             ==>   (==) d1 1 1       &&  (==) d2 [] [3]
             ==>   (#1 d1) 1 1       &&  (==) d2 [] [3]
             ==>   primEqInt 1 1     &&  (==) d2 [] [3]
             ==>   True              &&  (==) d2 [] [3]
             ==>   (==) d2 [] [3]
             ==>   False


.ST 14.3.1 Superclasses
-------------------
In general, a type class declaration has the form:

             class  context => Class a1 ... an  where
                 type declarations for member functions
                 default definitions of member functions

where Class is the name of the new type class which takes n  arguments,
represented by distinct type variables a1, ..., an.  As in the case  of
instance declarations, the context that appears on the left  hand  side
of the `=>'  symbol  specifies  a  list  of  predicates  that  must  be
satisfied in order to construct any instance of "Class".

The predicates in the context part of a class  declaration  are  called
the superclasses of Class.  This  terminology  is  taken  from  Haskell
where all classes have a single parameter and each of the predicates in
the context part of a class declaration has the  form  C  a1;  in  this
situation, any instance of Class must also be an instance of each class
C named in the context.   In  other  words,  each  such  C  contains  a
superset of the types in Class.

As an example of a class declaration with a non-empty context, consider
the following declaration from the standard prelude which introduces  a
class Ord whose instances are types  with  both  strict  (<),  (>)  and
non-strict  (<=),  (>=)  versions  of  an  ordering  defined  on  their
elements:

    class Eq a => Ord a where
        (<), (<=), (>), (>=) :: a -> a -> Bool
        max, min             :: a -> a -> a

        x <  y            = x <= y && x /= y
        x >= y            = y <= x
        x >  y            = y < x

        max x y | x >= y  = x
                | y >= x  = y
        min x y | x <= y  = x
                | y <= x  = y

Notice that this definition provides default definitions for all of the
member functions except (<=), so  that  in  general  only  this  single
function needs to be defined to construct an instance of class Ord.

There are two reasons for defining Eq as a superclass of Ord:

  o  The default definition for (<) relies on the  use  of  (/=)  taken
     from class Eq.  In order to guarantee that this is always valid we
     must ensure that every instance of Ord must also be an instance of
     Eq.

  o  Given the definition of a non-strict ordering (<=) on the elements
     of a type, it is always possible to construct a definition for the
     (==) operator (and hence for (/=)) using the equation:

                      x==y   =   x<=y && y<=x

     There will therefore be no loss in generality by requiring  Eq  to
     be a superclass of Ord, and conversely, no difficulty in  defining
     an instance of Eq to accompany any instance of  Ord  for  which an
     instance of Eq has not already be provided.

     As an example, the following definitions  provide  an  alternative
     way to implement the equality operation on  elements  of  the  Set
     datatype described in section  14.2.3,  in  terms  of  the  subset
     ordering defined in class Ord:

         instance Ord (Set a) => Eq (Set a) where
             x == y   =   x <= y  &&  y <= x

         instance Eq a => Ord (Set a) where
             Set xs <= Set ys  =  all (`elem` ys) xs

     This definition is in fact no less efficient or effective than the
     original version.

Dictionaries for superclasses are dealt with in much the  same  way  as
the instance specific dictionaries described above.  For  example,  the
general layout of a dictionary for an instance of Ord is illustrated in
the following diagram:

 +--------+--------+--------+--------+--------+--------+--------+-----
 |        |        |        |        |        |        |        |
 |  (<)   |  (<=)  |  (>)   |  (>=)  |  max   |  min   |  Eq a  | .....
 |        |        |        |        |        |        |        |
 +--------+--------+--------+--------+--------+--------+--------+-----

Note the use of the seventh element of this dictionary which points  to
the dictionary for the appropriate instance of Eq.  This is used in the
translation of the default definition for (<) which is equivalent to:

      defLessThan d x y  =  (<=) d x y  &&  (/=) (#7 d) x y


.ST 14.3.2 Combining classes
------------------------
In general, a dictionary is made up of three separate parts:

     +-------------------+-------------------+-------------------+
     |  Implementation   |    Superclass     | Instance specific |
     | of class members  |   Dictionaries    |   Dictionaries    |
     |                   |                   |                   |
     +-------------------+-------------------+-------------------+

Each of these may be empty.  We have already  seen  examples  in  which
there are no superclass dictionaries (e.g.  instances  of  Eq)  and  in
which there are no  instance  specific  dictionaries  (e.g.   Eq  Int).
Classes with no member functions (corresponding to dictionaries with no
member functions) are sometimes useful as a convenient abbreviation for
a list of predicates.  For example:

    class  C a  where  cee :: a -> a
    class  D a  where  dee :: a -> a

    class  (C a, D a) => CandD a

makes CandD a an abbreviation for the context (C a, D a).  Thinking  of
single parameter type classes as sets of types, the  type  class  CandD
corresponds to the intersection of classes C and D.

Just as the type inferred  for  a  particular  function  definition  or
expression  does  not  involve  type  synonyms  unless  explicit   type
signatures are used, the Gofer  type  system  will  not  use  a  single
predicate of the form CandD a instead of the two predicates C a and D a
unless  explicit signatures are used:

    ? :t dee . cee
    \d129 d130 -> dee d130 . cee d129 :: (C a, D a) => a -> a
    ? :t dee . cee :: CandD a => a -> a
    \d129 -> dee (#2 d129) . cee (#1 d129) :: CandD a => a -> a
    ?

In Haskell,  all  instances  of  a  class  such  as  CandD  must   have
explicit declarations, in addition to  the  corresponding  declarations
for instances for C and D.  This problem can be avoided  by  using  the
more general form of instance declaration permitted in Gofer; a  single
instance declaration:

    instance CandD a

is all that is required to ensure that any instance  of  CandD  can  be
obtained, so long as corresponding instances for C and D can be found.


.ST 14.3.3 Simplified contexts
--------------------------
Consider the function defined by the following equation:

    eg1 x   =   [x] == [x]  ||  x == x

This definition does not restrict the type of x in any way except that,
if x :: a, then there must be instances Eq [a] and Eq a which are  used
for the two occurrences of the (==) operator in the equation.  We might
therefore expect the type of eg1 to be:

    (Eq [a], Eq a) => a -> Bool

with translation:

    eg1 d1 d2 x  =  (==) d1 [x] [x]  ||  (==) d2 x x

However, as can be seen  from  the  case  where  a=Int  illustrated  in
section 14.3, given d1::Eq [a] we can always find a dictionary for Eq a
by taking the third element of d1 i.e. (#3 d1)::Eq a.  Since it is more
efficient to select an element from a  dictionary  than  to  complicate
both type and translation with extra parameters, the type  assigned  to
"eg1" by default is:

    Eq [a] => a -> Bool

with translation:

    eg1 d1 x  =  (==) d1 [x] [x]  || (==) (#3 d1) x x

In general, given a set of predicates corresponding  to  the  instances
required by an expression,  Gofer  will  always  attempt  to  find  the
smallest possible subset of these  predicates  such  that  all  of  the
required dictionaries can still  be  obtained,  whilst  minimising  the
number of dictionary parameters that are used.

The original type and translation for eg1 given above can  be  produced
by including an explicit type signature  in  the  file  containing  the
definition of eg1:

    eg1   ::  (Eq [a], Eq a) => a -> Bool
    eg1 x  =  [x] == [x]  ||  x == x

But even with this definition, Gofer will still always try to  minimise
the number of dictionaries used in any particular expression:

    ? :t eg1
    \d153 -> eg1 d153 (#3 d153) :: Eq [a] => a -> Bool
    ?

As another example, consider the expression "(\x y->  x==x  ||  y==y)".
The type and translation assigned to this term can  be  found  directly
using Gofer:
 
    ? :t (\x y-> x==x || y==y)
    \d121 d122 x y -> (==) d122 x x ||
                      (==) d121 y y
                  :: (Eq b, Eq a) => a -> b -> Bool
    ?

Note that the translation has two dictionary parameters d121  and  d122
corresponding to the two predicates Eq a and Eq b respectively.   Since
both of these dictionaries can be obtained from a  dictionary  for  the
predicate Eq (a,b), we can use an explicit type signature to produce  a
translation which needs only one dictionary parameter:

    ? :t (\x y-> x==x || y==y) :: Eq (a,b) => a -> b -> Bool
    \d121 x y -> (==) (#3 d121) x x ||
                 (==) (#4 d121) y y
             :: Eq (a,b) => a -> b -> Bool
    ?


.cc 8
.ST 14.4 Other issues
-----------------

.ST 14.4.1 Unresolved overloading
-----------------------------
Consider  the  use  of  the  (==)  operator  in  the  following   three
situations:

  o  In the expression "2 == 3", it is clear that the appropriate value
     for the equality operator in this case is primIntEq as defined  by
     the instance declaration for Eq Int.  The expression can therefore
     be translated to "primEqInt 2 3".

  o  In the function definition "f x  =  x==x",  we  cannot  completely
     determine the appropriate value for (==) because it depends on the
     type assigned to the variable "x",  which  may  itself  vary  with
     different uses of the function "f".  It is however possible to add
     an extra parameter to the definition,  giving "f d x = (==) d x x"
     and taking the type of "f" to be Eq a => a -> Bool.

     In this way, the problem of finding the appropriate definition for
     the (==) operator is deferred until the function is actually used.

  o  In the expression "[]==[]", the appropriate value for (==) must be
     obtained from the dictionary for some instance of the form Eq [a],
     but there is not  sufficient  information  in  the  expression  to
     determine what the value of the type variable a should be.

     Looking back to the instance declaration for Eq [a], we find  that
     the definition of (==) depends on the value of the dictionary  for
     the instance Eq a.  In this particular case, it is clear that  the
     expression will always evaluate to True, regardless of  the  value
     of this dictionary.  Unfortunately, the only way that this can  be
     detected is by evaluating the expression to see if the calculation
     can be completed without reference to the  dictionary  value  (see
     the comments in the aside at the end of this section).

     Attempting to evaluate this expression  in  Gofer  will  therefore
     result in an error message indicating that the expression does not
     contain sufficient information to resolve the use  of  overloading
     in the expression:

         ? [] == []
         ERROR: Unresolved overloading
         *** type        : Eq [a] => Bool
         *** translation : \d129 -> (==) d129 [] []
         ?

     Note  that  the  expression  has  been  converted  into  a  lambda
     expression using the dictionary variable  d129  to  represent  the
     dictionary for the unknown instance Eq [a].

     One simple way to resolve the overloading in an expression of this
     kind is to use an explicit type signature.   For  example,  if  we
     specify that the second empty list is an empty list of type [Int]:

         ? [] == ([]::[Int])
         True
         (2 reductions, 9 cells)
         ?

The same problem occurs in Haskell, where it  is  described  using  the
idea of an `ambiguous type' -- i.e.  a  type  expression  of  the  form
context => type where one or more of the type  variables  appearing  in
the given context do not appear in  the  remaining  part  of  the  type
expression.

Further examples of unresolved overloading occur  with  other  classes.
As an example consider the class Reader defined by:

    class Reader a where 
        parse   :: String -> a   
        unparse :: a -> String

whose  member  functions  provide  methods  for  obtaining  the  string
representation of an element of an instance type,  and  for  converting
such representations  back  into  the  original values.  (The  standard
Haskell Text class  contains  similar  functions.)   Now  consider  the
expression "parse . unparse" which maps values from  some  instance  of
Reader to  values  of  another  instance  via  an  intermediate  string
representation.

    ? parse . unparse
    ERROR: Unresolved overloading
    *** type        : (Reader a, Reader b) => a -> b
    *** translation : \d129 d130 -> parse d130 . unparse d129
    ?

One of the first things that might surprise the reader here is that the
value produced by "parse . unparse" does not have to  be  of  the  same
type as the argument; for example, we would not usually expect to  have
any sensible interpretation for a floating point number  obtained  from
the string representation of a boolean value!

This can be fixed by using an explicit type declaration,  although  the
expression still produces unresolved overloading:

    ? (parse . unparse) :: Reader a => a -> a
    ERROR: Unresolved overloading
    *** type        : Reader a => a -> a
    *** translation : \d130 -> parse d130 . unparse d130
    ?

Notice however that the type of this expression  is  not  ambiguous  so
that the unresolved overloading in this example can be eliminated  when
the function is actually used:

    ? ((parse . unparse) :: Reader a => a -> a) 'a'
    'a'
    (4 reductions, 11 cells)
    ?

A more serious problem occurs with the  expression  "unparse  .  parse"
which maps string values to string values via some  intermediate  type.
Clearly this will lead to a problem with unresolved overloading:

    ? unparse . parse
    ERROR: Unresolved overloading
    *** type        : Reader a => String -> String
    *** translation : \d130 -> unparse d130 . parse (#0 d130)
    ?

Notice that the type obtained in  this  case  is  ambiguous;  the  type
variable a which appears in the predicate Reader a does not  appear  in
the type String -> String.  There are a number  of  ways  of  resolving
this kind of ambiguity:

  o  Using an explicitly typed expression: Assuming  for  example  that
     Char is an instance of Reader, we can write:

         ? unparse . (parse :: String -> Char)
         v113 {dict} . v112 {dict}
         (5 reductions, 42 cells)
         ?

     without any ambiguity.  If such type  signatures  are  used  in  a
     number of places, it  might  be  better  to  define  an  auxiliary
     function and use that instead:

         charParse :: String -> Char
         charParse  = parse

         ? unparse . charParse
         v113 {dict} . charParse
         (4 reductions, 37 cells)
         ?

     In such situations, it  is  perhaps  worth  asking  if  overloaded
     functions are in  fact  the  most  appropriate  solution  for  the
     problem at hand!

  o  Using an extra dummy parameter in a  function  definition.   In  a
     definition such as:

         f = unparse . parse

     we can introduce an additional dummy parameter `x'  which  is  not
     used except to determine the type of the result produced by  parse
     in f:

         f x  =  unparse . (parse `asTypeOf` (\""->x))

     where the standard prelude operator `asTypeOf` defined by:

         asTypeOf      :: a -> a -> a
         x `asTypeOf` _ = x

     is used to ensure that the type of parse in the definition of f is
     the same as that of the function (\""->x) -- in other  words,  the
     type must be String -> a where a is the type of the variable x.

     The resulting type for f is:

          f :: Reader a => a -> String -> String

     Notice how the addition of the dummy parameter has  been  used  to
     eliminate the ambiguity present in the original type.

     This kind of `coding trick' is rather messy and is not recommended
     for anything but the simplest examples.

[ASIDE: The idea of evaluating an expression with an ambiguous type  to
see if it does actually need the unspecified  dictionaries  could  have
been  implemented  quite easily in  Gofer  using  an  otherwise  unused
datatype Unresolved and generating instance declarations such as:

    instance Eq Unresolved where
        (==) = error "unresolved overloading for (==)"
        (/=) = error "unresolved overloading for (/=)"

for each class.  Given a particular expression, we  can  then  use  the
type Unused in place of any ambiguous type variables in its type.   The
evaluation of the expression could then be attempted, either completing
successfully if  the  dictionaries  are  not  required,  but  otherwise
resulting in a run-time error.

This approach is not used in Gofer; instead, the programmer is notified
of any unresolved  polymorphism  when  the  program  is  type  checked,
avoiding the possibility that a program  might  contain  an  undetected
ambiguity.]


.ST 14.4.2 `Recursive' dictionaries
-------------------------------
Unlike Haskell, there are no restrictions on the form of the predicates
that may appear in the context  part  of  a  Gofer  class  or  instance
declaration.  This has a  number  of  potentially  useful  applications
because it enables the  Gofer  programs  to  use  mutually  `recursive'
systems of dictionaries.

One example of this is the ability  to  implement  a  large  family  of
related functions using a group of classes instead of having to  use  a
single class.  The following example illustrates the technique with  an
alternative definition for the class Eq in  which  the  (==)  and  (/=)
operators are placed in different classes:

    class Neq a => Eq a  where  (==) :: a -> a -> Bool

    class Eq a => Neq a  where  (/=) :: a -> a -> Bool
                                x/=y  = not (x == y)


[ASIDE: These declarations clash with those in the standard prelude and
hence cannot actually be used in Gofer unless a modified version of the
standard prelude is used instead.]

If we then give instance declarations:

    instance Eq Int  where (==) = primEqInt
    instance Neq Int

and try to evaluate the expression "2==3" then the following system  of
dictionaries will be generated:

        d1 :: Eq Int                   d2 :: Neq Int
        +-----------+-----------+      +-----------+-----------+
        |           |           |      |           |           |
    +-->| primEqInt |d2::Neq Int+----->| defNeq d2 |d1::Eq Int +---+
    |   |           |           |      |           |           |   |
    |   +-----------+-----------+      +-----------+-----------+   |
    |                                                              |
    +------------------------------<-------------------------------+

where the function "defNeq" is derived from the  default definition  in
the class Neq and is equivalent to:

               defNeq d x y  =  not ((==) (#2 d) x y)

Incidentally, if the instance declaration for Neq Int  above  had  been
replaced by:

    instance Neq a

then the effect of these declarations would be similar to the  standard
definition of the class Eq, except that it would  not  be  possible  to
override the  default  definition  for  (/=).   In  other  words,  this
approach would give the same effect as defining  (/=)  as  a  top-level
function rather than a member function in the class Eq:

    class Eq a  where  (==) :: a -> a -> Bool

    (/=)   ::  Eq a => a -> a -> Bool
    x /= y  =  not (x == y)

There are other situations in which recursive dictionaries of the  kind
described above can be  used.   A  further  example  is  given  in  the
following section.  Unfortunately, the lack of restrictions on the form
of class and instance declarations can also lead to  problems  in  some
(mostly pathological) cases.  As an example, consider the class:

    class Bad [a] => Bad a  where  bad :: a -> a

Without defining any instances of Bad, it is not possible to  construct
any dictionaries for instances of Bad:

    ? bad 2
    ERROR: Cannot derive instance in expression
    *** Expression        : bad d126 2
    *** Required instance : Bad Int
    ?

If however we add the instance declarations:

    instance Bad Int where bad = id
    instance Bad [a] where bad = id

then any attempt to construct  a  dictionary  for  Bad  Int  will  also
require a dictionary for the superclass Bad  [Int]  and  then  for  the
superclass of that instance Bad [[Int]] etc...  Since Gofer has only  a
finite amount of space for  storing  dictionaries,  this  process  will
eventually terminate when that space has been used up:

    ? bad 2
    ERROR: Dictionary storage space exhausted
    ?

[ASIDE: depending on the configuration of your  particular  version  of
Gofer and on the nature of the class and instance declarations that are
involved, an alternative error message "ERROR: Too many type  variables
in type checker" may be produced instead of the message shown above.]

From a practical point of view, this problem is unlikely to  cause  too
many real difficulties:

  o  Class declarations involving  predicates  such  as  those  in  the
     declaration of Bad are unlikely to be used in realistic programs.

  o  All dictionaries are constructed before evaluation  begins.   This
     process is guaranteed to terminate  because  each  new  dictionary
     that is created uses up part of  the  space  used  to  hold  Gofer
     dictionaries.  The  construction  process  will  either  terminate
     successfully once complete, or be aborted as soon as  all  of  the
     dictionary space has been used.

It remains to see what impact (if any) this has on realistic  programs,
and if later versions of  Gofer  should  be  modified  to  impose  some
syntactic restrictions (as in Haskell) or perhaps some form  of  static
checking of the contexts appearing in class and instance  declarations.


.ST 14.4.3 Classes with multiple parameters
---------------------------------------
Gofer is the first language to support the use  of  type  classes  with
multiple parameters.  This again is  an  experimental  feature  of  the
language, intended to make it possible to explore  the  claims  from  a
number of researchers about the use of such classes.

Initial experiments suggest that multiple parameter  type  classes  are
likely  to  lead  to  large  numbers  of   problems   with   unresolved
overloading.  Ultimately, this may mean that such classes are  only  of
practical use in explicitly typed languages, or  alternatively  that  a
more powerful and general defaulting mechanism (similar to that used in
Haskell with numeric classes) is required to  support  user  controlled
overloading resolution.

The following declaration introduces a class  Iso  whose  elements  are
pairs of isomorphic types:

    class Iso b a => Iso a b  where  iso :: a -> b

The single member function "iso"  represents  the  isomorphism  mapping
elements of type a to corresponding  elements  of  type  b.   Note  the
`superclass' context in this declaration which formalises the idea that
if a is isomorphic to b then b is also isomorphic to a.  The class  Iso
therefore provides  further  examples  of  the  recursive  dictionaries
described in the previous section.

The fact that any type is isomorphic to itself can be described by the
following instance declaration:

    instance Iso a a where iso x = x

For example, the dictionary structure created in order to evaluate the
expression "iso 2 = 3" is:

                   d :: Iso Int Int
                   +--------------+--------------+
                   |              |              |
               +-->|      id      |d::Iso Int Int+--+
               |   |              |              |  |
               |   +--------------+--------------+  |
               |                                    |
               +------------------<-----------------+

    ? iso 2 == 3
    False
    (4 reductions, 11 cells)
    ? 

Our first taste of the problems to come occurs when we try to  evaluate
the expression "iso 2 == iso 3":

    ? iso 2 == iso 3
    ERROR: Unresolved overloading
    *** type        : (Eq a, Iso Int a) => Bool
    *** translation : \d130 d132 -> (==) d130 (iso d132 2) (iso d132 3)
    ?

In this case, the "iso" function is used to map the integers 2 and 3 to
elements of some type a, isomorphic to Int, and the values produced are
then compared using (==) at the instance Eq  a;  there  is  no  way  of
discovering what the value of a should be  without  using  an  explicit
type signature.

Further instances can be defined.  The following two  declarations  are
needed to describe the (approximate) isomorphism between lists of pairs
and pairs of lists:

    instance Iso [(a,b)] ([a],[b]) where  
        iso xs = (map fst xs, map snd xs)
 
    instance Iso ([a],[b]) [(a,b)] where
        iso (xs,ys) = zip xs ys

Unfortunately, even apparently straightforward examples  give  problems
with  unresolved  overloading,  forcing  the  use  of   explicit   type
declarations:

    ? iso [(1,2),(3,4)]
    ERROR: Unresolved overloading
    *** type        : Iso [(Int,Int)] a => a
    *** translation : \d126 -> iso d126 [(1,2),(3,4)]

    ? (iso [(1,2),(3,4)]) :: ([Int],[Int])
    ([1, 3],[2, 4])
    (22 reductions, 64 cells)
    ?

A second example of a multiple  parameter  type  class  is  defined  as
follows:

    class Ord a => Collects a b where
        emptyCollection :: b
        addToCollection :: a -> b -> b
        listCollection  :: b -> [a]

The basic intuition is that the predicate Collects a b  indicates  that
elements of type b can be used to represent collections of elements  of
type a.  A number of people have suggested using type classes  in  this
way to provide features similar to the (similarly named, but  otherwise
different) classes that occur in object-oriented languages.

Obvious implementations involve the use  of  ordered  lists  or  binary
search trees defined by instances of the form:

    data STree a = Empty | Node a (STree a) (STree a)
 
    instance Collects a [a] where ....
    instance Collects a (STree a) where ....

Once again, there are significant problems even  with  simple  examples
using these functions.  As an example, the standard way of  defining  a
function of type:

                  Collects a b => [a] -> b

mapping a list of values to a collection  of  those  values  using  the
higher order function "foldr":

    listToCollection = foldr addToCollection emptyCollection

actually produces a function with ambiguous type:

    ? :t foldr addToCollection emptyCollection
    \d139 d140 -> foldr (addToCollection d140) (emptyCollection d139)
              :: (Collects c b, Collects a b) => [a] -> b
    ?

which cannot be resolved, even with an explicit type declaration.


.ST 14.4.4 Overloading and numeric values
-------------------------------------
One of the most common uses of overloading is to allow the use  of  the
standard arithmetic operators such as (+), (*) etc. on the elements  of
a range of numeric types including integers and floating  point  values
in addition to user defined numeric types such as  arbitrary  precision
integers,  complex  and  rational  numbers,   vectors   and   matrices,
polynomials etc.  In Haskell, these features are supported by a  number
of built-in types and a complex hierarchy of  type  classes  describing
the operations defined on the elements of each numeric type.

As an experimental language, intended primarily for  the  investigation
of general purpose overloading, Gofer has  only  two  built-in  numeric
types; Int and Float (the second of  which  is  not  supported  in  all
implementations).  Similarly, although the Gofer system could  be  used
to  implement the  full  hierarchy  of  Haskell  numeric  classes,  the
standard prelude uses a single numeric type class Num defined by:

    class Eq a => Num a where           -- simplified numeric class
        (+), (-), (*), (/) :: a -> a -> a
        negate             :: a -> a
        fromInteger        :: Int -> a

The first four member functions (+), (-), (*),  (/)  are  the  standard
arithmetic functions on instances of Num, whilst "negate" denotes unary
negation.  The final member function, fromInteger is used to coerce any
integer value to the corresponding value in another  instance  of  Num.
An expression such as "fromInteger 3" is called an  overloaded  numeric
constant and has type Num a => a indicating that it can be  used  as  a
value of any instance of Num.  See below for examples.

Both Float and Int are defined as  instances  of  Num  using  primitive
functions for integer and floating point arithmetic:

    instance Num Int where
        (+)           = primPlusInt
        (-)           = primMinusInt
        (*)           = primMulInt
        (/)           = primDivInt
        negate        = primNegInt
        fromInteger x = x

    instance Num Float where
        (+)         = primPlusFloat
        (-)         = primMinusFloat
        (*)         = primMulFloat
        (/)         = primDivFloat 
        negate      = primNegFloat
        fromInteger = primIntToFloat

These definitions make it  possible  to  evaluate  numeric  expressions
involving both types:

    ? 2 + 3
    5
    (3 reductions, 6 cells)
    ? 3.2 + 4.321
    7.521
    (3 reductions, 13 cells)
    ?

Note  however  that  any  attempt  to  evaluate  an  expression  mixing
different arithmetic types is likely to cause a type error:

    ? 4.2 * 4
    ERROR: Type error in application
    *** expression     : 4.2 * 4
    *** term           : 4.2
    *** type           : Float
    *** does not match : Int
    ?

Further problems occur when we try to define functions intended  to  be
used with arbitrary instances  of  Num  rather  than  specific  numeric
types.  As an example of this, the  standard  prelude  function  "sum",
roughly equivalent to:

    sum []     = 0
    sum (x:xs) = x + sum xs

has type [Int] -> Int,  rather than the  more general Num a => [a] -> a
which could be used to find the sum of a list of numeric values in  any
instance of Num.  The problem in this particular case is caused by the
integer constant 0 in the first line of the definition.  Replacing this
with the expression fromInteger 0 leads to the following definition for
a generic sum function of the required type:

    genericSum       :: Num a => [a] -> a
    genericSum []     = fromInteger 0
    genericSum (x:xs) = x + genericSum xs

For example:

    ? genericSum [1,2,3]
    6
    (10 reductions, 18 cells)
    ? genericSum [1.0,2.0,3.0]
    6.0
    (11 reductions, 27 cells)
    ?

The fromInteger function  can  also  be  used  to  solve  the  previous
problem:

    ? 4.2 * fromInteger 4
    16.8
    (3 reductions, 13 cells)
    ?

In Haskell, any integer  constant  k  appearing  in  an  expression  is
treated as if the programmer had actually written  "fromInteger  k"  so
that  both  of  the  preceding  problems  are  automatically  resolved.
Unfortunately, this  also  creates  some  new  problems;  applying  the
function fromInteger to each integer constant in the previous  examples
causes problems with unresolved overloading:

    ? fromInteger 2 + fromInteger 3
    ERROR: Unresolved overloading
    *** type        : Num a => a
    *** translation : \d143 -> (+) d143 (fromInteger d143 2)
                                        (fromInteger d143 3)
    ?

Once again, Haskell provides a solution to this problem in the form  of
a `default mechanism' for  numeric  types  which,  once  the  following
problem has been detected, will typically `default'  the  unknown  type
represented by the type variable a above to be Int, so that the  result
is actually equivalent to the following:

    ? (fromInteger 2 + fromInteger 3) :: Int
    5
    (4 reductions, 8 cells)
    ?

There are a number of problems with the Haskell default mechanism; both
theoretical and practical.  In addition, if a default mechanism of some
form is used then it should also be capable of dealing  with  arbitrary
user-defined type classes, rather than  a  small  group  of  `standard'
classes, in order to provide solutions to  the  unresolved  overloading
problems described in  previous  sections.   Therefore,  for  the  time
being, Gofer does  not  support  any  form  of  default  mechanism  and
overloaded numeric constants can only be obtained by  explicit  use  of
the fromInteger function.


.ST 14.4.5 Constants in dictionaries
--------------------------------
The Gofer system constructs new dictionaries as necessary, and  deletes
them when they are no longer required.  At any one time,  there  is  at
most one dictionary for each instance of a class.   Coupled  with  lazy
evaluation, this has a number of advantages for classes in which member
functions are defined by variable declarations as in section 9.10.   As
an example, consider the class Finite defined by:

    class Finite a  where  members :: [a]

The only member in this class is a list enumerating the elements of the
type.  For example:

    instance Finite Bool  where  members = [False, True]
 
    instance (Finite a, Finite b) => Finite (a,b) where
        members = [ (x,y) | x<-members, y<-members ]

In order to overcome any problems with unresolved overloading, explicit
type signatures are often needed to resolve overloading:

    ? members :: [Bool]
    [False, True]
    (6 reductions, 26 cells)
    ? length (members :: [((Bool,Bool),(Bool,Bool))])
    16
    (103 reductions, 195 cells)
    ?

In some cases, the required overloading is implicit  from  the  context
and no additional type information is required,  as  in  the  following
example:

    ? [ x && y | (x,y) <- members ]
    [False, False, False, True]
    (29 reductions, 90 cells)
    ?

We can also use the technique of passing a `dummy' parameter to resolve
overloading problems in a function definition:

    size  :: Finite a => a -> Int
    size x = length (members `asTypeOf` [x])

which calculates the number of elements of  a  finite  type,  given  an
arbitrary element of that type:

    ? size (True,False)
    4
    (31 reductions, 60 cells)
    ?

Now consider the expression "size (True,False)  +  size  (True,False)".
At first glance, we expect  this  to  repeat  the  calculation  in  the
previous example two  times,  requiring  approximately  twice  as  many
reductions and cells as before.  However,  before  this  expression  is
evaluated, Gofer constructs a dictionary for Finite  (Bool,Bool).   The
evaluation of the first summand forces Gofer to evaluate the value  for
"members" in this dictionary.  Since precisely the same  dictionary  is
used to calculate the value of the second summand,  the  evaluation  of
"members" is not repeated and the complete  calculation  actually  uses
rather fewer reductions and cells:

    ? size (True,False) + size (True,False)
    8
    (51 reductions, 90 cells)
    ?

On the other hand, repeating the original calculation gives exactly the
same number of reductions and cells as before, because the dictionaries
constructed at the beginning of each calculation are not  retained  for
use in subsequent calculations.

We can force Gofer to construct specific  dictionaries  whilst  reading
from a file of definitions, so that they are not deleted at the end  of
each calculation, using an explicitly typed  variable  definition  such
as:

    boolBoolMembers = members :: [(Bool,Bool)]

This forces Gofer to construct the dictionary Finite (Bool,Bool)  when
the file of definitions is loaded and prevents it from being deleted at
the end of each calculation.  Having  loaded  a  file  containing  this
definition, the  first two  attempts  to  evaluate  "size (True,False)"
give:

    ? size (True,False)
    4
    (31 reductions, 60 cells)
    ? size (True,False)
    4
    (20 reductions, 32 cells)
    ?


.ST 14.4.6 The monomorphism restriction
-----------------------------------
This section  describes  a  technique  used  to  limit  the  amount  of
overloading used in the definition of certain values to avoid a  number
of technical problems.  This particular topic has attracted quite a lot
of attention within the Haskell community where  it  is  affectionately
known as the `dreaded monomorphism restriction'.  Although the  initial
formulation of the rule was rather cumbersome and limiting, the current
version used in both  Gofer  and  Haskell  is  unlikely  to  cause  any
problems in practice.  In  addition,  many  of  the  examples  used  to
motivate the need for the monomorphism restriction in Haskell occur  as
a result  of  the  use  of  implicitly  overloaded  numeric  constants,
described in section 14.4.4, and hence do not occur in Gofer.

The monomorphism restriction takes its name from the way  in  which  it
limits the amount of polymorphism that can be used in particular  kinds
of declaration.  Although we touch  on  this  point  in  the  following
discussion, the description given here uses  an  equivalent,  but  less
abstract approach, based on observations about  the  implementation  of
overloaded functions.

Basic ideas:
------------
As we have seen,  the  implementation  of  overloading  used  by  Gofer
depends on being able to add extra arguments to a  function  definition
to supply the required dictionary parameters.   For  example,  given  a
function definition such as:

    isElement x []     =  False
    isElement x (y:ys) =  x==y || isElement x ys

we first add a dictionary parameter for the use of the overloaded  (==)
operator on the right hand side, obtaining:

    isElement x []     = False
    isElement x (y:ys) = (==) d x y || isElement x ys

Finally, we have to add the variable d  as  a  new  parameter  for  the
function isElement, on both the  left  and  right  hand  sides  of  the
definition:

    isElement d x []     = False
    isElement d x (y:ys) = (==) d x y || isElement d x ys

The monomorphism restriction imposes conditions which prevent this last
step from being used for certain kinds of value binding.

.cc 5
Declaration groups:
-------------------
Before giving the full details, it  is  worth  pointing  out  that,  in
general,  the  monomorphism  restriction  affects   groups   of   value
declarations rather than just individual  definitions.   To  illustrate
this point, consider the function definitions:

    f x y  =  x==y || g x y
    g x y  =  not (f x y)

Adding an appropriate dictionary parameter for the (==) operator gives:

    f x y  =  (==) d x y || g x y
    g x y  =  not (f x y)

The next stage is to  make  this  dictionary  variable  into  an  extra
parameter to the function f wherever it appears, giving:

    f d x y  =  (==) d x y || g x y
    g x y    =  not (f d x y)

But now the right hand side  of  the  second  definition  mentions  the
dictionary variable d  which  must  therefore  be  added  as  an  extra
parameter to g:

    f d x y  =  (==) d x y || g d x y
    g d x y  =  not (f d x y)

In other words, if dictionary parameters are added  to  any  particular
function  definition,  then  each  use  of  that  function  in  another
definition will also be require  extra  dictionary  parameters.   As  a
result, the monomorphism restriction has to be applied to the  smallest
groups of  declarations  such  that  any  pair  of  mutually  recursive
bindings are in the same group.

As the example above shows, if one (or more) of the bindings in a given
declaration group is affected by the monomorphism restriction  so  that
the appropriate dictionary parameters cannot be added as parameters for
that definition, then the same condition must also be imposed on all of
the other bindings in the group.  [Adding the extra parameter to  f  in
the example forces us to  add  an  extra  parameter  for  g;  if  extra
parameters were not permitted for g then they could not be added to f.]

.cc 5
Restricted bindings:
--------------------
There are three main reasons for avoiding adding dictionary  parameters
to a particular value binding:

  o  Dictionary parameters unnecessary.  If the dictionary  values  are
     completely determined by context then it is not necessary to  pass
     the appropriate values as dictionary parameters.  For example, the
     function definition:

         f x  =   x == 0  ||  x == 2

     can be translated as:

         f x  =   (==) {dict} x 0  ||  (==) {dict} x 2

     where, in both cases, the symbol {dict} denotes the dictionary for
     Eq Int.  As a further optimisation, once the dictionary  is  fully
     determined, this can be simplified to:

         f x  =   primEqInt x 0 || primEqInt x 2

  o  Dictionary parameters cannot be added in a pattern  binding.   One
     potential solution to this problem would be to replace the pattern
     binding by an equivalent set of function bindings.   In  practice,
     we do not use this technique because it typically causes ambiguity
     problems, as illustrated by the pattern binding:

         (plus,times) = ((+), (*))

     Translating this into a group of function bindings gives:

         newVariable  = ((+), (*))
         plus         = fst newVariable     -- fst (x,_) = x
         times        = snd newVariable     -- snd (_,y) = y

     The type of newVariable is (Num a, Num b) => (a->a->a, b->b->b) so
     that  the  correct  translation  of  these  bindings   using   two
     dictionary variables gives:

         newVariable da db = ((+) da, (*) db)
         plus da db        = fst (newVariable da db)
         times da db       = snd (newVariable da db)
 
     and hence the correct types for plus and times are:
 
         plus  :: (Num a, Num b) => a -> a -> a
         times :: (Num a, Num b) => b -> b -> b
     
     both of which are ambiguous.

  o  Adding dictionary parameters may translate a  variable  definition
     into  a  function  definition,  loosing  the  benefits  of  shared
     evaluation.  As an  example,  consider  the  following  definition
     using the function "size" and the class Finite  described  in  the
     previous section:

         twiceSize x = n + n  where n = size x

     Since the variable n is defined using a local definition, we would
     not expect to have to evaluate size x more than once to  determine
     the  value  of  twiceSize.   However,  adding   extra   dictionary
     parameters without restriction gives:

         twiceSize d x  = n d + n d  where  n d = size d x

     Now that n has been replaced by a function, the evaluation will be
     repeated, once for each occurrence of the expression  "n  d".   In
     order to avoid this kind of problem, the monomorphism  restriction
     does not usually allow extra parameters to be added to a  variable
     definition.  Thus the original definition above will be translated
     to give:

         twiceSize d x  =  n + n  where n = size d x

     Note that the same rule is applied to variable definitions at  the
     top-level of a file of definitions, resulting in an error  if  any
     dictionary parameters are required for the right hand side of  the
     definition.  As an example of this:

         twiceMembers = members ++ members

     which produces an error message of the form:

         ERROR "ex" (line 157): Unresolved top-level overloading
         *** Binding             : twiceMembers
         *** Inferred type       : [_7]
         *** Outstanding context : Finite _7
         ?

     [COMMENT: A type expression of the form _n (such  as  _7  in  this
     particular example) represents a  fixed  (i.e.  monomorphic)  type
     variable.]

     In  the  case  of  a  variable   declaration,   the   monomorphism
     restriction can be overcome by giving an explicit  type  signature
     including an appropriate context, to indicate  that  the  variable
     defined is intended to be used as an overloaded  value.   In  this
     case, we need only include the declaration:

         twiceMembers :: Finite a => [a]

     in the file containing the definition for twiceMembers to suppress
     the previous error message and allow the function to be used as  a
     fully overloaded variable.

     Note that the monomorphism restriction interferes with the use  of
     polymorphism.  For example, the definition:

         aNumber = length (twiceMembers::[Bool]) +
                   length (twiceMembers::[(Bool,Bool)])
                   where twiceMembers = members ++ members

     will not be accepted because the monomorphism  restriction  forces
     the local definition of  "twiceMembers"  to  be  restricted  to  a
     single overloading (the dictionary parameter supplied to each  use
     of members must be constant throughout the local definition):

         ERROR "ex" (line 12): Type error in type signature expression
         *** term           : twiceMembers
         *** type           : [(Bool,Bool)]
         *** does not match : [Bool]
         ?

     Once again, this problem can  be  fixed  using  an  explicit  type
     declaration:

         aNumber = length (twiceMembers::[Bool]) +
                   length (twiceMembers::[(Bool,Bool)])  
                   where twiceMembers :: Finite a => [a]
                         twiceMembers  = members ++ members


Formal definition:
------------------
The  examples  above  describe  the  motivation  for  the  monomorphism
restriction, captured by the following definition:

Dictionary variables will not  be  used  as  extra  parameters  in  the
definition of a value in a given declaration group G if:

   either:  G includes a pattern binding

       or:  G includes a variable declaration, but does not include  an
            explicit type signature for any of  the  variables  in  the
            group.

If neither of these conditions hold, then equivalent sets of dictionary
parameters will be added to each declaration in the group.

.pa
.>appx_a
.ST APPENDIX A: SUMMARY OF GRAMMAR

This section gives a summary of the grammar for the  language  used  by
Gofer.  The non-terminals <interp> and <module> describe the syntax  of
expressions that can be entered into the Gofer interpreter and that  of
files of definitions that can be loaded into Gofer respectively.

The following notational conventions are used in the Grammar  which  is
specified using a variant of BNF:

  o <angle brackets> are used to distinguish names of nonterminals from
    keywords.

  o vertical | bars  are used to separate alternatives.

  o {braces} enclose items which may be repeated zero or more times.

  o [brackets] are used for optional items.

  o (parentheses) are used for grouping.

  o "quotes" surround characters which might otherwise be confused with
    the notations introduced above.

The following terminal symbols are used but not defined by the grammar:

  VARID    identifier beginning with lower case letter as described in
           section 6.
  CONID    like VARID, but beginning with upper case letter.
  VAROP    operator symbol not beginning with a colon, as described in
           section 6.
  CONOP    constructor function operator, like VAROP, but beginning
           with a colon character.
  INTEGER  integer constant, as described in section 7.3.
  FLOAT    floating point constant, as described in section 7.4.
  CHAR     character constant, as described in section 7.5.
  STRING   string constant, as described in section 7.7.


Top-level grammar
-----------------

    <module>   ::= "{" <topdecls> "}"               module

    <interp>   ::= <exp> [<where>]                  top-level expression

    <topdecls> ::= <topdecls>; <topdecls>           multiple declarations
                |  data <typeLhs> = <constrs>       datatype declaration
                |  type <typeLhs> = <type>          synonym declaration
                |  infixl [<digit>] <op> {, <op>}   fixity declarations
                |  infixr [<digit>] <op> {, <op>}
                |  infix  [<digit>] <op> {, <op>}
                |  primitive <prims> :: <type>      primitive bindings
                |  <class>                          class declaration
                |  <inst>                           instance declaration
                |  <decls>                          value declarations

    <typeLhs>  ::= CONID {VARID}                    type declaration lhs

    <constrs>  ::= <constrs> "|" <constrs>          multiple constructors
                |  <type> CONOP <type>              infix constructor
                |  CONID {<type>}                   constructor, n>=0

    <prims>    ::= <prims>, <prims>                 multiple bindings
                |  <var> <string>                   primitive binding

Type expressions
----------------

    <sigType>  ::= [<context> => ] <type>           [qualified] type

    <context>  ::= "(" [<pred> {, <pred>}] ")"      general form
                |  <pred>                           singleton context
    <pred>     ::= CONID <type> {<type>}            predicate

    <type>     ::= <ctype> [ -> <type> ]            function type
    <ctype>    ::= CONID {<atype>}                  datatype or synonym
                |  <atype>
    <atype>    ::= VARID                            type variable
                |  "(" ")"                          unit type
                |  "(" <type> ")"                   parenthesised type
                |  "(" <type>,<type> {,<type>} ")"  tuple type
                |  "[" <type> "]"                   list type

Class and instance declarations
-------------------------------

    <class>    ::= class [<context> =>] <pred> [<cbody>]
    <cbody>    ::= where "{" <cdecls> "}"           class body
    <cdecls>   ::= <cdecls>; <cdecls>               multiple declarations
                |  <var> {, <var>} :: <type>        member functions
                |  <fun> <rhs> [<where>]            default bindings

    <inst>     ::= instance [<context> =>] <pred> [<ibody>]
    <ibody>    ::= where "{" <idecls> "}"           instance body
    <idecls>   ::= <idecls>; <idecls>               multiple declarations
                |  <fun> <rhs> [<where>]            member definition

Value declarations
------------------

    <decls>  ::= <decls>; <decls>                 multiple declarations
              |  <var> {, <var>} :: <sigType>     type declaration
              |  <fun> <rhs> [<where>]            function binding
              |  <pat> <rhs> [<where>]            pattern binding

    <rhs>    ::= = <exp>                          simple right hand side
              |  <gdRhs> {<gdRhs>}                guarded right hand sides

    <gdRhs>  ::= "|" <exp> = <exp>                guarded right hand side

    <where>  ::= where "{" <decls> "}"            local definitions

    <fun>    ::= <var>                            function of arity 0
              |  <pat> <varop> <pat>              infix operator
              |  "(" <pat> <varop> ")"            section-like notation
              |  "(" <varop> <pat> ")"
              |  <fun> <apat>                     function with argument
              |  "(" <fun> ")"                    parenthesised lhs

Expressions
-----------

    <exp>    ::= \ <apat> {<apat>} -> <exp>       lambda expression
              |  let "{" <decls> "}" in <exp>     local definition
              |  if <exp> then <exp> else <exp>   conditional expression
              |  case <exp> of "{" <alts> "}"     case expression
              |  <opExp> :: <sigType>             typed expression
              |  <opExp>
    <opExp>  ::= <opExp> <op> <opExp>             operator application
              |  <pfxExp>
    <pfxExp> ::= - <appExp>                       negation
              |  <appExp>
    <appExp> ::= <appExp> <atomic>                function application
              |  <atomic>
    <atomic> ::= <var>                            variable
              |  <conid>                          constructor
              |  INTEGER                          integer literal
              |  FLOAT                            floating point literal
              |  CHAR                             character literal
              |  STRING                           string literal
              |  "(" ")"                          unit element
              |  "(" <exp> ")"                    parenthesised expr.
              |  (<exp> <op>)                     sections
              |  (<op> <exp>)
              |  "[" <list> "]"                   list expression
              |  "(" <exp>, <exp> {, <exp>} ")"   tuple

    <list>   ::= [ <exp> {, <exp>} ]              enumerated list
              |  <exp> "|" <quals>                list comprehension
              |  <exp> ..                         arithmetic sequence
              |  <exp>, <exp> ..
              |  <exp> .. <exp>
              |  <exp>, <exp> .. <exp>
    <quals>  ::= <quals>, <quals>                 multiple qualifiers
              |  <pat> <- <exp>                   generator
              |  <pat> = <exp>                    local definition
              |  <exp>                            boolean guard

    <alts>   ::= <alts>; <alts>                   multiple alternatives
              |  <pat> <altRhs> [<where>]         alternative
    <altRhs> ::= -> <exp>                         single alternative
              |  <gdAlt> {<gdAlt>}                guarded alternatives
    <gdAlt>  ::= "|" <exp> -> <exp>               guarded alternative

Patterns
--------

    <pat>    ::= <pat> <conop> <pat>              operator application
              |  <var> + <integer>                (n+k) pattern
              |  <appPat>
    <appPat> ::= <appPat> <apat>                  application
              |  <apat>
    <apat>   ::= <var>                            variable
              |  <var> @ <pat>                    as pattern
              |  ~ <pat>                          irrefutable pattern
              |  _                                wildcard
              |  <conid>                          constructor
              |  INTEGER                          integer literal
              |  CHAR                             character literal
              |  STRING                           string literal
              |  "(" ")"                          unit element
              |  "(" <pat> ")"                    parenthesised expr.
              |  (<pat> <conop>)                  sections
              |  (<conop> <pat>)
              |  "[" [ <pat> {, <pat>} ] "]"      list
              |  "(" <pat>, <pat> {, <pat>} ")"   tuple

Variables and operators
-----------------------

    <var>    ::= <varid>  |  "(" - ")"            variable
    <op>     ::= <varop>  |  <conop>   |  -       operator

    <varid>  ::= VARID    |  "(" VAROP ")"        variable identifier
    <varop>  ::= VAROP    |  ` VARID `            variable operator

    <conid>  ::= CONID    |  "(" CONOP ")"        constructor identifier
    <conop>  ::= CONOP    |  ` CONID `            constructor operator

.pa
.>appx_b
.ST APPENDIX B: CONTENTS OF STANDARD PRELUDE

.in ../standard.prelude
.pa
.>appx_c
.ST APPENDIX C: RELATIONSHIP WITH HASKELL 1.1

The language supported by Gofer is both syntactically and  semantically
similar to that of  the  functional  programming  language  Haskell  as
defined in the report  for  Haskell  version  1.1  [5].   This  section
details the differences between the two languages, outlined briefly  in
section 2.

.cc 5
Haskell features not included in Gofer:
---------------------------------------
  o  Modules

  o  Arrays

  o  Derived instances for standard classes -- the ability to construct
     instances of particular classes automatically.

  o  Default mechanism for eliminating unresolved overloading involving
     numeric and standard classes.   Since  Gofer  is  an  experimental
     system, it can be  used  with  a  range  of  completely  different
     prelude files; there is no concept of `standard classes'.

  o  Overloaded numeric constants.  In  the  absence  of  a  defaulting
     mechanism  as  mentioned  in  the  previous  item,  problems  with
     unresolved overloading make implicitly typed programming involving
     numeric constants impractical in an interpreter based system.

  o  Full range of numeric types  and  classes.   Gofer  has  only  two
     primitive numeric types Int and Float (the second of which is  not
     supported in the PC version).  Although is would  be  possible  to
     modify the standard prelude so that  Gofer  uses  the  same  class
     hierarchy as Haskell, this is unnecessarily sophisticated for  the
     intended uses of Gofer.

  o  Datatype definitions in Haskell may involve class constraints such
     as:

              data  Ord a => Set a = Set [a]

     It is  not  clear  how  such  constraints  should  be  interpreted
     (particularly in the light of the  extended  form  of  constraints
     used by Gofer) in such a way to  make  them useful whilst avoiding
     unwanted ambiguity problems.


.cc 5
Gofer features not supported in Haskell:
----------------------------------------
  o  Type classes may have multiple parameters.

  o  Predicates  in  type  expressions  may  involve   arbitrary   type
     expressions, not just type variables as used in Haskell.

  o  Instances of type classes can be defined at  non-overlapping,  but
     otherwise arbitrary types, as described in section 14.2.5.

  o  List comprehensions  may include  local definitions,  specified by
     qualifiers of the form <pat>=<expr> as described in section 10.2.

  o  No restrictions are placed on the form of predicates  that  appear
     in the context for a class or instance declaration.   This  has  a
     number  of  consequences,  including  the  possibility  of   using
     (mutually)  recursive  groups  of  dictionaries,  but  means  that
     decidability of the predicate entailment  relation  may  be  lost.
     This is not a great problem  in  practice,  since  all  dictionary
     construction  is  performed  before  evaluation   and   supposedly
     non-terminating dictionary constructions will actually generate an
     error due to the limited amount of  space  available  for  holding
     dictionaries (see section 14.4.2).


.cc 5
Other differences:
------------------
  o  Whilst superficially similar the approach to type classes in Gofer
     is quite different from that used in Haskell.  In particular,  the
     approach used in Gofer ensures that all necessary dictionaries are
     constructed before the evaluation of an expression begins,  rather
     than being built (possibly several times) during the evaluation as
     is the case with Haskell.  See section 14 and reference  [11]  for
     further details.

  o  Input/Output facilities - Gofer supports  only  a  subset  of  the
     requests available in Haskell.  In principle, it should not be too
     difficult to add most of the remaining forms of request (with  the
     exception of those associated with binary files)  to  Gofer.   The
     principal motivation for including the I/O facilities in Gofer was
     to  make  it  possible  to  experiment  with  simple   interactive
     programs.

  o  In Gofer, unary minus has greater  precedence  than  any  operator
     symbol, but lower than that of function application.  In  Haskell,
     the precedence of unary minus is the same as  that  of  the  infix
     (subtraction) operator of the same name.

  o  In Haskell, the character `-'  can  only  be  used  as  the  first
     character of an operator symbol.  In  Gofer,  this  character  may
     appear  in  any  position  in  an  operator  (except  for  symbols
     beginning with "--", which indicates the start of a comment).  The
     only problems that I am aware  of  with  this  is  that  a  lambda
     expression such as "\-2->2" will be parsed as such  by  a  Haskell
     system, but cause a syntax error in Gofer.  This  form  of  lambda
     expression is sufficiently unusual that I do not believe this will
     cause any problems in practice; in any case, the  parsing  problem
     can be solved by inserting a space: "\ -2->2".

  o  Pattern bindings are not currently permitted in either instance or
     class declarations.  This restriction has  been  made  simply  for
     ease of implementation, is not an inherent problem with  the  type
     class system and is likely to be  relaxed  in  later  versions  of
     Gofer if appropriate.  I have yet to see any examples in which the
     lack of pattern bindings in class and instance declarations causes
     any kind of deficiency.

  o  Qualified  type  signatures  are  not  permitted  for  the  member
     functions  in  Gofer  class  declarations.    Once   again,   this
     restriction was made for ease of implementation  rather  than  any
     pressing technical issues.  It is  likely  that  this  restriction
     will be relaxed in future versions of Gofer,  although  I  am  not
     convinced that proper use can be made  of  such  member  functions
     without some form of nested instance declarations (yuk!).

  o  The definition of the class Text given  in  the  standard  prelude
     does not include the Haskell functions for reading/parsing  values
     from strings; the only reason for omitting these functions was  to
     try to avoid unnecessary complexity in the standard prelude.   The
     standard prelude  can  be  modified  to  include  the  appropriate
     additional definitions if these are required.


.cc 5
Known problems in Gofer:
------------------------
  o  The null escape sequence "\&" is not generated  in  the  printable
     representations of strings produced by both the primitive function
     primPrint (used to implement the show' function) and  the  version
     of show defined in the standard prelude.  This means that  certain
     strings values are  not printed correctly  e.g.  show' "\245\&123"
     produces the string "\245123".  This is unlikely to cause too many
     problems in practice.

  o  Unification of a type variable a with a  type  expression  of  the
     form T a where T is  a  synonym  name  whose  expansion  does  not
     involve a will fail.   It  is  not  entirely  clear  whether  this
     behaviour is correct or not.

  o  Formfeeds '\f' and vertical tabs '\v' are  not  treated  as  valid
     whitespace characters in the way suggested by the Haskell  report.

  o  Inability to recover from program stack  overlow  errors  in  some
     situations.  This problem only affects the  PC  implementation  of
     Gofer.

  o  Implementation of ReadFile may lose referential transparency;  the
     response to a particular ReadFile request may  be  affected  by  a
     later WriteFile or AppendFile request for the same  file.   Whilst
     this problem can be solved for UNIX based implementations, I  have
     not yet found a portable solution suitable for all of the  systems
     on which Gofer can be used.


.cc 5
Areas for possible future improvement:
--------------------------------------
  o  Relaxing the restriction on type synonyms in predicates.

  o  General  purpose  automatic  default  mechanism  for   eliminating
     certain forms of unresolved overloading.

  o  Improved checking and use of superclass and  instance  constraints
     during static analysis and type checking.

  o  Simple facility to force dictionary construction at load-time.

  o  Provision for shell escapes :! etc within the Gofer interpreter.

  o  Debugging  facilities,  including  breakpoints  and  tracing  from
     within interpreter.

  o  Separate interpreter and compiler programs for creating standalone
     applications using Gofer.
.pa
.>appx_d
.ST APPENDIX D: USING GOFER WITH BIRD+WADLER

Bird and Wadler's textbook  [1]  gives  an  excellent  introduction  to
functional programming, providing an insight into both basic techniques
and matters of programming style as well as describing  the  underlying
mathematics and its use for program development and  derivation.   Most
of the programs in that book can be used with Gofer although there  are
a number of differences between the two notations.  Fortunately, it  is
not difficult to  translate  from  one  notation  to  the  other.   The
following points are particularly useful for this:

  o  Type constructors in Gofer  begin with capital letters (e.g. Bool,
     Char etc..) where lower case is used in  [1]  (e.g.   bool,  char,
     etc..).  Note that Gofer has no general numeric type "num" as used
     in [1];  Use  either  Int,  Float,  or  overloading  in  Gofer  as
     appropriate.

  o  Datatype definitions in [1] are written in the form lhs::=constrs.
     The equivalent definition in Gofer is: data lhs = constrs.

     Similarly, a type synonym definition in [1] of the form lhs == rhs
     can be written in Gofer as: type lhs = rhs.

  o  The differences between the syntax used for  guarded equations  in
     Gofer compared with the notation used in  [1]  have  already  been
     discussed in section 9.2.  For example:

     Using the notation of [1]:       Using Gofer:

     filter p (x:xs)                  filter p (x:xs)
       = x : filter p xs, if p x         | p x       = x : filter p xs
       = filter p xs,     otherwise      | otherwise = filter p xs

  o  In Gofer,  list comprehension qualifiers  are separated by  commas
     rather than semicolons as used in [1].

  o  A number of the  function names and types in the  standard prelude
     are different:

             [1]         Gofer            [1]         Gofer
             ---         -----            ---         ----
             (#)         length           takewhile   takeWhile
             (~)         not              dropwhile   dropWhile
             (/\)        (&&)             zipwith     zipWith
             (\/)        (||)             swap        flip
             (!)         (!!)             in          elem
             (--)        (\\)             scan        scanl
             hd          head             some        any
             tl          tail             listmin     minimum
             decode      chr              listmax     maximum
             code        ord

     See appendix B for a complete list of standard functions in Gofer.

     The version of foldl  using  "strict"  which  appears  in  [1]  is
     available in Gofer as the function "foldl'".

     The role of "zip" and "zipwith" in [1] is filled by the "zip"  and
     "zipWith" families of functions in Gofer.  An  expression  of  the
     form "zip (xs,ys)" in [1] is equivalent to "zip xs  ys"  in  Gofer
     etc...

  o  Gofer does not enforce the condition assumed in [1] that the  left
     hand sides of each of the equations defining a  function  must  be
     disjoint.

  o  The equality operator in Gofer is written as  "=="  and the single
     equality character "=" is a reserved symbol used to separate  left
     and right hand sides of equations.  Many  C  programmers  will  be
     familiar with this kind of notation (together with  the  kinds  of
     problems it can create!).

  o  Some of the  identifiers used in  [1] are reserved words in Gofer.
     Examples that are particularly likely to occur  include  "in"  and
     "then".
.pa
.>appx_e
.ST APPENDIX E: PRIMITIVES

[WARNING: The features described in this appendix  are  typically  only
needed when alternative versions of the standard prelude  are  created.
These features should only be used by expert users; misuse may lead  to
failure and runtime errors in the Gofer interpreter.  It is not usually
a good idea to use primitive functions directly in your programs.]

A number of primitive functions are builtin to the  Gofer  interpreter,
and may be bound to function symbols using a declaration of the form:

    primitive name1 code1, name2 code2, ...., namen coden :: type

where each name is an identifier (or an  operator  symbol  enclosed  by
parentheses) and each code is a string literal  taken  from  the  table
below.  The type specified to the right of the  ::  symbol  must  be  a
valid type for the functions being defined -- WARNING: GOFER  DOES  NOT
ATTEMPT TO CHECK FOR SUITABILITY OF THE DECLARED TYPE.   The  following
definition, taken from the standard prelude,  illustrates  the  use  of
this feature to bind  a  function  named  primPrint  to  the  primitive
function with code name string "primPrint" and type Int -> a ->  String
-> String:

    primitive primPrint "primPrint"  :: Int -> a -> String -> String

The primitive functions currently available are:

category     code name string    type
--------     ----------------    ----

integer      primPlusInt         Int -> Int -> Int 
arithmetic   primMinusInt        Int -> Int -> Int
             primMulInt          Int -> Int -> Int
             primDivInt          Int -> Int -> Int
             primModInt          Int -> Int -> Int
             primRemInt          Int -> Int -> Int
             primNegInt          Int -> Int -> Int


floating     primPlusFloat       Float -> Float -> Float
point        primMinusFloat      Float -> Float -> Float
arithmetic   primMulFloat        Float -> Float -> Float
             primDivFloat        Float -> Float -> Float
             primNegFloat        Float -> Float -> Float


coercion     primIntToChar       Int -> Char  -- chr in the standard prelude
functions    primCharToInt       Char -> Int  -- ord in the standard prelude
             primIntToFloat      Int -> Float -- implements fromInteger

equality     primEqInt           Int -> Int -> Bool
and <=       primLeInt           Int -> Int -> Bool
primitives   primEqFloat         Float -> Float -> Bool
             primLeFloat         Float -> Float -> Bool


.cc 5
generic      primGenericEq       a -> a -> Bool
ordering     primGenericNe       a -> a -> Bool
primitives   primGenericGt       a -> a -> Bool
             primGenericLe       a -> a -> Bool
             primGenericGe       a -> a -> Bool
             primGenericLt       a -> a -> Bool

             These functions implement the standard generic  (i.e.  non
             overloaded) ordering primitives.  They are  not  currently
             used in the standard prelude.  A simplified prelude may be
             created by binding the  standard  operator  symbols  (==),
             (/=),  (>),  (<=),  (>=)  and  (<)  to   these   functions
             respectively.

output       primPrint           Int -> a -> String -> String

             This function is used to implement the show'  function  in
             the standard prelude and is not usually used directly.

             primPrint d e s produces a textual representation  of  the
             value of the expression e as a  string,  followed  by  the
             string s.  The integer parameter d is used as an indicator
             of the current precedence level.  The  primPrint  function
             is the  standard  method  of  printing  the  value  of  an
             expression whose type is not equivalent to the type String
             used by the top-level of the Gofer interpreter.

sequencing   primStrict          (a -> b) -> a -> b

             The primStrict function (bound to the identifier  "strict"
             in the standard prelude)  forces  the  evaluation  of  its
             second argument before the function supplied as the  first
             argument is  applied  to  it.   See  section  9.4  for  an
             illustration.

.pa
.>appx_f
.ST APPENDIX F: INTERPRETER COMMAND SUMMARY

Command      Description
-------      -----------
<expr>       Analyse expression for errors, typecheck and evaluate.  If
             the expression has type Dialogue,  execute  as  a  program
             using the I/O facilities as described in section  12.   If
             the expression has type String, evaluate and print  result
             as a lazy list of characters.   In  any  other  case,  the
             standard  prelude  function  show'  is  applied   to   the
             expression and used to print the value of  the  result  in
             the form of a string, as in the previous case.

:t <expr>    Analyse expression for errors,  typecheck  and  print  the
:type <expr> translation and inferred type of the term.
:T

:q           Exit Gofer interpreter.
:quit
:Q

:?           Display summary of interpreter commands.
:h
:H

:l f1 .. fn  Removes any previously loaded  files  of  definitions  and
             attempts to load the contents of the files f1 upto fn  one
             after the other.

:L           Remove any previously loaded files of  definitions.   Only
             those functions and values defined in the standard prelude
             will still be be available.

:load        Equivalent forms of the :l command.
:L

:a f1 .. fn  Load the contents of the files f1 upto fn in  addition  to
             any previously loaded files.   If  any  of  the  files  of
             definitions which  have  already  been  loaded  have  been
             modified  since  they  were   last  read   then  they  are
             automatically reloaded before any of the files f1 upto  fn
             are read.

             If successful, a command of  the  form  ":l  f1  ..fn"  is
             equivalent to the sequence of commands:
                               :l
                               :a f1
                                .
                                .
                               :a fn

:also        Equivalent forms of the :a command.
:A

:r           Repeat the last load command,  attempting  to  reload  any
             files which have subsequently been modified.  Since  later
             files may depend on the definitions in earlier ones,  once
             one file has been reloaded, all subsequent files will also
             need to be reloaded.

:reload      Equivalent forms of the :r command.
:R

:e file      Suspend current Gofer session and start an editor  program
             to modify or view the named file.  The Gofer session  will
             be resumed when the editor  program  terminates,  and  any
             script files that  have  been  changed  will  be  reloaded
             automatically.

             Note that a separate editor program is required  and  that
             Gofer must be properly installed to use this feature.  The
             default editor is usually vi (Calvin version 2.0 is a good
             substitute for a PC), although this may have been  changed
             when your system was installed.   In  any  case,  you  can
             always substitute an editor of your choice by setting  the
             environment variable EDITOR to the name of your  favourite
             editor program.

             There are a number  of  factors  which  will  affect  your
             choice of editor.  On a slow machine, with only a  limited
             amount of memory, you  will  probably  need  to  choose  a
             relatively small editor which  can  be  loaded  reasonably
             quickly and does not require too much memory.  On  a  more
             powerful system, you may find it more  convenient  to  use
             Gofer from a window based environment, running your editor
             in one window with Gofer in another.

:e           Using the :e command without specifying a particular  file
             to be edited starts up  an  editor  program  as  described
             above either for the file  of  definitions  most  recently
             loaded into Gofer or, if an error occurred whilst  loading
             a file of definitions, for  the  file  of  definitions  in
             which the error was last detected.

             With many editor programs, it is even  possible  to  start
             the editor at the  line  where  the  error  occurred.   As
             before, it is possible to change the default behaviour  of
             Gofer in this case by  setting  the  environment  variable
             EDITLINE to a command string which can be  used  to  start
             the editor program with a given file at  a  specific  line
             number.  The positions in the string  at  which  the  file
             name and line number values should be inserted  should  be
             indicated by the strings "%s" and "%d"  respectively,  and
             may appear in either order.  The default  command  string,
             which is used if EDITLINE is not set is "vi +%d %s".

:edit        Equivalent forms of the :e command.
:E
.pa
.>appx_g
.ST APPENDIX G: BIBLIOGRAPHY

[1]  Introduction to functional programming, Richard  Bird  and  Philip
     Wadler, Prentice Hall International, 1989.

[2]  The Implementation of functional programming languages,  Simon  L.
     Peyton Jones, Prentice Hall International, 1987.

[3]  Lambda Lifting:  Transforming  Programs  to  Recursive  Equations,
     Thomas  Johnsson,  in  Lecture  Notes  in  Computer  Science  201,
     Springer Verlag, 1985.  [but try to get a copy of the  version  of
     this paper included in Johnsson's thesis which  benefits  from  an
     extended typeface and is a little easier to read!]

[4]  How to make ad-hoc polymorphism less  ad-hoc,  Philip  Wadler  and
     Stephen Blott, University of Glasgow, in the  proceedings  of  the
     16th ACM annual symposium on Principles of Programming  Languages,
     Austin, Texas, January 1989.

[5]  Report on the programming language Haskell,  a  non-strict  purely
     functional language (Version 1.1), Paul Hudak,  Philip  Wadler  et
     al.  Technical report Yale University/Glasgow University.  August,
     1991.

[6]  Introduction to Orwell 6.00, Philip  Wadler  and  Quentin  Miller,
     University of Oxford, 1990.

[7]  Lazy ML user's manual, Lennart  Augustsson  and  Thomas  Johnsson,
     1990.

[8]  Computing with lattices: An application of type classes,  Mark  P.
     Jones, Technical report PRG-TR-11-90, Programming Research  Group,
     Oxford University Computing Laboratory, June 1990.

[9]  Towards a theory of qualified  types,  Mark  P.  Jones,  Technical
     report PRG-TR-6-91, Programming Research Group, Oxford  University
     Computing Laboratory, April 1991.

[10] Type inference for  qualified  types,  Mark  P.  Jones,  Technical
     report PRG-TR-10-91, Programming Research Group, Oxford University
     Computing Laboratory, June 1991.

[11] A new approach to type classes,  Mark  P.  Jones,  distributed  to
     Haskell mailing list 1991.

[12] Practical issues in the implementation of qualified types, Mark P.
     Jones, Forthcoming 1991.
