Empty log message
authorSimon Peyton Jones <simonpj@microsoft.com>
Wed, 28 Mar 2001 15:04:23 +0000 (15:04 +0000)
committerSimon Peyton Jones <simonpj@microsoft.com>
Wed, 28 Mar 2001 15:04:23 +0000 (15:04 +0000)
98 files changed:
libraries/Makefile [new file with mode: 0644]
libraries/README [new file with mode: 0644]
libraries/array.verb [new file with mode: 0644]
libraries/char.verb [new file with mode: 0644]
libraries/code/Array.hs [new file with mode: 0644]
libraries/code/Char.hs [new file with mode: 0644]
libraries/code/Complex.hs [new file with mode: 0644]
libraries/code/IO.hs [new file with mode: 0644]
libraries/code/Ix.hs [new file with mode: 0644]
libraries/code/List.hs [new file with mode: 0644]
libraries/code/Locale.hs [new file with mode: 0644]
libraries/code/Maybe.hs [new file with mode: 0644]
libraries/code/Monad.hs [new file with mode: 0644]
libraries/code/Numeric.hs [new file with mode: 0644]
libraries/code/Random.hs [new file with mode: 0644]
libraries/code/Ratio.hs [new file with mode: 0644]
libraries/code/Time.hs [new file with mode: 0644]
libraries/complex.verb [new file with mode: 0644]
libraries/cputime.verb [new file with mode: 0644]
libraries/directory.verb [new file with mode: 0644]
libraries/h98-libs.gif [new file with mode: 0644]
libraries/h98-libs.ppt [new file with mode: 0644]
libraries/headers/Array.hs [new file with mode: 0644]
libraries/headers/CPUTime.hs [new file with mode: 0644]
libraries/headers/Char.hs [new file with mode: 0644]
libraries/headers/Complex.hs [new file with mode: 0644]
libraries/headers/Directory.hs [new file with mode: 0644]
libraries/headers/IO.hs [new file with mode: 0644]
libraries/headers/IO1.hs [new file with mode: 0644]
libraries/headers/Ix.hs [new file with mode: 0644]
libraries/headers/List.hs [new file with mode: 0644]
libraries/headers/List1.hs [new file with mode: 0644]
libraries/headers/Locale.hs [new file with mode: 0644]
libraries/headers/Maybe.hs [new file with mode: 0644]
libraries/headers/Monad.hs [new file with mode: 0644]
libraries/headers/Numeric.hs [new file with mode: 0644]
libraries/headers/Random.hs [new file with mode: 0644]
libraries/headers/Ratio.hs [new file with mode: 0644]
libraries/headers/System.hs [new file with mode: 0644]
libraries/headers/Time.hs [new file with mode: 0644]
libraries/headers/Time1.hs [new file with mode: 0644]
libraries/html.config [new file with mode: 0644]
libraries/index-intro.verb [new file with mode: 0644]
libraries/index.html [new file with mode: 0644]
libraries/introduction.verb [new file with mode: 0644]
libraries/io.verb [new file with mode: 0644]
libraries/ix.verb [new file with mode: 0644]
libraries/library.verb [new file with mode: 0644]
libraries/list.verb [new file with mode: 0644]
libraries/locale.verb [new file with mode: 0644]
libraries/maybe.verb [new file with mode: 0644]
libraries/monad.verb [new file with mode: 0644]
libraries/numeric.verb [new file with mode: 0644]
libraries/random.verb [new file with mode: 0644]
libraries/ratio.verb [new file with mode: 0644]
libraries/system.verb [new file with mode: 0644]
libraries/time.verb [new file with mode: 0644]
report/Makefile [new file with mode: 0644]
report/Prelude.hs [new file with mode: 0644]
report/PreludeIO.hs [new file with mode: 0644]
report/PreludeList.hs [new file with mode: 0644]
report/PreludeText.hs [new file with mode: 0644]
report/README [new file with mode: 0644]
report/basic.verb [new file with mode: 0644]
report/classes.eps [new file with mode: 0644]
report/classes.gif [new file with mode: 0644]
report/classes.ppt [new file with mode: 0644]
report/decls.verb [new file with mode: 0644]
report/derived.verb [new file with mode: 0644]
report/exps.verb [new file with mode: 0644]
report/h98.gif [new file with mode: 0644]
report/h98.ppt [new file with mode: 0644]
report/haskell.bbl [new file with mode: 0644]
report/haskell.verb [new file with mode: 0644]
report/html.config [new file with mode: 0644]
report/index-extra.verb [new file with mode: 0644]
report/index-intro.verb [new file with mode: 0644]
report/index.html [new file with mode: 0644]
report/intro.verb [new file with mode: 0644]
report/io-13.verb [new file with mode: 0644]
report/iso-chars.verb [new file with mode: 0644]
report/lambda.gif [new file with mode: 0644]
report/layout.verb [new file with mode: 0644]
report/lexemes.verb [new file with mode: 0644]
report/literate.verb [new file with mode: 0644]
report/modules.verb [new file with mode: 0644]
report/plain_haskell.verb [new file with mode: 0644]
report/pragmas.verb [new file with mode: 0644]
report/preface-13.verb [new file with mode: 0644]
report/prelude-index.idx [new file with mode: 0644]
report/standard-prelude.verb [new file with mode: 0644]
report/syntax-iso.verb [new file with mode: 0644]
report/syntax-lexical.verb [new file with mode: 0644]
tools/Makefile [new file with mode: 0644]
tools/index.hs [new file with mode: 0644]
tools/splitAndIndexPgm [new file with mode: 0644]
tools/tex.hs [new file with mode: 0644]
tools/verbatim.lex [new file with mode: 0644]

diff --git a/libraries/Makefile b/libraries/Makefile
new file mode 100644 (file)
index 0000000..9ef4d70
--- /dev/null
@@ -0,0 +1,159 @@
+# Makefile for the Haskell Library Report
+# read the README file before you start!
+#
+
+# Begin by saying
+#      touch library.idx
+
+default: library.ps html
+
+
+#########################################
+#      Tools you need
+#########################################
+
+# Stuf from the tools/directory
+RUN_TEX   = ../tools/run_tex
+RUN_INDEX = ../tools/run_index
+VERBATIM  = ../tools/verbatim
+
+# splitAndIndexPgm won't work unless you have "perl"
+SPLITPGM = perl ../tools/splitAndIndexPgm
+
+CC    = gcc
+RM    = rm -f
+LATEX = latex
+MAKEINDEX = makeindex
+
+# 'expand' expands tabs to spaces
+# On my machine the windows program (which does something
+# quite different) shadows it.  Sigh.
+EXPAND = expand
+
+
+#########################################
+#      Files
+#########################################
+
+# I've been having problems with that damn NT messing up filenames in the html
+# generator so I'm changing the .verb files to lower case  -- jcp
+
+PARTS =                library.tex introduction.tex ratio.tex complex.tex ix.tex \
+                numeric.tex \
+                array.tex io.tex char.tex monad.tex list.tex \
+                system.tex directory.tex \
+                maybe.tex time.tex cputime.tex random.tex \
+               locale.tex 
+
+CODE =         code/Ratio.tex code/Complex.tex code/Ix.tex \
+                code/Numeric.tex \
+                code/Array.tex code/Char.tex code/List.tex \
+                code/Monad.tex code/Maybe.tex code/IO.tex \
+               code/Time.tex code/Locale.tex
+
+CODEV =                code/Ratio.verb code/Complex.verb code/Ix.verb \
+                code/Numeric.verb \
+                code/Array.verb code/Char.verb code/List.verb \
+                code/Monad.verb code/Maybe.verb code/IO.verb code/Bit.verb \
+               code/Time.verb code/Locale.verb
+
+HEADERS =      headers/Ratio.tex headers/Complex.tex headers/Ix.tex \
+                headers/Numeric.tex \
+                headers/Array.tex headers/IO.tex headers/Char.tex \
+               headers/List.tex headers/List1.tex \
+                headers/Monad.tex headers/System.tex headers/Directory.tex \
+                headers/Maybe.tex headers/IO1.tex headers/Random.tex \
+               headers/Time.tex headers/Time1.tex headers/CPUTime.tex \
+               headers/Locale.tex 
+
+HEADERSV =     headers/Ratio.verb headers/Complex.verb headers/Ix.verb \
+                headers/Numeric.verb \
+                headers/Array.verb headers/IO.verb headers/Char.verb \
+               headers/List.verb headers/List1.verb \
+                headers/Monad.verb headers/System.verb headers/Directory.verb \
+                headers/Maybe.verb headers/IO1.verb headers/Random.verb \
+               headers/Time.verb headers/CPUTime.verb \
+               headers/Locale.verb 
+
+# The normally formatted report -- 2 sided, one-up
+library.dvi: library.ind ${PARTS} ${CODE} ${HEADERS} index-intro.tex
+
+html: index.html ${PARTS} ${SYNTAX} ${PRELUDE}
+       -mkdir haskell98-library-html
+       $(RUN_TEX)
+       $(RUN_TEX)
+       cp *.gif index.html haskell98-library-html
+
+# remove this rule if you don't have "makeindex"
+library.ind: library.idx
+       makeindex -i -t library.ilg < library.idx > library.ind
+
+veryclean: clean
+       $(RM) *~ code/*~ headers/*~
+
+clean:
+       $(RM) *.dvi *.log *.aux *.ilg *.blg *.toc haskell.tex \
+               $(PARTS) $(CODE) $(HEADERS) \
+               library.ps library.pdf haskell98-library-html/*
+       cp library.ind library.ind.two-sided 
+       echo "Don't delete the Prelude*.tex files"
+       echo "Not everyone has \"perl\" to re-make them"
+
+
+# Stuff to make the "two-up" version for SIGPLAN Notices:
+# We take the A4 pages and double them up onto (virtual) A3 pages:
+# (two A5 pages make one A4 page; two A4 pages make one A3 page; ...)
+#
+#      % dvidvi '2:0,1(210mm,0)' haskell.dvi > haskell-2up.dvi
+#
+# We now print the "A3" pages in landscape, but "magnify" them by
+# 1 / sqrt(2) ~ 0.7071; this should make our "A4" pages print in an
+# A4 space: presto! 2up printing!
+# (except that I've tried to make it give us 1" margins all round
+#  when we print on US 8.5"x11" paper)
+#
+#      % dvips -t landscape -x 707 haskell-2up.dvi > haskell-2up.ps
+#
+# if your "dvips" is set up properly, it will run Metafont for you,
+# creating just-right magnifications for all the fonts.
+#
+# print with: lpr -Pmy-laserwriter haskell-2up.ps
+
+# These rules keep failing for me (segmentation fault on haskell-2up.dvi)
+# The output seems fine, though, and the individual commands work
+# perfectly(!).  More network wierdness?  KH
+
+
+verbs:  $(CODEV) $(HEADERSV)
+
+library.ps : library.dvi
+       dvips library.dvi -o library.ps
+
+
+publish: library.ps html
+       gzip < library.ps > y:Haskell/haskell98-library/library.ps.gz
+       cp haskell98-library-html/* y:Haskell/haskell98-library
+       tar cvf - haskell98-library-html | gzip > y:Haskell/haskell98-library/haskell98-library-html.tar.gz
+
+publish-pdf: library.pdf
+       gzip < library.pdf > y:Haskell/haskell98-library/library.pdf.gz
+
+
+#########################################
+#      Suffix rules
+#########################################
+
+.SUFFIXES:     .hs .verb .tex .dvi
+
+.verb.tex:
+       expand < $< | $(VERBATIM) >$@
+
+.hs.verb:
+       expand < $< | $(SPLITPGM) >$@
+
+.hs.tex:
+       expand < $< | $(SPLITPGM) | $(VERBATIM) >$@
+
+.tex.dvi:
+       $(LATEX) $<
+
diff --git a/libraries/README b/libraries/README
new file mode 100644 (file)
index 0000000..2f9946d
--- /dev/null
@@ -0,0 +1,116 @@
+
+This is the Haskell 98 library report, source distribution.  
+
+This has all files needed to generate either the postscript or the
+html version of the Haskell library report.  Some of these files are
+generated from others - these are marked with a (*) and are included in
+case the tool used to generate the file is unavailable.
+
+To generate the postscript library report you need lex, perl, latex,
+makeindex, and dvips.
+
+To generate the html library report you need Hugs 1.4 (probably any Haskell
+1.4 compiler will do).
+
+
+Source files: 
+  library.verb  -- Top level of the library report
+  introduction.verb
+  ratio.verb
+  complex.verb
+  numeric.verb
+  ix.verb
+  array.verb
+  list.verb
+  maybe.verb
+  char.verb
+  monad.verb
+  io.verb
+  directory.verb
+  system.verb
+  time.verb
+  locale.verb
+  cputime.verb
+  random.verb
+  index-intro.verb
+
+Haskell files:
+code/*.hs         -- executable versions of most libraries (IO incomplete),
+                  -- CPUTime, Random, Directory not included
+headers/*.hs      -- Lists all exported names from each library
+
+Tex generated files:
+  library.dvi (*) -- to make a .ps from
+  library.idx (*)
+  library.ind (*
+  library.aux (*) -- The aux file generated by latex; used by html translator
+
+Html support:
+
+tex.hs             -- Program to generate html from verb / hs
+html.config        -- configuration file for tex.hs.
+index.html         -- Html top level
+title.gif          -- title graphic 
+
+Other files:
+
+Makefile         -- Lots of extra cruft no longer used. 
+verbatim.lex     -- lex program to expand .verb into .tex
+splitAndIndexPgm -- perl script to convert .hs to .verb
+splitAndIndexPgm.kh -- an old perl script to convert .hs to .verb
+library.dvi (*)  -- in case you just want to run dvips
+library.ind (*)  -- is case you don't have makeindex 
+library.idx (*)  -- makes building easier
+
+
+To build the .dvi you need to patch the makefile to call the proper
+version of perl.  You will have some `non-grokked' instances in the
+perl.  Remember that you have to run latex twice.  If anyone converts
+the perl program to perl5 please send it to us!  Also, the indexing misses
+a few definitions.
+
+Report any problems to peterson-john@cs.yale.edu
+
+Building the HTML files
+~~~~~~~~~~~~~~~~~~~~~~~
+Build the html by creating a `html' subdirectory, copy the .html and
+.gif files to it, and run tex.hs twice (like tex - to get forward refs
+right).  
+
+Build the html by creating a `html' subdirectory, copy the .html and
+.gif files to it, and run tex.hs twice (like tex - to get forward refs
+right).  Run index.hs to generate the function index.  You're done.
+The 'make html' does most of this.
+
+There is one file you need to work on:
+
+       report/html.config
+
+Edit the title in the headers and footers. 
+You can hack in whatever html you want for page headers and
+footers .  You can also hack on the output directory setting (htmldir)
+to direct the output wherever you want.  You'll have to fiddle
+"index.hs" if you do this, though.  You can also add the line
+
+       style = microsoftsymbols,article
+
+This exploits the symbol font that microsoft uses in its browser.
+Much nicer for some of the equations.  Probably a good idea since most
+browsers handle the symbol font OK nowadays.
+
+As to the building process:
+
+To build the html library report: (using the .aux file and all the .verb files) 
+
+cd <library directory>
+runhugs tex.hs
+runhugs tex.hs
+
+Like latex, you have to run tex.hs twice.  Unless you make massive
+changes, though, you can probably just do it once.  I'm sure ghc will
+compile tex.hs if you want to speed things up. 
+
+Note there is no index.hs here.
+
+
+
diff --git a/libraries/array.verb b/libraries/array.verb
new file mode 100644 (file)
index 0000000..b71bb7c
--- /dev/null
@@ -0,0 +1,182 @@
+%**<title>The Haskell 98 Library Report: Arrays</title>
+%**~header
+\section{Arrays}
+\label{arrays}
+\index{array}
+
+\outline{
+\inputHS{headers/Array}
+}
+
+\Haskell{} provides indexable {\em arrays}, which may be thought of as
+functions whose domains are isomorphic to contiguous subsets of the
+integers.
+Functions restricted in this way can be
+implemented efficiently; in particular, a programmer may
+reasonably expect rapid access to the components.  To ensure
+the possibility of such an implementation, arrays are treated as data, not as
+general functions.
+
+Since most array functions involve the class @Ix@, this module is
+exported from @Array@ so that modules need not import both @Array@ and
+@Ix@. 
+
+\subsection{Array Construction}
+If @a@ is an index type and @b@ is any type, the type of arrays with
+indices in @a@ and elements in @b@ is written @Array a b@.\indextycon{Array}
+An array may be created by the function @array@\indextt{array}.
+The first argument of @array@ is a pair of {\em bounds}, each of the
+index type of the array.  These bounds are the lowest and
+highest indices in the array, in that order.  For example, a
+one-origin vector of length @10@ has bounds @(1,10)@, and a one-origin @10@
+by @10@ matrix has bounds @((1,1),(10,10))@.
+
+The second argument of @array@ is a list of {\em associations}
+of the form ($index$,~$value$).  Typically, this list will
+be expressed as a comprehension.  An association @(i, x)@ defines the
+value of the array at index @i@ to be @x@.  The array is undefined (i.e.~$\bot$) if
+any index in the list is out of bounds.  If any two associations in the
+list have the same index, the value at that index is undefined (i.e.~$\bot$).
+Because the indices must be checked for these errors, @array@ is
+strict in the bounds argument and in the indices of the association list,
+but nonstrict in the values.  Thus, recurrences such as the following are
+possible:
+\bprog
+@
+a = array (1,100) ((1,1) : [(i, i * a!(i-1)) | i <- [2..100]])
+@
+\eprog
+Not every index within the bounds of the array need
+appear in the association list, but the values associated with indices
+that do not appear will be undefined.
+Figure~\ref{array-examples} shows some examples that use the
+@array@ constructor.
+
+\begin{figure}[tb]
+\outline{
+@
+-- Scaling an array of numbers by a given number:
+scale :: (Num a, Ix b) => a -> Array b a -> Array b a
+scale x a = array b [(i, a!i * x) | i <- range b]
+           where b = bounds a
+
+-- Inverting an array that holds a permutation of its indices
+invPerm :: (Ix a) => Array a a -> Array a a
+invPerm a = array b [(a!i, i) | i <- range b]
+           where b = bounds a
+
+-- The inner product of two vectors
+inner :: (Ix a, Num b) => Array a b -> Array a b -> b
+inner v w = if b == bounds w
+               then sum [v!i * w!i | i <- range b]
+               else error "inconformable arrays for inner product"
+           where b = bounds v
+@
+}
+\ecaption{Array examples}
+\label{array-examples}
+\end{figure}
+
+The @(!)@\index{!@@{\tt {\char'041}}} operator denotes array subscripting.
+% array subscripting -- if the index lies outside the bounds of the
+% array, the result is undefined.  
+The @bounds@\indextt{bounds} function
+applied to an array returns its bounds.
+The functions @indices@\indextt{indices}, @elems@\indextt{elems}, and
+@assocs@,\indextt{assocs} when applied to an array, return lists of
+the indices, elements, or associations, respectively, in index order.
+An array may be constructed from a pair of bounds and a list
+of values in index order using the function @listArray@\indextt{listArray}.
+
+If, in any dimension, the lower bound is greater than the upper bound,
+then the array is legal, but empty.  Indexing an empty array always
+gives an array-bounds error, but @bounds@ still yields the bounds
+with which the array was constructed.
+
+\subsubsection{Accumulated Arrays}
+\index{array!accumulated}
+
+Another array creation function, @accumArray@,\indextt{accumArray}
+relaxes the restriction that a given index may appear at most once in
+the association list, using an {\em accumulating function} which
+combines the values of associations with the same index.
+% \cite{nikhil:id-nouveau,wadler:array-primitive}:
+The first argument of @accumArray@ is the accumulating function; the
+second is an initial value; the remaining two arguments are a bounds
+pair and an association list, as for the @array@ function.
+For example, given a list of values of some index type, @hist@
+produces a histogram of the number of occurrences of each index within
+a specified range:
+\bprog
+@
+hist :: (Ix a, Num b) => (a,a) -> [a] -> Array a b
+hist bnds is = accumArray (+) 0 bnds [(i, 1) | i<-is, inRange bnds i]
+@
+\eprog
+If the accumulating function is strict, then @accumArray@ is
+strict in the values, as well as the indices, in the
+association list.  Thus, unlike ordinary arrays,
+accumulated arrays should not in general be recursive.
+
+\subsection{Incremental Array Updates}
+\label{array-update}
+
+The operator @(//)@\indextt{//} takes an array and a list of pairs and returns
+an array identical to the left argument except that it has
+been updated by the associations in the right argument.  (As with
+the @array@ function, the indices in the association list must
+be unique for the updated elements to be defined.)  For example,
+if @m@ is a 1-origin, @n@ by @n@ matrix, then
+@m//[((i,i), 0) | i <- [1..n]]@ is the same matrix, except with
+the diagonal zeroed.
+
+@accum@\indextt{accum} "f" takes an array
+and an association list and accumulates pairs from the list into
+the array with the accumulating function "f".  Thus @accumArray@
+can be defined using @accum@:\nopagebreak[4]
+\bprog
+@
+accumArray f z b = accum f (array b [(i, z) | i <- range b])
+@
+\eprogNoSkip
+
+\subsection{Derived Arrays}
+\index{array!derived}
+
+The two functions @map@\indextt{map} and @ixmap@\indextt{ixmap}
+derive new arrays from existing ones; they may be
+thought of as providing function composition on the left and right,
+respectively, with the mapping that the original array embodies.
+The @map@ function transforms the array values while 
+@ixmap@ allows for transformations on array indices.
+Figure~\ref{derived-array-examples} shows some examples.
+
+\begin{figure}[tb]
+\outline{
+@
+-- A rectangular subarray
+subArray :: (Ix a) => (a,a) -> Array a b -> Array a b
+subArray bnds = ixmap bnds (\i->i)
+
+-- A row of a matrix
+row :: (Ix a, Ix b) => a -> Array (a,b) c -> Array b c
+row i x = ixmap (l',u') (\j->(i,j)) x where ((l,l'),(u,u')) = bounds x
+
+-- Diagonal of a square        matrix
+diag :: (Ix a) => Array (a,a) b -> Array a b
+diag x = ixmap (l,u) (\i->(i,i)) x
+        where ((l,l'),(u,u')) | l == l' && u == u'  = bounds x
+
+-- Projection of first components of an array of pairs
+firstArray :: (Ix a) => Array a (b,c) -> Array a b
+firstArray = map (\(x,y)->x)
+@
+}
+\ecaption{Derived array examples}
+\label{derived-array-examples}
+\end{figure}
+
+\subsection{Library {\tt Array}}
+\label {Libarray}
+\inputHS{code/Array}
+%**~footer
diff --git a/libraries/char.verb b/libraries/char.verb
new file mode 100644 (file)
index 0000000..dc8832b
--- /dev/null
@@ -0,0 +1,88 @@
+%**<title>The Haskell 98 Library Report: Character Utilities</title>
+%**~header
+\section{Character Utilities}
+
+\outline{
+\inputHS{headers/Char}
+}
+\indextt{isAscii}
+\indextt{isLatin1}
+\indextt{isControl}
+\indextt{isPrint}
+\indextt{isSpace}
+\indextt{isUpper}
+\indextt{isLower}
+\indextt{isAlpha}
+\indextt{isDigit}
+\indextt{isOctDigit}
+\indextt{isHexDigit}
+\indextt{isAlphaNum}
+\indextt{toUpper}
+\indextt{toLower}
+
+This library provides a limited set of operations on the Unicode
+character set.  
+The first 128 entries of this character set are identical to the
+ASCII set; with the next 128 entries comes the remainder of the
+Latin-1 character set.
+This module offers only a limited view of the
+full Unicode character set; the full set of Unicode character
+attributes is not accessible in this library.
+
+Unicode characters may be divided into five general categories:
+non-printing, lower case alphabetic, other alphabetic, numeric digits, and
+other printable characters.  For the purposes of Haskell, any
+alphabetic character which is not lower case is treated as upper case
+(Unicode actually has three cases: upper, lower, and title).  Numeric
+digits may be part of identifiers but digits outside the ASCII range are not
+used by the reader to represent numbers.  
+
+For each sort of Unicode character, here are the predicates which
+return @True@:
+\begin{center}
+\begin{tabular}{|l|llll|}
+\hline
+Character Type & Predicates  & & & \\
+\hline
+Lower Case Alphabetic & @isPrint@ & @isAlphaNum@ & @isAlpha@ & @isLower@ \\
+Other Alphabetic & @isPrint@ & @isAlphaNum@ & @isAlpha@ & @isUpper@ \\
+Digits & @isPrint@ & @isAlphaNum@ & & \\
+Other Printable & @isPrint@ & & & \\
+Non-printing & & & &\\
+\hline
+\end{tabular}
+\end{center}
+
+The @isDigit@, @isOctDigit@, and @isHexDigit@ functions select only
+ASCII characters.  @intToDigit@ and @digitToInt@ convert between 
+a single digit @Char@ and the corresponding @Int@.  
+@digitToInt@ operates fails unless its argument satisfies @isHexDigit@,
+but recognises both upper and lower-case hexadecimal digits (i.e. @'0'@..@'9'@,
+@'a'@..@'f'@, @'A'@..@'F'@).  @intToDigit@ fails unless its argument is in the range
+@0@..@15@, and generates lower-case hexadecmial digits.
+
+The @isSpace@ function recognizes only white characters in the Latin-1
+range.
+
+The function @showLitChar@ converts a character to a string using
+only printable characters, using Haskell source-language escape conventions.
+The function @readLitChar@ does the reverse.
+
+Function @toUpper@ converts a letter to the corresponding
+upper-case letter, leaving any other character unchanged.  Any
+Unicode letter which has an upper-case equivalent is transformed.
+Similarly, @toLower@ converts a letter to the
+corresponding lower-case letter, leaving any other character
+unchanged.
+
+The @ord@ and @chr@ functions are @fromEnum@ and @toEnum@
+restricted to the type @Char@.
+
+\clearpage
+\subsection{Library {\tt Char}}
+\label{Char}
+\inputHS{code/Char}
+
+%**~footer
+
+
diff --git a/libraries/code/Array.hs b/libraries/code/Array.hs
new file mode 100644 (file)
index 0000000..aa3193e
--- /dev/null
@@ -0,0 +1,79 @@
+module  Array ( 
+    module Ix,  -- export all of Ix 
+    Array, array, listArray, (!), bounds, indices, elems, assocs, 
+    accumArray, (//), accum, ixmap ) where
+
+import Ix
+import List( (\\) )
+
+infixl 9  !, //
+
+data (Ix a) => Array a b = MkArray (a,a) (a -> b) deriving ()
+
+array       :: (Ix a) => (a,a) -> [(a,b)] -> Array a b
+array b ivs =
+    if and [inRange b i | (i,_) <- ivs]
+        then MkArray b
+                     (\j -> case [v | (i,v) <- ivs, i == j] of
+                            [v]   -> v
+                            []    -> error "Array.!: \
+                                           \undefined array element"
+                            _     -> error "Array.!: \
+                                           \multiply defined array element")
+        else error "Array.array: out-of-range array association"
+
+listArray             :: (Ix a) => (a,a) -> [b] -> Array a b
+listArray b vs        =  array b (zipWith (\ a b -> (a,b)) (range b) vs)
+
+(!)                   :: (Ix a) => Array a b -> a -> b
+(!) (MkArray _ f)     =  f
+
+bounds                :: (Ix a) => Array a b -> (a,a)
+bounds (MkArray b _)  =  b
+
+indices               :: (Ix a) => Array a b -> [a]
+indices               =  range . bounds
+
+elems                 :: (Ix a) => Array a b -> [b]
+elems a               =  [a!i | i <- indices a]
+
+assocs                :: (Ix a) => Array a b -> [(a,b)]
+assocs a              =  [(i, a!i) | i <- indices a]
+
+(//)                  :: (Ix a) => Array a b -> [(a,b)] -> Array a b
+a // us               =  array (bounds a)
+                            ([(i,a!i) | i <- indices a \\ [i | (i,_) <- us]]
+                             ++ us)
+
+accum                 :: (Ix a) => (b -> c -> b) -> Array a b -> [(a,c)]
+                                   -> Array a b
+accum f               =  foldl (\a (i,v) -> a // [(i,f (a!i) v)])
+
+accumArray            :: (Ix a) => (b -> c -> b) -> b -> (a,a) -> [(a,c)]
+                                   -> Array a b
+accumArray f z b      =  accum f (array b [(i,z) | i <- range b])
+
+ixmap                 :: (Ix a, Ix b) => (a,a) -> (a -> b) -> Array b c
+                                         -> Array a c
+ixmap b f a           = array b [(i, a ! f i) | i <- range b]
+
+instance  (Ix a)          => Functor (Array a) where
+    fmap fn (MkArray b f) =  MkArray b (fn . f) 
+
+instance  (Ix a, Eq b)  => Eq (Array a b)  where
+    a == a'             =  assocs a == assocs a'
+
+instance  (Ix a, Ord b) => Ord (Array a b)  where
+    a <=  a'            =  assocs a <=  assocs a'
+
+instance  (Ix a, Show a, Show b) => Show (Array a b)  where
+    showsPrec p a = showParen (p > 9) (
+                    showString "array " .
+                    shows (bounds a) . showChar ' ' .
+                    shows (assocs a)                  )
+
+instance  (Ix a, Read a, Read b) => Read (Array a b)  where
+    readsPrec p = readParen (p > 9)
+           (\r -> [(array b as, u) | ("array",s) <- lex r,
+                                     (b,t)       <- reads s,
+                                     (as,u)      <- reads t   ])
diff --git a/libraries/code/Char.hs b/libraries/code/Char.hs
new file mode 100644 (file)
index 0000000..7244b4e
--- /dev/null
@@ -0,0 +1,150 @@
+module Char ( 
+    isAscii, isLatin1, isControl, isPrint, isSpace, isUpper, isLower,
+    isAlpha, isDigit, isOctDigit, isHexDigit, isAlphaNum,
+    digitToInt, intToDigit,
+    toUpper, toLower,
+    ord, chr,
+    readLitChar, showLitChar, lexLitChar,
+
+       -- ...and what the Prelude exports
+    Char, String
+    ) where
+
+import Array  -- used for character name table.
+import Numeric (readDec, readOct, lexDigits, readHex)
+import UnicodePrims  -- source of primitive Unicode functions.
+
+-- Character-testing operations
+isAscii, isControl, isPrint, isSpace, isUpper, isLower,
+ isAlpha, isDigit, isOctDigit, isHexDigit, isAlphaNum :: Char -> Bool
+
+isAscii c                =  c < '\x80'
+
+isLatin1 c               =  c <= '\xff'
+
+isControl c              =  c < ' ' || c >= '\DEL' && c <= '\x9f'
+
+isPrint                  =  primUnicodeIsPrint
+
+isSpace c                =  c `elem` " \t\n\r\f\v\xA0"
+       -- Only Latin-1 spaces recognized
+
+isUpper                  =  primUnicodeIsUpper -- 'A'..'Z'
+
+isLower                  =  primUnicodeIsLower -- 'a'..'z'
+
+isAlpha c                =  isUpper c || isLower c
+
+isDigit c                =  c >= '0' && c <= '9'
+
+isOctDigit c             =  c >= '0' && c <= '7'
+
+isHexDigit c             =  isDigit c || c >= 'A' && c <= 'F' ||
+                                         c >= 'a' && c <= 'f'
+
+isAlphaNum               =  primUnicodeIsAlphaNum
+
+
+-- Digit conversion operations
+digitToInt :: Char -> Int
+digitToInt c
+  | isDigit c            =  fromEnum c - fromEnum '0'
+  | c >= 'a' && c <= 'f' =  fromEnum c - fromEnum 'a' + 10
+  | c >= 'A' && c <= 'F' =  fromEnum c - fromEnum 'A' + 10
+  | otherwise            =  error "Char.digitToInt: not a digit"
+
+intToDigit :: Int -> Char
+intToDigit i
+  | i >= 0  && i <=  9   =  toEnum (fromEnum '0' + i)
+  | i >= 10 && i <= 15   =  toEnum (fromEnum 'a' + i - 10)
+  | otherwise            =  error "Char.intToDigit: not a digit"
+
+
+-- Case-changing operations
+toUpper                  :: Char -> Char
+toUpper                  =  primUnicodeToUpper
+
+toLower                  :: Char -> Char
+toLower                  =  primUnicodeToLower
+
+-- Character code functions
+ord                     :: Char -> Int
+ord                     =  fromEnum
+
+chr                     :: Int  -> Char
+chr                     =  toEnum
+
+-- Text functions
+readLitChar             :: ReadS Char
+readLitChar ('\\':s)    =  readEsc s
+        where
+        readEsc ('a':s)  = [('\a',s)]
+        readEsc ('b':s)  = [('\b',s)]
+        readEsc ('f':s)  = [('\f',s)]
+        readEsc ('n':s)  = [('\n',s)]
+        readEsc ('r':s)  = [('\r',s)]
+        readEsc ('t':s)  = [('\t',s)]
+        readEsc ('v':s)  = [('\v',s)]
+        readEsc ('\\':s) = [('\\',s)]
+        readEsc ('"':s)  = [('"',s)]
+        readEsc ('\'':s) = [('\'',s)]
+        readEsc ('^':c:s) | c >= '@' && c <= '_'
+                         = [(chr (ord c - ord '@'), s)]
+        readEsc s@(d:_) | isDigit d
+                         = [(chr n, t) | (n,t) <- readDec s]
+        readEsc ('o':s)  = [(chr n, t) | (n,t) <- readOct s]
+        readEsc ('x':s)  = [(chr n, t) | (n,t) <- readHex s]
+        readEsc s@(c:_) | isUpper c
+                         = let table = ('\DEL', "DEL") : assocs asciiTab
+                           in case [(c,s') | (c, mne) <- table,
+                                             ([],s') <- [match mne s]]
+                              of (pr:_) -> [pr]
+                                 []     -> []
+        readEsc _        = []
+
+       match                         :: (Eq a) => [a] -> [a] -> ([a],[a])
+       match (x:xs) (y:ys) | x == y  =  match xs ys
+       match xs     ys               =  (xs,ys)
+
+readLitChar (c:s)       =  [(c,s)]
+
+showLitChar               :: Char -> ShowS
+showLitChar c | c > '\DEL' =  showChar '\\' . 
+                              protectEsc isDigit (shows (ord c))
+showLitChar '\DEL'         =  showString "\\DEL"
+showLitChar '\\'           =  showString "\\\\"
+showLitChar c | c >= ' '   =  showChar c
+showLitChar '\a'           =  showString "\\a"
+showLitChar '\b'           =  showString "\\b"
+showLitChar '\f'           =  showString "\\f"
+showLitChar '\n'           =  showString "\\n"
+showLitChar '\r'           =  showString "\\r"
+showLitChar '\t'           =  showString "\\t"
+showLitChar '\v'           =  showString "\\v"
+showLitChar '\SO'          =  protectEsc (== 'H') (showString "\\SO")
+showLitChar c              =  showString ('\\' : asciiTab!c)
+
+protectEsc p f             = f . cont
+                             where cont s@(c:_) | p c = "\\&" ++ s
+                                   cont s             = s
+asciiTab = listArray ('\NUL', ' ')
+           ["NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
+            "BS",  "HT",  "LF",  "VT",  "FF",  "CR",  "SO",  "SI", 
+            "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
+            "CAN", "EM",  "SUB", "ESC", "FS",  "GS",  "RS",  "US", 
+            "SP"] 
+
+lexLitChar          :: ReadS String
+lexLitChar ('\\':s) =  [('\\':esc, t) | (esc,t) <- lexEsc s]
+        where
+          lexEsc (c:s)     | c `elem` "abfnrtv\\\"'" = [([c],s)]
+          lexEsc s@(d:_)   | isDigit d               = lexDigits s
+          lexEsc ('^':c:s) | c >= '@' && c <= '_'    = [(['^',c],s)]
+          -- Very crude approximation to \XYZ.  Let readers work this out.
+          lexEsc s@(c:_)   | isUpper c               = [span isCharName s]
+          lexEsc _                                   = []
+          isCharName c = isUpper c || isDigit c
+
+lexLitChar (c:s)    =  [([c],s)]
+lexLitChar ""       =  []
+
diff --git a/libraries/code/Complex.hs b/libraries/code/Complex.hs
new file mode 100644 (file)
index 0000000..cbfaee0
--- /dev/null
@@ -0,0 +1,94 @@
+
+module Complex(Complex((:+)), realPart, imagPart, conjugate, mkPolar,
+               cis, polar, magnitude, phase)  where
+
+infix  6  :+
+
+data  (RealFloat a)     => Complex a = !a :+ !a  deriving (Eq,Read,Show)
+
+
+realPart, imagPart :: (RealFloat a) => Complex a -> a
+realPart (x:+y)         =  x
+imagPart (x:+y)         =  y
+
+conjugate       :: (RealFloat a) => Complex a -> Complex a
+conjugate (x:+y) =  x :+ (-y)
+
+mkPolar                 :: (RealFloat a) => a -> a -> Complex a
+mkPolar r theta         =  r * cos theta :+ r * sin theta
+
+cis             :: (RealFloat a) => a -> Complex a
+cis theta       =  cos theta :+ sin theta
+
+polar           :: (RealFloat a) => Complex a -> (a,a)
+polar z                 =  (magnitude z, phase z)
+
+magnitude :: (RealFloat a) => Complex a -> a
+magnitude (x:+y) =  scaleFloat k
+                    (sqrt ((scaleFloat mk x)^2 + (scaleFloat mk y)^2))
+                   where k  = max (exponent x) (exponent y)
+                         mk = - k
+
+phase :: (RealFloat a) => Complex a -> a
+phase (0 :+ 0) = 0
+phase (x :+ y) = atan2 y x
+
+
+instance  (RealFloat a) => Num (Complex a)  where
+    (x:+y) + (x':+y')  =  (x+x') :+ (y+y')
+    (x:+y) - (x':+y')  =  (x-x') :+ (y-y')
+    (x:+y) * (x':+y')  =  (x*x'-y*y') :+ (x*y'+y*x')
+    negate (x:+y)      =  negate x :+ negate y
+    abs z              =  magnitude z :+ 0
+    signum 0           =  0
+    signum z@(x:+y)    =  x/r :+ y/r  where r = magnitude z
+    fromInteger n      =  fromInteger n :+ 0
+
+instance  (RealFloat a) => Fractional (Complex a)  where
+    (x:+y) / (x':+y')  =  (x*x''+y*y'') / d :+ (y*x''-x*y'') / d
+                          where x'' = scaleFloat k x'
+                                y'' = scaleFloat k y'
+                                k   = - max (exponent x') (exponent y')
+                                d   = x'*x'' + y'*y''
+
+    fromRational a     =  fromRational a :+ 0
+
+instance  (RealFloat a) => Floating (Complex a)        where
+    pi             =  pi :+ 0
+    exp (x:+y)     =  expx * cos y :+ expx * sin y
+                      where expx = exp x
+    log z          =  log (magnitude z) :+ phase z
+
+    sqrt 0         =  0
+    sqrt z@(x:+y)  =  u :+ (if y < 0 then -v else v)
+                      where (u,v) = if x < 0 then (v',u') else (u',v')
+                            v'    = abs y / (u'*2)
+                            u'    = sqrt ((magnitude z + abs x) / 2)
+
+    sin (x:+y)     =  sin x * cosh y :+ cos x * sinh y
+    cos (x:+y)     =  cos x * cosh y :+ (- sin x * sinh y)
+    tan (x:+y)     =  (sinx*coshy:+cosx*sinhy)/(cosx*coshy:+(-sinx*sinhy))
+                      where sinx  = sin x
+                            cosx  = cos x
+                            sinhy = sinh y
+                            coshy = cosh y
+
+    sinh (x:+y)    =  cos y * sinh x :+ sin  y * cosh x
+    cosh (x:+y)    =  cos y * cosh x :+ sin y * sinh x
+    tanh (x:+y)    =  (cosy*sinhx:+siny*coshx)/(cosy*coshx:+siny*sinhx)
+                      where siny  = sin y
+                            cosy  = cos y
+                            sinhx = sinh x
+                            coshx = cosh x
+
+    asin z@(x:+y)  =  y':+(-x')
+                      where  (x':+y') = log (((-y):+x) + sqrt (1 - z*z))
+    acos z@(x:+y)  =  y'':+(-x'')
+                      where (x'':+y'') = log (z + ((-y'):+x'))
+                            (x':+y')   = sqrt (1 - z*z)
+    atan z@(x:+y)  =  y':+(-x')
+                      where (x':+y') = log (((1-y):+x) / sqrt (1+z*z))
+
+    asinh z        =  log (z + sqrt (1+z*z))
+    acosh z        =  log (z + (z+1) * sqrt ((z-1)/(z+1)))
+    atanh z        =  log ((1+z) / sqrt (1-z*z))
diff --git a/libraries/code/IO.hs b/libraries/code/IO.hs
new file mode 100644 (file)
index 0000000..6327f1b
--- /dev/null
@@ -0,0 +1,28 @@
+module IO where
+
+-- Just provide an implementation of the system-indendent
+-- actions that IO exports.
+
+try            :: IO a -> IO (Either IOError a)
+try f          =  catch (do r <- f
+                            return (Right r))
+                        (return . Left)
+
+bracket        :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
+bracket before after m = do
+        x  <- before
+        rs <- try (m x)
+        after x
+        case rs of
+           Right r -> return r
+           Left  e -> ioError e
+
+-- variant of the above where middle computation doesn't want x
+bracket_        :: IO a -> (a -> IO b) -> IO c -> IO c
+bracket_ before after m = do
+         x  <- before
+         rs <- try m
+         after x
+         case rs of
+            Right r -> return r
+            Left  e -> ioError e
diff --git a/libraries/code/Ix.hs b/libraries/code/Ix.hs
new file mode 100644 (file)
index 0000000..5d0eb89
--- /dev/null
@@ -0,0 +1,42 @@
+module Ix ( Ix(range, index, inRange), rangeSize ) where
+
+class  (Ord a) => Ix a  where
+    range               :: (a,a) -> [a]
+    index               :: (a,a) -> a -> Int
+    inRange             :: (a,a) -> a -> Bool
+
+rangeSize :: Ix a => (a,a) -> Int
+rangeSize b@(l,h) | null (range b) = 0
+                  | otherwise      = index b h + 1 
+       -- NB: replacing "null (range b)" by  "l > h" fails if
+       -- the bounds are tuples.  For example,
+       --      (2,1) > (1,2), 
+       -- but 
+       --      range ((2,1),(1,2)) = []
+
+
+instance  Ix Char  where
+    range (m,n)                = [m..n]
+    index b@(c,c') ci
+        | inRange b ci  =  fromEnum ci - fromEnum c
+        | otherwise     =  error "Ix.index: Index out of range."
+    inRange (c,c') i    =  c <= i && i <= c'
+
+instance  Ix Int  where
+    range (m,n)                = [m..n]
+    index b@(m,n) i
+        | inRange b i   =  i - m
+        | otherwise     =  error "Ix.index: Index out of range."
+    inRange (m,n) i     =  m <= i && i <= n
+
+instance  Ix Integer  where
+    range (m,n)                = [m..n]
+    index b@(m,n) i
+        | inRange b i   =  fromInteger (i - m)
+        | otherwise     =  error "Ix.index: Index out of range."
+    inRange (m,n) i     =  m <= i && i <= n
+
+instance (Ix a,Ix b) => Ix (a, b) -- as derived, for all tuples
+instance Ix Bool                  -- as derived
+instance Ix Ordering              -- as derived
+instance Ix ()                    -- as derived
diff --git a/libraries/code/List.hs b/libraries/code/List.hs
new file mode 100644 (file)
index 0000000..a4df639
--- /dev/null
@@ -0,0 +1,264 @@
+module List ( 
+    elemIndex, elemIndices,
+    find, findIndex, findIndices,
+    nub, nubBy, delete, deleteBy, (\\), 
+    union, unionBy, intersect, intersectBy,
+    intersperse, transpose, partition, group, groupBy,
+    inits, tails, isPrefixOf, isSuffixOf,
+    mapAccumL, mapAccumR,
+    sort, sortBy, insert, insertBy, maximumBy, minimumBy,
+    genericLength, genericTake, genericDrop,
+    genericSplitAt, genericIndex, genericReplicate,
+    zip4, zip5, zip6, zip7,
+    zipWith4, zipWith5, zipWith6, zipWith7,
+    unzip4, unzip5, unzip6, unzip7, unfoldr,
+
+    -- ...and what the Prelude exports
+    []((:), []),
+    map, (++), concat, filter,
+    head, last, tail, init, null, length, (!!),
+    foldl, foldl1, scanl, scanl1, foldr, foldr1, scanr, scanr1,
+    iterate, repeat, replicate, cycle,
+    take, drop, splitAt, takeWhile, dropWhile, span, break,
+    lines, words, unlines, unwords, reverse, and, or,
+    any, all, elem, notElem, lookup,
+    sum, product, maximum, minimum, concatMap, 
+    zip, zip3, zipWith, zipWith3, unzip, unzip3
+    ) where
+
+import Maybe( listToMaybe )
+
+infix 5 \\
+
+elemIndex               :: Eq a => a -> [a] -> Maybe Int
+elemIndex x             =  findIndex (x ==)
+        
+elemIndices             :: Eq a => a -> [a] -> [Int]
+elemIndices x           =  findIndices (x ==)
+                        
+find                    :: (a -> Bool) -> [a] -> Maybe a
+find p                  =  listToMaybe . filter p
+
+findIndex               :: (a -> Bool) -> [a] -> Maybe Int
+findIndex p             =  listToMaybe . findIndices p
+
+findIndices             :: (a -> Bool) -> [a] -> [Int]
+findIndices p xs        =  [ i | (x,i) <- zip xs [0..], p x ]
+
+nub                     :: Eq a => [a] -> [a]
+nub                     =  nubBy (==)
+
+nubBy                   :: (a -> a -> Bool) -> [a] -> [a]
+nubBy eq []             =  []
+nubBy eq (x:xs)         =  x : nubBy eq (filter (\y -> not (eq x y)) xs)
+
+delete                  :: Eq a => a -> [a] -> [a]
+delete                  =  deleteBy (==)
+
+deleteBy                :: (a -> a -> Bool) -> a -> [a] -> [a]
+deleteBy eq x []        = []
+deleteBy eq x (y:ys)    = if x `eq` y then ys else y : deleteBy eq x ys
+
+(\\)                    :: Eq a => [a] -> [a] -> [a]
+(\\)                    =  foldl (flip delete)
+
+deleteFirstsBy          :: (a -> a -> Bool) -> [a] -> [a] -> [a]
+deleteFirstsBy eq       =  foldl (flip (deleteBy eq))
+
+union                   :: Eq a => [a] -> [a] -> [a]
+union                   =  unionBy (==)    
+
+unionBy                 :: (a -> a -> Bool) -> [a] -> [a] -> [a]
+unionBy eq xs ys        =  xs ++ foldl (flip (deleteBy eq)) (nubBy eq ys) xs
+
+intersect               :: Eq a => [a] -> [a] -> [a]
+intersect               =  intersectBy (==)
+
+intersectBy             :: (a -> a -> Bool) -> [a] -> [a] -> [a]
+intersectBy eq xs ys    =  [x | x <- xs, any (eq x) ys]
+
+intersperse             :: a -> [a] -> [a]
+intersperse sep []      =  []
+intersperse sep [x]     =  [x]
+intersperse sep (x:xs)  =  x : sep : intersperse sep xs
+
+-- transpose is lazy in both rows and columns,
+--      and works for non-rectangular 'matrices'
+-- For example, transpose [[1,2],[3,4,5],[]]  =  [[1,3],[2,4],[5]]
+-- Note that [h | (h:t) <- xss] is not the same as (map head xss)
+--     because the former discards empty sublists inside xss
+transpose                :: [[a]] -> [[a]]
+transpose []            = []
+transpose ([]     : xss) = transpose xss
+transpose ((x:xs) : xss) = (x : [h | (h:t) <- xss]) : 
+                          transpose (xs : [t | (h:t) <- xss])
+
+partition               :: (a -> Bool) -> [a] -> ([a],[a])
+partition p xs          =  foldr select ([],[]) xs
+                           where select x (ts,fs) | p x       = (x:ts,fs)
+                                                  | otherwise = (ts, x:fs)
+
+-- group splits its list argument into a list of lists of equal, adjacent
+-- elements.  e.g.,
+-- group "Mississippi" == ["M","i","ss","i","ss","i","pp","i"]
+group                   :: Eq a => [a] -> [[a]]
+group                   =  groupBy (==)
+
+groupBy                 :: (a -> a -> Bool) -> [a] -> [[a]]
+groupBy eq []           =  []
+groupBy eq (x:xs)       =  (x:ys) : groupBy eq zs
+                           where (ys,zs) = span (eq x) xs
+
+-- inits xs returns the list of initial segments of xs, shortest first.
+-- e.g., inits "abc" == ["","a","ab","abc"]
+inits                   :: [a] -> [[a]]
+inits []                =  [[]]
+inits (x:xs)            =  [[]] ++ map (x:) (inits xs)
+
+-- tails xs returns the list of all final segments of xs, longest first.
+-- e.g., tails "abc" == ["abc", "bc", "c",""]
+tails                   :: [a] -> [[a]]
+tails []                =  [[]]
+tails xxs@(_:xs)        =  xxs : tails xs
+
+isPrefixOf               :: Eq a => [a] -> [a] -> Bool
+isPrefixOf []     _      =  True
+isPrefixOf _      []     =  False
+isPrefixOf (x:xs) (y:ys) =  x == y && isPrefixOf xs ys
+
+isSuffixOf              :: Eq a => [a] -> [a] -> Bool
+isSuffixOf x y          =  reverse x `isPrefixOf` reverse y
+
+mapAccumL               :: (a -> b -> (a, c)) -> a -> [b] -> (a, [c])
+mapAccumL f s []        =  (s, [])
+mapAccumL f s (x:xs)    =  (s'',y:ys)
+                           where (s', y ) = f s x
+                                 (s'',ys) = mapAccumL f s' xs
+
+mapAccumR               :: (a -> b -> (a, c)) -> a -> [b] -> (a, [c])
+mapAccumR f s []        =  (s, [])
+mapAccumR f s (x:xs)    =  (s'', y:ys)
+                           where (s'',y ) = f s' x
+                                 (s', ys) = mapAccumR f s xs
+
+unfoldr                        :: (b -> Maybe (a,b)) -> b -> [a]
+unfoldr f b            = case f b of
+                               Nothing    -> []
+                               Just (a,b) -> a : unfoldr f b
+
+sort                    :: (Ord a) => [a] -> [a]
+sort                    =  sortBy compare
+
+sortBy                  :: (a -> a -> Ordering) -> [a] -> [a]
+sortBy cmp              =  foldr (insertBy cmp) []
+
+insert                 :: (Ord a) => a -> [a] -> [a]
+insert                 = insertBy compare
+
+insertBy                :: (a -> a -> Ordering) -> a -> [a] -> [a]
+insertBy cmp x []       =  [x]
+insertBy cmp x ys@(y:ys')
+                        =  case cmp x y of
+                                GT -> y : insertBy cmp x ys'
+                                _  -> x : ys
+
+maximumBy               :: (a -> a -> a) -> [a] -> a
+maximumBy max []        =  error "List.maximumBy: empty list"
+maximumBy max xs        =  foldl1 max xs
+
+minimumBy               :: (a -> a -> a) -> [a] -> a
+minimumBy min []        =  error "List.minimumBy: empty list"
+minimumBy min xs        =  foldl1 min xs
+
+genericLength           :: (Integral a) => [b] -> a
+genericLength []        =  0
+genericLength (x:xs)    =  1 + genericLength xs
+
+genericTake             :: (Integral a) => a -> [b] -> [b]
+genericTake _ []        =  []
+genericTake 0 _         =  []
+genericTake n (x:xs) 
+   | n > 0              =  x : genericTake (n-1) xs
+   | otherwise          =  error "List.genericTake: negative argument"
+
+genericDrop             :: (Integral a) => a -> [b] -> [b]
+genericDrop 0 xs        =  xs
+genericDrop _ []        =  []
+genericDrop n (_:xs) 
+   | n > 0              =  genericDrop (n-1) xs
+   | otherwise          =  error "List.genericDrop: negative argument"
+
+genericSplitAt          :: (Integral a) => a -> [b] -> ([b],[b])
+genericSplitAt 0 xs     =  ([],xs)
+genericSplitAt _ []     =  ([],[])
+genericSplitAt n (x:xs) 
+   | n > 0              =  (x:xs',xs'')
+   | otherwise          =  error "List.genericSplitAt: negative argument"
+       where (xs',xs'') =  genericSplitAt (n-1) xs
+
+genericIndex            :: (Integral a) => [b] -> a -> b
+genericIndex (x:_)  0   =  x
+genericIndex (_:xs) n 
+        | n > 0         =  genericIndex xs (n-1)
+        | otherwise     =  error "List.genericIndex: negative argument"
+genericIndex _ _        =  error "List.genericIndex: index too large"
+
+genericReplicate        :: (Integral a) => a -> b -> [b]
+genericReplicate n x    =  genericTake n (repeat x)
+zip4                    :: [a] -> [b] -> [c] -> [d] -> [(a,b,c,d)]
+zip4                    =  zipWith4 (,,,)
+
+zip5                    :: [a] -> [b] -> [c] -> [d] -> [e] -> [(a,b,c,d,e)]
+zip5                    =  zipWith5 (,,,,)
+
+zip6                    :: [a] -> [b] -> [c] -> [d] -> [e] -> [f] -> 
+                              [(a,b,c,d,e,f)]
+zip6                    =  zipWith6 (,,,,,)
+
+zip7                    :: [a] -> [b] -> [c] -> [d] -> [e] -> [f] ->
+                              [g] -> [(a,b,c,d,e,f,g)]
+zip7                    =  zipWith7 (,,,,,,)
+
+zipWith4                :: (a->b->c->d->e) -> [a]->[b]->[c]->[d]->[e]
+zipWith4 z (a:as) (b:bs) (c:cs) (d:ds)
+                        =  z a b c d : zipWith4 z as bs cs ds
+zipWith4 _ _ _ _ _      =  []
+
+zipWith5                :: (a->b->c->d->e->f) -> 
+                           [a]->[b]->[c]->[d]->[e]->[f]
+zipWith5 z (a:as) (b:bs) (c:cs) (d:ds) (e:es)
+                        =  z a b c d e : zipWith5 z as bs cs ds es
+zipWith5 _ _ _ _ _ _    =  []
+
+zipWith6                :: (a->b->c->d->e->f->g) ->
+                           [a]->[b]->[c]->[d]->[e]->[f]->[g]
+zipWith6 z (a:as) (b:bs) (c:cs) (d:ds) (e:es) (f:fs)
+                        =  z a b c d e f : zipWith6 z as bs cs ds es fs
+zipWith6 _ _ _ _ _ _ _  =  []
+
+zipWith7                :: (a->b->c->d->e->f->g->h) ->
+                           [a]->[b]->[c]->[d]->[e]->[f]->[g]->[h]
+zipWith7 z (a:as) (b:bs) (c:cs) (d:ds) (e:es) (f:fs) (g:gs)
+                   =  z a b c d e f g : zipWith7 z as bs cs ds es fs gs
+zipWith7 _ _ _ _ _ _ _ _ = []
+
+unzip4                  :: [(a,b,c,d)] -> ([a],[b],[c],[d])
+unzip4                  =  foldr (\(a,b,c,d) ~(as,bs,cs,ds) ->
+                                        (a:as,b:bs,c:cs,d:ds))
+                                 ([],[],[],[])
+
+unzip5                  :: [(a,b,c,d,e)] -> ([a],[b],[c],[d],[e])
+unzip5                  =  foldr (\(a,b,c,d,e) ~(as,bs,cs,ds,es) ->
+                                        (a:as,b:bs,c:cs,d:ds,e:es))
+                                 ([],[],[],[],[])
+
+unzip6                  :: [(a,b,c,d,e,f)] -> ([a],[b],[c],[d],[e],[f])
+unzip6                  =  foldr (\(a,b,c,d,e,f) ~(as,bs,cs,ds,es,fs) ->
+                                        (a:as,b:bs,c:cs,d:ds,e:es,f:fs))
+                                 ([],[],[],[],[],[])
+
+unzip7          :: [(a,b,c,d,e,f,g)] -> ([a],[b],[c],[d],[e],[f],[g])
+unzip7          =  foldr (\(a,b,c,d,e,f,g) ~(as,bs,cs,ds,es,fs,gs) ->
+                                (a:as,b:bs,c:cs,d:ds,e:es,f:fs,g:gs))
+                         ([],[],[],[],[],[],[])
diff --git a/libraries/code/Locale.hs b/libraries/code/Locale.hs
new file mode 100644 (file)
index 0000000..b56a648
--- /dev/null
@@ -0,0 +1,30 @@
+module Locale(TimeLocale(..), defaultTimeLocale) where
+
+data TimeLocale = TimeLocale {
+        wDays  :: [(String, String)],   -- full and abbreviated week days
+        months :: [(String, String)],   -- full and abbreviated months
+        amPm   :: (String, String),     -- AM/PM symbols
+        dateTimeFmt, dateFmt,           -- formatting strings
+          timeFmt, time12Fmt :: String     
+        } deriving (Eq, Ord, Show)
+
+defaultTimeLocale :: TimeLocale 
+defaultTimeLocale =  TimeLocale { 
+        wDays  = [("Sunday",   "Sun"),  ("Monday",    "Mon"),   
+                  ("Tuesday",  "Tue"),  ("Wednesday", "Wed"), 
+                  ("Thursday", "Thu"),  ("Friday",    "Fri"), 
+                  ("Saturday", "Sat")],
+
+        months = [("January",   "Jan"), ("February",  "Feb"),
+                  ("March",     "Mar"), ("April",     "Apr"),
+                  ("May",       "May"), ("June",      "Jun"),
+                  ("July",      "Jul"), ("August",    "Aug"),
+                  ("September", "Sep"), ("October",   "Oct"),
+                  ("November",  "Nov"), ("December",  "Dec")],
+
+        amPm = ("AM", "PM"),
+        dateTimeFmt = "%a %b %e %H:%M:%S %Z %Y",
+        dateFmt = "%m/%d/%y",
+        timeFmt = "%H:%M:%S",
+        time12Fmt = "%I:%M:%S %p"
+        }
diff --git a/libraries/code/Maybe.hs b/libraries/code/Maybe.hs
new file mode 100644 (file)
index 0000000..f1eac52
--- /dev/null
@@ -0,0 +1,38 @@
+module Maybe(
+    isJust, isNothing,
+    fromJust, fromMaybe, listToMaybe, maybeToList,
+    catMaybes, mapMaybe,
+
+    -- ...and what the Prelude exports
+    Maybe(Nothing, Just),
+    maybe
+  ) where
+
+isJust                 :: Maybe a -> Bool
+isJust (Just a)        =  True
+isJust Nothing         =  False
+
+isNothing             :: Maybe a -> Bool
+isNothing             =  not . isJust
+
+fromJust               :: Maybe a -> a
+fromJust (Just a)      =  a
+fromJust Nothing       =  error "Maybe.fromJust: Nothing"
+
+fromMaybe              :: a -> Maybe a -> a
+fromMaybe d Nothing    =  d
+fromMaybe d (Just a)   =  a
+
+maybeToList            :: Maybe a -> [a]
+maybeToList Nothing    =  []
+maybeToList (Just a)   =  [a]
+
+listToMaybe            :: [a] -> Maybe a
+listToMaybe []         =  Nothing
+listToMaybe (a:_)      =  Just a
+catMaybes              :: [Maybe a] -> [a]
+catMaybes ms           =  [ m | Just m <- ms ]
+
+mapMaybe               :: (a -> Maybe b) -> [a] -> [b]
+mapMaybe f             =  catMaybes . map f
diff --git a/libraries/code/Monad.hs b/libraries/code/Monad.hs
new file mode 100644 (file)
index 0000000..6d63563
--- /dev/null
@@ -0,0 +1,97 @@
+module Monad (
+    MonadPlus(mzero, mplus),
+    join, guard, when, unless, ap,
+    msum,
+    filterM, mapAndUnzipM, zipWithM, zipWithM_, foldM, 
+    liftM, liftM2, liftM3, liftM4, liftM5,
+
+    -- ...and what the Prelude exports
+    Monad((>>=), (>>), return, fail),
+    Functor(fmap),
+    mapM, mapM_, sequence, sequence_, (=<<), 
+    ) where
+
+
+-- The MonadPlus class definition
+
+class  (Monad m) => MonadPlus m  where
+    mzero  :: m a
+    mplus  :: m a -> m a -> m a
+
+
+-- Instances of MonadPlus
+
+instance  MonadPlus Maybe  where
+    mzero                 = Nothing
+
+    Nothing `mplus` ys    =  ys
+    xs      `mplus` ys    =  xs
+
+instance  MonadPlus []  where
+    mzero =  []
+    mplus = (++)
+
+
+-- Functions    
+
+
+msum            :: MonadPlus m => [m a] -> m a
+msum xs                 =  foldr mplus mzero xs
+
+join             :: (Monad m) => m (m a) -> m a
+join x           =  x >>= id
+
+when             :: (Monad m) => Bool -> m () -> m ()
+when p s         =  if p then s else return ()
+
+unless           :: (Monad m) => Bool -> m () -> m ()
+unless p s       =  when (not p) s
+
+ap               :: (Monad m) => m (a -> b) -> m a -> m b
+ap               =  liftM2 ($)
+
+guard            :: MonadPlus m => Bool -> m ()
+guard p          =  if p then return () else mzero
+
+mapAndUnzipM     :: (Monad m) => (a -> m (b,c)) -> [a] -> m ([b], [c])
+mapAndUnzipM f xs = sequence (map f xs) >>= return . unzip
+
+zipWithM         :: (Monad m) => (a -> b -> m c) -> [a] -> [b] -> m [c]
+zipWithM f xs ys =  sequence (zipWith f xs ys)
+
+zipWithM_         :: (Monad m) => (a -> b -> m c) -> [a] -> [b] -> m ()
+zipWithM_ f xs ys =  sequence_ (zipWith f xs ys)
+
+foldM            :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m a
+foldM f a []     =  return a
+foldM f a (x:xs) =  f a x >>= \ y -> foldM f y xs
+
+filterM :: Monad m => (a -> m Bool) -> [a] -> m [a]
+filterM p []     = return []
+filterM p (x:xs) = do { b  <- p x;
+                       ys <- filterM p xs; 
+                       return (if b then (x:ys) else ys)
+                  }
+
+liftM            :: (Monad m) => (a -> b) -> (m a -> m b)
+liftM f          =  \a -> do { a' <- a; return (f a') }
+
+liftM2           :: (Monad m) => (a -> b -> c) -> (m a -> m b -> m c)
+liftM2 f         =  \a b -> do { a' <- a; b' <- b; return (f a' b') }
+
+liftM3           :: (Monad m) => (a -> b -> c -> d) ->
+                                 (m a -> m b -> m c -> m d)
+liftM3 f         =  \a b c -> do { a' <- a; b' <- b; c' <- c;
+                                  return (f a' b' c') }
+
+liftM4           :: (Monad m) => (a -> b -> c -> d -> e) ->
+                                 (m a -> m b -> m c -> m d -> m e)
+liftM4 f         =  \a b c d -> do { a' <- a; b' <- b; c' <- c; d' <- d;
+                                    return (f a' b' c' d') }
+
+liftM5           :: (Monad m) => (a -> b -> c -> d -> e -> f) ->
+                                 (m a -> m b -> m c -> m d -> m e -> m f)
+liftM5 f         =  \a b c d e -> do { a' <- a; b' <- b; c' <- c; d' <- d;
+                                      e' <- e; return (f a' b' c' d' e') }
+
+
diff --git a/libraries/code/Numeric.hs b/libraries/code/Numeric.hs
new file mode 100644 (file)
index 0000000..524b767
--- /dev/null
@@ -0,0 +1,304 @@
+module Numeric(fromRat,
+               showSigned, showInt,
+               readSigned, readInt,
+               readDec, readOct, readHex, 
+               floatToDigits,
+               showEFloat, showFFloat, showGFloat, showFloat, 
+               readFloat, lexDigits) where
+
+import Char
+import Ratio
+import Array
+
+-- This converts a rational to a floating.  This should be used in the
+-- Fractional instances of Float and Double.
+
+fromRat :: (RealFloat a) => Rational -> a
+fromRat x = 
+    if x == 0 then encodeFloat 0 0              -- Handle exceptional cases
+    else if x < 0 then - fromRat' (-x)          -- first.
+    else fromRat' x
+
+-- Conversion process:
+-- Scale the rational number by the RealFloat base until
+-- it lies in the range of the mantissa (as used by decodeFloat/encodeFloat).
+-- Then round the rational to an Integer and encode it with the exponent
+-- that we got from the scaling.
+-- To speed up the scaling process we compute the log2 of the number to get
+-- a first guess of the exponent.
+fromRat' :: (RealFloat a) => Rational -> a
+fromRat' x = r
+  where b = floatRadix r
+        p = floatDigits r
+        (minExp0, _) = floatRange r
+        minExp = minExp0 - p            -- the real minimum exponent
+        xMin = toRational (expt b (p-1))
+        xMax = toRational (expt b p)
+        p0 = (integerLogBase b (numerator x) -
+              integerLogBase b (denominator x) - p) `max` minExp
+        f = if p0 < 0 then 1 % expt b (-p0) else expt b p0 % 1
+        (x', p') = scaleRat (toRational b) minExp xMin xMax p0 (x / f)
+        r = encodeFloat (round x') p'
+
+-- Scale x until xMin <= x < xMax, or p (the exponent) <= minExp.
+scaleRat :: Rational -> Int -> Rational -> Rational -> 
+             Int -> Rational -> (Rational, Int)
+scaleRat b minExp xMin xMax p x =
+    if p <= minExp then
+        (x, p)
+    else if x >= xMax then
+        scaleRat b minExp xMin xMax (p+1) (x/b)
+    else if x < xMin  then
+        scaleRat b minExp xMin xMax (p-1) (x*b)
+    else
+        (x, p)
+
+-- Exponentiation with a cache for the most common numbers.
+minExpt = 0::Int
+maxExpt = 1100::Int
+expt :: Integer -> Int -> Integer
+expt base n =
+    if base == 2 && n >= minExpt && n <= maxExpt then
+        expts!n
+    else
+        base^n
+
+expts :: Array Int Integer
+expts = array (minExpt,maxExpt) [(n,2^n) | n <- [minExpt .. maxExpt]]
+
+-- Compute the (floor of the) log of i in base b.
+-- Simplest way would be just divide i by b until it's smaller then b,
+-- but that would be very slow!  We are just slightly more clever.
+integerLogBase :: Integer -> Integer -> Int
+integerLogBase b i =
+     if i < b then
+        0
+     else
+        -- Try squaring the base first to cut down the number of divisions.
+        let l = 2 * integerLogBase (b*b) i
+            doDiv :: Integer -> Int -> Int
+            doDiv i l = if i < b then l else doDiv (i `div` b) (l+1)
+        in  doDiv (i `div` (b^l)) l
+
+
+-- Misc utilities to show integers and floats 
+
+showSigned    :: Real a => (a -> ShowS) -> Int -> a -> ShowS
+showSigned showPos p x | x < 0 = showParen (p > 6)
+                                           (showChar '-' . showPos (-x))
+                       | otherwise = showPos x
+
+-- showInt is used for positive numbers only
+showInt    :: Integral a => a -> ShowS
+showInt n r | n < 0 = error "Numeric.showInt: can't show negative numbers"
+            | otherwise =
+              let (n',d) = quotRem n 10
+                  r'     = toEnum (fromEnum '0' + fromIntegral d) : r
+              in  if n' == 0 then r' else showInt n' r'
+
+
+readSigned :: (Real a) => ReadS a -> ReadS a
+readSigned readPos = readParen False read'
+                     where read' r  = read'' r ++
+                                      [(-x,t) | ("-",s) <- lex r,
+                                                (x,t)   <- read'' s]
+                           read'' r = [(n,s)  | (str,s) <- lex r,
+                                                (n,"")  <- readPos str]
+
+
+-- readInt reads a string of digits using an arbitrary base.  
+-- Leading minus signs must be handled elsewhere.
+
+readInt :: (Integral a) => a -> (Char -> Bool) -> (Char -> Int) -> ReadS a
+readInt radix isDig digToInt s =
+   [(foldl1 (\n d -> n * radix + d) (map (fromIntegral . digToInt) ds), r)
+          | (ds,r) <- nonnull isDig s ]
+
+-- Unsigned readers for various bases
+readDec, readOct, readHex :: (Integral a) => ReadS a
+readDec = readInt 10 isDigit digitToInt
+readOct = readInt  8 isOctDigit digitToInt
+readHex = readInt 16 isHexDigit digitToInt
+
+
+showEFloat     :: (RealFloat a) => Maybe Int -> a -> ShowS
+showFFloat     :: (RealFloat a) => Maybe Int -> a -> ShowS
+showGFloat     :: (RealFloat a) => Maybe Int -> a -> ShowS
+showFloat      :: (RealFloat a) => a -> ShowS
+
+showEFloat d x =  showString (formatRealFloat FFExponent d x)
+showFFloat d x =  showString (formatRealFloat FFFixed d x)
+showGFloat d x =  showString (formatRealFloat FFGeneric d x)
+showFloat      =  showGFloat Nothing 
+
+-- These are the format types.  This type is not exported.
+
+data FFFormat = FFExponent | FFFixed | FFGeneric
+
+formatRealFloat :: (RealFloat a) => FFFormat -> Maybe Int -> a -> String
+formatRealFloat fmt decs x = s
+  where base = 10
+        s = if isNaN x then 
+                "NaN"
+            else if isInfinite x then 
+                if x < 0 then "-Infinity" else "Infinity"
+            else if x < 0 || isNegativeZero x then 
+                '-' : doFmt fmt (floatToDigits (toInteger base) (-x))
+            else 
+                doFmt fmt (floatToDigits (toInteger base) x)
+        doFmt fmt (is, e) =
+            let ds = map intToDigit is
+            in  case fmt of
+                FFGeneric -> 
+                    doFmt (if e < 0 || e > 7 then FFExponent else FFFixed)
+                          (is, e)
+                FFExponent ->
+                    case decs of
+                    Nothing ->
+                        case ds of
+                         ['0'] -> "0.0e0"
+                         [d]   -> d : ".0e" ++ show (e-1)
+                         d:ds  -> d : '.' : ds ++ 'e':show (e-1)
+                    Just dec ->
+                        let dec' = max dec 1 in
+                        case is of
+                         [0] -> '0':'.':take dec' (repeat '0') ++ "e0"
+                         _ ->
+                          let (ei, is') = roundTo base (dec'+1) is
+                              d:ds = map intToDigit
+                                         (if ei > 0 then init is' else is')
+                          in d:'.':ds  ++ "e" ++ show (e-1+ei)
+                FFFixed ->
+                    case decs of
+                    Nothing ->
+                        let f 0 s ds = mk0 s ++ "." ++ mk0 ds
+                            f n s "" = f (n-1) (s++"0") ""
+                            f n s (d:ds) = f (n-1) (s++[d]) ds
+                            mk0 "" = "0"
+                            mk0 s = s
+                        in  f e "" ds
+                    Just dec ->
+                        let dec' = max dec 0 in
+                        if e >= 0 then
+                            let (ei, is') = roundTo base (dec' + e) is
+                                (ls, rs) = splitAt (e+ei) (map intToDigit is')
+                            in  (if null ls then "0" else ls) ++ 
+                                (if null rs then "" else '.' : rs)
+                        else
+                            let (ei, is') = roundTo base dec'
+                                              (replicate (-e) 0 ++ is)
+                                d : ds = map intToDigit
+                                            (if ei > 0 then is' else 0:is')
+                            in  d : '.' : ds
+
+roundTo :: Int -> Int -> [Int] -> (Int, [Int])
+roundTo base d is = case f d is of
+                (0, is) -> (0, is)
+                (1, is) -> (1, 1 : is)
+  where b2 = base `div` 2
+        f n [] = (0, replicate n 0)
+        f 0 (i:_) = (if i >= b2 then 1 else 0, [])
+        f d (i:is) = 
+            let (c, ds) = f (d-1) is
+                i' = c + i
+            in  if i' == base then (1, 0:ds) else (0, i':ds)
+
+--
+-- Based on "Printing Floating-Point Numbers Quickly and Accurately"
+-- by R.G. Burger and R. K. Dybvig, in PLDI 96.
+-- This version uses a much slower logarithm estimator.  It should be improved.
+
+-- This function returns a list of digits (Ints in [0..base-1]) and an
+-- exponent.
+
+floatToDigits :: (RealFloat a) => Integer -> a -> ([Int], Int)
+
+floatToDigits _ 0 = ([0], 0)
+floatToDigits base x =
+    let (f0, e0) = decodeFloat x
+        (minExp0, _) = floatRange x
+        p = floatDigits x
+        b = floatRadix x
+        minExp = minExp0 - p            -- the real minimum exponent
+        -- Haskell requires that f be adjusted so denormalized numbers
+        -- will have an impossibly low exponent.  Adjust for this.
+        (f, e) = let n = minExp - e0
+                 in  if n > 0 then (f0 `div` (b^n), e0+n) else (f0, e0)
+
+        (r, s, mUp, mDn) =
+           if e >= 0 then
+               let be = b^e in
+               if f == b^(p-1) then
+                   (f*be*b*2, 2*b, be*b, b)
+               else
+                   (f*be*2, 2, be, be)
+           else
+               if e > minExp && f == b^(p-1) then
+                   (f*b*2, b^(-e+1)*2, b, 1)
+               else
+                   (f*2, b^(-e)*2, 1, 1)
+        k = 
+            let k0 =
+                    if b==2 && base==10 then
+                        -- logBase 10 2 is slightly bigger than 3/10 so
+                        -- the following will err on the low side.  Ignoring
+                        -- the fraction will make it err even more.
+                        -- Haskell promises that p-1 <= logBase b f < p.
+                        (p - 1 + e0) * 3 `div` 10
+                    else
+                        ceiling ((log (fromInteger (f+1)) + 
+                                 fromInt e * log (fromInteger b)) / 
+                                  log (fromInteger base))
+                fixup n =
+                    if n >= 0 then
+                        if r + mUp <= expt base n * s then n else fixup (n+1)
+                    else
+                        if expt base (-n) * (r + mUp) <= s then n
+                                                           else fixup (n+1)
+            in  fixup k0
+
+        gen ds rn sN mUpN mDnN =
+            let (dn, rn') = (rn * base) `divMod` sN
+                mUpN' = mUpN * base
+                mDnN' = mDnN * base
+            in  case (rn' < mDnN', rn' + mUpN' > sN) of
+                (True,  False) -> dn : ds
+                (False, True)  -> dn+1 : ds
+                (True,  True)  -> if rn' * 2 < sN then dn : ds else dn+1 : ds
+                (False, False) -> gen (dn:ds) rn' sN mUpN' mDnN'
+        rds =
+            if k >= 0 then
+                gen [] r (s * expt base k) mUp mDn
+            else
+                let bk = expt base (-k)
+                in  gen [] (r * bk) s (mUp * bk) (mDn * bk)
+    in  (map toInt (reverse rds), k)
+
+
+
+-- This floating point reader uses a less restrictive syntax for floating
+-- point than the Haskell lexer.  The `.' is optional.
+
+readFloat     :: (RealFloat a) => ReadS a
+readFloat r    = [(fromRational ((n%1)*10^^(k-d)),t) | (n,d,s) <- readFix r,
+                                                       (k,t)   <- readExp s]
+                 where readFix r = [(read (ds++ds'), length ds', t)
+                                        | (ds,d) <- lexDigits r,
+                                          (ds',t) <- lexFrac d ]
+
+                       lexFrac ('.':ds) = lexDigits ds
+                       lexFrac s        = [("",s)]        
+
+                       readExp (e:s) | e `elem` "eE" = readExp' s
+                       readExp s                     = [(0,s)]
+
+                       readExp' ('-':s) = [(-k,t) | (k,t) <- readDec s]
+                       readExp' ('+':s) = readDec s
+                       readExp' s       = readDec s
+
+lexDigits        :: ReadS String 
+lexDigits        =  nonnull isDigit
+
+nonnull          :: (Char -> Bool) -> ReadS String
+nonnull p s      =  [(cs,t) | (cs@(_:_),t) <- [span p s]]
+
diff --git a/libraries/code/Random.hs b/libraries/code/Random.hs
new file mode 100644 (file)
index 0000000..764d85a
--- /dev/null
@@ -0,0 +1,112 @@
+module Random (
+       RandomGen(next, split),
+       StdGen, mkStdGen,
+
+       Random( random,   randomR, 
+               randoms,  randomRs,
+               randomIO, randomRIO ),
+
+       getStdRandom,
+       getStdGen, setStdGen, newStdGen
+  ) where
+       
+---------------- The RandomGen class ---------------------------
+
+class RandomGen g where
+  next  :: g  -> (Int, g)
+  split :: g -> (g, g)         -- May not exist for all RandomGens
+
+
+---------------- A standard instance of RandomGen ---------------
+data StdGen = ...      -- Abstract
+
+instance RandomGen StdGen where ...
+
+-- The show/read instances provide a primitive way to save
+-- the state of a random number generator
+-- It is expected read (show g) == g
+
+instance Read StdGen where ...
+       -- read succeeds on *any* string, not only those
+       -- constructed with show.  Hence you can use any
+       -- string as way to construct a RandomGen.
+       --   - read guarantees to consume a finite portion of
+       --     the string
+       --   - different strings are likely to result in 
+       --     different generators
+
+instance Show StdGen where ...
+
+mkStdGen :: Int -> StdGen
+-- Make a StdGen from an Int.  Different Ints should result
+-- in different generators.
+
+
+---------------- The Random class ---------------------------
+
+class Random a where
+   randomR :: RandomGen g => (a, a) -> g -> (a, g)
+       -- Returns a random value uniformly distributed in [lo,hi]
+       -- It is unspecified what happens if lo > hi
+
+   random  :: RandomGen g => g -> (a, g)
+       -- Return any value of type a.
+       -- For bounded types, the range is normally the whole type
+       -- For Fractional types, the range is normally [0..1]
+       -- For Integer, the range is (arbitrarily) the range of Int
+
+   randomRs :: RandomGen g => (a, a) -> g -> [a]
+   randoms  :: RandomGen g => g -> [a]
+
+   randomIO :: IO a
+   randomRIO :: (a,a) -> IO a
+
+       -- Default methods
+   randoms g = x : randoms g' 
+            where 
+              (x,g') = random g
+   randomRs = ...similar...
+
+   randomIO        = getStdRandom random
+   randomRIO range = getStdRandom (randomR range)
+
+
+instance Random Int     where ...
+instance Random Integer where ...
+instance Random Float   where ...
+instance Random Double  where ...
+instance Random Bool    where ...
+instance Random Char    where ...
+
+
+---------------- The global random generator ---------------------------
+
+-- There is a single, implicit, global random number generator
+-- of type StdGen, held in some global variable maintained by the IO monad
+--
+-- It is initialised non-deterministically; to get
+-- deterministic behaviour use setStdGen.
+
+setStdGen :: StdGen -> IO ()   -- Set the global generator
+getStdGen :: IO StdGen -- Get the global generator
+
+getStdRandom :: (StdGen -> (a, StdGen)) -> IO a
+       -- Use the supplied function to get a value from
+       -- the current global random generator, g, and update the
+       -- global generator with the new generator returned
+getStdRandom f = do
+       g <- getStdGen
+       let (val, g') = f g
+       setStdGen g'
+       return val
+
+newStdGen :: IO StdGen
+       -- Apply split to the current global random generator
+       -- update it with one of the results and return the other
+newStdGen = do
+       g <- getStdGen
+       let (s1,s2) = split g
+       setStdGen s1
+       return s2
+
+
diff --git a/libraries/code/Ratio.hs b/libraries/code/Ratio.hs
new file mode 100644 (file)
index 0000000..ae88b26
--- /dev/null
@@ -0,0 +1,95 @@
+-- Standard functions on rational numbers
+
+module  Ratio (
+    Ratio, Rational, (%), numerator, denominator, approxRational ) where
+
+infixl 7  %
+
+prec = 7 :: Int
+
+data  (Integral a)      => Ratio a = !a :% !a  deriving (Eq)
+type  Rational          =  Ratio Integer
+
+(%)                     :: (Integral a) => a -> a -> Ratio a
+numerator, denominator  :: (Integral a) => Ratio a -> a
+approxRational          :: (RealFrac a) => a -> a -> Rational
+
+
+-- "reduce" is a subsidiary function used only in this module.
+-- It normalises a ratio by dividing both numerator
+-- and denominator by their greatest common divisor.
+--
+-- E.g., 12 `reduce` 8    ==  3 :%   2
+--       12 `reduce` (-8) ==  3 :% (-2)
+
+reduce _ 0              =  error "Ratio.% : zero denominator"
+reduce x y              =  (x `quot` d) :% (y `quot` d)
+                           where d = gcd x y
+
+x % y                   =  reduce (x * signum y) (abs y)
+
+numerator (x :% _)      =  x
+
+denominator (_ :% y)    =  y
+
+
+instance  (Integral a)  => Ord (Ratio a)  where
+    (x:%y) <= (x':%y')  =  x * y' <= x' * y
+    (x:%y) <  (x':%y')  =  x * y' <  x' * y
+
+instance  (Integral a)  => Num (Ratio a)  where
+    (x:%y) + (x':%y')   =  reduce (x*y' + x'*y) (y*y')
+    (x:%y) * (x':%y')   =  reduce (x * x') (y * y')
+    negate (x:%y)       =  (-x) :% y
+    abs (x:%y)          =  abs x :% y
+    signum (x:%y)       =  signum x :% 1
+    fromInteger x       =  fromInteger x :% 1
+
+instance  (Integral a)  => Real (Ratio a)  where
+    toRational (x:%y)   =  toInteger x :% toInteger y
+
+instance  (Integral a)  => Fractional (Ratio a)  where
+    (x:%y) / (x':%y')   =  (x*y') % (y*x')
+    recip (x:%y)        =  if x < 0 then (-y) :% (-x) else y :% x
+    fromRational (x:%y) =  fromInteger x :% fromInteger y
+
+instance  (Integral a)  => RealFrac (Ratio a)  where
+    properFraction (x:%y) = (fromIntegral q, r:%y)
+                            where (q,r) = quotRem x y
+
+instance  (Integral a)  => Enum (Ratio a)  where
+    toEnum           =  fromIntegral
+    fromEnum         =  fromInteger . truncate -- May overflow
+    enumFrom         =  numericEnumFrom                -- These numericEnumXXX functions
+    enumFromThen     =  numericEnumFromThen    -- are as defined in Prelude.hs
+    enumFromTo       =  numericEnumFromTo      -- but not exported from it!
+    enumFromThenTo   =  numericEnumFromThenTo
+
+instance  (Read a, Integral a)  => Read (Ratio a)  where
+    readsPrec p  =  readParen (p > prec)
+                              (\r -> [(x%y,u) | (x,s)   <- reads r,
+                                                ("%",t) <- lex s,
+                                                (y,u)   <- reads t ])
+
+instance  (Integral a)  => Show (Ratio a)  where
+    showsPrec p (x:%y)  =  showParen (p > prec)
+                               (shows x . showString " % " . shows y)
+
+
+
+approxRational x eps    =  simplest (x-eps) (x+eps)
+        where simplest x y | y < x      =  simplest y x
+                           | x == y     =  xr
+                           | x > 0      =  simplest' n d n' d'
+                           | y < 0      =  - simplest' (-n') d' (-n) d
+                           | otherwise  =  0 :% 1
+                                        where xr@(n:%d) = toRational x
+                                              (n':%d')  = toRational y
+
+              simplest' n d n' d'       -- assumes 0 < n%d < n'%d'
+                        | r == 0     =  q :% 1
+                        | q /= q'    =  (q+1) :% 1
+                        | otherwise  =  (q*n''+d'') :% n''
+                                     where (q,r)      =  quotRem n d
+                                           (q',r')    =  quotRem n' d'
+                                           (n'':%d'') =  simplest' d' r' d r
diff --git a/libraries/code/Time.hs b/libraries/code/Time.hs
new file mode 100644 (file)
index 0000000..93f0c56
--- /dev/null
@@ -0,0 +1,135 @@
+module Time (
+        ClockTime, 
+        Month(January,February,March,April,May,June,
+              July,August,September,October,November,December),
+        Day(Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday),
+       CalendarTime(CalendarTime, ctYear, ctMonth, ctDay, ctHour, ctMin,
+                    ctPicosec, ctWDay, ctYDay, ctTZName, ctTZ, ctIsDST),
+       TimeDiff(TimeDiff, tdYear, tdMonth, tdDay, 
+                tdHour, tdMin, tdSec, tdPicosec),
+        getClockTime, addToClockTime, diffClockTimes,
+        toCalendarTime, toUTCTime, toClockTime,
+        calendarTimeToString, formatCalendarTime ) where
+
+import Ix(Ix)
+import Locale(TimeLocale(..),defaultTimeLocale)
+import Char ( intToDigit )
+
+data ClockTime = ...                    -- Implementation-dependent
+instance Ord  ClockTime where ...
+instance Eq   ClockTime where ...
+
+data Month =  January   | February | March    | April
+           |  May       | June     | July     | August
+           |  September | October  | November | December
+           deriving (Eq, Ord, Enum, Bounded, Ix, Read, Show)
+
+data Day   =  Sunday | Monday  | Tuesday  | Wednesday | Thursday 
+           |  Friday | Saturday
+           deriving (Eq, Ord, Enum, Bounded, Ix, Read, Show)
+
+data CalendarTime = CalendarTime {
+                ctYear                          :: Int,
+                ctMonth                         :: Month,
+                ctDay, ctHour, ctMin, ctSec     :: Int,
+                ctPicosec                       :: Integer,
+                ctWDay                          :: Day,
+                ctYDay                          :: Int,
+                ctTZName                        :: String,
+                ctTZ                            :: Int,
+                ctIsDST                         :: Bool
+        } deriving (Eq, Ord, Read, Show)
+
+data TimeDiff = TimeDiff {
+                tdYear, tdMonth, tdDay, tdHour, tdMin, tdSec :: Int,
+                tdPicosec                                    :: Integer
+        } deriving (Eq, Ord, Read, Show)
+
+
+getClockTime            :: IO ClockTime
+getClockTime            = ...           -- Implementation-dependent
+
+addToClockTime          :: TimeDiff     -> ClockTime -> ClockTime
+addToClockTime td ct    =  ...          -- Implementation-dependent
+
+diffClockTimes          :: ClockTime    -> ClockTime -> TimeDiff
+diffClockTimes ct1 ct2  =  ...          -- Implementation-dependent
+
+toCalendarTime          :: ClockTime    -> IO CalendarTime
+toCalendarTime ct       =  ...          -- Implementation-dependent
+
+toUTCTime               :: ClockTime    -> CalendarTime
+toUTCTime ct            =  ...          -- Implementation-dependent
+
+toClockTime             :: CalendarTime -> ClockTime
+toClockTime cal         =  ...          -- Implementation-dependent
+
+calendarTimeToString    :: CalendarTime -> String
+calendarTimeToString    =  formatCalendarTime defaultTimeLocale "%c"
+
+formatCalendarTime :: TimeLocale -> String -> CalendarTime -> String
+formatCalendarTime l fmt ct@(CalendarTime year mon day hour min sec sdec 
+                                           wday yday tzname _ _) =
+        doFmt fmt
+  where doFmt ('%':c:cs) = decode c ++ doFmt cs
+        doFmt (c:cs) = c : doFmt cs
+        doFmt "" = ""
+
+        to12 :: Int -> Int
+        to12 h = let h' = h `mod` 12 in if h' == 0 then 12 else h'
+
+        decode 'A' = fst (wDays l  !! fromEnum wday)
+        decode 'a' = snd (wDays l  !! fromEnum wday)
+        decode 'B' = fst (months l !! fromEnum mon)
+        decode 'b' = snd (months l !! fromEnum mon)
+        decode 'h' = snd (months l !! fromEnum mon)
+        decode 'C' = show2 (year `quot` 100)
+        decode 'c' = doFmt (dateTimeFmt l)
+        decode 'D' = doFmt "%m/%d/%y"
+        decode 'd' = show2 day
+        decode 'e' = show2' day
+        decode 'H' = show2 hour
+        decode 'I' = show2 (to12 hour)
+        decode 'j' = show3 yday
+        decode 'k' = show2' hour
+        decode 'l' = show2' (to12 hour)
+        decode 'M' = show2 min
+        decode 'm' = show2 (fromEnum mon+1)
+        decode 'n' = "\n"
+        decode 'p' = (if hour < 12 then fst else snd) (amPm l)
+        decode 'R' = doFmt "%H:%M"
+        decode 'r' = doFmt (time12Fmt l)
+        decode 'T' = doFmt "%H:%M:%S"
+        decode 't' = "\t"
+        decode 'S' = show2 sec
+        decode 's' = ...                -- Implementation-dependent
+        decode 'U' = show2 ((yday + 7 - fromEnum wday) `div` 7)
+        decode 'u' = show (let n = fromEnum wday in 
+                           if n == 0 then 7 else n)
+        decode 'V' = 
+            let (week, days) = 
+                   (yday + 7 - if fromEnum wday > 0 then 
+                               fromEnum wday - 1 else 6) `divMod` 7
+            in  show2 (if days >= 4 then
+                          week+1 
+                       else if week == 0 then 53 else week)
+
+        decode 'W' = 
+            show2 ((yday + 7 - if fromEnum wday > 0 then 
+                               fromEnum wday - 1 else 6) `div` 7)
+        decode 'w' = show (fromEnum wday)
+        decode 'X' = doFmt (timeFmt l)
+        decode 'x' = doFmt (dateFmt l)
+        decode 'Y' = show year
+        decode 'y' = show2 (year `rem` 100)
+        decode 'Z' = tzname
+        decode '%' = "%"
+        decode c   = [c]
+
+show2, show2', show3 :: Int -> String
+show2 x = [intToDigit (x `quot` 10), intToDigit (x `rem` 10)]
+
+show2' x = if x < 10 then [ ' ', intToDigit x] else show2 x
+
+show3 x = intToDigit (x `quot` 100) : show2 (x `rem` 100)
+
diff --git a/libraries/complex.verb b/libraries/complex.verb
new file mode 100644 (file)
index 0000000..33343a3
--- /dev/null
@@ -0,0 +1,49 @@
+%**<title>The Haskell 98 Library Report: Complex Numbers</title>
+%**~header
+\section{Complex Numbers}
+\label{lib-num}
+
+\outline{
+\inputHS{headers/Complex}
+}
+
+Complex numbers are an algebraic type.
+The constructor @(:+)@\indextt{:+} forms a complex number from its
+real and imaginary rectangular components.  This constructor is
+strict: if either the real part or the imaginary part of the number is
+$\bot$, the entire number is $\bot$.  A complex number may also
+be formed from polar components of magnitude and phase by the function
+@mkPolar@\indextt{mkPolar}.  The function @cis@\indextt{polar}
+produces a complex number from an angle "t".
+Put another way, @cis@ "t" is a complex value with magnitude "1"
+and phase "t" (modulo "2\pi").
+
+The function @polar@\indextt{polar} takes a complex number and
+returns a (magnitude, phase) pair in canonical form: The magnitude is
+nonnegative, and the phase, in the range $(- \pi , \pi ]$; if the
+magnitude is zero, then so is the phase.  
+
+The functions @realPart@\indextt{realPart} and
+@imagPart@\indextt{imagPart} extract the rectangular components of a
+complex number and the functions @magnitude@\indextt{magnitude} and
+@phase@\indextt{phase} extract the polar components of a complex
+number.  The function @conjugate@\indextt{conjugate} computes the
+conjugate of a complex number in the usual way.
+
+The magnitude and sign of a complex number are defined as follows:
+\bprog
+@
+abs z            =  magnitude z :+ 0
+signum 0         =  0
+signum z@@(x:+y)   =  x/r :+ y/r  where r = magnitude z
+@
+\eprog
+That is, @abs@ $z$ is a number with the magnitude of $z$, but oriented
+in the positive real direction, whereas @signum@ $z$ has the phase of
+$z$, but unit magnitude.
+
+\subsection{Library {\tt Complex}}
+\inputHS{code/Complex}
+
+%**~footer
+
diff --git a/libraries/cputime.verb b/libraries/cputime.verb
new file mode 100644 (file)
index 0000000..23c14db
--- /dev/null
@@ -0,0 +1,19 @@
+%**<title>The Haskell 98 Library Report: CPU Time</title>
+%**~header
+\section{CPU Time}
+\label{cputime}
+\index{CPU time}
+\index{execution time}
+
+\outline {
+\inputHS{headers/CPUTime}
+}
+
+Computation @getCPUTime@ returns the number of picoseconds of CPU time
+used by the current program.  The precision of this result is given by
+@cpuTimePrecision@.  This is the smallest measurable difference in CPU
+time that the implementation can record, and is given as an integral
+number of picoseconds.
+
+%**~footer
+
diff --git a/libraries/directory.verb b/libraries/directory.verb
new file mode 100644 (file)
index 0000000..2671b1d
--- /dev/null
@@ -0,0 +1,164 @@
+%**<title>The Haskell 98 Library Report: Directory functions</title>
+%**~header
+
+%% Other useful functions from SML 96 include modification time
+%% and path-testing (is this a full path/real path).
+
+\section{Directory Functions}
+\index{directories}
+\index{the file system}
+
+\outline{
+\inputHS{headers/Directory}
+}
+\indextt{createDirectory}\indextt{removeDirectory}\indextt{removeFile}
+\indextt{renameDirectory}\indextt{renameFile}
+\indextt{getDirectoryContents}\indextt{getCurrentDirectory}
+\indextt{setCurrentDirectory}
+
+These functions operate on directories in the file system.  
+
+Any @Directory@ operation could raise an @isIllegalOperationError@, as
+described in Section~\ref{IOError}; all other permissible errors are
+described below.  Note that, in particular, if an implementation does
+not support an operation it should raise an @isIllegalOperationError@.
+
+A directory contains a series of entries, each of which is a named
+reference to a file system object (file, directory etc.).  Some
+entries may be hidden, inaccessible, or have some administrative
+function (for instance, ``.'' or ``..'' under POSIX), but all such
+entries are considered to form part of the directory contents.
+Entries in sub-directories are not, however, considered to form part
+of the directory contents.  Although there may be
+file system objects other than files and directories, this library
+does not distinguish between physical files and other non-directory
+objects.  All such objects should therefore be treated as if they are files.
+
+Each file system object is referenced by a {\it path}\index{path}.  There is
+normally at least one absolute path to each file system object.  In
+some operating systems, it may also be possible to have paths which
+are relative to the current directory.
+
+Computation @createDirectory@~"dir" creates a new directory "dir" which is
+initially empty, or as near to empty as the operating system allows.
+\index{making directories}
+
+{\em Error reporting}:
+the @createDirectory@ computation may fail with:
+@isPermissionError@ if the user is not permitted to create the directory;
+@isAlreadyExistsError@ if the directory already exists.
+
+Computation @removeDirectory@~"dir" removes an existing directory
+"dir"\index{deleting directories}\index{removing directories}.  The
+implementation may specify additional constraints which must be
+satisfied before a directory can be removed (for instance, the directory has to
+be empty, or may not be in use by other processes).  It is not legal
+for an implementation to partially remove a directory unless the
+entire directory is removed. A conformant implementation need not
+support directory removal in all situations (for instance, removal of the root
+directory).
+
+Computation @removeFile@~"file" removes the directory entry for an existing
+file "file", where "file" is not itself a directory\index{deleting
+files}\index{removing files}. The implementation may specify additional
+constraints which must be satisfied before a file can be removed (for instance, the
+file may not be in use by other processes).
+
+{\em Error reporting}:
+the @removeDirectory@ and @removeFile@ computations may fail with:
+@isPermissionError@ if the user is not permitted to remove the file/directory;
+or @isDoesNot@-@ExistError@ if the file/directory does not exist.
+
+Computation @renameDirectory@~"old"~"new" changes the name of an existing
+directory from "old" to "new"\index{renaming directories}\index{moving
+directories}.  If the "new" directory already exists, it is atomically
+replaced by the "old" directory.  If the "new" directory is neither
+the "old" directory nor an alias of the "old" directory, it is removed
+as if by @removeDirectory@.  A conformant implementation need not
+support renaming directories in all situations (for instance, renaming to an
+existing directory, or across different physical devices), but the
+constraints must be documented.
+
+Computation @renameFile@~"old"~"new" changes the name of an existing file
+system object from "old" to "new"\index{renaming files}\index{moving files}.
+If the "new" object already exists, it is atomically replaced by the "old"
+object.  Neither path may refer to an existing directory.  A conformant
+implementation need not support renaming files in all situations
+(for instance, renaming across different physical devices), but the constraints must be
+documented.
+
+{\em Error reporting}:
+the @renameDirectory@ and @renameFile@ computations may fail with:
+@isPermissionError@ if the user is not permitted to rename the file/directory,
+or if either argument to @renameFile@ is a directory;
+or @isDoesNotExistError@ if the file/directory does not exist.
+
+Computation @getDirectoryContents@~"dir" returns a list of {\em all} entries
+in "dir"\index{reading a directory}.
+
+If the operating system has a notion of current directories,
+@getCurrentDirectory@ returns an absolute path to the
+current directory of the calling process\index{current directory}.
+
+{\em Error reporting}:
+the @getDirectoryContents@ and @getCurrentDirectory@ computations may fail with:
+@isPermissionError@ if the user is not permitted to access the directory;
+or @isDoesNotExistError@ if the directory does not exist.
+
+If the operating system has a notion of current directories,
+@setCurrentDirectory@~"dir" changes the current directory of the
+calling process to "dir"\index{changing the directory}\index{setting the directory}.
+
+{\em Error reporting}:
+the @setCurrentDirectory@ computation may fail with:
+@isPermission@-@Error@ if the user is not permitted to change directory
+to that specified;
+or @isDoesNotExist@-@Error@ if the directory does not exist.
+
+The @Permissions@ type is used to record whether certain operations are
+permissible on a file/directory.  @getPermissions@ and
+@setPermissions@ get and set these permissions, respectively.  
+Permissions apply both to files and directories.  For
+directories, the @executable@ field will be @False@, and for files the
+@searchable@ field will be @False@.  Note that directories may be
+searchable without being readable, if permission has been given to use
+them as part of a path, but not to examine the directory contents.
+
+Note that to change
+some, but not all permissions, a construct on the following lines must
+be used.  
+\bprog
+@
+makeReadable f = do
+                   p <- getPermissions f
+                   setPermissions f (p {readable = True})
+@
+\eprog
+The operation @doesDirectoryExist@ returns @True@ if the argument file
+exists and is a directory, and @False@ otherwise. The operation @doesFileExist@ returns @True@
+if the argument file exists and is not a directory, and @False@ otherwise.
+
+The @getModificationTime@ operation returns the
+clock time at which the file/directory was last modified.
+
+{\em Error reporting}:
+the @get(set)Permissions@,
+@doesFile(Directory)Exist@,
+and @getMod@-@ificationTime@
+computations may fail with:
+@isPermissionError@ if the user is not permitted to access
+the appropriate information;
+or @isDoesNotExistError@ if the file/directory does not exist.
+The @setPermissions@
+computation may also fail with:
+@isPermissionError@ if the user is not permitted to change
+the permission for the specified file or directory;
+or @isDoesNotExistError@ if the file/directory does not exist.
+% Duplicates the first case above, and would require
+% extensive consistency checking throughout. KH
+% The @doesFileExist@ and @doesDirectoryExist@ computations
+% may also fail with @isPermissionError@ if some part of the path
+% to the file/directory cannot be searched.
+
+%**~footer
+
diff --git a/libraries/h98-libs.gif b/libraries/h98-libs.gif
new file mode 100644 (file)
index 0000000..e997197
Binary files /dev/null and b/libraries/h98-libs.gif differ
diff --git a/libraries/h98-libs.ppt b/libraries/h98-libs.ppt
new file mode 100644 (file)
index 0000000..985730e
Binary files /dev/null and b/libraries/h98-libs.ppt differ
diff --git a/libraries/headers/Array.hs b/libraries/headers/Array.hs
new file mode 100644 (file)
index 0000000..2bb99d0
--- /dev/null
@@ -0,0 +1,32 @@
+module  Array ( 
+        module Ix,  -- export all of Ix for convenience
+        Array, array, listArray, (!), bounds, indices, elems, assocs, 
+        accumArray, (//), accum, ixmap ) where
+
+import Ix
+
+infixl 9  !, //
+
+data  (Ix a)    => Array a b = ...     -- Abstract
+
+array           :: (Ix a) => (a,a) -> [(a,b)] -> Array a b
+listArray       :: (Ix a) => (a,a) -> [b] -> Array a b
+(!)             :: (Ix a) => Array a b -> a -> b
+bounds          :: (Ix a) => Array a b -> (a,a)
+indices         :: (Ix a) => Array a b -> [a]
+elems           :: (Ix a) => Array a b -> [b]
+assocs          :: (Ix a) => Array a b -> [(a,b)]
+accumArray      :: (Ix a) => (b -> c -> b) -> b -> (a,a) -> [(a,c)]
+                             -> Array a b
+(//)            :: (Ix a) => Array a b -> [(a,b)] -> Array a b
+accum           :: (Ix a) => (b -> c -> b) -> Array a b -> [(a,c)]
+                             -> Array a b
+ixmap           :: (Ix a, Ix b) => (a,a) -> (a -> b) -> Array b c
+                             -> Array a c
+
+instance                            Functor (Array a) where ...
+instance  (Ix a, Eq b)           => Eq   (Array a b)  where ...
+instance  (Ix a, Ord b)          => Ord  (Array a b)  where ...
+instance  (Ix a, Show a, Show b) => Show (Array a b)  where ...
+instance  (Ix a, Read a, Read b) => Read (Array a b)  where ...
+
diff --git a/libraries/headers/CPUTime.hs b/libraries/headers/CPUTime.hs
new file mode 100644 (file)
index 0000000..9eaaf09
--- /dev/null
@@ -0,0 +1,4 @@
+module CPUTime ( getCPUTime ) where
+
+getCPUTime        :: IO Integer
+cpuTimePrecision  :: Integer
diff --git a/libraries/headers/Char.hs b/libraries/headers/Char.hs
new file mode 100644 (file)
index 0000000..8d70f3d
--- /dev/null
@@ -0,0 +1,26 @@
+module Char ( 
+    isAscii, isLatin1, isControl, isPrint, isSpace, isUpper, isLower, 
+    isAlpha, isDigit, isOctDigit, isHexDigit, isAlphaNum, 
+    digitToInt, intToDigit,
+    toUpper, toLower,
+    ord, chr,
+    readLitChar, showLitChar, lexLitChar
+
+       -- ...and what the Prelude exports
+    Char, String
+    ) where
+
+isAscii, isLatin1, isControl, isPrint, isSpace, isUpper, isLower, 
+ isAlpha, isDigit, isOctDigit, isHexDigit, isAlphaNum :: Char -> Bool
+
+toUpper, toLower        :: Char -> Char
+
+digitToInt :: Char -> Int
+intToDigit :: Int -> Char
+
+ord        :: Char -> Int
+chr        :: Int  -> Char
+
+lexLitChar  :: ReadS String
+readLitChar :: ReadS Char
+showLitChar :: Char -> ShowS
diff --git a/libraries/headers/Complex.hs b/libraries/headers/Complex.hs
new file mode 100644 (file)
index 0000000..d78b78a
--- /dev/null
@@ -0,0 +1,21 @@
+module  Complex ( 
+    Complex((:+)), realPart, imagPart, conjugate, 
+    mkPolar, cis, polar, magnitude, phase ) where
+
+infix  6  :+
+
+data  (RealFloat a)     => Complex a = !a :+ !a
+
+realPart, imagPart      :: (RealFloat a) => Complex a -> a
+conjugate              :: (RealFloat a) => Complex a -> Complex a
+mkPolar                        :: (RealFloat a) => a -> a -> Complex a
+cis                    :: (RealFloat a) => a -> Complex a
+polar                  :: (RealFloat a) => Complex a -> (a,a)
+magnitude, phase        :: (RealFloat a) => Complex a -> a
+
+instance  (RealFloat a) => Eq         (Complex a)  where ...
+instance  (RealFloat a) => Read       (Complex a)  where ...
+instance  (RealFloat a) => Show       (Complex a)  where ...
+instance  (RealFloat a) => Num        (Complex a)  where ...
+instance  (RealFloat a) => Fractional (Complex a)  where ...
+instance  (RealFloat a) => Floating   (Complex a)  where ...
diff --git a/libraries/headers/Directory.hs b/libraries/headers/Directory.hs
new file mode 100644 (file)
index 0000000..e0e5d99
--- /dev/null
@@ -0,0 +1,39 @@
+module Directory ( 
+    Permissions,
+    readable, writable, executable, searchable, 
+    createDirectory, removeDirectory, removeFile, 
+    renameDirectory, renameFile, getDirectoryContents,
+    getCurrentDirectory, setCurrentDirectory,
+    doesFileExist, doesDirectoryExist,
+    getPermissions, setPermissions,
+    getModificationTime ) where
+
+import Time ( ClockTime )
+
+data Permissions = ...         -- Abstract
+
+instance Eq   Permissions where ...
+instance Ord  Permissions where ...
+instance Read Permissions where ...
+instance Show Permissions where ...
+
+readable, writable, executable, searchable :: Permissions -> Bool
+
+createDirectory        :: FilePath -> IO ()
+removeDirectory        :: FilePath -> IO ()
+removeFile             :: FilePath -> IO ()
+renameDirectory        :: FilePath -> FilePath -> IO ()
+renameFile             :: FilePath -> FilePath -> IO ()
+
+getDirectoryContents   :: FilePath -> IO [FilePath]
+getCurrentDirectory    :: IO FilePath
+setCurrentDirectory    :: FilePath -> IO ()
+
+doesFileExist          :: FilePath -> IO Bool
+doesDirectoryExist     :: FilePath -> IO Bool
+
+getPermissions         :: FilePath -> IO Permissions
+setPermissions         :: FilePath -> Permissions -> IO ()
+
+getModificationTime    :: FilePath -> IO ClockTime
+
diff --git a/libraries/headers/IO.hs b/libraries/headers/IO.hs
new file mode 100644 (file)
index 0000000..a9c7d64
--- /dev/null
@@ -0,0 +1,47 @@
+module IO (
+    Handle, HandlePosn,
+    IOMode(ReadMode,WriteMode,AppendMode,ReadWriteMode),
+    BufferMode(NoBuffering,LineBuffering,BlockBuffering),
+    SeekMode(AbsoluteSeek,RelativeSeek,SeekFromEnd),
+    stdin, stdout, stderr, 
+    openFile, hClose, hFileSize, hIsEOF, isEOF,
+    hSetBuffering, hGetBuffering, hFlush, 
+    hGetPosn, hSetPosn, hSeek, 
+    hWaitForInput, hReady, hGetChar, hGetLine, hLookAhead, hGetContents, 
+    hPutChar, hPutStr, hPutStrLn, hPrint,
+    hIsOpen, hIsClosed, hIsReadable, hIsWritable, hIsSeekable,
+    isAlreadyExistsError, isDoesNotExistError, isAlreadyInUseError, 
+    isFullError, isEOFError,
+    isIllegalOperation, isPermissionError, isUserError, 
+    ioeGetErrorString, ioeGetHandle, ioeGetFileName,
+    try, bracket, bracket_
+
+    -- ...and what the Prelude exports
+    IO, FilePath, IOError, ioError, userError, catch, interact,
+    putChar, putStr, putStrLn, print, getChar, getLine, getContents,
+    readFile, writeFile, appendFile, readIO, readLn
+    ) where
+
+import Ix(Ix)
+
+data Handle = ...                      -- implementation-dependent
+instance Eq Handle where ...
+instance Show Handle where ..           -- implementation-dependent
+
+data HandlePosn = ...                  -- implementation-dependent
+instance Eq HandlePosn where ...
+instance Show HandlePosn where ---      -- implementation-dependent
+
+
+data IOMode      =  ReadMode | WriteMode | AppendMode | ReadWriteMode
+                    deriving (Eq, Ord, Ix, Bounded, Enum, Read, Show)
+data BufferMode  =  NoBuffering | LineBuffering 
+                 |  BlockBuffering (Maybe Int)
+                    deriving (Eq, Ord, Read, Show)
+data SeekMode    =  AbsoluteSeek | RelativeSeek | SeekFromEnd
+                    deriving (Eq, Ord, Ix, Bounded, Enum, Read, Show)
+
+stdin, stdout, stderr :: Handle
+
+openFile              :: FilePath -> IOMode -> IO Handle
+hClose                :: Handle -> IO ()
diff --git a/libraries/headers/IO1.hs b/libraries/headers/IO1.hs
new file mode 100644 (file)
index 0000000..c99450f
--- /dev/null
@@ -0,0 +1,46 @@
+hFileSize             :: Handle -> IO Integer
+hIsEOF                :: Handle -> IO Bool
+isEOF                 :: IO Bool
+isEOF                 =  hIsEOF stdin
+
+hSetBuffering         :: Handle  -> BufferMode -> IO ()
+hGetBuffering         :: Handle  -> IO BufferMode
+hFlush                :: Handle -> IO () 
+hGetPosn              :: Handle -> IO HandlePosn
+hSetPosn              :: HandlePosn -> IO () 
+hSeek                 :: Handle -> SeekMode -> Integer -> IO () 
+
+hWaitForInput        :: Handle -> Int -> IO Bool
+hReady                :: Handle -> IO Bool 
+hReady h             =  hWaitForInput h 0
+hGetChar              :: Handle -> IO Char
+hGetLine              :: Handle -> IO String
+hLookAhead            :: Handle -> IO Char
+hGetContents          :: Handle -> IO String
+hPutChar              :: Handle -> Char -> IO ()
+hPutStr               :: Handle -> String -> IO ()
+hPutStrLn             :: Handle -> String -> IO ()
+hPrint                :: Show a => Handle -> a -> IO ()
+
+hIsOpen               :: Handle -> IO Bool
+hIsClosed             :: Handle -> IO Bool
+hIsReadable           :: Handle -> IO Bool
+hIsWritable           :: Handle -> IO Bool
+hIsSeekable           :: Handle -> IO Bool
+
+isAlreadyExistsError  :: IOError -> Bool
+isDoesNotExistError   :: IOError -> Bool
+isAlreadyInUseError   :: IOError -> Bool
+isFullError           :: IOError -> Bool
+isEOFError            :: IOError -> Bool
+isIllegalOperation    :: IOError -> Bool
+isPermissionError     :: IOError -> Bool
+isUserError           :: IOError -> Bool
+
+ioeGetErrorString     :: IOError -> String
+ioeGetHandle          :: IOError -> Maybe Handle
+ioeGetFileName        :: IOError -> Maybe FilePath
+
+try                   :: IO a -> Either IOError a
+bracket               :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
+bracket_              :: IO a -> (a -> IO b) -> IO c -> IO c
diff --git a/libraries/headers/Ix.hs b/libraries/headers/Ix.hs
new file mode 100644 (file)
index 0000000..d0a9848
--- /dev/null
@@ -0,0 +1,16 @@
+module Ix ( Ix(range, index, inRange), rangeSize ) where
+
+class  (Ord a) => Ix a  where
+    range               :: (a,a) -> [a]
+    index               :: (a,a) -> a -> Int
+    inRange             :: (a,a) -> a -> Bool
+
+rangeSize               :: (Ix a) => (a,a) -> Int
+
+instance                   Ix Char      where ...
+instance                   Ix Int       where ...
+instance                   Ix Integer   where ...
+instance  (Ix a, Ix b)  => Ix (a,b)     where ...
+-- et cetera
+instance                   Ix Bool      where ...
+instance                   Ix Ordering  where ...
diff --git a/libraries/headers/List.hs b/libraries/headers/List.hs
new file mode 100644 (file)
index 0000000..615ae98
--- /dev/null
@@ -0,0 +1,44 @@
+module List ( 
+    elemIndex, elemIndices,
+    find, findIndex, findIndices,
+    nub, nubBy, delete, deleteBy, (\\), deleteFirstsBy,
+    union, unionBy, intersect, intersectBy,
+    intersperse, transpose, partition, group, groupBy,
+    inits, tails, isPrefixOf, isSuffixOf,
+    mapAccumL, mapAccumR,
+    sort, sortBy, insert, insertBy, maximumBy, minimumBy,
+    genericLength, genericTake, genericDrop,
+    genericSplitAt, genericIndex, genericReplicate,
+    zip4, zip5, zip6, zip7,
+    zipWith4, zipWith5, zipWith6, zipWith7,
+    unzip4, unzip5, unzip6, unzip7, unfoldr,
+
+    -- ...and what the Prelude exports
+    []((:), []),
+    map, (++), concat, filter,
+    head, last, tail, init, null, length, (!!),
+    foldl, foldl1, scanl, scanl1, foldr, foldr1, scanr, scanr1,
+    iterate, repeat, replicate, cycle,
+    take, drop, splitAt, takeWhile, dropWhile, span, break,
+    lines, words, unlines, unwords, reverse, and, or,
+    any, all, elem, notElem, lookup,
+    sum, product, maximum, minimum, concatMap, 
+    zip, zip3, zipWith, zipWith3, unzip, unzip3
+    ) where
+
+infix 5 \\
+
+elemIndex           :: Eq a => a -> [a] -> Maybe Int
+elemIndices         :: Eq a => a -> [a] -> [Int]
+find                :: (a -> Bool) -> [a] -> Maybe a
+findIndex           :: (a -> Bool) -> [a] -> Maybe Int
+findIndices         :: (a -> Bool) -> [a] -> [Int]
+nub                 :: Eq a => [a] -> [a]
+nubBy               :: (a -> a -> Bool) -> [a] -> [a]
+delete              :: Eq a => a -> [a] -> [a]
+deleteBy            :: (a -> a -> Bool) -> a -> [a] -> [a]
+(\\)                :: Eq a => [a] -> [a] -> [a]
+deleteFirstsBy      :: (a -> a -> Bool) -> [a] -> [a] -> [a]
+union               :: Eq a => [a] -> [a] -> [a]
+unionBy             :: (a -> a -> Bool) -> [a] -> [a] -> [a]
+
diff --git a/libraries/headers/List1.hs b/libraries/headers/List1.hs
new file mode 100644 (file)
index 0000000..9e55b0d
--- /dev/null
@@ -0,0 +1,44 @@
+intersect           :: Eq a => [a] -> [a] -> [a]
+intersectBy         :: (a -> a -> Bool) -> [a] -> [a] -> [a]
+intersperse         :: a -> [a] -> [a]
+transpose           :: [[a]] -> [[a]]
+partition           :: (a -> Bool) -> [a] -> ([a],[a])
+group               :: Eq a => [a] -> [[a]]
+groupBy             :: (a -> a -> Bool) -> [a] -> [[a]]
+inits               :: [a] -> [[a]] 
+tails               :: [a] -> [[a]] 
+isPrefixOf          :: Eq a => [a] -> [a] -> Bool
+isSuffixOf          :: Eq a => [a] -> [a] -> Bool
+mapAccumL           :: (a -> b -> (a, c)) -> a -> [b] -> (a, [c])
+mapAccumR           :: (a -> b -> (a, c)) -> a -> [b] -> (a, [c])
+unfoldr                    :: (b -> Maybe (a,b)) -> b -> [a]
+sort                :: Ord a => [a] -> [a]
+sortBy              :: (a -> a -> Ordering) -> [a] -> [a]
+insert             :: Ord a => a -> [a] -> [a]
+insertBy            :: (a -> a -> Ordering) -> a -> [a] -> [a]
+maximumBy           :: (a -> a -> Ordering) -> [a] -> a
+minimumBy           :: (a -> a -> Ordering) -> [a] -> a
+genericLength       :: Integral a => [b] -> a
+genericTake        :: Integral a => a -> [b] -> [b]
+genericDrop        :: Integral a => a -> [b] -> [b]
+genericSplitAt     :: Integral a => a -> [b] -> ([b],[b])
+genericIndex       :: Integral a => [b] -> a -> b
+genericReplicate    :: Integral a => a -> b -> [b]
+
+zip4                :: [a] -> [b] -> [c] -> [d] -> [(a,b,c,d)]
+zip5                :: [a] -> [b] -> [c] -> [d] -> [e] -> [(a,b,c,d,e)]
+zip6                :: [a] -> [b] -> [c] -> [d] -> [e] -> [f] 
+                          -> [(a,b,c,d,e,f)]
+zip7                :: [a] -> [b] -> [c] -> [d] -> [e] -> [f] -> [g]
+                          -> [(a,b,c,d,e,f,g)]
+zipWith4            :: (a->b->c->d->e) -> [a]->[b]->[c]->[d]->[e]
+zipWith5            :: (a->b->c->d->e->f) -> 
+                       [a]->[b]->[c]->[d]->[e]->[f]
+zipWith6            :: (a->b->c->d->e->f->g) ->
+                       [a]->[b]->[c]->[d]->[e]->[f]->[g]
+zipWith7            :: (a->b->c->d->e->f->g->h) ->
+                       [a]->[b]->[c]->[d]->[e]->[f]->[g]->[h]
+unzip4              :: [(a,b,c,d)] -> ([a],[b],[c],[d])
+unzip5              :: [(a,b,c,d,e)] -> ([a],[b],[c],[d],[e])
+unzip6              :: [(a,b,c,d,e,f)] -> ([a],[b],[c],[d],[e],[f])
+unzip7              :: [(a,b,c,d,e,f,g)] -> ([a],[b],[c],[d],[e],[f],[g])
diff --git a/libraries/headers/Locale.hs b/libraries/headers/Locale.hs
new file mode 100644 (file)
index 0000000..a9a57d1
--- /dev/null
@@ -0,0 +1,11 @@
+module Locale(TimeLocale(..), defaultTimeLocale) where
+
+data TimeLocale = TimeLocale {
+        wDays  :: [(String, String)],   -- full and abbreviated week days
+        months :: [(String, String)],   -- full and abbreviated months
+        amPm   :: (String, String),     -- AM/PM symbols
+        dateTimeFmt, dateFmt,           -- formatting strings
+          timeFmt, time12Fmt :: String     
+        } deriving (Eq, Ord, Show)
+
+defaultTimeLocale :: TimeLocale 
diff --git a/libraries/headers/Maybe.hs b/libraries/headers/Maybe.hs
new file mode 100644 (file)
index 0000000..e536efa
--- /dev/null
@@ -0,0 +1,17 @@
+module Maybe(
+    isJust, isNothing,
+    fromJust, fromMaybe, listToMaybe, maybeToList,
+    catMaybes, mapMaybe,
+
+    -- ...and what the Prelude exports
+    Maybe(Nothing, Just),
+    maybe
+  ) where
+
+isJust, isNothing    :: Maybe a -> Bool
+fromJust             :: Maybe a -> a
+fromMaybe            :: a -> Maybe a -> a
+listToMaybe          :: [a] -> Maybe a
+maybeToList          :: Maybe a -> [a]
+catMaybes            :: [Maybe a] -> [a]
+mapMaybe             :: (a -> Maybe b) -> [a] -> [b]
diff --git a/libraries/headers/Monad.hs b/libraries/headers/Monad.hs
new file mode 100644 (file)
index 0000000..561e29f
--- /dev/null
@@ -0,0 +1,40 @@
+module Monad (
+    MonadPlus(mzero, mplus),
+    join, guard, when, unless, ap,
+    msum,
+    filterM, mapAndUnzipM, zipWithM, zipWithM_, foldM, 
+    liftM, liftM2, liftM3, liftM4, liftM5,
+
+    -- ...and what the Prelude exports
+    Monad((>>=), (>>), return, fail),
+    Functor(fmap),
+    mapM, mapM_, sequence, sequence_, (=<<), 
+    ) where
+
+class  Monad m => MonadPlus m  where
+    mzero  :: m a
+    mplus  :: m a -> m a -> m a
+
+join             :: Monad m => m (m a) -> m a
+guard            :: MonadPlus m => Bool -> m ()
+when             :: Monad m => Bool -> m () -> m ()
+unless           :: Monad m => Bool -> m () -> m ()
+ap              :: Monad m => m (a -> b) -> m a -> m b
+
+mapAndUnzipM     :: Monad m => (a -> m (b,c)) -> [a] -> m ([b], [c])
+zipWithM         :: Monad m => (a -> b -> m c) -> [a] -> [b] -> m [c]
+zipWithM_        :: Monad m => (a -> b -> m c) -> [a] -> [b] -> m ()
+foldM            :: Monad m => (a -> b -> m a) -> a -> [b] -> m a
+filterM                 :: Monad m => (a -> m Bool) -> [a] -> m [a]
+
+msum            :: MonadPlus m => [m a] -> m a
+
+liftM            :: Monad m => (a -> b) -> (m a -> m b)
+liftM2           :: Monad m => (a -> b -> c) -> (m a -> m b -> m c)
+liftM3           :: Monad m => (a -> b -> c -> d) ->
+                               (m a -> m b -> m c -> m d)
+liftM4           :: Monad m => (a -> b -> c -> d -> e) ->
+                               (m a -> m b -> m c -> m d -> m e)
+liftM5           :: Monad m => (a -> b -> c -> d -> e -> f) ->
+                               (m a -> m b -> m c -> m d -> m e -> m f)
+
diff --git a/libraries/headers/Numeric.hs b/libraries/headers/Numeric.hs
new file mode 100644 (file)
index 0000000..82c9426
--- /dev/null
@@ -0,0 +1,27 @@
+module Numeric(fromRat,
+               showSigned, showInt,
+               readSigned, readInt,
+               readDec, readOct, readHex, 
+               floatToDigits,
+               showEFloat, showFFloat, showGFloat, showFloat, 
+               readFloat, lexDigits) where
+
+fromRat        :: (RealFloat a) => Rational -> a
+showSigned     :: (Real a) => (a -> ShowS) -> Int -> a -> ShowS
+showInt        :: Integral a => a -> ShowS
+readSigned     :: (Real a) => ReadS a -> ReadS a
+readInt        :: (Integral a) =>
+                    a -> (Char -> Bool) -> (Char -> Int) -> ReadS a
+readDec        :: (Integral a) => ReadS a
+readOct        :: (Integral a) => ReadS a
+readHex        :: (Integral a) => ReadS a
+
+showEFloat     :: (RealFloat a) => Maybe Int -> a -> ShowS
+showFFloat     :: (RealFloat a) => Maybe Int -> a -> ShowS
+showGFloat     :: (RealFloat a) => Maybe Int -> a -> ShowS
+showFloat      :: (RealFloat a) => a -> ShowS
+
+floatToDigits  :: (RealFloat a) => Integer -> a -> ([Int], Int)
+
+readFloat      :: (RealFloat a) => ReadS a
+lexDigits      :: ReadS String 
diff --git a/libraries/headers/Random.hs b/libraries/headers/Random.hs
new file mode 100644 (file)
index 0000000..7589e2a
--- /dev/null
@@ -0,0 +1,49 @@
+module Random (
+       RandomGen(next, split),
+       StdGen, mkStdGen,
+       Random( random,   randomR, 
+               randoms,  randomRs,
+               randomIO, randomRIO ),
+       getStdRandom, getStdGen, setStdGen, newStdGen
+  ) where
+       
+---------------- The RandomGen class ------------------------
+
+class RandomGen g where
+  next  :: g  -> (Int, g)
+  split :: g -> (g, g)
+
+---------------- A standard instance of RandomGen -----------
+data StdGen = ...      -- Abstract
+
+instance RandomGen StdGen where ...
+instance Read     StdGen where ...
+instance Show     StdGen where ...
+
+mkStdGen :: Int -> StdGen
+
+---------------- The Random class ---------------------------
+class Random a where
+   randomR :: RandomGen g => (a, a) -> g -> (a, g)
+   random  :: RandomGen g => g -> (a, g)
+
+   randomRs :: RandomGen g => (a, a) -> g -> [a]
+   randoms  :: RandomGen g => g -> [a]
+
+   randomRIO :: (a,a) -> IO a
+   randomIO  :: IO a
+
+instance Random Int     where ...
+instance Random Integer where ...
+instance Random Float   where ...
+instance Random Double  where ...
+instance Random Bool    where ...
+instance Random Char    where ...
+
+---------------- The global random generator ----------------
+newStdGen    :: IO StdGen
+setStdGen    :: StdGen -> IO ()
+getStdGen    :: IO StdGen      
+getStdRandom :: (StdGen -> (a, StdGen)) -> IO a
+
+
diff --git a/libraries/headers/Ratio.hs b/libraries/headers/Ratio.hs
new file mode 100644 (file)
index 0000000..13755cf
--- /dev/null
@@ -0,0 +1,19 @@
+module Ratio (
+    Ratio, Rational, (%), numerator, denominator, approxRational ) where
+
+infixl 7  %
+data  (Integral a)     => Ratio a = ...
+type  Rational         =  Ratio Integer
+(%)                    :: (Integral a) => a -> a -> Ratio a
+numerator, denominator :: (Integral a) => Ratio a -> a
+approxRational         :: (RealFrac a) => a -> a -> Rational
+instance  (Integral a)  => Eq         (Ratio a)  where ...
+instance  (Integral a) => Ord        (Ratio a)  where ...
+instance  (Integral a) => Num        (Ratio a)  where ...
+instance  (Integral a) => Real       (Ratio a)  where ...
+instance  (Integral a) => Fractional (Ratio a)  where ...
+instance  (Integral a) => RealFrac   (Ratio a)  where ...
+instance  (Integral a) => Enum       (Ratio a)  where ...
+instance  (Read a,Integral a) => Read (Ratio a)  where ...
+instance  (Integral a)  => Show       (Ratio a)  where ...
+
diff --git a/libraries/headers/System.hs b/libraries/headers/System.hs
new file mode 100644 (file)
index 0000000..e534519
--- /dev/null
@@ -0,0 +1,14 @@
+module System ( 
+    ExitCode(ExitSuccess,ExitFailure),
+    getArgs, getProgName, getEnv, system, exitWith, exitFailure
+  ) where
+
+data ExitCode = ExitSuccess | ExitFailure Int 
+                deriving (Eq, Ord, Read, Show)
+
+getArgs                :: IO [String]
+getProgName            :: IO String
+getEnv                 :: String -> IO String
+system                 :: String -> IO ExitCode
+exitWith               :: ExitCode -> IO a
+exitFailure            :: IO a
diff --git a/libraries/headers/Time.hs b/libraries/headers/Time.hs
new file mode 100644 (file)
index 0000000..971c0a3
--- /dev/null
@@ -0,0 +1,44 @@
+module Time (
+       ClockTime, 
+       Month(January,February,March,April,May,June,
+             July,August,September,October,November,December),
+       Day(Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday),
+       CalendarTime(CalendarTime, ctYear, ctMonth, ctDay, ctHour, ctMin,
+                    ctPicosec, ctWDay, ctYDay, ctTZName, ctTZ, ctIsDST),
+       TimeDiff(TimeDiff, tdYear, tdMonth, tdDay, tdHour,
+                tdMin, tdSec, tdPicosec),
+       getClockTime, addToClockTime, diffClockTimes,
+        toCalendarTime, toUTCTime, toClockTime,
+        calendarTimeToString, formatCalendarTime ) where
+
+import Ix(Ix)
+
+data ClockTime = ...                   -- Implementation-dependent
+instance Ord  ClockTime where ...
+instance Eq   ClockTime where ...
+
+data Month =  January   | February | March    | April
+           |  May       | June     | July     | August
+           |  September | October  | November | December
+           deriving (Eq, Ord, Enum, Bounded, Ix, Read, Show)
+
+data Day   =  Sunday | Monday  | Tuesday  | Wednesday | Thursday 
+           |  Friday | Saturday
+           deriving (Eq, Ord, Enum, Bounded, Ix, Read, Show)
+
+data CalendarTime = CalendarTime {
+               ctYear                          :: Int,
+               ctMonth                         :: Month,
+               ctDay, ctHour, ctMin, ctSec     :: Int,
+               ctPicosec                       :: Integer,
+               ctWDay                          :: Day,
+               ctYDay                          :: Int,
+               ctTZName                        :: String,
+               ctTZ                            :: Int,
+               ctIsDST                         :: Bool
+       } deriving (Eq, Ord, Read, Show)
+
+data TimeDiff = TimeDiff {
+               tdYear, tdMonth, tdDay, tdHour, tdMin, tdSec :: Int,
+               tdPicosec                                    :: Integer
+       } deriving (Eq, Ord, Read, Show)
diff --git a/libraries/headers/Time1.hs b/libraries/headers/Time1.hs
new file mode 100644 (file)
index 0000000..1ce79d5
--- /dev/null
@@ -0,0 +1,11 @@
+-- Functions on times
+getClockTime         :: IO ClockTime
+                    
+addToClockTime       :: TimeDiff  -> ClockTime -> ClockTime
+diffClockTimes       :: ClockTime -> ClockTime -> TimeDiff
+                    
+toCalendarTime       :: ClockTime    -> IO CalendarTime
+toUTCTime            :: ClockTime    -> CalendarTime
+toClockTime          :: CalendarTime -> ClockTime
+calendarTimeToString :: CalendarTime -> String
+formatCalendarTime   :: TimeLocale -> String -> CalendarTime -> String
diff --git a/libraries/html.config b/libraries/html.config
new file mode 100644 (file)
index 0000000..e82a4d2
--- /dev/null
@@ -0,0 +1,43 @@
+aux=library.aux
+htmldir=haskell98-library-html/
+refs=librefs
+files=introduction.verb
+files=ratio.verb
+files=complex.verb
+files=numeric.verb
+files=ix.verb
+files=array.verb
+files=list.verb
+files=maybe.verb
+files=char.verb
+files=monad.verb
+files=io.verb
+files=directory.verb
+files=system.verb
+files=time.verb
+files=locale.verb
+files=cputime.verb
+files=random.verb
+#files=bit.verb
+#files=nat.verb
+#files=signed.verb
+
+
+
+index=haskell98-library-html/libindex.html
+style=article
+
+~top=<a href="index.html">top</a>
+~style=<body bgcolor="#ffffff">
+~id=<i>The Haskell 98 Library Report</i><br>
+~back=<a href="~prev.html">back</a>
+~nxt=<a href="~next.html">next</a>
+~contents=<a href="libindex.html">contents</a>
+~foot=<br><font size=2>1 February, 1999</font>
+~footer=<hr>~id~top | ~back | ~nxt | ~contents ~foot
+~sfooter=<hr>~id~top | back | ~nxt | ~contents ~foot
+~efooter=<hr>~id~top | ~back | next | ~contents ~foot
+~header=~style ~id ~top | ~back | ~nxt | ~contents <br><hr>
+~sheader=~style ~id ~top | back | ~nxt | ~contents <br><hr>
+~eheader=~style ~id ~top | ~back | next | ~contents <br><hr>
+~indexHeader=<title>Haskell 98 Library Index</title>~style ~id~top <br><h3>Haskell 98 Library Report: Index</h3>
diff --git a/libraries/index-intro.verb b/libraries/index-intro.verb
new file mode 100644 (file)
index 0000000..902ccc4
--- /dev/null
@@ -0,0 +1,3 @@
+Code entities are shown in @typewriter@ font.  Ordinary index entries
+are shown in a roman font.
+
diff --git a/libraries/index.html b/libraries/index.html
new file mode 100644 (file)
index 0000000..6245ace
--- /dev/null
@@ -0,0 +1,78 @@
+<title> The Haskell Library Report 1.4 </title>
+
+<body bgcolor="#ffffff">
+
+<div align=center>
+
+<img src="h98-libs.gif" alt="Haskell 98 Libraries">
+
+<h3 align="center">Standard Libraries for Haskell 98</h3>
+<h3 align="center">1 February 1999</h3>
+<hr>
+<a href="http://research.microsoft.com/Users/simonpj">
+Simon Peyton Jones</a> [editor], Microsoft Research, Cambridge <br>
+<a href="http://www.cs.chalmers.se/~rjmh">
+John Hughes</a> [editor], Chalmers University of Technology <br>
+<a href="http://www.cs.chalmers.se/~augustss">
+Lennart Augustsson</a>, Chalmers University of Technology <br>
+<a href="http://www.inmet.com/~dlb">
+Dave Barton</a>, Intermetrics <br>
+<a href="http://www.comp.vuw.ac.nz/Staff/Brian-Boutel.html">
+Brian Boutel</a>, Victoria University of Wellington <br>
+<a href="http://fas.sfu.ca/cs/people/Faculty/Burton/">
+Warren Burton</a>, Simon Fraser University <br>
+<a href="http://coyote.lanl.gov/HOMES/jfasel.html">
+Joseph Fasel</a>, Los Alamos National Laboratory <br>
+<a href="http://www.dcs.st-and.ac.uk/~kh/kh.html">
+Kevin Hammond</a>, University of St. Andrews <br>
+<a href="http://titan.informatik.uni-bonn.de/~ralf">
+Ralf Hinze</a>, University of Bonn <br>
+<a href="http://www.cs.yale.edu/homes/hudak-paul.html">
+Paul Hudak</a>, Yale University <br>
+<a href="http://www.cs.chalmers.se/~johnsson">
+Thomas Johnsson</a>, Chalmers University of Technology <br>
+<a href="http://www.cs.nott.ac.uk/Department/Staff/mpj/index.html">
+Mark Jones</a>, University of Nottingham <br>
+<a href="http://www.cse.ogi.edu/~jl">
+John Launchbury</a>, Oregon Graduate Institute <br>
+<a href="http://haskell.org/erik.html">
+Erik Meijer</a>, Utrecht University<br>
+<a href="http://www.cs.yale.edu/homes/peterson-john.html">
+John Peterson</a>, Yale University <br>
+<a href="http://www.cs.yale.edu/homes/reid-alastair.html">
+Alastair Reid</a>, Yale University <br>
+<a href="http://www.cs.york.ac.uk/~colin/home.html">
+Colin Runciman</a>, York University <br>
+<a href="http://cm.bell-labs.com/cm/cs/who/wadler/">
+Philip Wadler</a>, University of Glasgow <br>
+</div>
+<hr>
+Contents:
+<ul>
+<li><a href="introduction.html">Introduction</a>
+<li><a href="ratio.html">Ratio</a>
+<li><a href="complex.html">Complex</a>
+<li><a href="numeric.html">Numeric</a>
+<li><a href="ix.html">Ix</a>
+<li><a href="array.html">Array</a>
+<li><a href="list.html">List</a>
+<li><a href="maybe.html">Maybe</a>
+<li><a href="char.html">Char</a>
+<li><a href="monad.html">Monad</a>
+<li><a href="io.html">IO</a>
+<li><a href="directory.html">Directory</a>
+<li><a href="system.html">System</a>
+<li><a href="time.html">Time</a>
+<li><a href="locale.html">Locale</a>
+<li><a href="cputime.html">CPUTime</a>
+<li><a href="random.html">Random</a>
+</ul>
+<p>
+There is also a <a href="libindex.html"> complete index</a>.
+
+<p>
+The master version of the Haskell Library Report is at <a
+href="http://haskell.org/library"> haskell.org</a>.  Any corrections or
+changes in the report are found there.
+
+</body>
diff --git a/libraries/introduction.verb b/libraries/introduction.verb
new file mode 100644 (file)
index 0000000..29db1f1
--- /dev/null
@@ -0,0 +1,86 @@
+%**<title>The Haskell 98 Library Report: Introduction</title>
+%**~sheader
+
+\markboth{PREFACE}{PREFACE}
+\begin{center}
+{\Large \bf Preface}
+\end{center}
+
+\vspace{.2in}
+
+This document defines the standard libraries for \Haskell{} 98.
+
+The libraries presented here represent a selection of basic
+functionality that is expected to be useful to many \Haskell{}
+programmers.  Most implementations provide further libraries
+which are not a recognized part of the \Haskell{} standard.
+
+The latest version of this report, as well many other available libraries,
+can be found on the web at @http://haskell.org@.
+
+We would like to express our thanks to those who have contributed
+directly or indirectly to this report without being named as authors,
+including
+Olaf Chitil,
+Tony Davie,
+Sigbjorn Finne,
+Andy Gill, 
+Mike Gunter,
+Fergus Henderson,
+Kent Karlsson,
+Sandra Loosemore,
+Graeme Moss,
+Sven Panne,
+Keith Wansbrough.
+
+\clearpage
+\section{Introduction}
+\label{introduction}
+
+This document defines the standard libraries for \Haskell{} 98.  Like the @Prelude@,
+these libraries are a required part of a \Haskell{}
+implementation.  Unlike the Prelude, however, these modules must
+be {\em explicitly} imported into scope.
+
+When possible, library functions are described solely by executable
+\Haskell{} code.  Functions which require implementation-dependent
+primitives are
+represented by type signatures without definitions.
+Some data types are implementation-dependent: these are indicated
+by comments in the source.
+
+The code found here is a {\em specification}, rather than an
+{\em implementation}.  Implementations may choose more efficient versions of
+these functions.  However, all
+properties of these specifications must be preserved, including
+strictness properties. 
+
+Classes defined in libraries may be derivable.  This report includes
+the derivation of such classes when appropriate.  
+When @Prelude@ types
+are instances of derivable library classes a commented empty instance
+declaration is used.  The comment, ``as derived'', indicates that the
+instance is the same as would have been generated by a @deriving@ in
+the Prelude type declaration. 
+
+The following table summarises the fixities of all the operators 
+introduced by the standard libraries:
+\begin{table}[htb]
+\[
+\centerline{
+\begin{tabular}{|r||l|l|l|}
+\hline 
+Prec-  & Left associative      & Non-associative       & Right associative \\
+edence & operators             & operators             & operators \\ \hline\hline
+9 & @Array.!@, @Array.//@      & & \\ \hline
+7 & @Ratio.%@                  & & \\ \hline
+6 &                            & @Complex.:+@          & \\ \hline
+5 &                            & @List.\\@             & \\ \hline
+\end{tabular}}
+\]
+\ecaption{Precedences and fixities of library operators}
+\indextt{>>=}
+\end{table}
+
+
+%**~sfooter
diff --git a/libraries/io.verb b/libraries/io.verb
new file mode 100644 (file)
index 0000000..7e02d42
--- /dev/null
@@ -0,0 +1,598 @@
+%**<title>The Haskell 98 Library Report: IO</title>
+%**~header
+\section{Input/Output}
+\label{IO}
+\index{input/output}
+\index{I/O}
+\indextt{IO}
+
+% Gotta break the figure ...
+\outline{
+\inputHS{headers/IO}
+}
+\outline{
+\inputHS{headers/IO1}
+}
+
+The monadic I/O system used in \Haskell{} is described by the
+\Haskell{} language report.  Commonly used I/O functions such as
+@print@ are part of the standard prelude and need not be explicitly
+imported.  This library contain more advanced I/O features.
+Some related operations on file systems are contained in the
+@Directory@ library.
+
+\subsection{I/O Errors}
+\index{I/O errors}
+\label{IOError}
+Errors of type @IOError@ are used by the I/O monad.  This is an
+abstract type; the library provides functions to interrogate and
+construct values in @IOError@:\indextt{IOError}
+\begin{itemize}
+\item
+@isAlreadyExistsError@\indextt{isAlreadyExistsError}
+ -- the operation failed because one of its
+arguments already exists.
+\item
+@isDoesNotExistError@\indextt{isDoesNotExistError}
+ -- the operation failed because one of its
+arguments does not exist.
+\item
+@isAlreadyInUseError@\indextt{isAlreadyInUseError}
+ -- the operation failed because one of its
+arguments is a single-use resource, which is already being used (for
+example, opening the same file twice for writing might give this
+error).
+\item
+@isFullError@\indextt{isFullError}
+ -- the operation failed because the device is full.
+\item
+@isEOFError@\indextt{isEOFError}
+ -- the operation failed because the end of file
+has been reached.
+\item
+@isIllegalOperation@\indextt{isIllegalOperation}
+ -- the operation is not possible.
+\item
+@isPermissionError@\indextt{isPermissionError}
+ -- the operation failed because the user does not
+have sufficient operating system privilege to perform that operation.
+\item
+@isUserError@\indextt{isUserError}
+ -- a programmer-defined error value has been raised using
+@fail@.\indextt{fail}
+\end{itemize}
+All these functions return return a @Bool@, which is @True@ if
+its argument is the corresponding kind of error, and @False@
+otherwise.  
+
+Any computation which returns an @IO@ result may fail with
+@isIllegalOperationError@.  Additional errors which could be raised by
+an implementation are listed after the corresponding operation.  In
+some cases, an implementation will not be able to distinguish between
+the possible error causes.  In this case it should return
+@isIllegalOperationError@.
+
+Three additional functions are provided to obtain information about an
+error value.  These are @ioeGetHandle@\indextt{ioeGetHandle} which
+returns @Just@~"hdl" if the error value refers to handle "hdl" and
+@Nothing@ otherwise; @ioeGetFileName@\indextt{ioeGetFileName} which
+returns @Just@~"name" if the error value refers to file "name", and
+@Nothing@ otherwise; and @ioeGetErrorString@\indextt{ioeGetErrorString} which returns a
+string.  For ``user'' errors (those which are raised using @fail@),
+the string returned by @ioeGetErrorString@ is the argument that was passed to
+@fail@; for all other errors, the string is implementation-dependent.
+
+The @try@ function returns an error in a computation explicitly using
+the @Either@ type.
+
+The @bracket@ function 
+captures a common allocate, compute, deallocate idiom in which the
+deallocation step must occur even in the case of an error during
+computation.  This is similar to try-catch-finally in Java.
+% Inline the code here since there's no other functions in IO that
+% are not primitive.
+
+\inputHS{code/IO}
+
+
+\subsection{Files and Handles}
+\Haskell{} interfaces to the external world through an abstract {\em file
+system}\index{file system}.  This file system is a collection of named {\em file
+system objects}, which may be organised
+in {\em directories}\index{directories} (see @Directory@).  
+In some implementations, directories may themselves be file system
+objects and could be entries in other directories.  For simplicity,
+any non-directory file system object is termed a {\em file}\index{file},
+although it could in fact be a communication channel, or any other
+object recognised by the operating system.  {\em Physical
+files}\index{physical file} are 
+persistent, ordered files, and normally reside on disk.
+
+File and directory names are values of type @String@, whose precise
+meaning is operating system dependent.  Files can be opened, yielding
+a handle which can then be used to operate on the contents of that
+file.
+
+\label{Handles}
+\index{handles}
+
+\Haskell{} defines operations to read and write characters from and to files,
+represented by values of type @Handle@.  Each value of this type is a {\em
+handle}: a record used by the \Haskell{} run-time system to {\em manage} I/O
+with file system objects.  A handle has at least the following properties:
+
+\begin{itemize}
+\item
+ whether it manages input or output or both;
+\item
+ whether it is {\em open}, {\em closed} or {\em semi-closed};
+\item
+ whether the object is seekable;
+\item
+ whether buffering is disabled, or enabled on a line or block basis;
+\item
+ a buffer (whose length may be zero).
+\end{itemize}
+
+Most handles will also have a current I/O position indicating where the next
+input or output operation will occur.  A handle is {\em readable} if it
+manages only input or both input and output; likewise, it is {\em writable} if
+it manages only output or both input and output.  A handle is {\em open} when
+first allocated.  Once it is closed it can no longer be used for either input
+or output, though an implementation cannot re-use its storage while references
+remain to it.  Handles are in the @Show@ and @Eq@ classes.  The string
+produced by showing a handle is system dependent; it should include 
+enough information to identify the handle for debugging.  A handle is
+equal according to @==@ only to itself; no attempt
+is made to compare the internal state of different handles for equality.
+
+\subsubsection{Semi-Closed Handles}
+\label{SemiClosed}
+\index{semi-closed handles}
+
+The operation @hGetContents@\indextt{hGetContents} puts a handle "hdl" into an intermediate
+state, {\em semi-closed}.  In this state, "hdl" is effectively closed,
+but items are read from "hdl" on demand and accumulated in a special
+stream returned by @hGetContents@~"hdl".
+Any operation except for @hClose@ that fails because a handle is
+closed, also fails if a handle is semi-closed.  A semi-closed handle
+becomes closed:
+\begin{itemize}
+\item
+if  @hClose@ is applied to it;
+\item
+if an I/O error occurs when reading an item from the
+file item from the stream;
+\item
+or once the entire contents of the file has been read.
+\end{itemize}
+
+Once a semi-closed handle becomes closed, the contents of the
+associated stream becomes fixed, and is the list of those items which
+were successfully read from that handle. Any I/O errors encountered while
+a handle is semi-closed are simply discarded.
+
+\subsubsection{Standard Handles}
+\label{StandardHandles}
+\index{standard handles}
+
+Three handles are allocated during program initialisation.  The first
+two (@stdin@\indextt{stdin} and @stdout@\indextt{stdout}) manage input or output from the \Haskell{}
+program's standard input or output channel respectively.  The third
+(@stderr@\indextt{stderr}) manages output to the standard error channel.  These
+handles are initially open.
+
+\subsection{Opening and Closing Files}
+\label{OpeningClosing}
+
+\subsubsection{Opening Files}
+\label{Opening}
+\index{opening a file}
+\index{creating a file}
+
+Computation @openFile@~"file"~"mode"\indextt{openFile} allocates and
+returns a new, open handle to manage the file "file".
+% I don't believe this footnote is technically correct -- functions
+% are never computations IIRC: the computation is the action
+% that occurs when the function is applied to a state token -- KH
+% \footnote{We use
+% the term "computation" instead of "function" here to separate
+% functions which denote actions in the I/O monad from those outside the monad.}
+It manages
+input if "mode"\indextycon{IOMode} is @ReadMode@\indextt{ReadMode},
+output if "mode" is @WriteMode@\indextt{WriteMode} or
+@AppendMode@,\indextt{AppendMode} and both input and output if mode is
+@ReadWriteMode@.\indextt{ReadWriteMode}
+
+If the file does not exist and it is opened for output, it should be created
+as a new file.  If "mode" is @WriteMode@ and the file already exists, then it
+should be truncated to zero length.  Some operating systems delete empty
+files, so there is no guarantee that the file will exist following an
+@openFile@ with "mode" @WriteMode@ unless it is subsequently written to
+successfully.  The handle is positioned at the end of the file if "mode" is
+@AppendMode@, and otherwise at the beginning (in which case its internal I/O
+position is 0).  The initial buffer mode is implementation-dependent.
+
+If @openFile@ fails on a file opened for output, the file may still
+have been created if it did not already exist.
+
+Implementations should enforce as far as possible, locally to the
+\Haskell{} process, multiple-reader single-writer locking on files.
+Thus there may either be many handles on the same file which manage
+input, or just one handle on the file which manages output.  If any
+open or semi-closed handle is managing a file for output, no new
+handle can be allocated for that file.  If any open or semi-closed
+handle is managing a file for input, new handles can only be allocated
+if they do not manage output.  Whether two files are the same is
+implementation-dependent, but they should normally be the same if they
+have the same absolute path name and neither has been renamed, for
+example.
+
+{\em Error reporting}: the @openFile@ computation may fail with
+@isAlreadyInUseError@ if the file is already open and cannot be
+reopened;
+@isDoesNotExistError@ if the file does not exist; or
+@isPermissionError@ if the user does not have
+permission to open the file.
+
+%ADG: this is obvious!
+%KH:  Not really.  It's actually quite subtle!
+
+\subsubsection{Closing Files}
+\label{Closing}
+\index{closing a file}
+
+Computation @hClose@~"hdl"\indextt{hClose} makes handle "hdl" closed.  Before the
+computation finishes, if "hdl" is writable its buffer is flushed as
+for @hFlush@.
+If the operation fails for any reason, any further operations on the 
+handle will still fail as if "hdl" had been successfully closed.
+
+\subsection{Determining the Size of a File}
+\label{FileSize}
+\index{size of file}
+
+For a handle "hdl" which is attached to a physical file, @hFileSize@\indextt{hFileSize}
+"hdl" returns the size of that file in 8-bit bytes ("\geq" 0).
+
+\subsubsection{Detecting the End of Input}
+\label{EOF}
+\index{end of file}
+
+For a readable handle "hdl", computation @hIsEOF@~"hdl"\indextt{hIsEOF} returns @True@
+if no further input can be taken from "hdl"; for a handle attached to a 
+physical file this means that the current I/O position is equal to the length of the file.
+Otherwise, it returns @False@.  The computation @isEOF@\indextt{isEOF} is identical,
+except that it works only on @stdin@.
+
+% The computation may fail with:
+% \begin{itemize}
+% \item
+% @HardwareFault@
+% A physical I/O error has occurred.
+% [@EIO@]
+% \item
+% @ResourceExhausted@
+% Insufficient resources are available to perform the operation.
+% [@ENOMEM@]
+% \item
+% @IllegalOperation@
+% The handle is not open for reading.
+% \end{itemize}
+
+\subsubsection{Buffering Operations}
+\label{Buffering}
+\index{file buffering}
+
+Three kinds of buffering are supported: line-buffering, 
+block-buffering or no-buffering.  These modes have the following effects.
+For output, items are written out from the internal buffer 
+according to the buffer mode:
+\begin{itemize}
+\item
+{\bf line-buffering:}
+the entire buffer is written out whenever a newline is output, the
+buffer overflows, a flush is issued, or the handle is closed.
+\item
+{\bf block-buffering:}
+the entire buffer is written out whenever it overflows, a flush is
+issued, or the handle is closed.
+\item
+{\bf no-buffering:}
+output is written immediately, and never stored in the buffer.
+\end{itemize}
+The buffer is emptied as soon as it has been written out.
+
+Similarly, input occurs according to the buffer mode for handle "hdl".
+\begin{itemize}
+\item
+{\bf line-buffering:}
+when the buffer for "hdl" is not empty, the next item is obtained from
+the buffer; otherwise, when the buffer is empty, characters are read into
+the buffer until the next newline character is encountered or the buffer is full.  No
+characters are available until the newline character is available or the buffer is full.
+\item
+{\bf block-buffering:} 
+when the buffer for "hdl" becomes empty, the
+next block of data is read into the buffer.
+\item
+{\bf no-buffering:} 
+the next input item is read and returned.
+\end{itemize}
+
+For most implementations, physical files will normally be block-buffered 
+and terminals will normally be line-buffered.
+
+Computation @hSetBuffering@~"hdl"~"mode"\indextt{hSetBuffering} sets the
+mode of buffering for handle "hdl" on subsequent reads and writes.
+\begin{itemize}
+\item
+If "mode" is @LineBuffering@, line-buffering is
+enabled if possible.
+\item
+If "mode" is @BlockBuffering@~"size", then block-buffering
+is enabled if possible.  The size of the buffer is "n" items
+if "size" is @Just @"n" and is otherwise implementation-dependent.
+\item
+If "mode" is @NoBuffering@, then buffering is disabled if possible.
+\end{itemize}
+
+If the buffer mode is changed from @BlockBuffering@ or
+@LineBuffering@ to @NoBuffering@, then 
+\begin{itemize}
+\item
+if "hdl" is writable, the buffer is flushed as for 
+@hFlush@;
+\item
+if "hdl" is not writable, the contents of the buffer is discarded.
+\end{itemize}
+
+{\em Error reporting}: the @hSetBuffering@ computation may fail with
+@isPermissionError@ if
+the handle has already been used for reading or writing
+and the implementation does not allow the buffering mode to
+be changed.
+
+Computation @hGetBuffering@~"hdl"\indextt{hGetBuffering} returns the current buffering mode
+for "hdl".
+
+The default buffering mode when a handle is opened is
+implementation-dependent and may depend on the file system object which is
+attached to that handle.
+
+\subsubsection{Flushing Buffers}
+\label{Flushing}
+\index{flushing a file buffer}
+
+Computation @hFlush@~"hdl"\indextt{hFlush} causes any items buffered for output in
+handle "hdl" to be sent immediately to the operating system.
+
+{\em Error reporting}: the @hFlush@ computation may fail with:
+@isFullError@ if the device is full; @isPermissionError@ if a
+system resource limit would be exceeded.  It is unspecified whether the
+characters in the buffer are discarded or retained under these circumstances.
+
+\subsection{Repositioning Handles}
+\label{Seeking}
+\index{random access files}
+\index{seeking a file}
+
+\subsubsection{Revisiting an I/O Position}
+
+Computation @hGetPosn@~"hdl"\indextt{hGetPosn} returns the current I/O position of "hdl" as a
+value of the abstract type @HandlePosn@.  If a call to "@hGetPosn@~h" returns a position "p",
+then computation @hSetPosn@~"p"\indextt{hSetPosn} sets the
+position of "h" to the position it held at the time of the call to @hGetPosn@.
+
+
+{\em Error reporting}: the @hSetPosn@ computation may fail with:
+@isPermissionError@ if a system resource limit would be exceeded.
+
+\subsubsection{Seeking to a new Position}
+
+Computation @hSeek@~"hdl"~"mode"~"i"\indextt{hSeek} sets the position of handle
+"hdl" depending on "mode".\indextycon{SeekMode}  If "mode" is:
+\begin{itemize}
+\item
+@AbsoluteSeek@:\indextt{AbsoluteSeek} the position of "hdl" is set to "i".
+\item
+@RelativeSeek@:\indextt{RelativeSeek} the position of "hdl" is set to offset "i" from
+the current position.
+\item
+@SeekFromEnd@:\indextt{SeekFromEnd} the position of "hdl" is set to offset "i" from
+the end of the file.
+\end{itemize}
+The offset is given in terms of 8-bit bytes.
+
+If "hdl" is block- or line-buffered, then seeking to a position which is not
+in the current buffer will first cause any items in the output buffer to be
+written to the device, and then cause the input buffer to be discarded.  Some
+handles may not be seekable (see @hIsSeekable@), or only support a subset of
+the possible positioning operations (for instance, it may only be possible to
+seek to the end of a tape, or to a positive offset from the beginning or
+current position).  It is not possible to set a negative I/O position, or for
+a physical file, an I/O position beyond the current end-of-file.
+
+{\em Error reporting}:
+the @hSeek@ computation may fail with:
+@isPermissionError@ if a system resource limit would be exceeded.
+
+\subsection{Handle Properties}
+\label{Query}
+
+The functions 
+@hIsOpen@\indextt{hIsOpen}, 
+@hIsClosed@\indextt{hIsClosed},
+@hIsReadable@\indextt{hIsReadable},
+@hIsWritable@\indextt{hIsWritable} and
+@hIsSeekable@\indextt{hIsSeekable}
+return information about the properties of a handle.
+Each of these returns @True@ if the handle has the specified property, and
+@False@ otherwise.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Haskell 1.3 Text Input: LibReadTextIO
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\subsection{Text Input and Output}
+\index{reading from a file}
+%\indextt{LibReadTextIO}
+
+Here we define a standard set of input operations for reading
+characters and strings from text files, using handles.  Many of these
+functions are generalizations of Prelude functions.  I/O in the
+Prelude generally uses @stdin@ and @stdout@; here, handles are explicitly
+specified by the I/O operation.
+
+\subsubsection{Checking for Input}
+\label{hReady}
+\label{hWaitForInput}
+\index{polling a handle for input}
+
+Computation @hWaitForInput@~"hdl"~"t"\indextt{hWaitForInput} 
+waits until input is available on handle "hdl".
+It returns @True@ as soon as input is available on "hdl", or @False@ if no input is available
+within "t" milliseconds.
+
+Computation @hReady@~"hdl"\indextt{hReady} indicates whether at least one item is
+available for input from handle "hdl".
+
+Computation @hGetChar@~"hdl"\indextt{hGetChar} reads a character from
+the file or channel managed by "hdl".
+
+Computation @hGetLine@~"hdl"\indextt{hGetLine} reads a line from
+the file or channel managed by "hdl", similar to @getLine@ in the
+Prelude. 
+
+{\em Error reporting}:
+the @hWaitForInput@, @hReady@ and @hGetChar@ computations may fail with:
+@isEOFError@ if the end of file has been reached.
+
+\subsubsection{Reading Ahead}
+\label{hLookahead}
+\index{lookahead}
+
+Computation @hLookAhead@~"hdl"\indextt{hLookAhead} returns the next character from handle
+"hdl" without removing it from the input buffer, blocking until a
+character is available.
+
+{\em Error reporting}:
+the @hLookahead@ computation may fail with:
+@isEOFError@ if the end of file has been reached.
+
+\label{hGetContents}
+\index{get the contents of a file}
+
+Computation @hGetContents@~"hdl"\indextt{hGetContents} returns the list of
+characters corresponding to the unread portion of the channel or file managed
+by "hdl", which is made semi-closed.
+
+{\em Error reporting}:
+the @hGetContents@ computation may fail with:
+@isEOFError@ if the end of file has been reached.
+
+Computation @hPutChar@~"hdl"~"c"\indextt{hPutChar} writes the character "c" to the file
+or channel managed by "hdl".  Characters may be buffered if buffering
+is enabled for "hdl".
+
+Computation @hPutStr@~"hdl"~"s"\indextt{hPutStr} writes the string
+"s" to the file or channel managed by "hdl".
+
+Computation @hPrint@~"hdl"~"t"\indextt{hPrint} writes the string representation of "t"
+given by the @shows@ function to the file or channel managed by "hdl" and appends a newline.
+
+{\em Error reporting}:
+the @hPutChar@, @hPutStr@ and @hPrint@ computations may fail with:
+@isFull@-@Error@ if the device is full;
+or @isPermissionError@ if another system resource limit would be exceeded.
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Haskell 1.3 Examples
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\subsection{Examples}
+\index{input/output examples}
+
+Here are some simple examples to illustrate \Haskell{} I/O.
+
+\subsubsection{Summing Two Numbers}
+
+This program reads and sums two @Integer@s.
+\bprog
+@
+import IO
+
+main = do
+         hSetBuffering stdout NoBuffering            
+         putStr   "Enter an integer: "        
+         x1 <- readNum 
+         putStr   "Enter another integer: "          
+         x2 <- readNum                          
+         putStr  ("Their sum is " ++ show (x1+x2) ++ "\n")
+       where readNum :: IO Integer
+             readNum =  do { line <- getLine; readIO line }
+@
+\eprog
+
+\subsubsection{Copying Files}
+
+A simple program to create a copy of a file, with all lower-case
+characters translated to upper-case.  This program will not allow a
+file to be copied to itself.  This version uses character-level I/O.
+Note that exactly two arguments must be supplied to the program.
+\bprog
+@
+import IO
+import System
+
+main = do 
+         [f1,f2] <- getArgs
+         h1 <- openFile f1 ReadMode     
+         h2 <- openFile f2 WriteMode 
+         copyFile h1 h2            
+         hClose h1                  
+         hClose h2
+
+copyFile h1 h2 = do
+                   eof <- hIsEOF h1
+                   if eof then return () else
+                      do
+                        c <- hGetChar h1
+                        hPutChar h2 (toUpper c)   
+                        copyFile h1 h2
+@
+\eprog
+
+An equivalent but much shorter version, using string I/O is:
+\bprog
+@
+import System
+
+main = do
+         [f1,f2] <- getArgs
+         s <- readFile f1
+         writeFile f2 (map toUpper s)
+@
+\eprog
+
+%      Not any more in Haskell 98!
+% The @~@ used in the patterns above is a necessary consequence of the
+% @do@-notation which has been used for the I/O operations.  In general,
+% if the pattern on the left of any @<-@ fails to match, the value of
+% the entire @do@-expression is defined to be the ``zero'' in the
+% underlying monad.  However, since the @IO@ monad has no zero, the @~@
+% is required in order to force the pattern to be irrefutable.  Without
+% the @~@, a class error would occur because there is no instance of
+% @IO@ for class @MonadZero@.
+
+
+%**~footer
diff --git a/libraries/ix.verb b/libraries/ix.verb
new file mode 100644 (file)
index 0000000..2808aee
--- /dev/null
@@ -0,0 +1,109 @@
+%**<title>The Haskell 98 Library Report: Indexing Operations</title>
+%**~header
+\section{Indexing Operations}
+
+\outline{
+\inputHS{headers/Ix}
+}
+The @Ix@ class is used to map a continuous subrange of values in a
+type onto integers.  It is used primarily for array indexing (see
+Section~\ref{arrays}).  
+The @Ix@ class contains the methods @range@\indextt{range},
+@index@\indextt{index}, and @inRange@\indextt{inRange}. 
+The @index@ operation maps a bounding pair, which defines the lower
+and upper bounds of the range, and a 
+subscript, to an integer.  The @range@ operation enumerates all
+subscripts; the @inRange@ operation tells whether a particular subscript
+lies in the range defined by a bounding pair.
+
+An implementation is entitled to assume the following laws about these
+operations:
+\bprog
+@
+        range (l,u) !! index (l,u) i == i   -- when i is in range
+
+        inRange (l,u) i == i `elem` range (l,u)
+@
+\eprog
+
+% It is the responsibility of the programmer to enforce bounds
+% checking for non-derived instances of class @Ix@, if desired.
+% An implementation is not required to check that an index
+% lies within the bounds of an array when accessing that array.
+
+\subsection{Deriving Instances of @Ix@}
+\index{Ix@@{\tt Ix}!derived instance}
+
+Derived instance declarations for the class @Ix@ are only possible
+for enumerations\index{enumeration} (i.e.~datatypes having
+only nullary constructors) and single-constructor datatypes,
+including arbitrarily large tuples, whose constituent types are
+instances of @Ix@.   
+\begin{itemize}
+\item
+For an {\em enumeration}, the nullary constructors are assumed to be
+numbered left-to-right with the indices being $0$ to $n-1\/$ inclusive.
+This is the same numbering defined by the @Enum@ class.  For example,
+given the datatype:
+\bprog
+@
+data Colour = Red | Orange | Yellow | Green | Blue | Indigo | Violet
+@
+\eprog
+we would have:
+\bprog
+@
+range   (Yellow,Blue)        ==  [Yellow,Green,Blue]
+index   (Yellow,Blue) Green  ==  1
+inRange (Yellow,Blue) Red    ==  False
+@
+\eprog
+\item
+For {\em single-constructor datatypes}, the derived instance declarations
+are as shown for tuples in
+Figure~\ref{prelude-index}.
+\end{itemize}
+
+\begin{figure}[tb]
+\outline{
+@
+instance  (Ix a, Ix b)  => Ix (a,b) where
+        range ((l,l'),(u,u'))
+                = [(i,i') | i <- range (l,u), i' <- range (l',u')]
+        index ((l,l'),(u,u')) (i,i')
+                =  index (l,u) i * rangeSize (l',u') + index (l',u') i'
+        inRange ((l,l'),(u,u')) (i,i')
+                = inRange (l,u) i && inRange (l',u') i'
+
+-- Instances for other tuples are obtained from this scheme:
+--
+--  instance  (Ix a1, Ix a2, ... , Ix ak) => Ix (a1,a2,...,ak)  where
+--      range ((l1,l2,...,lk),(u1,u2,...,uk)) =
+--          [(i1,i2,...,ik) | i1 <- range (l1,u1),
+--                            i2 <- range (l2,u2),
+--                            ...
+--                            ik <- range (lk,uk)]
+--
+--      index ((l1,l2,...,lk),(u1,u2,...,uk)) (i1,i2,...,ik) =
+--        index (lk,uk) ik + rangeSize (lk,uk) * (
+--         index (lk-1,uk-1) ik-1 + rangeSize (lk-1,uk-1) * (
+--          ...
+--           index (l1,u1)))
+--
+--      inRange ((l1,l2,...lk),(u1,u2,...,uk)) (i1,i2,...,ik) =
+--          inRange (l1,u1) i1 && inRange (l2,u2) i2 &&
+--              ... && inRange (lk,uk) ik
+@
+}
+\ecaption{Derivation of Ix instances}
+\label{prelude-index}
+\indextt{Ix}                                                
+\indextt{range}\indextt{index}\indextt{inRange}   
+\indextt{rangeSize}                                         
+\end{figure}
+
+\clearpage
+\subsection{Library {\tt Ix}}
+\inputHS{code/Ix}
+
+%**~footer
diff --git a/libraries/library.verb b/libraries/library.verb
new file mode 100644 (file)
index 0000000..b1c2e54
--- /dev/null
@@ -0,0 +1,520 @@
+%
+% $Header: /home/cvs/root/haskell-report/libraries/library.verb,v 1.1 2001/03/28 14:16:23 simonpj Exp $
+%
+% NOTE:--------------------------------------------------------------
+% The formatting of this report and the ``new font selection scheme''
+% for LaTeX don't agree w/ each other.  Using an ``oldlfont'' style
+% option may help.
+% -------------------------------------------------------------------
+%
+
+% -------------------------------------------------------------------
+% formatting for ONE-SIDED printing:
+%  * De-comment the \documentstyle, etc., here; comment out the
+%    two-sided ones below.
+%  * Change the definition of \startnewstuff (below).
+%  * Copy the pre-built index file for one-sided printing:
+%       cp haskell.ind.one-sided haskell.ind
+%  * Comment out the "twosidefix" stuff from Joe Fasel, just below.
+%  * If you don't have "makeindex", make the adjustments
+%    listed in the README file.
+%  * Run "make haskell.dvi" several times (three, at most) to be
+%    sure that cross-references stabilise.  [For the 1.1 report,
+%    one run should be enough.]
+\documentstyle[twoside,11pt,makeidx]{article}
+\oddsidemargin=.25in
+\evensidemargin=.25in
+
+% formatting for double-sided
+%\documentstyle[twoside,11pt,makeidx]{article}
+% Inverted for SIGPLAN -- Page 1 is a LEFT page!!
+%\evensidemargin=0in
+%\oddsidemargin=.5in
+%\evensidemargin=.5in
+%\oddsidemargin=0in
+%---------------------------------------------------------------------
+% Joe Fasel said this "twosidefix" is necessary if you really
+% have a two-sided printer:
+%       (note: double @@'s for verbatim-ery)
+\makeatletter
+\def\titlepage{\@@restonecolfalse\if@@twocolumn\@@restonecoltrue\onecolumn
+ \else \newpage \fi \thispagestyle{empty}\c@@page\m@@ne}
+\def\endtitlepage{\if@@twoside\newpage\thispagestyle{empty}\hbox{}
+                        \else \c@@page\@@z \fi
+   \if@@restonecol\twocolumn \else \newpage \fi}
+\makeatother
+%---------------------------------------------------------------------
+
+% the major sections have \cleardoublepages between them
+% if you want those between EVERY section, change the
+% following defn:
+\newcommand{\startnewsection}{\clearpage}
+%
+% if doing one-sided printing, change this defn to
+% be just "\clearpage":
+\newcommand{\startnewstuff}{\clearpage}
+%\newcommand{\startnewstuff}{\cleardoublepage}
+% keep some pages from looking unbelievably appalling
+\raggedbottom
+
+% Fix those ugly floating figures.
+\renewcommand{\floatpagefraction}{0.1}
+\renewcommand{\textfraction}{0.1}
+\renewcommand{\topfraction}{1.0}
+\renewcommand{\bottomfraction}{1.0}
+
+% table of contents: show only down to subsections
+\setcounter{tocdepth}{2}
+
+% general formatting
+\textheight=8.5in
+\textwidth=6.0in
+\topmargin=0in
+\pagestyle{headings}
+
+\makeindex
+% an extra thing for makeindex
+\newcommand{\seealso}[2]{{\em see also\/} #1}
+
+% NEWCOMMANDS
+
+% general
+\newcommand{\folks}[1]{\begin{quote}\sf#1\end{quote}}
+\newcommand{\sectionpart}[1]{\vspace{2 ex}\noindent{\bf #1}}
+\newcommand{\bq}{\begin{quote}}
+\newcommand{\eq}{\end{quote}}
+\newcommand{\bt}{\begin{tabular}}
+\newcommand{\et}{\end{tabular}}
+\newcommand{\bi}{\begin{itemize}}
+\newcommand{\ei}{\end{itemize}}
+\newcommand{\struthack}[1]{\rule{0pt}{#1}}
+\newcommand{\inputHS}{\input}
+\newcommand{\ignorehtml}[1]{#1}
+
+%\newcommand{\ToDo}[1]{}
+\newcommand{\ToDo}[1]{({\bf $\spadesuit$ ToDo:} {\em #1})}
+
+\newcommand{\WeSay}[1]{}
+%\newcommand{\WeSay}[1]{({\bf $\clubsuit$ YaleSays:} {\em #1})}
+
+\newcommand{\anchor}[2]{#2}
+
+% indexing
+\newcommand{\indextt}[1]{\index{#1@@{\tt #1}}}
+\newcommand{\indexsyn}[1]{\index{#1@@{\it #1}}}
+\newcommand{\indexmodule}[1]{\index{#1@@{\tt #1} (module)}}
+\newcommand{\indextycon}[1]{\index{#1@@{\tt #1} (datatype)}}
+\newcommand{\indexsynonym}[1]{\index{#1@@{\tt #1} (type synonym)}}
+\newcommand{\indexnote}[1]{#1n}
+
+\makeatletter
+\def\theindex{\@@restonecoltrue\if@@twocolumn\@@restonecolfalse\fi
+\columnseprule \z@@
+\columnsep 35pt\twocolumn[\section*{Index}
+        \addcontentsline{toc}{section}{Index}
+        \input{index-intro}\vskip 20pt]
+ \@@mkboth{INDEX}{INDEX}\thispagestyle{plain}\parindent\z@@
+ \parskip\z@@ plus .3pt\relax\let\item\@@idxitem
+}
+\makeatother
+
+% outlined figures
+\newcommand{\ecaption}[1]{\vspace{-1 ex}\caption{#1}\vspace{1 ex}}
+% partain fiddled here...
+%   also had to change two lines in verbatim.lex from
+%<SYNTAX>{nl}"|"{sp}    { printf ("$\\\\ \n$\\it "); 
+%                         printf ("$\\>\\makebox[3em]{$|$}$\\it "); }
+% to
+%
+%<SYNTAX>{nl}"|"{sp}    { printf ("$\\\\ \n$\\it "); 
+%                         printf ("$\\>\\makebox[3.5em]{$|$}$\\it "); }
+% so things would still line up.  Oh what a hack.
+%
+%\newcommand{\outline}{\outlinewidth{1.0}}
+%\newcommand{\outlinewidth}[2]{
+%\begin{center}
+%\fbox{ \begin{minipage}{#1\textwidth}
+%\vspace{1 ex}
+%#2
+%\end{minipage} }
+%\vspace{1 ex}
+%\end{center}
+%}
+% 6.0in (\textwidth) - 15pt (overfullness) ~=~ 415pt
+\newcommand{\outline}[1]{%
+\begin{center}
+\fbox{ \begin{minipage}{415pt}
+\vspace{1 ex}
+#1
+\end{minipage} }
+\vspace{1 ex}
+\end{center}
+}
+
+\newcommand{\outlinec}{\outline}  % Centered outlines in html
+
+% haskell code
+% partain fiddled here...
+% \newcommand{\bprog}{\par \begin{tabular}{|l} 
+%                   \mbox \bgroup \begin{minipage} {\textwidth} }
+% 6.0in (\textwidth) - 17pt (\parindent) ~=~ 412pt
+%\newcommand{\bprog}{\par \begin{tabular}{@@{}l@@{}} 
+%                   \mbox \bgroup \begin{minipage} {412pt} }
+%\newcommand{\eprog}{\end{minipage} 
+%                    \egroup
+%                    \end{tabular}\\[\parskip]}
+% 17pt is \parindent
+% this method gives a 17pt indent in _all_ situations
+\newcommand{\bprog}{%
+\par\noindent\begin{tabular}{@@{\hspace*{17pt}}l@@{}}}
+\newcommand{\eprog}{%
+\end{tabular}\\[\parskip]}
+\newcommand{\eprogNoSkip}{%
+\end{tabular}}
+%
+% variants for stdprelude; don't indent, and skip a little more
+\newcommand{\bprogB}{%
+\begin{tabular}{@@{}l@@{}}}
+\newcommand{\eprogB}{%
+\end{tabular}\\[0.6\baselineskip]}
+
+%special characters
+\newcommand{\bkq}{\mbox{\it \char'022}} % (syntax) backquote char
+\newcommand{\bkqB}{\bkq} % (syntax) backquote char (Before)
+\newcommand{\bkqA}{\hspace{-.2em}\mbox{\it \char'022}}% (syntax) backquote char (After)
+%\newcommand{\fwq}{\mbox{\it \char'023}} % (syntax) (forward) quote char
+% math formatting
+\newcommand{\ba}{\begin{array}}
+\newcommand{\ea}{\end{array}}
+\newcommand{\mc}{\multicolumn}
+\newcommand{\pile}[1]{\ba[t]{@@{}l@@{}} #1 \ea}
+\newcommand{\eqn}[1]{\ba[t]{@@{}lcl@@{}} #1 \ea}
+\newcommand{\equate}[1]{\[\eqn{#1}\]}
+\newcommand{\la}{\leftarrow}
+\newcommand{\ra}{\rightarrow}
+\newcommand{\sq}[1]{[\,#1\,]}
+\newcommand{\ab}[1]{\langle#1\rangle}
+\newcommand{\ablarge}[1]{\langle \pile{#1\,\rangle}}
+\newcommand{\lb}{[\![}
+\newcommand{\rb}{]\!]}
+\newcommand{\db}[1]{\lb#1\rb}
+\newcommand{\ti}[1]{\mbox{{\it #1}}}
+\newcommand{\tr}[1]{\mbox{{\rm #1}}}
+\newcommand{\tb}[1]{\mbox{{\bf #1}}}
+\newcommand{\x}{\times}
+\newcommand{\lam}{\lambda}
+\newcommand{\kr}{\kappa_{\rho}}
+\newcommand{\syneq}{\rightarrow}
+% denotational semantics
+\newcommand{\denote}[3]{\[\ba{c} {\cal #1} : #2 \\[1 ex] #3 \ea\]}
+\newcommand{\den}[2]{{\cal #1}\db{#2}\,}
+
+\newcommand{\A}{\den{A}}
+\newcommand{\B}{\den{B}}
+\newcommand{\D}{\den{D}}
+\newcommand{\E}{\den{E}}
+\newcommand{\F}{\den{F}}
+\newcommand{\G}{\den{G}}
+\newcommand{\I}{\den{I}}
+%%% \renewcommand{\L}{\den{L}}
+\newcommand{\LE}{\den{L_E}}
+\newcommand{\LH}{\den{L_H}}
+\newcommand{\M}{\den{M}}
+%%% \renewcommand{\O}{\den{O}}
+\renewcommand{\P}{\den{P}}
+\newcommand{\Pbot}{\den{P_{\bot}}}
+\newcommand{\Q}{\den{Q}}
+\newcommand{\R}{\den{R}}
+\renewcommand{\S}{\den{S}}
+\newcommand{\V}{\den{V}}
+\newcommand{\W}{\den{W}}
+\newcommand{\T}[2]{\den{T}{#1}\,\db{#2}}
+% meta language
+\newcommand{\PP}{\den{P'}}
+\newcommand{\PS}{\den{P_S}}
+\newcommand{\otherwise}{\quad\tr{otherwise}}
+\newcommand{\case}[2]{\pile{
+ \tr{case}\ (#1)\ \tr{of} \\
+ \ba{@@{\quad}l@@{\ \ra\ }l@@{}} #2 \ea}}
+\newcommand{\where}[2]{#1 \quad\tr{where}\quad #2}
+\newcommand{\wherelarge}[2]{\pile{#1 \\ \tr{where} \\ \eqn{#2}}}
+\newcommand{\cond}[3]{#1 \ra #2,\ #3}
+\newcommand{\condlarge}[1]{\ba[t]{@@{}l@@{\ \ra\ }l@@{}} #1 \ea}
+\newcommand{\range}[2]{{}_{#1}^{#2}\,}
+% semantic operators
+\newcommand{\concat}{\frown}
+\newcommand{\seq}[1]{\ti{List}\ #1}
+\newcommand{\opt}[1]{\widetilde{#1}}
+\newcommand{\ov}{\opt{v}}
+\newcommand{\fail}{\ti{none}}
+\newcommand{\nonfail}{\ti{proper}}
+\newcommand{\sym}{\bigtriangledown}
+\newcommand{\pri}{\mathbin{\vec{\sym}}}
+\newcommand{\mrg}{\mathbin{\dot{\sym}}}
+\newcommand{\Sym}{\mathbin{\nabla}}
+\newcommand{\Pri}{\mathbin{\vec{\Sym}}}
+\newcommand{\Mrg}{\mathbin{\dot{\Sym}}}
+\newcommand{\optSym}{\mathbin{\opt{\Sym}}}
+\newcommand{\optodot}{\mathbin{\opt{\odot}}}
+\newcommand{\proj}{\mid}
+\newcommand{\restrict}{\setminus}
+\newcommand{\sel}[4]{\ti{sel}_{#3#2}\ #4}
+\newcommand{\bindnone}{\ti{bindnone}}
+\newcommand{\bindvar}[2]{\ti{bindvar}\ \db{#1}\ #2}
+\newcommand{\bindcon}[2]{\ti{bindcon}\ \db{#1}\ #2}
+\newcommand{\bindconlarge}[4]{
+ #4\ \bindcon{#1}{\ablarge{ #2, \\ #3}}}
+\newcommand{\bindmod}[2]{\ti{bindmod}\ \db{#1}\ #2}
+
+\newcommand{\lookupval}[2]{\ti{lookupval}\ #1\ \db{#2}} %%% NEW
+\newcommand{\lookupcon}[1]{\ti{lookupcon}\ \db{#1}} %%% NEW
+\newcommand{\lookupdecon}[2]{\ti{lookupdecon}\ #1\ \db{#2}} %%% NEW
+
+% used in static.verb
+\newcommand{\TT}{\den{T_T}}
+\newcommand{\TA}{\den{T_A}}
+\newcommand{\TB}{\den{T_B}}
+\newcommand{\TD}{\den{T_D}}
+\newcommand{\TDA}{\den{T_{D_A}}}
+\newcommand{\TDB}{\den{T_{D_B}}}
+\newcommand{\TDP}{\den{T_{P_D}}}
+\newcommand{\TE}{\den{T_E}}
+\newcommand{\TLE}{\den{T_{L_E}}}
+\newcommand{\TLH}{\den{T_{L_H}}}
+%%% \newcommand{\TG}{\den{T_G}}
+\newcommand{\TQ}{\den{T_Q}}
+%%% \newcommand{\TR}{\den{T_R}}
+\newcommand{\TF}{\den{T_F}}
+\newcommand{\TFA}{\den{T_F'}}
+\newcommand{\TP}{\den{T_P}}
+\newcommand{\TPP}{\den{T_P'}}
+\newcommand{\TPS}{\den{T_{PS}}}
+\newcommand{\MGU}{\ti{MGU}}
+\newcommand{\TI}{\den{T_I}}
+\newcommand{\TL}{\den{T_L}}
+\newcommand{\TM}{\den{T_M}}
+%%% \newcommand{\TO}{\den{T_O}}
+\newcommand{\TS}{\den{T_S}}
+\newcommand{\TV}{\den{T_V}}
+\newcommand{\tenvm}{\ddot{\nabla}}
+\renewcommand{\tb}[1]{\triangleright#1\triangleleft}
+\newcommand{\unbindvar}[2]{\ti{unbindvar}\ \db{#1}\ #2}
+\newcommand{\unbindcon}[2]{\ti{unbindcon}\ \db{#1}\ #2}
+
+%
+% \newcommand{\bindnone}{\ab{[], []}}
+% \newcommand{\bindvar}[2]{\ab{[\,#1 \mapsto #2\,], []}}
+% \newcommand{\bindcon}[2]{\ab{[], [\,#1 \mapsto #2\,]}}
+% \newcommand{\bindconlarge}[4]{
+%  \langle [], [\,#1 \mapsto \langle \pile{#2 \\ #3 \rangle\,] #4 \rangle}}
+% \newcommand{\bindmod}[2]{[\,#1 \mapsto #2\,]}
+%
+% Haskell syntax macros: math mode assumed
+\newcommand{\system}[2]{#1@;;@\cdots@;;@#2}
+\newcommand{\module}[4]{module\ #1@:@\ #2\ #3\ #4}
+%%% \newcommand{\exportnone}{\,}
+%%% \newcommand{\export}[1]{@export@\ #1@;@}
+%%% \newcommand{\importnone}{\,}
+%%% \newcommand{\importcomb}[2]{#1\ #2}
+%%% \newcommand{\import}[1]{@import@\ #1@;@}
+%%% \newcommand{\importwith}[2]{@import@\ #1\ #2@;@}
+%%% \newcommand{\rename}[2]{#1@<-@#2}
+%%% \newcommand{\declcomb}[2]{#1\ @;;@\ #2}
+\newcommand{\exposing}[1]{@expose@\ #1}
+\newcommand{\hiding}[1]{@hide@\ #1}
+\newcommand{\importnone}{\;}
+\newcommand{\importcomb}[2]{#1\ @;;@\ #2}
+\newcommand{\import}[2]{@import@\ #1\ #2}
+\newcommand{\rename}[2]{#1\ @=@\ #2}
+\newcommand{\declcomb}[2]{#1\ @;;@\ #2}
+
+\newcommand{\type}[2]{@type@\ #1\ @=@\;#2}
+\newcommand{\data}[2]{@data@\ #1\ @=@\;#2}
+\newcommand{\tuple}[2]{@tuple@\ #1\ @=@\;#2} %%% NEW!
+\newcommand{\view}[3]{@view@\ #1\ @=@\;#2\ @where@\ @{@\ #3\ @}@}
+\newcommand{\class}[2]{@class@\ #1\ @where@\ @{@\ #2\ @}@}
+\newcommand{\instance}[2]{@instance@\ #1\ @where@\ @{@\ #2\ @}@}
+\newcommand{\signature}[2]{#1\ @::@\ #2}
+\newcommand{\binding}[2]{#1\ @=@\ #2}
+\newcommand{\lamexpr}[2]{@\@ #1 @->@ #2}
+% While lambda defs. change...  if change, take care of preceding line MMG
+\newcommand{\lamb}{@\ @}
+\newcommand{\whereexpr}[2]{#1\ @where@\ @{@\ #2\ @}@}
+\newcommand{\compexpr}[2]{@[@#1\ @|@\ #2@]@}
+\newcommand{\genclause}[2]{#1\ @<-@\ #2}
+\newcommand{\qualcomb}[2]{#1\ @,@\ #2}
+\newcommand{\genguard}[1]{\ #1\ }
+\newcommand{\caseexpr}[2]{@case@\ #1\ @of@\ @{@\ #2\ @}@}
+\newcommand{\simplecaseexpr}[5]{@case@\ #1\ @of@\ @{@\ #2\ @->@\ #3;\ #4\ @->@\ #5\ @}@} 
+\newcommand{\iteexpr}[3]{@if@\ #1\ @then@\ #2\ @else@\ #3}
+\newcommand{\itexpr}[2]{@if@\ #1\ @then@\ #2}
+\newcommand{\gpat}[2]{#1\ @|@\ #2}
+\newcommand{\aspat}[2]{#1 @ @@ @ #2}
+\newcommand{\fclause}[2]{#1\ @=@\ #2}
+\newcommand{\fsym}[2]{#1\ @;@\ #2}
+\newcommand{\fpri}[2]{#1\ @;@\ @else@\ @;@\ #2}
+\newcommand{\aclause}[2]{#1\ @->@\ #2}
+\newcommand{\saclause}[4]{#1\ @->@\ #2;\ #3\ @->@\ #4}
+\newcommand{\asym}[2]{#1\ @;@\ #2}
+\newcommand{\apri}[2]{#1\ @;@\ @else@\ @;@\ #2}
+\newcommand{\dotted}[3]{#1\ #2\ \ldots\ #3}
+\newcommand{\functype}[2]{#1\ @->@\ #2}
+\newcommand{\predtype}[2]{#1\ @=>@ #2}
+\newcommand{\xp}{\dotted{x}{p_1}{p_n}}
+\newcommand{\xpg}{\dotted{x}{p_1}{p_n\ @{@\ g\ @}@}}
+\newcommand{\es}{e_1\ \ldots\ e_n}
+\newcommand{\ps}{p_1\ \ldots\ p_n}
+\newcommand{\vs}{v_1\ \ldots\ v_n} %%% NEW
+\newcommand{\xs}{x_1\ \ldots\ x_n} %%% NEW
+\newcommand{\cT}{\dotted{c}{T_1}{T_n}}
+\newcommand{\cTm}{\dotted{c_i}{T_{i1}}{T_{in_i}}\, @|@\range{i=1}{m}}
+% syntax meta-language
+\newcommand{\arity}[1]{\tr{arity}\ #1}
+\newcommand{\infix}[1]{\tr{infix}\ #1}
+\newcommand{\prefix}[1]{\tr{prefix}\ #1}
+%
+\newcommand{\tl}[1]{{\sc #1}}
+%OLD: \newcommand{\Haskell}{{\sc Haskell}}
+\newcommand{\Haskell}{Haskell}
+
+%\newcommand{\subsubsubsection}[1]{\par\noindent{\it #1}}
+\newcommand{\subsubsubsection}{\subsubsection*}
+
+%\sloppy
+
+% a few hyphenation patterns, anyone?
+\hyphenation{da-ta-type da-ta-types}
+\hyphenation{Has-kell}
+
+
+\begin{document}
+
+
+% Set the float fractions to sensible values
+\setcounter{topnumber}{2}
+\setcounter{bottomnumber}{0}
+\setcounter{totalnumber}{2}
+\setcounter{dbltopnumber}{2}
+\renewcommand{\textfraction}{0.1}
+\renewcommand{\floatpagefraction}{0.9}
+\renewcommand{\dblfloatpagefraction}{0.9}
+
+\setcounter{page}{0}
+
+\begin{titlepage}
+
+\setcounter{page}{0}
+
+\outline{
+\vspace{.3in}
+\begin{center}
+{\LARGE\bf Standard Libraries} \\[.1in]
+{\Large\bf for the} \\[.1in]
+{\huge\bf Haskell 98} \\[.3in]
+{\LARGE\bf Programming Language} \\[.3in]
+{\large\bf 1 February 1999}
+\end{center}
+
+\vspace{.15in}
+\begin{center} \large
+Simon Peyton Jones$^8$ [editor] \\
+John Hughes$^3$ [editor] \\
+Lennart Augustsson$^3$ \\
+Dave Barton$^7$ \\
+Brian Boutel$^4$ \\
+Warren Burton$^5$ \\
+Joseph Fasel$^6$ \\
+Kevin Hammond$^2$ \\
+Ralf Hinze$^{12}$ \\
+Paul Hudak$^1$ \\
+Thomas Johnsson$^3$ \\
+Mark Jones$^9$ \\
+John Launchbury$^{14}$ \\
+Erik Meijer$^{10}$\\
+John Peterson$^1$ \\
+Alastair Reid$^1$ \\
+Colin Runciman$^{13}$ \\
+Philip Wadler$^{11}$ \\
+\end{center}
+\vspace{.15in}
+
+\begin{quotation} \noindent
+Authors' affiliations:
+(1)~Yale University
+(2)~University of St.~Andrews
+(3)~Chalmers University of Technology
+(4)~Victoria University of Wellington
+(5)~Simon Fraser University
+(6)~Los Alamos National Laboratory
+(7)~Intermetrics
+(8)~Microsoft Research, Cambridge
+(9)~University of Nottingham
+(10)~Utrecht University
+(11)~Bell Labs
+(12)~University of Bonn
+(13)~York University
+(14)~Oregon Graduate Institute
+\end{quotation}
+\vspace{.2in}
+}
+
+\end{titlepage}
+
+\tableofcontents
+\startnewstuff
+
+\sloppy
+\setlength{\parskip}{0.25cm}
+\setlength{\parsep}{0.25cm}
+\setlength{\topsep}{0cm}
+\setlength{\parindent}{0cm}
+\renewcommand{\textfraction}{0.2}
+\renewcommand{\floatpagefraction}{0.7}
+% \parskip=6pt plus2pt minus2pt
+
+%\markboth{\rm \thepage\hfil \sl \leftmark}{{\sl \rightmark}\hfil \rm\thepage}
+\pagestyle{headings}
+\startnewstuff
+\pagenumbering{arabic}
+
+\input{introduction}\startnewsection
+\input{ratio}\startnewsection
+\input{complex}\startnewsection
+\input{numeric}\startnewsection
+\input{ix}\startnewsection
+\input{array}\startnewsection
+\input{list}\startnewsection
+\input{maybe}\startnewsection
+\input{char}\startnewsection
+\input{monad}\startnewsection
+\input{io}\startnewsection
+\input{directory}\startnewsection
+\input{system}\startnewsection
+\input{time}\startnewsection
+\input{locale}\startnewsection
+\input{cputime}\startnewsection
+\input{random}\startnewsection
+% \input{bit}\startnewsection
+% \input{nat}\startnewsection
+% \input{signed}\startnewsection
+%\input{interrupt}\startnewsection
+
+% There's no extra indexing stuff yet.
+% \startnewstuff
+% insert the extra indexing things LAST
+% \input{index-extra}
+
+% There's currently no bibliography!  -- jcp
+
+% Add a contents line for the References -- may be off by one page
+%\addcontentsline{toc}{section}{References}
+% \bibliographystyle{plain}
+% \bibliography{library}
+%
+\startnewstuff
+\printindex
+\end{document}
+
+% Local Variables: 
+% mode: latex
+% End:
diff --git a/libraries/list.verb b/libraries/list.verb
new file mode 100644 (file)
index 0000000..34e1eae
--- /dev/null
@@ -0,0 +1,221 @@
+%**<title>The Haskell 98 Library Report: List Utilities</title>
+%**~header
+\section{List Utilities}
+
+\outline{
+\inputHS{headers/List}
+}
+\outline{
+\inputHS{headers/List1}
+}
+
+This library defines some lesser-used operations over lists.
+
+\subsection{Indexing lists}
+
+Function @elemIndex val list@\indextt{elemIndex} returns the index of
+the first occurrence, if any, of @val@  
+in @list@ as @Just index@.  @Nothing@ is returned if @not (val `elem` list)@.
+
+Function @elemIndices val list@\indextt{elemIndices} returns an
+in-order list of indices, giving the occurrences of @val@ in @list@.
+
+Function @find@ returns the first element of a list that satisfies a predicate,
+or Nothing, if there is no such element.
+@findIndex@ returns the corresponding index.
+@findIndices@ returns a list of all such indices.
+
+\subsection{``Set'' operations}
+
+There are a number of ``set'' operations defined over the @List@ type.
+@nub@ (meaning ``essence'') removes duplicates elements from a list.
+@delete@, @(\\)@, @union@ and @intersect@ preserve the invariant that 
+lists don't contain duplicates, provided that their first argument
+contains no duplicates.
+
+\begin{itemize}
+\item
+@delete x@ removes the first occurrence of @x@ from its list argument,
+e.g.,  
+\bprog
+@
+  delete 'a' "banana" == "bnana"
+@
+\eprog
+
+\item
+@(\\)@ is list difference (non-associative).  In the result of @xs \\ ys@,
+the first occurrence of each element of @ys@ in turn (if any)
+has been removed from @xs@.  Thus, @(xs ++ ys) \\ xs == ys@.
+@union@ is list union, e.g., 
+\bprog
+@
+  "dog" `union` "cow" == "dogcw"
+@
+\eprog
+
+\item
+@intersect@ is list intersection, e.g.,  
+\bprog
+@
+  intersect [1,2,3,4] `intersect` [2,4,6,8] == [2,4]
+@
+\eprog
+\end{itemize}
+
+\subsection{List transformations}
+
+\begin{itemize}
+\item
+@intersperse sep@ inserts @sep@ between the elements of its list argument,
+e.g.,  
+\bprog
+@
+  intersperse ',' "abcde" == "a,b,c,d,e"
+@
+\eprog
+
+\item
+@transpose@ transposes the rows and columns of its argument,
+e.g., 
+\bprog
+@
+  transpose [[1,2,3],[4,5,6]] == [[1,4],[2,5],[3,6]]
+@
+\eprog
+
+\item
+@partition@ takes a predicate and a list and returns a pair of lists:
+those elements of the argument list that do and do not satisfy the
+predicate, respectively; i.e.,
+\bprog
+@
+  partition p xs == (filter p xs, filter (not . p) xs)
+@
+\eprog
+
+\item
+@sort@/@sortBy@ implement a stable sorting algorithm, here specified
+in terms of the @insertBy@ function, which inserts objects into a list
+according to the specified ordering relation.
+
+\item
+@group@ splits its list argument into a list of lists of equal, adjacent
+elements. For exmaple
+\bprog
+@
+  group "Mississippi" == ["M","i","ss","i","ss","i","pp","i"]
+@
+\eprog
+
+\item
+@inits@ returns the list of initial segments of its argument list, shortest first.
+\bprog
+@
+  inits "abc" == ["","a","ab","abc"]
+@
+\eprog
+
+\item
+@tails@ returns the list of all final segments of its argument list, longest first.
+\bprog
+@
+  tails "abc" == ["abc", "bc", "c",""]
+@
+
+\eprog
+\item
+@mapAccumL f s l@ applies @f@ to an accumulating ``state'' parameter @s@
+and to each element of @l@ in turn.
+
+\item
+@mapAccumR@ is similar to @mapAccumL@ except that the list
+is processed from right-to-left rather than left-to-right.
+\end{itemize}
+
+\subsection{@unfoldr@}
+
+The @unfoldr@ function undoes a @foldr@ operation.  Note that,
+in general, only invertible functions can be unfolded.
+\bprog
+@
+  unfoldr f' (foldr f z xs) == xs
+@
+\eprog
+if the following holds:
+\bprog
+@
+  f' (f x y) = Just (x,y)
+  f' z       = Nothing
+@
+\eprog
+
+\subsection{Predicates}
+
+@isPrefixOf@ and @isSuffixOf@ check whether the first argument is a prefix (resp. suffix)
+of the second argument.
+
+
+\subsection{The ``@By@'' operations}
+
+By convention, overloaded functions have a non-overloaded
+counterpart whose name is suffixed with ``@By@''.  For example, the
+function @nub@ could be defined as follows:
+\bprog
+@
+  nub                     :: (Eq a) => [a] -> [a]
+  nub []                  =  []
+  nub (x:xs)              =  x : nub (filter (\y -> x /= y) xs)
+@
+\eprog
+However, the equality method may not be appropriate in all situations.
+The function:
+\bprog
+@
+  nubBy                   :: (a -> a -> Bool) -> [a] -> [a]
+  nubBy eq []             =  []
+  nubBy eq (x:xs)         =  x : nubBy eq (filter (\y -> not (eq x y)) xs)
+@
+\eprog
+allows the programmer to supply their own equality test.
+When the ``@By@'' function replaces an @Eq@ context by a binary predicate,
+the predicate is assumed to define an equivalence; when the ``@By@''
+function replaces an @Ord@ context by a binary predicate, the
+predicate is assumed to define a total ordering.
+
+The ``@By@'' variants are as follows:
+@nubBy@, @deleteBy@, @unionBy@, @intersectBy@, @groupBy@,
+@sortBy@, @insertBy@, @maximumBy@, @minimumBy@.  The library does not
+provide @elemBy@, because @any (eq x)@ does the same job as @elemBy eq x@ would.
+A handful of overloaded functions (@elemIndex@, @elemIndices@, @isPrefixOf@, @isSuffixOf@)
+were not considered important enough to have ``@By@'' variants.
+
+% Several of the functions defined here are derivatives of, or
+% related to, Prelude functions.  These functions are
+% @elem@, @maximum@, @minimum@, @zip@, @zip3@, @zipWith@,
+% @zipWith3@, @unzip@, @unzip3@, 
+% [according to Keith] @take@, @drop@, @splitAt@, @index@, @replicate@.
+
+\subsection{The ``@generic@'' operations}
+
+The prefix ``@generic@'' indicates an overloaded function that is
+a generalised version of a @Prelude@ function.  For example,
+\bprog
+@
+  genericLength       :: Integral a => [b] -> a
+@ 
+\eprog
+is a generalised verion of @length@.
+
+The ``@generic@'' operations are as follows:
+@genericLength@, @genericTake@, @genericDrop@,
+    @genericSplitAt@, @genericIndex@, @genericReplicate@.
+
+
+
+\clearpage
+\subsection{Library {\tt List}}
+\label{List}
+\inputHS{code/List}
+
+%**~footer
diff --git a/libraries/locale.verb b/libraries/locale.verb
new file mode 100644 (file)
index 0000000..249fc8f
--- /dev/null
@@ -0,0 +1,19 @@
+%**<title>The Haskell 98 Library Report: Locale</title>
+%**~header
+\section{Locale}
+\label{locale}
+\index{locale}
+
+\outline {
+\inputHS{headers/Locale}
+}
+
+The @Locale@ library provides the ability to adapt to local
+conventions.  At present, it supports only time and date information
+as used by @calendarTimeToString@ from the @Time@ library.
+
+\clearpage
+\subsection{Library {\tt Locale}}
+\inputHS{code/Locale}
+
+%**~footer
diff --git a/libraries/maybe.verb b/libraries/maybe.verb
new file mode 100644 (file)
index 0000000..f9105ab
--- /dev/null
@@ -0,0 +1,30 @@
+%**<title>The Haskell 98 Library Report: Maybe Utilities</title>
+%**~header
+\section{Maybe Utilities}
+
+\outline{
+\inputHS{headers/Maybe}
+}
+
+The type constructor @Maybe@ is defined in @Prelude@ as
+\bprog
+@
+data Maybe a = Nothing | Just a
+@
+\eprog
+The purpose of the @Maybe@ type is to provide a method of dealing with
+illegal or optional values without terminating the program, as would
+happen if @error@ were used, and without using @IOError@ from the @IO@
+monad, which would cause the expression to become monadic.  A correct
+result is encapsulated by wrapping it in @Just@; an incorrect result
+is returned as @Nothing@.
+
+Other operations on @Maybe@ are provided as part of the monadic
+classes in the Prelude.
+
+\clearpage
+\subsection{Library {\tt Maybe}}
+\label {Maybe}
+\inputHS{code/Maybe}
+
+%**~footer
diff --git a/libraries/monad.verb b/libraries/monad.verb
new file mode 100644 (file)
index 0000000..737cbc2
--- /dev/null
@@ -0,0 +1,187 @@
+%**<title>The Haskell 98 Library Report: Monad Utilities</title>
+%**~header
+\section{Monad Utilities}
+\label{Monad}
+
+\outline{
+\inputHS{headers/Monad}
+}
+
+The @Monad@ library defines the @MonadPlus@ class, and 
+provides some useful operations on monads.
+
+\subsection{Naming conventions}
+
+The functions in this library use the following naming conventions:
+\begin{itemize}
+\item
+A postfix ``@M@'' always stands for a function in the Kleisli category:
+@m@ is added to function results (modulo currying) and nowhere else.
+So, for example,
+\bprog
+@
+  filter  ::              (a ->   Bool) -> [a] ->   [a]
+  filterM :: (Monad m) => (a -> m Bool) -> [a] -> m [a]
+@
+\eprog
+
+\item A postfix ``@_@'' changes the result type from @(m a)@ to @(m ())@.
+Thus (in the @Prelude@):
+\bprog
+@
+sequence  :: Monad m => [m a] -> m [a] 
+sequence_ :: Monad m => [m a] -> m () 
+@
+\eprog
+
+\item A prefix ``@m@'' generalises an existing function to a monadic form.
+Thus, for example:
+\bprog
+@
+  sum  :: Num a       => [a]   -> a
+  msum :: MonadPlus m => [m a] -> m a
+@
+\eprog
+\end{itemize}
+
+\subsection{Class @MonadPlus@}
+
+The @MonadPlus@ class is defined as follows:
+\bprog
+@
+class  (Monad m) => MonadPlus m  where
+    mzero  :: m a
+    mplus  :: m a -> m a -> m a
+@
+\eprog
+The class methods @mzero@ and @mplus@ are the zero and plus
+of the monad.
+
+Lists and the @Maybe@ type are instances of @MonadPlus@, thus:
+\bprog
+@
+instance  MonadPlus Maybe  where
+    mzero                 = Nothing
+    Nothing `mplus` ys    = ys
+    xs      `mplus` ys    = xs
+
+instance  MonadPlus []  where
+    mzero = []
+    mplus = (++)
+@
+\eprog
+
+
+\subsection{Functions}
+
+The @join@ function is the conventional monad join operator.  It is
+used to remove one level of monadic structure, projecting its bound
+argument into the outer level.
+
+% There is no convincing small-scale example for mapAndUnzipM
+The @mapAndUnzipM@ function maps its first argument over a list,
+returning the result as a pair of lists.  This function is mainly used
+with complicated data structures or a state-transforming monad.
+
+The @zipWithM@ function generalises @zipWith@ to arbitrary monads.
+For instance the following function displays a file, prefixing
+each line with its line number,
+\bprog
+@
+listFile :: String -> IO ()
+listFile nm =
+  do cts <- openFile nm
+     zipWithM_ (\i line -> do putStr (show i); putStr ": "; putStrLn line)
+               [1..]
+               (lines cts)
+@
+\eprog
+
+The @foldM@ function is analogous to @foldl@, except that its result
+is encapsulated in a monad.  Note that @foldM@ works from
+left-to-right over the list arguments.  This could be an issue where
+@(>>)@ and the ``folded function'' are not commutative. 
+\bprog
+@
+    foldM f a1 [x1, x2, ..., xm ]
+==  
+    do
+      a2 <- f a1 x1
+      a3 <- f a2 x2
+      ...
+      f am xm
+@
+\eprog
+If right-to-left
+evaluation is required, the input list should be reversed.
+
+% Omitted for now.  These functions are very useful in parsing libraries
+% - but in a slightly modified form:
+% o It is conventional to return the _longest_ parse first - not 
+%   shortest first.
+% o The function is too strict - you can't get any part of the result
+%   until the entire parse completes.  The fix is to use the function
+%   force when defining zeroOrMore.
+%   
+%     force :: Parser a -> Parser a
+%     force (P m) = P (\i -> let x = p i in
+%                            (fst (head x), snd (head x)) : tail x)
+%
+%   but how are we to generalise this to an arbitrary monad?
+%
+% The @zeroOrMore@ function performs an action repeatedly - returning
+% the list of all results obtained.  The @oneOrMore@ function is similar
+% but the action must succeed at least once.  That is,
+% \bprog
+% <at>
+% zeroOrMore m = zero ++ 
+%               [ [a0]       | a0 <- m ] ++
+%               [ [a0,a1]    | a0 <- m, a1 <- m ] ++
+%               [ [a0,a1,a2] | a0 <- m, a1 <- m, a2 <- m ] ++
+%               ...
+% 
+% oneOrMore m  = [ [a0]       | a0 <- m ] ++
+%               [ [a0,a1]    | a0 <- m, a1 <- m ] ++
+%               [ [a0,a1,a2] | a0 <- m, a1 <- m, a2 <- m ] ++
+%               ...
+% <at>
+% \eprog
+
+The @when@ and @unless@ functions provide conditional execution of
+monadic expressions.  For example,
+\bprog
+@
+when debug (putStr "Debugging\n")
+@
+\eprog
+will output the string @"Debugging\n"@ if the Boolean value @debug@ is
+@True@, and otherwise do nothing.
+
+The monadic lifting operators promote a function to a monad.  The
+function arguments are scanned left to right.  For example,
+\bprog
+@
+liftM2 (+) [0,1] [0,2] = [0,2,1,3]
+liftM2 (+) (Just 1) Nothing = Nothing
+@
+\eprog
+
+In many situations, the @liftM@ operations can be replaced by uses
+of @ap@, which promotes function application.
+\bprog
+@
+return f `ap` x1 `ap` ... `ap` xn
+@
+\eprog
+is equivalent to
+\bprog
+@
+liftMn f x1 x2 ... xn
+@
+\eprog
+\clearpage
+\subsection{Library {\tt Monad}}
+\inputHS{code/Monad}
+
+%**~footer
+
diff --git a/libraries/numeric.verb b/libraries/numeric.verb
new file mode 100644 (file)
index 0000000..03327ad
--- /dev/null
@@ -0,0 +1,20 @@
+%**<title>The Haskell 98 Library Report: Numerics</title>
+%**~header
+\section{Numeric}
+\label{lib-numeric}
+
+\outline{
+\inputHS{headers/Numeric}
+}
+This library contains assorted numeric functions, many of which are
+used in the standard Prelude.  Most are
+self-explanatory.  The @floatToDigits@ function converts a floating
+point value into a series of digits and an exponent of a selected
+base.  This is used to build a set of floating point formatting
+functions.
+
+
+\subsection{Library {\tt Numeric}}
+\inputHS{code/Numeric}
+
+%**~footer
diff --git a/libraries/random.verb b/libraries/random.verb
new file mode 100644 (file)
index 0000000..ca3fd4d
--- /dev/null
@@ -0,0 +1,231 @@
+%**<title>The Haskell 98 Library Report: Random Numbers</title>
+%**~eheader
+\section{Random Numbers}
+\label{random numbers}
+
+\outline {
+\inputHS{headers/Random}
+}
+
+The @Random@ library deals with the common task of 
+pseudo-random number generation.  The library makes it possible to
+generate repeatable results, by starting with a specified initial
+random number generator; or to get different results on each run
+by using the system-initialised generator, or by supplying a seed
+from some other source.
+
+The library is split into two layers:
+\begin{itemize}
+\item A core {\em random number generator} provides a supply of bits.
+The class @RandomGen@ provides a common interface to such generators.
+
+\item The class @Random@ provides a way to extract particular values from
+a random number generator.  For example, the @Float@ instance of @Random@ 
+allows one to generate random values of type @Float@.
+\end{itemize}
+
+\subsection{The @RandomGen@ class, and the @StdGen@ generator}
+
+The class @RandomGen@ provides a common interface to random number generators.
+\bprog
+@
+  class RandomGen g where
+    next  :: g  -> (Int, g)
+    split :: g -> (g, g)
+@
+\eprog
+\indextt{next}
+\indextt{split}
+\indextt{RandomGen}
+\begin{itemize}
+\item The @next@ operation allows one to extract at least 30 bits (one @Int@'s worth)
+from the generator, returning a new generator as well.  The integer returned
+may be positive or negative.
+
+\item The @split@ operation allows one to obtain two distinct random number
+generators.  This is very useful in functional programs (for example, when
+passing a random number generator down to recursive calls), but very little work
+has been done on statistically robust implementations of @split@
+([1,4] are the only examples we know of).
+\end{itemize}
+
+The @Random@ library provides one instance of @RandomGen@, the abstract data
+type @StdGen@:
+\bprog
+@
+  data StdGen = ...    -- Abstract
+  
+  instance RandomGen StdGen where ...
+  instance Read      StdGen where ...
+  instance Show      StdGen where ...
+  
+  mkStdGen :: Int -> StdGen
+@
+\eprog
+\indextt{StdGen}
+\indextt{mkStdGen}
+The result of repeatedly using @next@ should be at least as
+statistically robust as the ``Minimal Standard Random Number Generator''
+described by [2,3].  Until more is known about implementations of @split@,
+all we require is that @split@ deliver generators that are (a) not identical
+and (b) independently robust in the sense just given.
+
+The @show@/@Read@ instances of @StdGen@ provide a primitive way to save
+the state of a random number generator.
+It is required that @read (show g) == g@.
+
+In addition, @read@ may be used to map an arbitrary string (not
+necessarily one produced by @show@) onto a value of type @StdGen@.
+In general, the @read@ instance of @StdGen@ has the following properties:
+\begin{itemize}
+\item It guarantees to succeed on any string.
+\item It guarantees to consume only a finite portion of the string.
+\item Different argument strings are likely to result in different results.
+\end{itemize}
+
+The function @mkStdGen@ provides an alternative way of producing an initial generator,
+by mapping an @Int@ into a generator.  Again, distinct arguments should be likely
+to produce distinct generators.
+
+Programmers may, of course, supply their own instances of @RandomGen@.
+
+\subsection{The @Random@ class}
+
+With a source of random number supply in hand, the @Random@ class allows
+the programmer to extract random values of a variety of types:
+\bprog
+@
+class Random a where
+   randomR :: RandomGen g => (a, a) -> g -> (a, g)
+   random  :: RandomGen g => g -> (a, g)
+
+   randomRs :: RandomGen g => (a, a) -> g -> [a]
+   randoms  :: RandomGen g => g -> [a]
+
+   randomRIO :: (a,a) -> IO a
+   randomIO :: IO a
+
+     -- Default methods
+   randoms g = x : randoms g' 
+                  where 
+                    (x,g') = random g
+   randomRs = ...similar...
+
+   randomIO        = getStdRandom random
+   randomRIO range = getStdRandom (randomR range)
+
+
+instance Random Int     where ...
+instance Random Integer where ...
+instance Random Float   where ...
+instance Random Double  where ...
+instance Random Bool    where ...
+instance Random Char    where ...
+@
+\eprog
+\indextt{Random}
+\indextt{random}
+\indextt{randomR}
+\indextt{randoms}
+\indextt{randomRs}
+\indextt{randomIO}
+\indextt{randomRIO}
+\begin{itemize}
+\item @randomR@ takes a range "(lo,hi)" and a random number generator "g",
+and returns a random value uniformly distributed in the closed interval "[lo,hi]", together
+with a new generator.  It is unspecified what happens if "lo>hi".
+For continuous types there is no requirement that the values "lo" and "hi" are
+ever produced, but they may be, depending on the implementation and the interval.
+
+% \begin{itemize}
+% \item For discrete types (such as @Int@ or @Bool@), 
+% ``uniformly distributed'' means that each value is equally likely to occur.
+% \item For floating-point types (instances of @Floating@, such as @Float@ or @Double@),
+% the probability of any particular (representable) value "v"
+% occurring is proportional to "ulp(v)/(h-l)", where "ulp(v)" is the
+% size of a unit change in the least significant bit position of "v".
+% \item For continuous types, such as @Rational@, ``uniformly distributed'' means
+% that the probability distribution of returned values is uniform over the interval.
+% \end{itemize}
+
+% \begin{itemize}
+% \item For discrete types (such as @Int@ or @Bool@), the range is the closed interval "[l,h]".
+% \item For fractional types (instances of @Fractional@, such as @Float@ or @Double@),
+% the range is the semi-closed interval "[l,h)".
+% \end{itemize}
+% for discrete types, or if "l \geq h" for fractional types.
+
+\item @random@ does the same as @randomR@, but does not take a range.
+\begin{itemize}
+\item For bounded types (instances of @Bounded@, such as @Char@), 
+the range is normally the whole type.
+\item For fractional types, the range is normally the semi-closed interval "[0,1)".
+\item For @Integer@, the range is (arbitrarily) the range of @Int@.
+\end{itemize}
+
+\item The plural versions, @randomRs@ and @randoms@, produce an infinite list of random
+values, and do not return a new generator.
+
+\item The @IO@ versions, @randomRIO@ and @randomIO@, use the global random number
+generator (see Section~\ref{global-rng}).
+\end{itemize}
+
+\subsection{The global random number generator}
+\label{global-rng}
+
+There is a single, implicit, global random number generator
+of type @StdGen@, held in some global variable maintained by the @IO@ monad.
+It is initialised automatically in some system-dependent fashion,
+for example, by using the time of day, or Linux's kernal random number generator.
+To get deterministic behaviour, use @setStdGen@.
+\bprog
+@
+  setStdGen    :: StdGen -> IO ()      
+  getStdGen    :: IO StdGen            
+  newStdGen    :: IO StdGen
+  getStdRandom :: (StdGen -> (a, StdGen)) -> IO a
+@
+\eprog
+\indextt{setStdGen}
+\indextt{getStdGen}
+\indextt{newStdGen}
+\indextt{getStdRandom}
+\begin{itemize}
+\item @getStdGen@ and @setStdGen@ get and set the global random
+number generator, respectively.
+
+\item @newStdGen@ applies @split@ to the current global random generator,
+updates it with one of the results, and returns the other.
+
+\item @getStdRandom@ uses the supplied function to get a value from
+the current global random generator, and updates the
+global generator with the new generator returned by the function.
+For example, @rollDice@ gets a random integer between 1 and 6:
+\bprog
+@
+  rollDice :: IO Int
+  rollDice = getStdRandom (randomR (1,6))
+@
+\eprog
+\end{itemize}    
+
+\subsection*{References}
+\begin{description}
+\item[{[1]}] FW Burton and RL Page, ``Distributed random number generation'',
+       Journal of Functional Programming, 2(2):203-212, April 1992.
+
+\item[{[2]}] SK Park, and KW Miller, ``Random number generators - good ones are hard to find'',
+       Comm ACM 31(10), Oct 1988, pp1192-1201.
+
+\item[{[3]}] DG Carta, ``Two fast implementations of the minimal standard random number generator'',
+       Comm ACM, 33(1), Jan 1990, pp87-88.
+
+\item[{[4]}] P Hellekalek, ``Don't trust parallel Monte Carlo'', Department of Mathematics,
+University of Salzburg, @http://random.mat.sbg.ac.at/~peter/pads98.ps@, 1998.
+\end{description}
+
+The Web site @http://random.mat.sbg.ac.at/@ is a great source of information.
+
+
+%**~efooter
+
diff --git a/libraries/ratio.verb b/libraries/ratio.verb
new file mode 100644 (file)
index 0000000..3b41f5b
--- /dev/null
@@ -0,0 +1,53 @@
+%**<title>The Haskell 98 Library Report: Rational Numbers</title>
+%**~header
+\section{Rational Numbers}
+\index{rational numbers}
+
+\outline{
+\inputHS{headers/Ratio}
+}
+
+For each @Integral@ type $t$, there is
+a type @Ratio@\indextycon{Ratio} $t$ of rational pairs with components of
+type $t$.  The type name @Rational@\indexsynonym{Rational} is a synonym for
+@Ratio Integer@.  
+
+@Ratio@ is an instance of classes @Eq@, @Ord@, @Num@, @Real@, 
+@Fractional@, @RealFrac@, @Enum@, @Read@, and @Show@.  In each case,
+the instance for $@Ratio@~t$ simply ``lifts'' the corresponding operations
+over $t$.  If $t$ is a bounded type, the results may be unpredictable;
+for example @Ratio Int@ may give rise to integer overflow even for
+rational numbers of small absolute size.
+
+The operator @(%)@\index{%@@{\tt {\char'045}}} forms the ratio of two
+integral numbers, reducing the fraction to terms with no common factor
+and such that the denominator is positive.  The functions
+@numerator@\indextt{numerator}
+and @denominator@\indextt{denominator} extract the components of a
+ratio; these are in reduced form with a positive denominator.
+@Ratio@ is an abstract type.  For example, @12 % 8@ is reduced to 3/2
+and @12 % (-8)@ is reduced to (-3)/2.
+
+The @approxRational@ function, applied to two real fractional numbers
+@x@ and @epsilon@, returns the simplest rational number within the open
+interval "(@x@-@epsilon@, @x@+@epsilon@)".
+A rational number "n/d" in reduced form is said to
+be simpler than another "n'/d'" if "|n| \leq |n'|" and "d \leq d'".
+Note that it can be proved that any real interval contains a unique
+simplest rational.
+
+
+%% Deleted the following -- this is implementation detail -- KH/AD.
+% ; here, for simplicity, we assume a closed rational
+% interval.  If such an interval includes at least one whole number, then
+% the simplest rational is the absolutely least whole number.  Otherwise,
+% the bounds are of the form "q/1 + r/d" and "q/1 + r'/d'", where "|r| < d"
+% and "|r'| < d'", and the simplest rational is "q/1" + the reciprocal of
+% the simplest rational between "d'/r'" and "d/r".
+
+\clearpage
+\subsection{Library {\tt Ratio}}
+\label{Ratio}
+\inputHS{code/Ratio}
+
+%**~footer
diff --git a/libraries/system.verb b/libraries/system.verb
new file mode 100644 (file)
index 0000000..94ce4a2
--- /dev/null
@@ -0,0 +1,64 @@
+%**<title>The Haskell 98 Library Report: System functions</title>
+%**~header
+
+\section{System Functions}
+
+\outline{
+\inputHS{headers/System}
+}
+\indextt{ExitCode}\indextt{ExitSuccess}\indextt{ExitFailure}
+\indextt{getArgs}\indextt{getProgName}\indextt{getEnv}
+\indextt{system}\indextt{exitWith}\indextt{exitFailure}
+
+%% It would be less draconian to return [] for operations
+%% other than system, exitWith. KH
+This library describes the interaction of the program with the
+operating system.  
+
+Any @System@ operation could raise an @isIllegalOperationError@, as
+described in Section~\ref{IOError}; all other permissible errors are
+described below.  Note that, in particular, if an implementation does
+not support an operation it must raise an @isIllegalOperationError@.
+
+The @ExitCode@ type defines the exit codes that a program can return.
+@ExitSuccess@ indicates successful termination; and @ExitFailure@
+"code" indicates program failure with value "code".  The exact
+interpretation of "code" is operating-system dependent.  In
+particular, some values of "code" may be prohibited (for instance, 0 on a
+POSIX-compliant system).
+
+Computation @getArgs@ returns a list of the program's command
+line arguments (not including the program name)\index{program arguments}.
+Computation @getProgName@ returns the name of the program
+as it was invoked\index{program name}.
+Computation @getEnv@~"var" returns the value
+of the environment variable "var"\index{environment variables}.
+If variable "var" is undefined, the
+@isDoesNotExistError@ exception is raised.
+Computation @system@~"cmd" returns the exit code produced when the
+operating system processes the command "cmd"\index{operating system
+commands}.
+
+Computation @exitWith@~"code" terminates the program, returning "code"
+to the program's caller\index{terminating a program}.  Before the
+program terminates, any open or semi-closed handles are first closed.
+The caller may interpret the return code as it wishes, but the program
+should return @ExitSuccess@ to mean normal completion, and
+@ExitFailure @"n" to mean that the program encountered a problem from
+which it could not recover.  The value @exitFailure@ is equal to
+@exitWith (ExitFailure @"exitfail"@)@, where "exitfail" is
+implementation-dependent.  @exitWith@ bypasses the error handling in
+the I/O monad and cannot be intercepted by @catch@.
+
+If a program terminates as a result of calling @error@\indextt{error} or
+because its value is otherwise determined to be "\bot"\index{"\bot"}, then it
+is treated identically to the computation @exitFailure@.  Otherwise, if any
+program "p" terminates without calling @exitWith@ explicitly, it is treated
+identically to the computation
+\bprog
+@(@"p"@ >> exitWith ExitSuccess) `catch` \ _ -> exitFailure@
+\eprog
+\indextt{catch}
+
+%**~footer
diff --git a/libraries/time.verb b/libraries/time.verb
new file mode 100644 (file)
index 0000000..73619d7
--- /dev/null
@@ -0,0 +1,76 @@
+%**<title>The Haskell 98 Library Report: Dates and Times</title>
+%**~header
+\section{Dates and Times}
+\label{time}
+\index{time}
+\index{time of day}\index{clock time}
+
+%% Note: HBC has Leap year calculations too.
+%% My feeling is that these are unnecessary given the much stronger
+%% ability here to find the differences between dates.
+
+\outline {
+\inputHS{headers/Time}
+}
+\outline{
+\inputHS{headers/Time1}
+}
+
+The @Time@ library provides standard functionality for clock times,
+including timezone information. It follows RFC~1129 in its use of
+Coordinated Universal Time (UTC).
+
+@ClockTime@ is an abstract type, used for the system's internal clock
+time.  Clock times may be compared directly or converted to a calendar
+time @CalendarTime@ for I/O or other manipulations.
+@CalendarTime@ is a user-readable and manipulable representation of
+the internal @ClockTime@ type.  The numeric fields have the following
+ranges.
+\outline{
+\begin{tabbing}
+\ignorehtml{
+\ \ \ \=ctpicosec\ \ \ \ \=-maxInt\ \=\ldots\ \=$(10^{12})-1$\ \ \ \ \ \=\kill}
+\>\underline{Value}\>\>\underline{Range}\>\>\underline{Comments} \\
+\\
+\>ctYear\>\>-maxInt\'$\ldots$\>maxInt\>Pre-Gregorian dates are inaccurate \\
+\>ctDay\>\>1\'$\ldots$\>31 \\
+\>ctHour\>\>0\'$\ldots$\>23\\
+\>ctMin\>\>0\'$\ldots$\>59\\
+\>ctSec\>\>0\'$\ldots$\>61\>Allows for two Leap Seconds\\
+\>ctPicosec\>\>0\'$\ldots$\>$(10^{12})-1$ \\
+\>ctYDay\>\>0\'$\ldots$\>365\>364 in non-Leap years \\
+\>ctTZ\>\>-89999\'$\ldots$\>89999\>Variation from UTC in seconds
+\end{tabbing}
+}
+The "ctTZName" field is the name of the time zone.  The "ctIsDST" field
+is @True@ if Daylight Savings Time would be in effect, and @False@
+otherwise.
+The @TimeDiff@ type records the difference between two clock times in
+a user-readable way.
+
+Function @getClockTime@ returns the current time in its internal
+representation.  The expression
+@addToClockTime@~"d"~"t" adds a time difference "d" and a
+clock time "t" to yield a new clock time.  The difference "d" may be either
+positive or negative.  The expression @diffClockTimes@~"t1"~"t2"
+returns the difference between two clock times "t1" and "t2" as a
+@TimeDiff@. 
+
+Function @toCalendarTime@~"t" converts "t" to a local time, modified
+by the timezone and daylight savings time settings in force at the
+time of conversion.  Because of this dependence on the local environment,
+@toCalendarTime@ is in the @IO@ monad.
+
+Function @toUTCTime@~"t" converts "t" into a @CalendarTime@
+in standard UTC format.
+@toClockTime@~"l" converts "l" into the corresponding internal
+@ClockTime@ ignoring the contents of the "ctWDay", "ctYDay",
+"ctTZName", and "ctIsDST" fields.
+
+Function @calendarTimeToString@ formats
+calendar times using local conventions and a formatting string.
+
+\subsection{Library {\tt Time}}
+\inputHS{code/Time}
+
+%**~header
diff --git a/report/Makefile b/report/Makefile
new file mode 100644 (file)
index 0000000..a4ee518
--- /dev/null
@@ -0,0 +1,185 @@
+# Makefile for the Haskell Report
+# read the README file before you start!
+
+##########################################
+# What to make if you type 'make'
+
+default: haskell.ps html
+
+# Begin by saying
+#      touch haskell.idx
+
+
+#########################################
+#      Tools you need
+#########################################
+
+# Stuf from the tools/directory
+RUN_TEX   = ../tools/run_tex
+RUN_INDEX = ../tools/run_index
+VERBATIM  = ../tools/verbatim
+
+# splitAndIndexPgm won't work unless you have "perl"
+SPLITPGM = perl ../tools/splitAndIndexPgm
+
+RM    = rm -f
+LATEX = latex
+MAKEINDEX = makeindex
+
+# 'expand' expands tabs to spaces
+# On my machine the windows program (which does something
+# quite different) shadows it.  Sigh.
+EXPAND = expand
+
+
+#########################################
+#      Files 
+#########################################
+
+PARTS =                preface-13.tex iso-chars.tex \
+               intro.tex lexemes.tex  exps.tex \
+               decls.tex  modules.tex  basic.tex  io-13.tex \
+               derived.tex \
+               index-extra.tex index-intro.tex layout.tex \
+               literate.tex pragmas.tex standard-prelude.tex
+SYNTAX =       syntax-lexical.tex syntax-iso.tex
+PRELUDE =      Prelude.tex PreludeList.tex \
+               PreludeText.tex PreludeIO.tex
+
+LIBPARTS =     lib-array.tex lib-intro.tex lib-io.tex lib-num.tex lib-os.tex lib-text.tex \
+               lib-index-intro.tex lib-posix.tex
+
+LIBS =         LibMonadicIO.tex LibStdIO.tex LibIOError.tex LibReadTextIO.tex LibWriteTextIO.tex \
+               LibSystem.tex LibDirectory.tex LibCPUTime.tex LibTime.tex LibUserInterrupt.tex \
+               LibRatio.tex LibArray.tex LibComplex.tex LibText.tex \
+               LibIO.tex LibIx.tex LibPosix.tex
+
+
+#########################################
+#      Main targets
+#########################################
+
+# The normally formatted report -- 2 sided, one-up
+haskell.verb: plain_haskell.verb
+       -cp plain_haskell.verb haskell.verb
+
+haskell.tex: haskell.verb
+       $(EXPAND) < $< | $(VERBATIM) >$@
+
+haskell.dvi:  haskell.tex ${PARTS} $(SYNTAX) ${PRELUDE}
+
+# Report as formatted for SIGPLAN -- 2 sided, 2-up, odd pages on left.
+# This is a bit horrible.  But almost nobody should need to do this. KH
+sigplan_haskell.dvi: sigplan_haskell.verb sigplan_article.sty \
+                    haskell.tex haskell.ind \
+                    ${PARTS} $(SYNTAX) ${PRELUDE}
+       cp sigplan_article.sty article.sty
+       cp sigplan_haskell.verb haskell.verb
+       -make haskell.dvi
+       cp plain_haskell.verb haskell.verb
+
+
+# I have no idea why run_tex is run twice.  SLPJ
+html: index.html ${PARTS} ${SYNTAX} ${PRELUDE}
+       -mkdir haskell98-report-html
+       $(RUN_TEX)
+       $(RUN_TEX)
+       $(RUN_INDEX)
+       cp index.html *.gif haskell98-report-html
+
+haskell.dvi: haskell.tex haskell.ind ${PARTS} $(SYNTAX) ${PRELUDE}
+
+haskell-libraries.dvi:  haskell-libraries.tex haskell-libraries.ind ${LIBPARTS} ${LIBS}
+
+sigplan_haskell-libraries.dvi:  sigplan_haskell-libraries.tex haskell-libraries.ind ${LIBPARTS} ${LIBS}
+
+# remove this rule if you don't have "makeindex"
+haskell.ind: haskell.idx
+       $(MAKEINDEX) -i -t haskell.ilg < haskell.idx > haskell.ind
+
+veryclean: clean
+       $(RM) *~ 
+
+clean:
+       $(RM) *.dvi *.log *.aux *.ilg *.blg *.toc ${PARTS} $(SYNTAX) \
+               haskell.tex haskell.ps haskell.pdf *.o lex.yy.c haskell98-report-html/*
+       cp haskell.ind haskell.ind.two-sided
+       echo "Don't delete the Prelude*.tex files"
+       echo "Not everyone has \"perl\" to re-make them"
+
+# Stuff to make the "two-up" version for SIGPLAN Notices:
+# We take the A4 pages and double them up onto (virtual) A3 pages:
+# (two A5 pages make one A4 page; two A4 pages make one A3 page; ...)
+#
+#      % dvidvi '2:0,1(210mm,0)' haskell.dvi > haskell-2up.dvi
+#
+# We now print the "A3" pages in landscape, but "magnify" them by
+# 1 / sqrt(2) ~ 0.7071; this should make our "A4" pages print in an
+# A4 space: presto! 2up printing!
+# (except that I've tried to make it give us 1" margins all round
+#  when we print on US 8.5"x11" paper)
+#
+#      % dvips -t landscape -x 707 haskell-2up.dvi > haskell-2up.ps
+#
+# if your "dvips" is set up properly, it will run Metafont for you,
+# creating just-right magnifications for all the fonts.
+#
+# print with: lpr -Pmy-laserwriter haskell-2up.ps
+
+# These rules keep failing for me (segmentation fault on haskell-2up.dvi)
+# The output seems fine, though, and the individual commands work
+# perfectly(!).  More network wierdness?  KH
+
+haskell-2up.ps : haskell-2up.dvi
+       dvips -t landscape -x 707 haskell-2up.dvi > haskell-2up.ps
+
+haskell-2up.dvi : haskellx.dvi
+       -dvidvi '2:0(0in,0in),1(160mm,0in)' haskellx.dvi > haskell-2up.dvi
+
+haskellx.dvi : sigplan_haskell.dvi
+       dviselect =4: haskell.dvi haskellx.dvi
+
+haskell-libraries-2up.ps : haskell-libraries-2up.dvi
+       dvips -t landscape -x 707 haskell-libraries-2up.dvi > haskell-libraries-2up.ps
+
+haskell-libraries-2up.dvi : haskell-librariesx.dvi
+       -dvidvi '2:0(0in,0in),1(160mm,0in)' haskell-librariesx.dvi > haskell-libraries-2up.dvi
+
+haskell-librariesx.dvi : sigplan_haskell-libraries.dvi
+       dviselect =4: sigplan_haskell-libraries.dvi haskell-librariesx.dvi
+
+haskell.ps : haskell.dvi
+       dvips haskell.dvi -o haskell.ps
+
+
+
+publish: haskell.ps html
+       gzip < haskell.ps > y:Haskell/haskell98-report/haskell.ps.gz
+       cp haskell98-report-html/* y:Haskell/haskell98-report
+       tar cvf - haskell98-report-html | gzip > y:Haskell/haskell98-report/haskell98-report-html.tar.gz
+
+publish-pdf: report.pdf
+       gzip < report.pdf > y:Haskell/haskell98-report/report.pdf.gz
+
+
+#########################################
+#      Suffix rules
+#########################################
+
+.SUFFIXES:     .hi .hs .verb .tex .dvi
+
+.verb.tex:
+       $(EXPAND) < $< | $(VERBATIM) >$@
+
+.hs.verb:
+       $(EXPAND) < $< | $(SPLITPGM) >$@
+
+%.tex: %.hs
+       $(EXPAND) < $< | $(SPLITPGM) | $(VERBATIM) >$@
+
+.hi.tex:
+       $(EXPAND) < $< | $(SPLITPGM) | $(VERBATIM) >$@
+
+.tex.dvi:
+       $(LATEX) $<
+
diff --git a/report/Prelude.hs b/report/Prelude.hs
new file mode 100644 (file)
index 0000000..259abaa
--- /dev/null
@@ -0,0 +1,579 @@
+module Prelude (
+    module PreludeList, module PreludeText, module PreludeIO,
+    Bool(False, True),
+    Maybe(Nothing, Just),
+    Either(Left, Right),
+    Ordering(LT, EQ, GT),
+    Char, String, Int, Integer, Float, Double, Rational, IO,
+--  List type: []((:), [])
+--  Tuple types: (,), (,,), etc.
+--  Trivial type: ()
+--  Functions: (->)
+    Eq((==), (/=)),
+    Ord(compare, (<), (<=), (>=), (>), max, min),
+    Enum(succ, pred, toEnum, fromEnum, enumFrom, enumFromThen,
+         enumFromTo, enumFromThenTo),
+    Bounded(minBound, maxBound),
+    Num((+), (-), (*), negate, abs, signum, fromInteger),
+    Real(toRational),
+    Integral(quot, rem, div, mod, quotRem, divMod, toInteger),
+    Fractional((/), recip, fromRational),
+    Floating(pi, exp, log, sqrt, (**), logBase, sin, cos, tan,
+             asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh),
+    RealFrac(properFraction, truncate, round, ceiling, floor),
+    RealFloat(floatRadix, floatDigits, floatRange, decodeFloat,
+              encodeFloat, exponent, significand, scaleFloat, isNaN,
+              isInfinite, isDenormalized, isIEEE, isNegativeZero, atan2),
+    Monad((>>=), (>>), return, fail),
+    Functor(fmap),
+    mapM, mapM_, sequence, sequence_, (=<<), 
+    maybe, either,
+    (&&), (||), not, otherwise,
+    subtract, even, odd, gcd, lcm, (^), (^^), 
+    fromIntegral, realToFrac, 
+    fst, snd, curry, uncurry, id, const, (.), flip, ($), until,
+    asTypeOf, error, undefined,
+    seq, ($!)
+  ) where
+
+import PreludeBuiltin  -- Contains all `prim' values
+import PreludeList
+import PreludeText
+import PreludeIO
+import Ratio( Rational )
+
+infixr 9  .
+infixr 8  ^, ^^, **
+infixl 7  *, /, `quot`, `rem`, `div`, `mod`
+infixl 6  +, -
+infixr 5  :
+infix  4  ==, /=, <, <=, >=, >
+infixr 3  &&
+infixr 2  ||
+infixl 1  >>, >>=
+infixr 1  =<<
+infixr 0  $, $!, `seq`
+
+-- Standard types, classes, instances and related functions
+
+-- Equality and Ordered classes
+
+class  Eq a  where
+    (==), (/=)       :: a -> a -> Bool
+
+        -- Minimal complete defintion:
+        --      (==) or (/=)
+    x /= y           =  not (x == y)
+    x == y           =  not (x /= y)
+
+class  (Eq a) => Ord a  where
+    compare                     :: a -> a -> Ordering
+    (<), (<=), (>=), (>) :: a -> a -> Bool
+    max, min             :: a -> a -> a
+
+        -- Minimal complete definition:
+        --      (<=) or compare
+        -- Using compare can be more efficient for complex types.
+    compare x y
+         | x == y    =  EQ
+         | x <= y    =  LT
+         | otherwise =  GT
+
+    x <= y           =  compare x y /= GT
+    x <  y           =  compare x y == LT
+    x >= y           =  compare x y /= LT
+    x >  y           =  compare x y == GT
+
+-- note that (min x y, max x y) = (x,y) or (y,x)
+    max x y 
+         | x >= y    =  x
+         | otherwise =  y
+    min x y
+         | x <  y    =  x
+         | otherwise =  y
+
+-- Enumeration and Bounded classes
+
+class  Enum a  where
+    succ, pred       :: a -> a
+    toEnum           :: Int -> a
+    fromEnum         :: a -> Int
+    enumFrom         :: a -> [a]             -- [n..]
+    enumFromThen     :: a -> a -> [a]        -- [n,n'..]
+    enumFromTo       :: a -> a -> [a]        -- [n..m]
+    enumFromThenTo   :: a -> a -> a -> [a]   -- [n,n'..m]
+
+        -- Minimal complete definition:
+        --      toEnum, fromEnum
+    succ             =  toEnum . (+1) . fromEnum
+    pred             =  toEnum . (subtract 1) . fromEnum
+    enumFrom x       =  map toEnum [fromEnum x ..]
+    enumFromTo x y   =  map toEnum [fromEnum x .. fromEnum y]
+    enumFromThenTo x y z = 
+                        map toEnum [fromEnum x, fromEnum y .. fromEnum z]
+
+class  Bounded a  where
+    minBound         :: a
+    maxBound         :: a
+
+-- Numeric classes
+
+class  (Eq a, Show a) => Num a  where
+    (+), (-), (*)    :: a -> a -> a
+    negate           :: a -> a
+    abs, signum      :: a -> a
+    fromInteger      :: Integer -> a
+
+        -- Minimal complete definition:
+        --      All, except negate or (-)
+    x - y            =  x + negate y
+    negate x         =  0 - x
+
+class  (Num a, Ord a) => Real a  where
+    toRational       ::  a -> Rational
+
+class  (Real a, Enum a) => Integral a  where
+    quot, rem        :: a -> a -> a   
+    div, mod         :: a -> a -> a
+    quotRem, divMod  :: a -> a -> (a,a)
+    toInteger        :: a -> Integer
+
+        -- Minimal complete definition:
+        --      quotRem, toInteger
+    n `quot` d       =  q  where (q,r) = quotRem n d
+    n `rem` d        =  r  where (q,r) = quotRem n d
+    n `div` d        =  q  where (q,r) = divMod n d
+    n `mod` d        =  r  where (q,r) = divMod n d
+    divMod n d       =  if signum r == - signum d then (q-1, r+d) else qr
+                        where qr@(q,r) = quotRem n d
+
+class  (Num a) => Fractional a  where
+    (/)              :: a -> a -> a
+    recip            :: a -> a
+    fromRational     :: Rational -> a
+
+        -- Minimal complete definition:
+        --      fromRational and (recip or (/))
+    recip x          =  1 / x
+    x / y            =  x * recip y
+
+class  (Fractional a) => Floating a  where
+    pi                  :: a
+    exp, log, sqrt      :: a -> a
+    (**), logBase       :: a -> a -> a
+    sin, cos, tan       :: a -> a
+    asin, acos, atan    :: a -> a
+    sinh, cosh, tanh    :: a -> a
+    asinh, acosh, atanh :: a -> a
+
+        -- Minimal complete definition:
+        --      pi, exp, log, sin, cos, sinh, cosh
+        --      asinh, acosh, atanh
+    x ** y           =  exp (log x * y)
+    logBase x y      =  log y / log x
+    sqrt x           =  x ** 0.5
+    tan  x           =  sin  x / cos  x
+    tanh x           =  sinh x / cosh x
+
+
+class  (Real a, Fractional a) => RealFrac a  where
+    properFraction   :: (Integral b) => a -> (b,a)
+    truncate, round  :: (Integral b) => a -> b
+    ceiling, floor   :: (Integral b) => a -> b
+
+        -- Minimal complete definition:
+        --      properFraction
+    truncate x       =  m  where (m,_) = properFraction x
+    
+    round x          =  let (n,r) = properFraction x
+                            m     = if r < 0 then n - 1 else n + 1
+                          in case signum (abs r - 0.5) of
+                                -1 -> n
+                                0  -> if even n then n else m
+                                1  -> m
+    
+    ceiling x        =  if r > 0 then n + 1 else n
+                        where (n,r) = properFraction x
+    
+    floor x          =  if r < 0 then n - 1 else n
+                        where (n,r) = properFraction x
+
+class  (RealFrac a, Floating a) => RealFloat a  where
+    floatRadix       :: a -> Integer
+    floatDigits      :: a -> Int
+    floatRange       :: a -> (Int,Int)
+    decodeFloat      :: a -> (Integer,Int)
+    encodeFloat      :: Integer -> Int -> a
+    exponent         :: a -> Int
+    significand      :: a -> a
+    scaleFloat       :: Int -> a -> a
+    isNaN, isInfinite, isDenormalized, isNegativeZero, isIEEE
+                     :: a -> Bool
+    atan2            :: a -> a -> a
+
+        -- Minimal complete definition:
+        --      All except exponent, significand, 
+        --                 scaleFloat, atan2
+    exponent x       =  if m == 0 then 0 else n + floatDigits x
+                        where (m,n) = decodeFloat x
+
+    significand x    =  encodeFloat m (- floatDigits x)
+                        where (m,_) = decodeFloat x
+
+    scaleFloat k x   =  encodeFloat m (n+k)
+                        where (m,n) = decodeFloat x
+
+    atan2 y x
+      | x>0           =  atan (y/x)
+      | x==0 && y>0   =  pi/2
+      | x<0  && y>0   =  pi + atan (y/x) 
+      |(x<=0 && y<0)  ||
+       (x<0 && isNegativeZero y) ||
+       (isNegativeZero x && isNegativeZero y)
+                      = -atan2 (-y) x
+      | y==0 && (x<0 || isNegativeZero x)
+                      =  pi    -- must be after the previous test on zero y
+      | x==0 && y==0  =  y     -- must be after the other double zero tests
+      | otherwise     =  x + y -- x or y is a NaN, return a NaN (via +)
+
+-- Numeric functions
+
+subtract         :: (Num a) => a -> a -> a
+subtract         =  flip (-)
+
+even, odd        :: (Integral a) => a -> Bool
+even n           =  n `rem` 2 == 0
+odd              =  not . even
+
+gcd              :: (Integral a) => a -> a -> a
+gcd 0 0          =  error "Prelude.gcd: gcd 0 0 is undefined"
+gcd x y          =  gcd' (abs x) (abs y)
+                    where gcd' x 0  =  x
+                          gcd' x y  =  gcd' y (x `rem` y)
+
+lcm              :: (Integral a) => a -> a -> a
+lcm _ 0          =  0
+lcm 0 _          =  0
+lcm x y          =  abs ((x `quot` (gcd x y)) * y)
+
+(^)              :: (Num a, Integral b) => a -> b -> a
+x ^ 0            =  1
+x ^ n | n > 0    =  f x (n-1) x
+                    where f _ 0 y = y
+                          f x n y = g x n  where
+                                    g x n | even n  = g (x*x) (n `quot` 2)
+                                          | otherwise = f x (n-1) (x*y)
+_ ^ _            = error "Prelude.^: negative exponent"
+
+(^^)             :: (Fractional a, Integral b) => a -> b -> a
+x ^^ n           =  if n >= 0 then x^n else recip (x^(-n))
+
+fromIntegral     :: (Integral a, Num b) => a -> b
+fromIntegral     =  fromInteger . toInteger
+
+realToFrac     :: (Real a, Fractional b) => a -> b
+realToFrac      =  fromRational . toRational
+
+-- Monadic classes
+
+class  Functor f  where
+    fmap              :: (a -> b) -> f a -> f b
+
+class  Monad m  where
+    (>>=)  :: m a -> (a -> m b) -> m b
+    (>>)   :: m a -> m b -> m b
+    return :: a -> m a
+    fail   :: String -> m a
+
+        -- Minimal complete definition:
+        --      (>>=), return
+    m >> k  =  m >>= \_ -> k
+    fail s  = error s
+
+sequence       :: Monad m => [m a] -> m [a] 
+sequence       =  foldr mcons (return [])
+                    where mcons p q = p >>= \x -> q >>= \y -> return (x:y)
+
+sequence_      :: Monad m => [m a] -> m () 
+sequence_      =  foldr (>>) (return ())
+
+-- The xxxM functions take list arguments, but lift the function or
+-- list element to a monad type
+mapM             :: Monad m => (a -> m b) -> [a] -> m [b]
+mapM f as        =  sequence (map f as)
+
+mapM_            :: Monad m => (a -> m b) -> [a] -> m ()
+mapM_ f as       =  sequence_ (map f as)
+
+(=<<)            :: Monad m => (a -> m b) -> m a -> m b
+f =<< x          =  x >>= f
+
+
+-- Trivial type
+
+data  ()  =  ()  deriving (Eq, Ord, Enum, Bounded)
+
+-- Function type
+
+data a -> b  -- No constructor for functions is exported.
+
+-- identity function
+id               :: a -> a
+id x             =  x
+
+-- constant function
+const            :: a -> b -> a
+const x _        =  x
+
+-- function composition
+(.)              :: (b -> c) -> (a -> b) -> a -> c
+f . g            =  \ x -> f (g x)
+
+-- flip f  takes its (first) two arguments in the reverse order of f.
+flip             :: (a -> b -> c) -> b -> a -> c
+flip f x y       =  f y x
+
+seq :: a -> b -> b
+seq = ...       -- Primitive
+
+-- right-associating infix application operators 
+-- (useful in continuation-passing style)
+($), ($!) :: (a -> b) -> a -> b
+f $  x    =  f x
+f $! x    =  x `seq` f x
+
+
+-- Boolean type
+
+data  Bool  =  False | True     deriving (Eq, Ord, Enum, Read, Show, Bounded)
+
+-- Boolean functions
+
+(&&), (||)       :: Bool -> Bool -> Bool
+True  && x       =  x
+False && _       =  False
+True  || _       =  True
+False || x       =  x
+                                        
+not              :: Bool -> Bool
+not True         =  False
+not False        =  True
+
+otherwise        :: Bool
+otherwise        =  True
+
+
+-- Character type
+
+data Char = ... 'a' | 'b' ... -- 2^16 unicode values
+
+instance  Eq Char  where
+    c == c'          =  fromEnum c == fromEnum c'
+
+instance  Ord Char  where
+    c <= c'          =  fromEnum c <= fromEnum c'
+
+instance  Enum Char  where
+    toEnum            = primIntToChar
+    fromEnum          = primCharToInt
+    enumFrom c        = map toEnum [fromEnum c .. fromEnum (maxBound::Char)]
+    enumFromThen c c' = map toEnum [fromEnum c, fromEnum c' .. fromEnum lastChar]
+                      where lastChar :: Char
+                               lastChar | c' < c    = minBound
+                                        | otherwise = maxBound
+
+instance  Bounded Char  where
+    minBound            =  '\0'
+    maxBound            =  '\xffff'
+
+type  String = [Char]
+
+
+-- Maybe type
+
+data  Maybe a  =  Nothing | Just a      deriving (Eq, Ord, Read, Show)
+
+maybe              :: b -> (a -> b) -> Maybe a -> b
+maybe n f Nothing  =  n
+maybe n f (Just x) =  f x
+
+instance  Functor Maybe  where
+    fmap f Nothing    =  Nothing
+    fmap f (Just x)   =  Just (f x)
+        
+instance  Monad Maybe  where
+    (Just x) >>= k   =  k x
+    Nothing  >>= k   =  Nothing
+    return           =  Just
+    fail s           =  Nothing
+
+-- Either type
+
+data  Either a b  =  Left a | Right b   deriving (Eq, Ord, Read, Show)
+
+either               :: (a -> c) -> (b -> c) -> Either a b -> c
+either f g (Left x)  =  f x
+either f g (Right y) =  g y
+
+-- IO type
+
+data  IO a  -- abstract
+
+instance  Functor IO where
+   fmap f x           =  x >>= (return . f)
+
+instance Monad IO where
+   (>>=)  = ...
+   return = ...
+
+   m >> k = m >>= \_ -> k
+   fail s = error s
+
+-- Ordering type
+
+data  Ordering  =  LT | EQ | GT
+          deriving (Eq, Ord, Enum, Read, Show, Bounded)
+
+
+-- Standard numeric types.  The data declarations for these types cannot
+-- be expressed directly in Haskell since the constructor lists would be
+-- far too large.
+
+data  Int  =  minBound ... -1 | 0 | 1 ... maxBound
+instance  Eq       Int  where ...
+instance  Ord      Int  where ...
+instance  Num      Int  where ...
+instance  Real     Int  where ...
+instance  Integral Int  where ...
+instance  Enum     Int  where ...
+instance  Bounded  Int  where ...
+
+data  Integer  =  ... -1 | 0 | 1 ...
+instance  Eq       Integer  where ...
+instance  Ord      Integer  where ...
+instance  Num      Integer  where ...
+instance  Real     Integer  where ...
+instance  Integral Integer  where ...
+instance  Enum     Integer  where ...
+
+data  Float
+instance  Eq         Float  where ...
+instance  Ord        Float  where ...
+instance  Num        Float  where ...
+instance  Real       Float  where ...
+instance  Fractional Float  where ...
+instance  Floating   Float  where ...
+instance  RealFrac   Float  where ...
+instance  RealFloat  Float  where ...
+
+data  Double
+instance  Eq         Double  where ...
+instance  Ord        Double  where ...
+instance  Num        Double  where ...
+instance  Real       Double  where ...
+instance  Fractional Double  where ...
+instance  Floating   Double  where ...
+instance  RealFrac   Double  where ...
+instance  RealFloat  Double  where ...
+
+-- The Enum instances for Floats and Doubles are slightly unusual.
+-- The `toEnum' function truncates numbers to Int.  The definitions
+-- of enumFrom and enumFromThen allow floats to be used in arithmetic
+-- series: [0,0.1 .. 1.0].  However, roundoff errors make these somewhat
+-- dubious.  This example may have either 10 or 11 elements, depending on
+-- how 0.1 is represented.
+
+instance  Enum Float  where
+    succ x           =  x+1
+    pred x           =  x-1
+    toEnum           =  fromIntegral
+    fromEnum         =  fromInteger . truncate   -- may overflow
+    enumFrom         =  numericEnumFrom
+    enumFromThen     =  numericEnumFromThen
+    enumFromTo       =  numericEnumFromTo
+    enumFromThenTo   =  numericEnumFromThenTo
+
+instance  Enum Double  where
+    succ x           =  x+1
+    pred x           =  x-1
+    toEnum           =  fromIntegral
+    fromEnum         =  fromInteger . truncate   -- may overflow
+    enumFrom         =  numericEnumFrom
+    enumFromThen     =  numericEnumFromThen
+    enumFromTo       =  numericEnumFromTo
+    enumFromThenTo   =  numericEnumFromThenTo
+
+numericEnumFrom         :: (Fractional a) => a -> [a]
+numericEnumFromThen     :: (Fractional a) => a -> a -> [a]
+numericEnumFromTo       :: (Fractional a, Ord a) => a -> a -> [a]
+numericEnumFromThenTo   :: (Fractional a, Ord a) => a -> a -> a -> [a]
+numericEnumFrom         =  iterate (+1)
+numericEnumFromThen n m =  iterate (+(m-n)) n
+numericEnumFromTo n m   =  takeWhile (<= m+1/2) (numericEnumFrom n)
+numericEnumFromThenTo n n' m = takeWhile p (numericEnumFromThen n n')
+                             where
+                               p | n' > n    = (<= m + (n'-n)/2)
+                                 | otherwise = (>= m + (n'-n)/2)
+
+-- Lists
+
+-- This data declaration is not legal Haskell
+-- but it indicates the idea
+data  [a]  =  [] | a : [a]  deriving (Eq, Ord)
+
+instance Functor [] where
+    fmap = map
+
+instance  Monad []  where
+    m >>= k          = concat (map k m)
+    return x         = [x]
+    fail s           = []
+
+-- Tuples
+
+data  (a,b)   =  (a,b)    deriving (Eq, Ord, Bounded)
+data  (a,b,c) =  (a,b,c)  deriving (Eq, Ord, Bounded)
+
+
+-- component projections for pairs:
+-- (NB: not provided for triples, quadruples, etc.)
+fst              :: (a,b) -> a
+fst (x,y)        =  x
+
+snd              :: (a,b) -> b
+snd (x,y)        =  y
+
+-- curry converts an uncurried function to a curried function;
+-- uncurry converts a curried function to a function on pairs.
+curry            :: ((a, b) -> c) -> a -> b -> c
+curry f x y      =  f (x, y)
+
+uncurry          :: (a -> b -> c) -> ((a, b) -> c)
+uncurry f p      =  f (fst p) (snd p)
+
+-- Misc functions
+
+-- until p f  yields the result of applying f until p holds.
+until            :: (a -> Bool) -> (a -> a) -> a -> a
+until p f x 
+     | p x       =  x
+     | otherwise =  until p f (f x)
+
+-- asTypeOf is a type-restricted version of const.  It is usually used
+-- as an infix operator, and its typing forces its first argument
+-- (which is usually overloaded) to have the same type as the second.
+asTypeOf         :: a -> a -> a
+asTypeOf         =  const
+
+-- error stops execution and displays an error message
+
+error            :: String -> a
+error            =  primError
+
+-- It is expected that compilers will recognize this and insert error
+-- messages that are more appropriate to the context in which undefined 
+-- appears. 
+
+undefined        :: a
+undefined        =  error "Prelude.undefined"
+
diff --git a/report/PreludeIO.hs b/report/PreludeIO.hs
new file mode 100644 (file)
index 0000000..71bc577
--- /dev/null
@@ -0,0 +1,75 @@
+module PreludeIO (
+    FilePath, IOError, ioError, userError, catch,
+    putChar, putStr, putStrLn, print,
+    getChar, getLine, getContents, interact,
+    readFile, writeFile, appendFile, readIO, readLn
+  ) where
+
+import PreludeBuiltin
+
+
+type  FilePath = String
+
+data IOError    -- The internals of this type are system dependent
+
+instance  Show IOError  where ...
+instance  Eq IOError  where ...
+
+ioError          ::  IOError -> IO a 
+ioError          =   primIOError
+
+userError        ::  String -> IOError
+userError        =   primUserError
+
+catch            ::  IO a -> (IOError -> IO a) -> IO a 
+catch            =   primCatch
+
+putChar          :: Char -> IO ()
+putChar          =  primPutChar
+
+putStr           :: String -> IO ()
+putStr s         =  mapM_ putChar s
+
+putStrLn         :: String -> IO ()
+putStrLn s       =  do putStr s
+                       putStr "\n"
+
+print            :: Show a => a -> IO ()
+print x          =  putStrLn (show x)
+
+getChar          :: IO Char
+getChar          =  primGetChar
+
+getLine          :: IO String
+getLine          =  do c <- getChar
+                       if c == '\n' then return "" else 
+                          do s <- getLine
+                             return (c:s)
+            
+getContents      :: IO String
+getContents      =  primGetContents
+
+interact         ::  (String -> String) -> IO ()
+interact f       =  do s <- getContents
+                       putStr (f s)
+
+readFile         :: FilePath -> IO String
+readFile         =  primReadFile
+
+writeFile        :: FilePath -> String -> IO ()
+writeFile        =  primWriteFile
+
+appendFile       :: FilePath -> String -> IO ()
+appendFile       =  primAppendFile
+
+  -- raises an exception instead of an error
+readIO   :: Read a => String -> IO a
+readIO s =  case [x | (x,t) <- reads s, ("","") <- lex t] of
+              [x] -> return x
+              []  -> ioError (userError "Prelude.readIO: no parse")
+              _   -> ioError (userError "Prelude.readIO: ambiguous parse")
+
+readLn           :: Read a => IO a
+readLn           =  do l <- getLine
+                       r <- readIO l
+                       return r
diff --git a/report/PreludeList.hs b/report/PreludeList.hs
new file mode 100644 (file)
index 0000000..67ad5fa
--- /dev/null
@@ -0,0 +1,311 @@
+-- Standard list functions
+
+module PreludeList (
+    map, (++), filter, concat,
+    head, last, tail, init, null, length, (!!), 
+    foldl, foldl1, scanl, scanl1, foldr, foldr1, scanr, scanr1,
+    iterate, repeat, replicate, cycle,
+    take, drop, splitAt, takeWhile, dropWhile, span, break,
+    lines, words, unlines, unwords, reverse, and, or,
+    any, all, elem, notElem, lookup,
+    Sum, product, maximum, minimum, concatMap, 
+    zip, zip3, zipWith, zipWith3, unzip, unzip3)
+  where
+
+import qualified Char(isSpace)
+
+infixl 9  !!
+infixr 5  ++
+infix  4  `elem`, `notElem`
+
+-- Map and append
+map :: (a -> b) -> [a] -> [a]
+map f []     = []
+map f (x:xs) = f x : map f xs
+
+(++) :: [a] -> [a] -> [a]
+[]     ++ ys = ys
+(x:xs) ++ ys = x : (xs ++ ys)
+
+filter :: (a -> Bool) -> [a] -> [a]
+filter p [] = []
+filter p (x:xs) | p x       = x : filter p xs
+                | otherwise = filter p xs
+
+concat :: [[a]] -> [a]
+concat xss = foldr (++) [] xss
+
+
+-- head and tail extract the first element and remaining elements,
+-- respectively, of a list, which must be non-empty.  last and init
+-- are the dual functions working from the end of a finite list,
+-- rather than the beginning.
+
+head             :: [a] -> a
+head (x:_)       =  x
+head []          =  error "Prelude.head: empty list"
+
+last             :: [a] -> a
+last [x]         =  x
+last (_:xs)      =  last xs
+last []          =  error "Prelude.last: empty list"
+
+tail             :: [a] -> [a]
+tail (_:xs)      =  xs
+tail []          =  error "Prelude.tail: empty list"
+
+init             :: [a] -> [a]
+init [x]         =  []
+init (x:xs)      =  x : init xs
+init []          =  error "Prelude.init: empty list"
+
+null             :: [a] -> Bool
+null []          =  True
+null (_:_)       =  False
+
+-- length returns the length of a finite list as an Int.
+length           :: [a] -> Int
+length []        =  0
+length (_:l)     =  1 + length l
+
+-- List index (subscript) operator, 0-origin
+(!!)                :: [a] -> Int -> a
+(x:_)  !! 0         =  x
+(_:xs) !! n | n > 0 =  xs !! (n-1)
+(_:_)  !! _         =  error "Prelude.!!: negative index"
+[]     !! _         =  error "Prelude.!!: index too large"
+
+-- foldl, applied to a binary operator, a starting value (typically the
+-- left-identity of the operator), and a list, reduces the list using
+-- the binary operator, from left to right:
+--  foldl f z [x1, x2, ..., xn] == (...((z `f` x1) `f` x2) `f`...) `f` xn
+-- foldl1 is a variant that has no starting value argument, and  thus must
+-- be applied to non-empty lists.  scanl is similar to foldl, but returns
+-- a list of successive reduced values from the left:
+--      scanl f z [x1, x2, ...] == [z, z `f` x1, (z `f` x1) `f` x2, ...]
+-- Note that  last (scanl f z xs) == foldl f z xs.
+-- scanl1 is similar, again without the starting element:
+--      scanl1 f [x1, x2, ...] == [x1, x1 `f` x2, ...]
+
+foldl            :: (a -> b -> a) -> a -> [b] -> a
+foldl f z []     =  z
+foldl f z (x:xs) =  foldl f (f z x) xs
+
+foldl1           :: (a -> a -> a) -> [a] -> a
+foldl1 f (x:xs)  =  foldl f x xs
+foldl1 _ []      =  error "Prelude.foldl1: empty list"
+
+scanl            :: (a -> b -> a) -> a -> [b] -> [a]
+scanl f q xs     =  q : (case xs of
+                            []   -> []
+                            x:xs -> scanl f (f q x) xs)
+
+scanl1           :: (a -> a -> a) -> [a] -> [a]
+scanl1 f (x:xs)  =  scanl f x xs
+scanl1 _ []      =  error "Prelude.scanl1: empty list"
+
+-- foldr, foldr1, scanr, and scanr1 are the right-to-left duals of the
+-- above functions.
+
+foldr            :: (a -> b -> b) -> b -> [a] -> b
+foldr f z []     =  z
+foldr f z (x:xs) =  f x (foldr f z xs)
+
+foldr1           :: (a -> a -> a) -> [a] -> a
+foldr1 f [x]     =  x
+foldr1 f (x:xs)  =  f x (foldr1 f xs)
+foldr1 _ []      =  error "Prelude.foldr1: empty list"
+
+scanr             :: (a -> b -> b) -> b -> [a] -> [b]
+scanr f q0 []     =  [q0]
+scanr f q0 (x:xs) =  f x q : qs
+                     where qs@(q:_) = scanr f q0 xs 
+
+scanr1           :: (a -> a -> a) -> [a] -> [a]
+scanr1 f  [x]    =  [x]
+scanr1 f  (x:xs) =  f x q : qs
+                    where qs@(q:_) = scanr1 f xs 
+scanr1 _ []      =  error "Prelude.scanr1: empty list"
+
+-- iterate f x returns an infinite list of repeated applications of f to x:
+-- iterate f x == [x, f x, f (f x), ...]
+iterate          :: (a -> a) -> a -> [a]
+iterate f x      =  x : iterate f (f x)
+
+-- repeat x is an infinite list, with x the value of every element.
+repeat           :: a -> [a]
+repeat x         =  xs where xs = x:xs
+
+-- replicate n x is a list of length n with x the value of every element
+replicate        :: Int -> a -> [a]
+replicate n x    =  take n (repeat x)
+
+-- cycle ties a finite list into a circular one, or equivalently,
+-- the infinite repetition of the original list.  It is the identity
+-- on infinite lists.
+
+cycle            :: [a] -> [a]
+cycle []         =  error "Prelude.cycle: empty list"
+cycle xs         =  xs' where xs' = xs ++ xs'
+
+-- take n, applied to a list xs, returns the prefix of xs of length n,
+-- or xs itself if n > length xs.  drop n xs returns the suffix of xs
+-- after the first n elements, or [] if n > length xs.  splitAt n xs
+-- is equivalent to (take n xs, drop n xs).
+
+take                   :: Int -> [a] -> [a]
+take 0 _               =  []
+take _ []              =  []
+take n (x:xs) | n > 0  =  x : take (n-1) xs
+take _     _           =  error "Prelude.take: negative argument"
+
+drop                   :: Int -> [a] -> [a]
+drop 0 xs              =  xs
+drop _ []              =  []
+drop n (_:xs) | n > 0  =  drop (n-1) xs
+drop _     _           =  error "Prelude.drop: negative argument"
+
+splitAt                  :: Int -> [a] -> ([a],[a])
+splitAt 0 xs             =  ([],xs)
+splitAt _ []             =  ([],[])
+splitAt n (x:xs) | n > 0 =  (x:xs',xs'') where (xs',xs'') = splitAt (n-1) xs
+splitAt _     _          =  error "Prelude.splitAt: negative argument"
+
+-- takeWhile, applied to a predicate p and a list xs, returns the longest
+-- prefix (possibly empty) of xs of elements that satisfy p.  dropWhile p xs
+-- returns the remaining suffix.  Span p xs is equivalent to 
+-- (takeWhile p xs, dropWhile p xs), while break p uses the negation of p.
+
+takeWhile               :: (a -> Bool) -> [a] -> [a]
+takeWhile p []          =  []
+takeWhile p (x:xs) 
+            | p x       =  x : takeWhile p xs
+            | otherwise =  []
+
+dropWhile               :: (a -> Bool) -> [a] -> [a]
+dropWhile p []          =  []
+dropWhile p xs@(x:xs')
+            | p x       =  dropWhile p xs'
+            | otherwise =  xs
+
+span, break             :: (a -> Bool) -> [a] -> ([a],[a])
+span p []            = ([],[])
+span p xs@(x:xs') 
+            | p x       =  (x:ys,zs) 
+            | otherwise =  ([],xs)
+                           where (ys,zs) = span p xs'
+
+break p                 =  span (not . p)
+
+-- lines breaks a string up into a list of strings at newline characters.
+-- The resulting strings do not contain newlines.  Similary, words
+-- breaks a string up into a list of words, which were delimited by
+-- white space.  unlines and unwords are the inverse operations.
+-- unlines joins lines with terminating newlines, and unwords joins
+-- words with separating spaces.
+
+lines            :: String -> [String]
+lines ""         =  []
+lines s          =  let (l, s') = break (== '\n') s
+                      in  l : case s' of
+                                []      -> []
+                                (_:s'') -> lines s''
+
+words            :: String -> [String]
+words s          =  case dropWhile Char.isSpace s of
+                      "" -> []
+                      s' -> w : words s''
+                            where (w, s'') = break Char.isSpace s'
+
+unlines          :: [String] -> String
+unlines          =  concatMap (++ "\n")
+
+unwords          :: [String] -> String
+unwords []       =  ""
+unwords ws       =  foldr1 (\w s -> w ++ ' ':s) ws
+
+-- reverse xs returns the elements of xs in reverse order.  xs must be finite.
+reverse          :: [a] -> [a]
+reverse          =  foldl (flip (:)) []
+
+-- and returns the conjunction of a Boolean list.  For the result to be
+-- True, the list must be finite; False, however, results from a False
+-- value at a finite index of a finite or infinite list.  or is the
+-- disjunctive dual of and.
+and, or          :: [Bool] -> Bool
+and              =  foldr (&&) True
+or               =  foldr (||) False
+
+-- Applied to a predicate and a list, any determines if any element
+-- of the list satisfies the predicate.  Similarly, for all.
+any, all         :: (a -> Bool) -> [a] -> Bool
+any p            =  or . map p
+all p            =  and . map p
+
+-- elem is the list membership predicate, usually written in infix form,
+-- e.g., x `elem` xs.  notElem is the negation.
+elem, notElem    :: (Eq a) => a -> [a] -> Bool
+elem x           =  any (== x)
+notElem x        =  all (/= x)
+
+-- lookup key assocs looks up a key in an association list.
+lookup           :: (Eq a) => a -> [(a,b)] -> Maybe b
+lookup key []    =  Nothing
+lookup key ((x,y):xys)
+    | key == x   =  Just y
+    | otherwise  =  lookup key xys
+
+-- sum and product compute the sum or product of a finite list of numbers.
+sum, product     :: (Num a) => [a] -> a
+sum              =  foldl (+) 0  
+product          =  foldl (*) 1
+
+-- maximum and minimum return the maximum or minimum value from a list,
+-- which must be non-empty, finite, and of an ordered type.
+maximum, minimum :: (Ord a) => [a] -> a
+maximum []       =  error "Prelude.maximum: empty list"
+maximum xs       =  foldl1 max xs
+
+minimum []       =  error "Prelude.minimum: empty list"
+minimum xs       =  foldl1 min xs
+
+concatMap        :: (a -> [b]) -> [a] -> [b]
+concatMap f      =  concat . map f
+
+-- zip takes two lists and returns a list of corresponding pairs.  If one
+-- input list is short, excess elements of the longer list are discarded.
+-- zip3 takes three lists and returns a list of triples.  Zips for larger
+-- tuples are in the List library
+
+zip              :: [a] -> [b] -> [(a,b)]
+zip              =  zipWith (,)
+
+zip3             :: [a] -> [b] -> [c] -> [(a,b,c)]
+zip3             =  zipWith3 (,,)
+
+-- The zipWith family generalises the zip family by zipping with the
+-- function given as the first argument, instead of a tupling function.
+-- For example, zipWith (+) is applied to two lists to produce the list
+-- of corresponding sums.
+
+zipWith          :: (a->b->c) -> [a]->[b]->[c]
+zipWith z (a:as) (b:bs)
+                 =  z a b : zipWith z as bs
+zipWith _ _ _    =  []
+
+zipWith3         :: (a->b->c->d) -> [a]->[b]->[c]->[d]
+zipWith3 z (a:as) (b:bs) (c:cs)
+                 =  z a b c : zipWith3 z as bs cs
+zipWith3 _ _ _ _ =  []
+
+
+-- unzip transforms a list of pairs into a pair of lists.  
+
+unzip            :: [(a,b)] -> ([a],[b])
+unzip            =  foldr (\(a,b) ~(as,bs) -> (a:as,b:bs)) ([],[])
+
+unzip3           :: [(a,b,c)] -> ([a],[b],[c])
+unzip3           =  foldr (\(a,b,c) ~(as,bs,cs) -> (a:as,b:bs,c:cs))
+                          ([],[],[])
+
+
diff --git a/report/PreludeText.hs b/report/PreludeText.hs
new file mode 100644 (file)
index 0000000..372552f
--- /dev/null
@@ -0,0 +1,205 @@
+module PreludeText (
+    ReadS, ShowS,
+    Read(readsPrec, readList),
+    Show(showsPrec, showList),
+    reads, shows, show, read, lex,
+    showChar, showString, readParen, showParen ) where
+
+-- The instances of Read and Show for
+--     Bool, Char, Maybe, Either, Ordering
+-- are done via "deriving" clauses in Prelude.hs
+
+import Char(isSpace, isAlpha, isDigit, isAlphaNum,
+            showLitChar, readLitChar, lexLitChar)
+
+import Numeric(showSigned, showInt, readSigned, readDec, showFloat,
+               readFloat, lexDigits)
+
+type  ReadS a  = String -> [(a,String)]
+type  ShowS    = String -> String
+
+class  Read a  where
+    readsPrec        :: Int -> ReadS a
+    readList         :: ReadS [a]
+
+       -- Minimal complete definition:
+       --      readsPrec
+    readList         = readParen False (\r -> [pr | ("[",s)  <- lex r,
+                                                    pr       <- readl s])
+                       where readl  s = [([],t)   | ("]",t)  <- lex s] ++
+                                        [(x:xs,u) | (x,t)    <- reads s,
+                                                    (xs,u)   <- readl' t]
+                             readl' s = [([],t)   | ("]",t)  <- lex s] ++
+                                        [(x:xs,v) | (",",t)  <- lex s,
+                                                    (x,u)    <- reads t,
+                                                    (xs,v)   <- readl' u]
+
+class  Show a  where
+    showsPrec        :: Int -> a -> ShowS
+    show            :: a -> String 
+    showList         :: [a] -> ShowS
+
+       -- Mimimal complete definition:
+       --      show or showsPrec
+    showsPrec _ x s   = show x ++ s
+
+    show x           = showsPrec 0 x ""
+
+    showList []       = showString "[]"
+    showList (x:xs)   = showChar '[' . shows x . showl xs
+                        where showl []     = showChar ']'
+                              showl (x:xs) = showChar ',' . shows x .
+                                             showl xs
+
+reads            :: (Read a) => ReadS a
+reads            =  readsPrec 0
+
+shows            :: (Show a) => a -> ShowS
+shows            =  showsPrec 0
+
+read             :: (Read a) => String -> a
+read s           =  case [x | (x,t) <- reads s, ("","") <- lex t] of
+                         [x] -> x
+                         []  -> error "Prelude.read: no parse"
+                         _   -> error "Prelude.read: ambiguous parse"
+
+showChar         :: Char -> ShowS
+showChar         =  (:)
+
+showString       :: String -> ShowS
+showString       =  (++)
+
+showParen        :: Bool -> ShowS -> ShowS
+showParen b p    =  if b then showChar '(' . p . showChar ')' else p
+
+readParen        :: Bool -> ReadS a -> ReadS a
+readParen b g    =  if b then mandatory else optional
+                    where optional r  = g r ++ mandatory r
+                          mandatory r = [(x,u) | ("(",s) <- lex r,
+                                                 (x,t)   <- optional s,
+                                                 (")",u) <- lex t    ]
+
+-- This lexer is not completely faithful to the Haskell lexical syntax.
+-- Current limitations:
+--    Qualified names are not handled properly
+--    Octal and hexidecimal numerics are not recognized as a single token
+--    Comments are not treated properly
+
+lex              :: ReadS String
+lex ""           =  [("","")]
+lex (c:s)
+   | isSpace c   =  lex (dropWhile isSpace s)
+lex ('\'':s)     =  [('\'':ch++"'", t) | (ch,'\'':t)  <- lexLitChar s,
+                                         ch /= "'" ]
+lex ('"':s)      =  [('"':str, t)      | (str,t) <- lexString s]
+                    where
+                    lexString ('"':s) = [("\"",s)]
+                    lexString s = [(ch++str, u)
+                                         | (ch,t)  <- lexStrItem s,
+                                           (str,u) <- lexString t  ]
+
+                    lexStrItem ('\\':'&':s) =  [("\\&",s)]
+                    lexStrItem ('\\':c:s) | isSpace c
+                                           =  [("\\&",t) | 
+                                               '\\':t <-
+                                                   [dropWhile isSpace s]]
+                    lexStrItem s           =  lexLitChar s
+
+lex (c:s) | isSingle c = [([c],s)]
+          | isSym c    = [(c:sym,t)       | (sym,t) <- [span isSym s]]
+          | isAlpha c  = [(c:nam,t)       | (nam,t) <- [span isIdChar s]]
+          | isDigit c  = [(c:ds++fe,t)    | (ds,s)  <- [span isDigit s],
+                                            (fe,t)  <- lexFracExp s     ]
+          | otherwise  = []    -- bad character
+             where
+              isSingle c =  c `elem` ",;()[]{}_`"
+             isSym c    =  c `elem` "!@#$%&*+./<=>?\\^|:-~"
+              isIdChar c =  isAlphaNum c || c `elem` "_'"
+
+              lexFracExp ('.':c:cs) | isDigit c
+                            = [('.':ds++e,u) | (ds,t) <- lexDigits (c:cs),
+                                               (e,u)  <- lexExp t]
+              lexFracExp s          = [("",s)]
+
+              lexExp (e:s) | e `elem` "eE"
+                       = [(e:c:ds,u) | (c:t)  <- [s], c `elem` "+-",
+                                                 (ds,u) <- lexDigits t] ++
+                         [(e:ds,t)   | (ds,t) <- lexDigits s]
+              lexExp s = [("",s)]
+
+instance  Show Int  where
+    showsPrec           = showSigned showInt
+
+instance  Read Int  where
+    readsPrec p         = readSigned readDec
+
+instance  Show Integer  where
+    showsPrec           = showSigned showInt
+
+instance  Read Integer  where
+    readsPrec p         = readSigned readDec
+
+instance  Show Float  where 
+    showsPrec p         = showFloat
+           
+instance  Read Float  where
+    readsPrec p         = readFloat
+
+instance  Show Double  where
+    showsPrec p         = showFloat
+
+instance  Read Double  where
+    readsPrec p         = readFloat
+
+instance  Show ()  where
+    showsPrec p () = showString "()"
+
+instance Read () where
+    readsPrec p    = readParen False
+                            (\r -> [((),t) | ("(",s) <- lex r,
+                                             (")",t) <- lex s ] )
+instance  Show Char  where
+    showsPrec p '\'' = showString "'\\''"
+    showsPrec p c    = showChar '\'' . showLitChar c . showChar '\''
+
+    showList cs = showChar '"' . showl cs
+                 where showl ""       = showChar '"'
+                       showl ('"':cs) = showString "\\\"" . showl cs
+                       showl (c:cs)   = showLitChar c . showl cs
+
+instance  Read Char  where
+    readsPrec p      = readParen False
+                            (\r -> [(c,t) | ('\'':s,t)<- lex r,
+                                            (c,"\'")  <- readLitChar s])
+
+    readList = readParen False (\r -> [(l,t) | ('"':s, t) <- lex r,
+                                               (l,_)      <- readl s ])
+        where readl ('"':s)      = [("",s)]
+              readl ('\\':'&':s) = readl s
+              readl s            = [(c:cs,u) | (c ,t) <- readLitChar s,
+                                               (cs,u) <- readl t       ]
+
+instance  (Show a) => Show [a]  where
+    showsPrec p      = showList
+
+instance  (Read a) => Read [a]  where
+    readsPrec p      = readList
+
+-- Tuples
+
+instance  (Show a, Show b) => Show (a,b)  where
+    showsPrec p (x,y) = showChar '(' . shows x . showChar ',' .
+                                       shows y . showChar ')'
+
+instance  (Read a, Read b) => Read (a,b)  where
+    readsPrec p       = readParen False
+                            (\r -> [((x,y), w) | ("(",s) <- lex r,
+                                                 (x,t)   <- reads s,
+                                                 (",",u) <- lex t,
+                                                 (y,v)   <- reads u,
+                                                 (")",w) <- lex v ] )
+
+-- Other tuples have similar Read and Show instances
+
+
+
diff --git a/report/README b/report/README
new file mode 100644 (file)
index 0000000..ffbfa42
--- /dev/null
@@ -0,0 +1,154 @@
+
+This is the Haskell 1.4 report, source distribution.  
+
+This has all files needed to generate either the postscript or the
+html version of the Haskell report.  Some of these files are generated
+from others - these are marked with a (*) and are included in case the
+tool used to generate the file is unavailable.
+
+To generate the postscript report you need lex, perl, latex,
+makeindex, and dvips.
+
+To generate the html report you need Hugs 1.4 (probably any Haskell
+1.4 compiler will do).
+
+
+Source files for the report:
+plain-haskell.verb  -- Top level of the report
+
+Sections of the report:
+intro.verb
+lexemes.verb
+exps.verb
+decls.verb
+modules.verb
+basic.verb
+io-13.verb
+standard-prelude.verb
+syntax-iso.verb
+literate.verb
+derived.verb
+pragmas.verb
+haskell.bib
+
+Extra .verb files:
+iso-chars.verb    -- Some bogus definitions for ISO chars.  Probably not 
+                  -- needed since I removed them from the syntax. 
+layout.verb       -- a section on layout repeated in the appendix
+index-extra.verb  -- extra stuff to get indexed (see also's)
+index-intro.verb  -- header for index
+
+Haskell source files:
+
+Prelude.hs
+PreludeList.hs
+PreludeIO.hs
+PreludeText.hs
+
+Figures:
+
+class-fig.cdr      --  The original class figure (Corel Draw 6 format)
+class-fig.eps (*)   --  Postscript version of class-fig
+class-fig.gif (*)  --  For html version
+cover.cdr          --  A nice looking cover for the report
+cover.eps (*)
+
+Html support:
+
+html.config        -- configuration file for tex.hs.
+haskell.aux (*)    -- The aux file generated by latex; used by html translator
+haskell.bbl (*)    -- used by html translator.  Hand edited to add
+                   -- html headers at front.
+prelude-index.idx  -- Html file containing index of prelude.  #'s are
+                   -- expanded by index.hs
+index.html         -- Top level of the html report (hand generated)
+lambda.gif         -- background for title page
+title.gif          -- title graphic 
+
+Other files:
+
+Makefile         -- Lots of extra cruft no longer used. 
+haskell.dvi (*)  -- in case you just want to run dvips
+haskell.ind (*)  -- is case you don't have makeindex 
+haskell.idx (*)  -- makes building easier
+
+
+To build the .dvi you need to patch the makefile to call the proper
+version of perl.  You will have some `non-grokked' instances in the
+perl.  Remember that you have to run latex twice.  If anyone converts
+the perl program to perl5 please send it to us!
+
+Report any problems to peterson-john@cs.yale.edu
+
+
+Building HTML files
+~~~~~~~~~~~~~~~~~~~
+Build the html by creating a `html' subdirectory, copy the .html and
+.gif files to it, and run tex.hs twice (like tex - to get forward refs
+right).  Run index.hs to generate the function index.  You're done.
+The 'make html' does most of this.
+
+There are three files you need to work on:
+
+       report/html.config
+
+Edit the title in the headers and footers. 
+You can hack in whatever html you want for page headers and
+footers .  You can also hack on the output directory setting (htmldir)
+to direct the output wherever you want.  You'll have to fiddle
+"index.hs" if you do this, though.  You can also add the line
+
+       style = microsoftsymbols,article
+
+This exploits the symbol font that microsoft uses in its browser.
+Much nicer for some of the equations.  Probably a good idea since most
+browsers handle the symbol font OK nowadays.
+
+       report/prelude-index.idx
+
+You will need to edit this a little bit; probably just a few renamings
+and deleting stuff that lives in the libraries now.  Add a few more 
+examples if you're feeling energetic.
+
+As to the building process:
+
+To build the html report: (using the .aux file and all the .verb files) 
+
+cd <report directory>
+runhugs tex.hs
+runhugs tex.hs
+runhugs index.hs
+
+Like latex, you have to run tex.hs twice.  Unless you make massive
+changes, though, you can probably just do it once.  I'm sure ghc will
+compile tex.hs if you want to speed things up. 
+
+
+
+Making figures
+~~~~~~~~~~~~~~
+The classes.eps files, which contains the classes hierarchy figure,
+is made in Powerpoint, from classses.ppt.  To get the .eps file,
+do the following:
+
+* Open classes.ppt
+* Print..
+* Check the print-to-file box, and save as classes.prn
+* Edit classes.prn
+       Kill the .prn header and footer (before % PS-Adobe), and after %EOF
+       Kill the entire setup code (from BeginSetup to EndSetup)
+       Kill the showpage near the end
+* Save as classes.eps
+* Open with Ghostview
+* Note the coords of the bottom LH and top RH corner, as reported by
+  Ghostview
+* Re-edit classes.eps, and put those coords in the
+       %BoundingBox line
+
+You also need to do
+       Save As.. 
+in Powerpoint, and save the thing as classes.gif, for the HTML version
+
+
+
+
diff --git a/report/basic.verb b/report/basic.verb
new file mode 100644 (file)
index 0000000..c1a7eaf
--- /dev/null
@@ -0,0 +1,1003 @@
+%
+% $Header: /home/cvs/root/haskell-report/report/basic.verb,v 1.1 2001/03/28 14:13:42 simonpj Exp $
+%
+%**<title>The Haskell 98 Report: Basic Types and Classes</title>
+%*section 6
+%**~header
+\section{Predefined Types and Classes}
+\label{basic-types-and-classes}
+The \Haskell{} Prelude contains predefined classes, types,
+and functions that are implicitly imported into every Haskell
+program.  In this section, we describe the types and classes found in
+the Prelude.
+Most functions are not described in detail here as they
+can easily be understood from their definitions as given in Appendix
+\ref{stdprelude}.
+Other predefined types such as arrays, complex numbers, and rationals
+are defined in the \Haskell{} Library Report.
+
+\subsection{Standard Haskell Types}
+\label{basic-types}
+These types are defined by the \Haskell{} Prelude.  Numeric types are
+described in Section \ref{numbers}.  When appropriate, the \Haskell{}
+definition of the type is given.  Some definitions may not be
+completely valid on syntactic grounds but they faithfully convey the
+meaning of the underlying type.
+
+\subsubsection{Booleans}
+\label{booleans}
+\index{boolean}
+\bprog
+@
+data  Bool  =  False | True deriving 
+                             (Read, Show, Eq, Ord, Enum, Bounded)
+@
+\eprog
+The boolean type @Bool@ is an enumeration. % ; Figure~\ref{prelude-bool}
+The basic boolean functions are @&&@ (and), @||@ (or), and @not@.
+The name @otherwise@ is defined as @True@ to make guarded expressions
+more readable.
+
+\label{prelude-bool}
+\indextycon{Bool}
+\indextt{False}\indextt{True}
+\index{""|""|@@{\tt  {\char'174}{\char'174}}}
+\index{&&@@{\tt  \&\&}}
+\indextt{not}
+\indextt{otherwise}
+
+\subsubsection{Characters and Strings}
+\label{characters}
+\index{character}\index{string}
+
+The character type @Char@\indextycon{Char}
+is an enumeration and consists of 16 bit values, conforming to
+the Unicode standard~\cite{unicode}.
+% of which the first 128
+% are the ASCII\index{ASCII character set} character set.  
+The lexical syntax for
+characters is defined in Section~\ref{lexemes-char}; character
+literals are nullary constructors in the datatype @Char@.  Type @Char@
+is an instance of the classes @Read@, @Show@, @Eq@, @Ord@, 
+@Enum@, and @Bounded@.  The @toEnum@ and @fromEnum@ functions,
+standard functions over bounded enumerations, map characters onto
+@Int@ values in the range "[ 0 , 2^{16}-1 ]".
+
+Note that ASCII control characters each have several representations
+in character literals: numeric escapes, ASCII mnemonic escapes,
+and the @\^@"X" notation.
+In addition, there are the following equivalences:
+@\a@ and @\BEL@, @\b@ and @\BS@, @\f@ and @\FF@, @\r@ and @\CR@,
+@\t@ and @\HT@, @\v@ and @\VT@, and @\n@ and @\LF@.
+
+A {\em string} is a list of characters:\nopagebreak[4]
+\bprog
+@
+type  String  =  [Char]
+@
+\eprog
+\indexsynonym{String}
+Strings may be abbreviated using the lexical syntax described in
+Section~\ref{lexemes-char}.  For example, @"A string"@ abbreviates
+\[
+@[ 'A',' ','s','t','r', 'i','n','g']@
+\]
+
+\subsubsection{Lists}
+\label{basic-lists}
+\index{list}
+\bprog
+@
+data  [a]  =  [] | a : [a]  deriving (Eq, Ord)
+@
+\eprog
+Lists are an algebraic datatype of two constructors, although
+with special syntax, as described in Section~\ref{lists}.
+The first constructor is the null list, written `@[]@' (``nil''),
+\index{[]@@{\tt  []} (nil)}%
+and the second is `@:@' (``cons'').
+\indextt{:}
+The module @PreludeList@ (see Appendix~\ref{preludelist}) 
+defines many standard list functions.  
+Arithmetic sequences
+\index{arithmetic sequence}
+and list comprehensions,
+\index{list comprehension}
+two convenient
+syntaxes for special kinds of lists, are described in
+Sections~\ref{arithmetic-sequences} and \ref{list-comprehensions},
+respectively.  Lists are an instance of classes @Read@, @Show@, @Eq@, @Ord@, 
+@Monad@, and @MonadPlus@.
+
+\subsubsection{Tuples}
+\label{basic-tuples}
+\index{tuple}
+
+Tuples are algebraic datatypes with special syntax, as defined
+in Section~\ref{tuples}.  Each tuple type has a single constructor.
+There is no upper bound on the size of a tuple.  However, some
+\Haskell{} implementations may restrict the size of tuples and limit
+the instances associated with larger tuples.
+The Prelude and libraries define tuple functions such as @zip@ for
+tuples up to a
+size of 7.  All tuples are instances of @Eq@, @Ord@, @Bounded@, @Read@,
+and @Show@.  Classes defined in the libraries may also supply
+instances for tuple types.
+
+The constructor for a tuple is written by omitting the expressions
+surrounding the commas; thus @(x,y)@ and @(,) x y@ produce the same
+value. The same holds for tuple type constructors; thus, @(Int,Bool,Int)@
+and @(,,) Int Bool Int@ denote the same type.
+\indextt{(,)}
+\indextt{(,,)}
+
+The following functions are defined for pairs (2-tuples):
+@fst@, @snd@, @curry@, and @uncurry@.  Similar functions are not
+predefined for larger tuples.
+\indextt{fst}
+\indextt{snd}
+\indextt{curry}
+\indextt{uncurry}
+\indextt{zip}
+
+\subsubsection{The Unit Datatype}
+\label{basic-trivial}
+\bprog
+@
+data  () = () deriving (Eq, Ord, Bounded, Enum, Read, Show)
+@
+\eprog
+The unit datatype @()@ has one non-"\bot"
+member, the nullary constructor @()@.  See also Section~\ref{unit-expression}.
+\index{trivial type}
+
+\subsubsection{Function Types}
+\index{function}
+Functions are an abstract type: no constructors directly create
+functional values.  Functions are an instance of the @Show@ class but
+not @Read@.  The following simple functions are found in the Prelude:
+@id@, @const@, @(.)@, @flip@, @($)@, and @until@.
+\indextt{id}
+\indextt{const}
+\indextt{.}
+\indextt{flip}
+\indextt{until}
+
+\subsubsection{The IO and IOError Types}
+The @IO@ type serves as a tag for operations (actions) that interact
+with the outside world.  The @IO@ type is abstract: no constructors are
+visible to the user.  @IO@ is an instance of the @Monad@ and 
+@Show@ classes.  Section \ref{io} describes I/O operations.
+
+@IOError@ is an abstract type representing errors raised by I/O
+operations.  It is an instance of @Show@ and @Eq@.  Values of this type
+are constructed by the various I/O functions and are not presented in
+any further detail in this report.  The Prelude contains a few
+I/O functions (defined in Section~\ref{preludeio}), and the Library
+Report contains many more.
+\indextycon{IO}
+\indextycon{IOError}
+
+\subsubsection{Other Types}
+\bprog
+@
+data  Maybe a     =  Nothing | Just a  deriving (Eq, Ord, Read, Show)
+data  Either a b  =  Left a | Right b  deriving (Eq, Ord, Read, Show)
+data  Ordering    =  LT | EQ | GT deriving
+                                  (Eq, Ord, Bounded, Enum, Read, Show)
+@
+\indextt{Just}
+\indextt{Nothing}
+\indextycon{Maybe}
+\indextt{Left}
+\indextt{Right}
+\indextycon{Either}
+\indextt{LT}
+\indextt{EQ}
+\indextt{GT}
+\indextycon{Ordering}
+\indextt{maybe}
+\indextt{either}
+\eprog
+The @Maybe@ type is an instance of classes @Functor@, @Monad@,
+and @MonadPlus@.  The @Ordering@ type is used by @compare@
+in the class @Ord@. The functions @maybe@ and @either@ are found in
+the Prelude.
+
+\subsection{Strict Evaluation}
+\label{strict-eval}
+\indextt{$!}
+\indextt{seq}
+Function application in Haskell is non-strict; that is, a function
+argument is evaluated only when required.  Sometimes it is desirable to
+force the evaluation of a value, using the @seq@ function:
+\bprog
+@
+  seq :: a -> b -> b
+@
+\eprog
+The function @seq@ is defined by the equations:
+\[\ba{l}
+"@seq@ \bot b = \bot" \\
+"@seq@  a b =  b,  if a \ne \bot" \\
+\ea\]
+@seq@ is usually introduced to improve performance by
+avoiding unneeded laziness.  Strict datatypes (see
+\index{strictness flags}
+Section~\ref{strictness-flags}) are defined in terms of the @$!@
+function. 
+However, it has important semantic consequences, because it is available
+{\em at every type}.
+As a consequence, "\bot" is
+not the same as @\x -> @ "\bot", since @seq@ can be used to distinguish them.
+For the same reason, the existence of @seq@ weakens Haskell's parametricity properties.
+
+The operator @$!@ is strict (call-by-value) application, and is defined
+in terms of @seq@.  The Prelude also defines lazy application, @$@.
+\bprog
+@
+  infixr 0 $, $!
+  ($), ($!) :: (a -> b) -> a -> b
+   f $  x   =          f x
+   f $! x   =  x `seq` f x
+@
+\eprog
+The lazy application operator @$@ may appear redundant, since 
+ordinary application @(f x)@ means the same as @(f $ x)@.
+However, @$@ has low, right-associative binding precedence,
+so it sometimes allows parentheses to be omitted; for example:
+\bprog
+@
+  f $ g $ h x  =  f (g (h x))
+@
+\eprog
+It is also useful in higher-order situations, such as @map ($ 0) xs@,
+or @zipWith ($) fs xs@.
+
+\subsection{Standard Haskell Classes}
+Figure~\ref{standard-classes} shows the hierarchy of 
+\Haskell{} classes defined in the Prelude and the Prelude types that
+are instances of these classes.
+\begin{figure}%
+%*ignore
+% \epsfbox{class-fig.eps}
+\includegraphics{classes.eps}
+% \struthack{11pt}
+%*endignore
+%**<div align=center><img src="classes.gif" alt="Diagram of standard Haskell classes"> 
+%**<h4>Figure 5</h4> </div>
+\ecaption{Standard Haskell Classes}
+\label{standard-classes}
+\end{figure}
+
+Default class method declarations (Section~\ref{classes}) are provided
+for many of the methods in standard classes.  For example, the declaration
+of class @Eq@ is:
+@
+  class  Eq a  where
+        (==), (/=)  ::  a -> a -> Bool
+
+        x /= y  = not (x == y)
+       x == y  = not (x /= y)
+@
+This declaration gives default method declarations for both @/=@ and @==@,
+each being defined in terms of the other.  If an instance declaration
+for @Eq@ defines neither @==@ nor @/=@, then both will loop.
+If one is defined, the default method for the other will make use of
+the one that is defined.  If both are defined, neither default method is used.
+
+A comment with each @class@ declaration in Appendix~\ref{stdprelude} specifies
+the smallest collection of method definitions that, 
+together with the default declarations,
+provide a definition for all the class methods.
+If there is no such comment, then all class methods must
+be given to fully specify an instance.
+
+\subsubsection{The Eq Class}
+\indexclass{Eq}
+\indextt{==}
+\indextt{/=}
+\bprog
+@
+  class  Eq a  where
+        (==), (/=)  ::  a -> a -> Bool
+
+        x /= y  = not (x == y)
+       x == y  = not (x /= y)
+@
+\eprog
+The @Eq@ class provides equality (@==@) and inequality (@/=@) methods.
+All basic datatypes except for functions and @IO@ are instances of this class.
+Instances of @Eq@ can be derived for any user-defined datatype whose
+constituents are also instances of @Eq@.
+
+\subsubsection{The Ord Class}
+\indexclass{Ord}
+\indextt{<}
+\indextt{<=}
+\indextt{>}
+\indextt{>=}
+\indextt{compare}
+\indextt{max}
+\indextt{min}
+\bprog
+@
+  class  (Eq a) => Ord a  where
+    compare              :: a -> a -> Ordering
+    (<), (<=), (>=), (>) :: a -> a -> Bool
+    max, min            :: a -> a -> a
+
+    compare x y
+           | x == y    = EQ
+           | x <= y    = LT
+           | otherwise = GT
+
+    x <= y              = compare x y /= GT
+    x <         y              = compare x y == LT
+    x >= y             = compare x y /= LT
+    x >         y              = compare x y == GT
+
+    -- note that (min x y, max x y) = (x,y) or (y,x)
+    max x y | x >= y   =  x
+           | otherwise =  y
+    min x y | x <  y   =  x
+           | otherwise =  y
+@
+\eprog
+The @Ord@ class is used for totally ordered datatypes.  All basic
+datatypes
+except for functions, @IO@, and @IOError@, are instances of this class.  Instances
+of @Ord@ 
+can be derived for any user-defined datatype whose constituent types
+are in @Ord@.  The declared order
+of the constructors in the data declaration determines the ordering in
+derived @Ord@ instances.
+The @Ordering@ datatype
+allows a single comparison to determine the precise ordering of two
+objects.
+
+%      Either all subsections should have this info, or none.
+% The defaults allow a user to create an @Ord@ instance 
+% either with a type-specific @compare@ function or with type-specific
+% @==@ and @<=@ functions.
+
+\subsubsection{The Read and Show Classes}
+\indexsynonym{ReadS}
+\indexsynonym{ShowS}
+\indexclass{Read}
+\indexclass{Show}
+\indextt{show}
+\indextt{readsPrec}
+\indextt{showsPrec}
+\indextt{readList}
+\indextt{showList}
+\bprog
+@
+type  ReadS a = String -> [(a,String)]
+type  ShowS   = String -> String
+
+class  Read a  where
+    readsPrec :: Int -> ReadS a
+    readList  :: ReadS [a]
+    -- ... default decl for readList given in Prelude
+
+class  Show a  where
+    showsPrec :: Int -> a -> ShowS
+    show      :: a -> String 
+    showList  :: [a] -> ShowS
+
+    showsPrec _ x s   = show x ++ s
+    show x           = showsPrec 0 x ""
+    -- ... default decl for showList given in Prelude
+@
+\eprog
+The @Read@ and @Show@ classes are used to convert values to
+or from strings. @showsPrec@ and @showList@ return a @String@-to-@String@
+function, to allow constant-time concatenation of its results using function
+composition.
+A specialised variant, @show@, is also provided, which
+uses precedence context zero, and returns an ordinary @String@.
+The method @showList@ is provided to allow the programmer to
+give a specialised way of showing lists of values.  This is particularly
+useful for the @Char@ type, where values of type @String@ should be
+shown in double quotes, rather than between square brackets.
+
+Derived instances of @Read@ and @Show@ replicate the style in which a
+constructor is declared: infix constructors and field names are used
+on input and output.  Strings produced by @showsPrec@ are usually
+readable by @readsPrec@.  
+
+All @Prelude@ types, except function types and @IO@ types,
+are instances of @Show@ and @Read@.
+(If desired, a programmer can easily make functions and @IO@ types 
+into (vacuous) instances of @Show@, by providing an instance declaration.)
+
+\indextt{reads}
+\indextt{shows}
+\indextt{read}
+For convenience, the Prelude provides the following auxiliary
+functions: 
+\bprog
+@
+reads          :: (Read a) => ReadS a
+reads          =  readsPrec 0
+
+shows          :: (Show a) => a -> ShowS
+shows          =  showsPrec 0
+
+read           :: (Read a) => String -> a
+read s                 =  case [x | (x,t) <- reads s, ("","") <- lex t] of
+                       [x] -> x
+                       []  -> error "PreludeText.read: no parse"
+                       _   -> error "PreludeText.read: ambiguous parse"
+@
+\eprog
+\indextt{shows}\indextt{reads}\indextt{show}\indextt{read}
+@shows@ and @reads@ use a default precedence of 0.  The @read@ function reads
+input from a string, which must be completely consumed by the input
+process.  The @lex@ function used by @read@ is also part of the Prelude.
+
+\subsubsection{The Enum Class}
+\indexclass{Enum}
+\indextt{toEnum}
+\indextt{fromEnum}
+\indextt{enumFrom}
+\indextt{enumFromThen}
+\indextt{enumFromTo}
+\indextt{enumFromThenTo}
+\bprog
+@
+class  Enum a  where
+    succ, pred         :: a -> a
+    toEnum              :: Int -> a
+    fromEnum            :: a -> Int
+    enumFrom           :: a -> [a]             -- [n..]
+    enumFromThen       :: a -> a -> [a]        -- [n,n'..]
+    enumFromTo         :: a -> a -> [a]        -- [n..m]
+    enumFromThenTo     :: a -> a -> a -> [a]   -- [n,n'..m]
+
+    -- Default declarations given in Prelude
+@
+\eprog
+Class @Enum@ defines operations on sequentially ordered types.
+The functions @succ@ and @pred@ return the successor and predecessor,
+respectively, of a value.
+The @toEnum@ and @fromEnum@ functions map values from a type in
+@Enum@ onto @Int@.  These functions are not meaningful for all
+instances of @Enum@: floating
+point values or @Integer@ may not be mapped onto an @Int@.  A
+runtime error occurs if either @toEnum@ or @fromEnum@ is given a value
+not mappable to the result type.  
+
+The @enumFrom@... methods are used when translating arithmetic
+sequences (Section~\ref{arithmetic-sequences}), and should
+obey the specification given in there.
+
+Instances of @Enum@ may be derived
+for any enumeration type (types whose constructors have no fields).
+There are also @Enum@ instances for floats.  
+
+\subsubsection{Class @Functor@}
+\indexclass{Functor}
+\indextt{fmap}
+\index{functor}
+
+\bprog
+@
+class  Functor f  where
+    fmap    :: (a -> b) -> (f a -> f b)
+@
+\eprog
+The @Functor@
+class is used for types that can be mapped over.  Lists, @IO@, and
+@Maybe@ are in this class. 
+
+Instances of @Functor@ should satisfy the following laws:
+\[\ba{lcl}
+@fmap id@&=&@id@\\
+@fmap (f . g)@&=&@fmap f . fmap g@\\
+\ea\]
+All instances defined in the Prelude satisfy these laws.
+
+
+\subsubsection{Class @Monad@}
+\label{monad-class}
+\indexclass{Monad}
+\indextt{return}
+\indextt{fail}
+\indextt{>>}
+\indextt{>>=}
+\index{monad}
+\bprog
+@
+class  Monad m  where
+    (>>=)   :: m a -> (a -> m b) -> m b
+    (>>)    :: m a -> m b -> m b
+    return  :: a -> m a
+    fail    :: String -> m a
+
+    m >> k  =  m >>= \_ -> k
+    fail s  = error s
+@
+\eprog
+The @Monad@ class defines the basic operations over a {\em monad}.
+See Section \ref{io} for more information about monads.
+
+``@do@'' expressions provide a convenient syntax for writing
+monadic expressions (see Section~\ref{do-expressions}).
+The @fail@ method is invoked on pattern-match failure in a @do@
+expression.
+
+In the Prelude, lists, 
+@Maybe@, and @IO@ are all instances of @Monad@.
+The @fail@ method for lists returns the empty list @[]@,
+and for @Maybe@ returns @Nothing@.  However, for @IO@, the @fail@ 
+method invokes @error@.
+
+Instances of @Monad@ should satisfy the following laws:
+\[\ba{lcl}
+@return a >>= k@&=&@k a@ \\
+@m >>= return@&=&@m@ \\
+@m >>= (\x -> k x >>= h)@&=&@(m >>= k) >>= h@\\
+@fmap f xs@&=&@xs >>= return . f@\\
+\ea\]
+All instances defined in the Prelude satisfy these laws.
+
+The Prelude provides the following auxiliary
+functions: 
+\bprog
+@
+sequence  :: Monad m => [m a] -> m [a] 
+sequence_ :: Monad m => [m a] -> m () 
+mapM      :: Monad m => (a -> m b) -> [a] -> m [b]
+mapM_     :: Monad m => (a -> m b) -> [a] -> m ()
+(=<<)     :: Monad m => (a -> m b) -> m a -> m b
+@
+\eprog
+\indextt{sequence}
+\index{sequence{\char '137}@@{\tt  sequence{\char '137}}}
+\index{mapM{\char '137}@@{\tt  mapM{\char '137}}}
+\indextt{mapM}
+\indextt{=<<}
+
+\subsubsection{The Bounded Class}
+\indexclass{Bounded}
+\indextt{minBound}
+\indextt{maxBound}
+@
+class  Bounded a  where
+    minBound, maxBound :: a
+@
+
+The @Bounded@ class is used to name the upper and lower limits of a
+type.  @Ord@ is not a superclass of @Bounded@ since types that are not
+totally ordered may also have upper and lower bounds.
+The types @Int@, @Char@, @Bool@,
+@()@, @Ordering@, and all tuples are instances of @Bounded@.  
+The @Bounded@ class may be derived
+for any enumeration type; @minBound@ is the first constructor listed
+in the @data@ declaration and @maxBound@ is the last.  @Bounded@ may
+also be derived for single-constructor datatypes whose constituent
+types are in @Bounded@.
+
+\subsection{Numbers}
+\label{numbers}
+\index{number}
+
+\Haskell{} provides several kinds of numbers; the numeric
+types and the operations upon them have been heavily influenced by
+%Common Lisp \cite{steele:common-lisp} and Scheme \cite{RRRRS}.
+Common Lisp and Scheme.
+Numeric function names and operators are usually overloaded, using
+several type classes with an inclusion relation shown in
+Figure~\ref{standard-classes}%
+%*ignore
+, page~\pageref{standard-classes}%
+%*endignore
+.
+The class @Num@\indexclass{Num} of numeric
+types is a subclass of @Eq@\indexclass{Eq}, since all numbers may be
+compared for equality; its subclass @Real@\indexclass{Real} is also a
+subclass of @Ord@\indexclass{Ord}, since the other comparison operations
+apply to all but complex numbers (defined in the @Complex@ library).
+The class @Integral@\indexclass{Integral} contains integers of both 
+limited and unlimited range; the class
+@Fractional@\indexclass{Fractional} contains all non-integral types; and
+the class @Floating@\indexclass{Floating} contains all floating-point
+types, both real and complex.
+
+The Prelude defines only the most basic numeric types: fixed sized
+integers (@Int@), arbitrary precision integers (@Integer@), single
+precision floating (@Float@), and double precision floating
+(@Double@).  Other numeric types such as rationals and complex numbers
+are defined in libraries.  In particular, the type @Rational@ is a
+ratio of two @Integer@ values, as defined in the @Rational@
+library.  
+
+The default floating point operations defined by the \Haskell{}
+Prelude do not 
+conform to current language independent arithmetic (LIA) standards.  These
+standards require considerably more complexity in the numeric
+structure and have thus been relegated to a library.  Some, but not
+all, aspects of the IEEE standard floating point standard have been
+accounted for in class @RealFloat@.
+
+The standard numeric types are listed in Table~\ref{standard-numeric-types}.
+The finite-precision integer type @Int@\indextycon{Int} covers at
+least the range 
+"[ - 2^{29}, 2^{29} - 1]\/".  As @Int@ is an instance of the @Bounded@
+class, @maxBound@ and @minBound@ can be used to determine the exact
+@Int@ range defined by an implementation.
+%(Figure~\ref{basic-numeric-2}, page~\pageref{basic-numeric-2}) define the limits of
+%@Int@\indextycon{Int} in each implementation.
+@Float@\indextycon{Float} is implementation-defined; it is desirable that
+this type be at least equal in range and precision to the IEEE
+single-precision type.  Similarly, @Double@\indextycon{Double} should
+cover IEEE double-precision.  The results of exceptional
+conditions (such as overflow or underflow) on the fixed-precision
+numeric types are undefined; an implementation may choose error
+("\bot", semantically), a truncated value, or a special value such as
+infinity, indefinite, etc.
+
+\begin{table}[tb]
+\[
+\bto{|l|l|l|}
+\hline
+\multicolumn{1}{|c|}{Type} & 
+       \multicolumn{1}{c|}{Class} &
+       \multicolumn{1}{c|}{Description} \\ \hline
+@Integer@ & @Integral@ & Arbitrary-precision integers \\
+@Int@ & @Integral@ & Fixed-precision integers \\
+@(Integral a) => Ratio a@ & @RealFrac@ & Rational numbers \\
+@Float@ & @RealFloat@ & Real floating-point, single precision \\
+@Double@ & @RealFloat@ & Real floating-point, double precision \\
+@(RealFloat a) => Complex a@ & @Floating@ & Complex floating-point \\
+\hline
+\eto
+\]
+%**<div align=center> <h4>Table 2</h4> </div>
+\ecaption{Standard Numeric Types}
+\label{standard-numeric-types}
+\index{numeric type}
+\end{table}
+
+The standard numeric classes and other numeric functions defined in
+the Prelude are shown
+in Figures~\ref{basic-numeric-1}--\ref{basic-numeric-2}.
+Figure~\ref{standard-classes} shows the class dependencies and
+built-in types that are instances of the numeric classes.
+
+\begin{figure}[tb]
+\outlinec{
+@
+class  (Eq a, Show a) => Num a  where
+    (+), (-), (*)      :: a -> a -> a
+    negate             :: a -> a
+    abs, signum                :: a -> a
+    fromInteger                :: Integer -> a
+
+class  (Num a, Ord a) => Real a  where
+    toRational         ::  a -> Rational
+
+class  (Real a, Enum a) => Integral a  where
+    quot, rem, div, mod        :: a -> a -> a
+    quotRem, divMod    :: a -> a -> (a,a)
+    toInteger          :: a -> Integer
+
+class  (Num a) => Fractional a  where
+    (/)                        :: a -> a -> a
+    recip              :: a -> a
+    fromRational       :: Rational -> a
+
+class  (Fractional a) => Floating a  where
+    pi                 :: a
+    exp, log, sqrt     :: a -> a
+    (**), logBase      :: a -> a -> a
+    sin, cos, tan      :: a -> a
+    asin, acos, atan   :: a -> a
+    sinh, cosh, tanh   :: a -> a
+    asinh, acosh, atanh :: a -> a
+@
+}
+%**<div align=center> <h4>Figure 6</h4> </div>
+\ecaption{Standard Numeric Classes and Related Operations, Part 1}
+\label{basic-numeric-1}
+\indexclass{Num}
+\indextt{+}
+\indextt{-}
+\indextt{*}
+\indextt{negate}\indextt{abs}\indextt{signum}         
+\indextt{fromInteger}
+\indexclass{Real}\indextt{toRational}
+\indexclass{Integral}
+\indextt{quotRem}\indextt{divMod}\indextt{mod}\indextt{div}
+\indextt{rem}\indextt{quot}
+\indextt{even}\indextt{odd}
+\indexclass{Fractional}
+\indextt{/}
+\indextt{recip}\indextt{fromRational}       
+\indexclass{Floating}\indextt{pi}\indextt{exp}\indextt{log}\indextt{sqrt} 
+\indextt{**}
+\indextt{logBase}
+\indextt{sin}\indextt{cos}\indextt{tan}                        
+\indextt{asin}\indextt{acos}\indextt{atan}               
+\indextt{sinh}\indextt{cosh}\indextt{tanh}               
+\indextt{asinh}\indextt{acosh}\indextt{atanh}      
+\end{figure}
+
+\begin{figure}[tb]
+\outlinec{
+@
+class  (Real a, Fractional a) => RealFrac a  where
+    properFraction     :: (Integral b) => a -> (b,a)
+    truncate, round    :: (Integral b) => a -> b
+    ceiling, floor     :: (Integral b) => a -> b
+
+class  (RealFrac a, Floating a) => RealFloat a  where
+    floatRadix         :: a -> Integer
+    floatDigits                :: a -> Int
+    floatRange         :: a -> (Int,Int)
+    decodeFloat                :: a -> (Integer,Int)
+    encodeFloat                :: Integer -> Int -> a
+    exponent           :: a -> Int
+    significand                :: a -> a
+    scaleFloat         :: Int -> a -> a
+    isNaN, isInfinite, isDenormalized, isNegativeZero, isIEEE 
+                        :: a -> Bool
+    atan2              :: a -> a -> a
+
+fromIntegral           :: (Integral a, Num b) => a -> b
+gcd, lcm               :: (Integral a) => a -> a-> a
+(^)                    :: (Num a, Integral b) => a -> b -> a
+(^^)                   :: (Fractional a, Integral b) => a -> b -> a
+
+fromRealFrac           :: (RealFrac a, Fractional b) => a -> b
+@
+}
+%**<div align=center> <h4>Figure 7</h4> </div>
+\ecaption{Standard Numeric Classes and Related Operations, Part 2}
+\label{basic-numeric-2}
+\indexclass{RealFrac}\indextt{properFraction}\indextt{approxRational}
+\indextt{truncate}\indextt{round}
+\indextt{ceiling}\indextt{floor}    
+\indexclass{RealFloat}
+\indextt{floatRadix}\indextt{floatDigits}\indextt{floatRange} 
+\indextt{decodeFloat}\indextt{encodeFloat}
+\indextt{exponent}\indextt{significand}\indextt{scaleFloat}
+\indextycon{Int}\indextycon{Integer}
+\indextt{minInt}\indextt{maxInt}                
+\indextt{fromIntegral}
+\indextt{gcd}\indextt{lcm} 
+\index{^@@{\tt  {\char'136}}} % this is ^.  Must have 2 spaces after tt!
+\index{^^@@{\tt  {\char'136}{\char'136}}} % this is ^^
+\indexclass{RealFrac}
+\indextycon{Float}\indextycon{Double}
+\indextt{fromRealFrac}
+\indextt{atan2}
+\end{figure}
+
+\subsubsection{Numeric Literals}
+\label{numeric-literals}
+
+The syntax of numeric literals is given in
+Section~\ref{lexemes-numeric}.  An integer literal represents the
+application
+of the function @fromInteger@\indextt{fromInteger} to the appropriate
+value of type 
+@Integer@.  Similarly, a floating literal stands for an application of
+@fromRational@\indextt{fromRational} to a value of type @Rational@ (that is, 
+@Ratio Integer@).  Given the typings:
+\bprog
+@
+fromInteger  :: (Num a) => Integer -> a
+fromRational :: (Fractional a) => Rational -> a
+@
+\eprog\indextt{fromInteger}\indextt{fromRational}%
+integer and floating literals have the
+typings @(Num a) => a@ and @(Fractional a) => a@, respectively.
+Numeric literals are defined in this indirect way so that they may be
+interpreted as values of any appropriate numeric type.
+See Section~\ref{default-decls} for a discussion of overloading ambiguity.
+
+\subsubsection{Arithmetic and Number-Theoretic Operations}
+\label{arithmetic-operators}
+\index{arithmetic operator}
+
+The infix class methods 
+@(+)@,
+\indextt{+}
+@(*)@,
+\indextt{*}
+@(-)@,
+\indextt{-}
+and the unary function
+@negate@\indextt{negate} (which can also be written as a prefix minus sign; see
+section~\ref{operators}) apply to all numbers.  The class methods
+@quot@\indextt{quot}, @rem@\indextt{rem}, @div@\indextt{div}, and
+@mod@\indextt{mod} apply only to integral numbers, while the class method
+@(/)@
+\indextt{/}
+applies only to fractional ones.  The @quot@, @rem@,
+@div@, and @mod@ class methods satisfy these laws:
+\[\ba{c}
+@(x @\bkqB@quot@\bkqA@ y)*y + (x @\bkqB@rem@\bkqA@ y) == x@\\
+@(x @\bkqB@div@\bkqA@  y)*y + (x @\bkqB@mod@\bkqA@ y) == x@
+\ea\]
+@`quot`@ is integer division truncated toward zero,
+while the result of @`div`@ is truncated toward
+negative infinity. 
+%Note that @quot@ should be used rather than
+%@div@ to give the semantics of Pascal's @div@.
+The @quotRem@ class method takes a dividend and a divisor as arguments
+and returns a (quotient, remainder) pair; @divMod@ is defined
+similarly:
+\bprog
+@
+quotRem x y  =  (x @\bkqB@quot@\bkqA@ y, x @\bkqB@rem@\bkqA@ y)
+divMod  x y  =  (x @\bkqB@div@\bkqA@ y, x @\bkqB@mod@\bkqA@ y)
+@
+\eprog
+Also available on integral numbers are the even and odd predicates:
+\bprog
+@
+even x     =  x @\bkqB@rem@\bkqA@ 2 == 0
+odd        =  not . even
+@
+\eprog\indextt{even}\indextt{odd}
+Finally, there are the greatest common divisor and least common
+multiple functions: @gcd@\indextt{gcd} "x" "y" is the greatest
+integer that divides both "x" and "y".  @lcm@\indextt{lcm} "x" "y"
+is the smallest positive integer that both "x" and "y" divide.
+
+\subsubsection{Exponentiation and Logarithms}
+\index{exponentiation}\index{logarithm}
+
+The one-argument exponential function @exp@\indextt{exp} and the
+logarithm function @log@\indextt{log} act on floating-point numbers and
+use base "e".  @logBase@\indextt{logBase} "a" "x" returns the
+logarithm of "x" in base "a".  @sqrt@\indextt{sqrt} returns the
+principal square root of a floating-point number.
+There are three two-argument exponentiation operations:
+@(^)@\index{^@@{\tt  {\char'136}}} raises any  % 
+number to a nonnegative integer power,
+@(^^)@\index{^^@@{\tt  {\char'136}{\char'136}}} raises a
+fractional number to any integer power, and @(**)@
+\indextt{**}
+takes two floating-point arguments.  The value of "x"@^0@ or "x"@^^0@
+is @1@ for any "x", including zero; @0**@"y" is undefined.
+  
+\subsubsection{Magnitude and Sign}
+\label{magnitude-sign}
+\index{magnitude}\index{sign}
+
+A number has a {\em magnitude}
+and a {\em sign}.  The functions @abs@\indextt{abs} and
+@signum@\indextt{signum} apply to any number and satisfy the law:
+\bprog
+@
+abs x * signum x == x
+@
+\eprog
+For real numbers, these functions are defined by:
+\bprog
+@
+abs x    | x >= 0  = x
+         | x <  0  = -x
+
+signum x | x >  0  = 1
+         | x == 0  = 0
+         | x <  0  = -1
+@
+\eprog
+
+\subsubsection{Trigonometric Functions}
+\index{trigonometric function}
+
+Class @Floating@ provides the 
+circular and hyperbolic sine\index{sine}, cosine\index{cosine},
+and tangent\index{tangent} functions and their inverses.
+Default implementations of @tan@, @tanh@, @logBase@, @**@, and @sqrt@ are
+provided, but implementors are free to provide more accurate implementations.
+
+Class @RealFloat@ provides a version of arctangent
+taking two real floating-point arguments.
+For real floating "x" and "y", @atan2@\indextt{atan2} "y" "x"
+computes the angle (from the positive x-axis) of the vector from the origin
+to the point "(x,y)".  @atan2@\indextt{atan2} "y" "x"
+returns a value in the range @[-pi, pi]@.  It
+follows the Common Lisp semantics for the origin when signed zeroes are
+supported.  @atan2@ "y" @1@, with "y" in a type that is @RealFloat@, should return the
+same value as @atan@ "y".  A default definition of @atan2@ is provided, but
+implementors can provide a more accurate implementation. 
+
+The precise definition of the above functions is as in Common Lisp,
+which in turn follows Penfield's proposal for
+APL~\cite{penfield:complex-apl}.  See these references for discussions
+of branch cuts, discontinuities, and implementation.
+
+\subsubsection{Coercions and Component Extraction}
+\label{coercion}
+\index{coercion}
+
+The @ceiling@\indextt{ceiling}, @floor@\indextt{floor},
+@truncate@\indextt{truncate}, and @round@\indextt{round}
+functions each take a real fractional argument and return an integral
+result.  \mbox{@ceiling@ "x"} returns the least integer not less than "x", and
+\mbox{@floor@ "x"}, the greatest integer not greater than "x".  \mbox{@truncate@ "x"}
+yields the integer nearest "x" between "0" and "x", inclusive.
+\mbox{@round@ "x"} returns the nearest integer to "x", the even integer if
+"x" is equidistant between two integers.
+
+%      Keith Wansbrough clarifies the above defn of @round@,
+%      which strangely rounds both 3.5 and 4.5 to 4
+%
+% This is generally considered the most accurate kind of rounding, since it 
+% avoids cumulative errors.  If you get lots of values on the 0.5 boundary, 
+% `round up' gives you an error of +0.5 for each, whereas round-to-even gives 
+% you a mean error of zero.
+% 
+% IEEE floating point does this by default for its basic operations.
+
+The function @properFraction@\indextt{properFraction} takes a real
+fractional number "x" and returns a pair "(n,f)" such that "x = n+f", and:
+"n" is an integral number with the same sign as "x"; and "f" is a
+fraction "f" with the same type and sign as "x", and with absolute
+value less than 1.
+The @ceiling@, @floor@, @truncate@, and @round@
+functions can be defined in terms of @properFraction@.
+
+Two functions convert numbers to type @Rational@:
+@toRational@\indextt{toRational} returns the rational equivalent of
+its real argument with full precision;
+@approxRational@\indextt{approxRational} takes two real fractional arguments
+"x" and "\epsilon" and returns the simplest rational number within
+"\epsilon" of "x", where a rational $ p/q $ in reduced form is
+{\em simpler} than another $ p^{\prime} / q^{\prime} $ if 
+$ |p| \leq |p^{\prime}| $ and $ q \leq q^{\prime} $.
+Every real interval contains a unique simplest rational;
+in particular, note that $ 0/1 $ is the simplest rational of all.%
+%\cite[Section 6.5.5]{RRRRS}.
+
+The class methods of class @RealFloat@\indexclass{RealFloat} allow
+efficient, machine-independent
+access to the components of a floating-point number.
+The functions @floatRadix@\indextt{floatRadix},
+@floatDigits@\indextt{floatDigits}, and
+@floatRange@\indextt{floatRange} give the parameters of a
+floating-point type:  the radix of the representation, the number of
+digits of this radix in the significand, and the lowest and highest
+values the exponent may assume, respectively.
+The function @decodeFloat@\indextt{decodeFloat}
+applied to a real floating-point number returns the significand
+expressed as an @Integer@ and an appropriately scaled exponent (an
+@Int@).  If \mbox{@decodeFloat x@} yields \mbox{@(@"m"@,@"n"@)@}, then @x@ is
+equal in value to "mb^n", where "b" is the floating-point radix, and
+furthermore, either "m" and "n" are both zero or else
+"b^{d-1}<=m<b^d", where "d" is the value of \mbox{@floatDigits x@}.
+@encodeFloat@\indextt{encodeFloat} performs the inverse of this
+transformation.  The functions @significand@\indextt{significand}
+and @exponent@\indextt{exponent} together provide the same
+information as @decodeFloat@,  but rather than an @Integer@,
+\mbox{@significand x@} yields a value of the same type as @x@, scaled to lie
+in the open interval "(-1,1)".  \mbox{@exponent 0@} is zero.  @scaleFloat@
+multiplies a floating-point number by an integer power of the radix.
+
+The functions @isNaN@, @isInfinite@, @isDenormalized@,
+@isNegativeZero@, and @isIEEE@ all support numbers represented using
+the IEEE standard.  For non-IEEE floating point numbers, these may all
+return false.
+
+Also available are the following coercion functions:
+\bprog
+@
+fromIntegral :: (Integral a, Num b) => a -> b
+fromRealFrac :: (RealFrac a, Fractional b) => a -> b
+@
+\eprogNoSkip\indextt{fromIntegral}\indextt{fromRealFrac}
+
+
+%**~footer
+
+% Local Variables: 
+% mode: latex
+% End:
diff --git a/report/classes.eps b/report/classes.eps
new file mode 100644 (file)
index 0000000..99ae2f4
--- /dev/null
@@ -0,0 +1,485 @@
+%!PS-Adobe-3.0
+%%Title: Microsoft PowerPoint - classes
+%%Creator: Windows NT 4.0
+%%CreationDate: 14:39 1/28/1999
+%%Pages: (atend)
+%%BoundingBox: 95 155 500 685
+%%LanguageLevel: 2
+%%DocumentNeededFonts: (atend)
+%%DocumentSuppliedFonts: (atend)
+%%EndComments
+%%BeginProlog
+
+%%BeginResource: procset NTPSOct95
+/NTPSOct95 100 dict dup begin/bd{bind def}bind def/ld{load def}bd/ed{exch def}
+bd/a{currentpoint}bd/c/curveto ld/d/dup ld/e/eofill ld/f/fill ld/tr/translate
+ld/gr/grestore ld/gs/gsave ld/j/setlinejoin ld/L/lineto ld/M/moveto ld/n
+/newpath ld/cp/closepath ld/rm/rmoveto ld/sl/setlinewidth ld/sd/setdash ld/g
+/setgray ld/r/setrgbcolor ld/s/stroke ld/t/show ld/aw/awidthshow ld/im
+/imagemask ld/MS{moveto show}bd/SF{findfont exch scalefont setfont}bd/SM{cmtx
+setmatrix}bd/MF{findfont exch makefont setfont}bd/CM{/cmtx matrix currentmatrix
+def}bd/B{M exch dup 0 rlt exch 0 exch rlt neg 0 rlt}bd/CB{B cp eoclip}bd/EA{1
+index 0/G0 put 4 string 1 1 4 -1 roll{3 copy neg exch cvs dup 0 71 put cvn 3 -1
+roll exch put}for pop}bd/rlt/rlineto ld/L2?/languagelevel where{pop
+languagelevel 2 ge}{false}ifelse def end def 
+%%EndResource
+%%EndProlog
+NTPSOct95 begin
+%%Page: 1 1
+NTPSOct95 /PageSV save put
+14.441 829.738 translate 72 600 div dup neg scale
+0 0 transform .25 add round .25 sub exch .25 add round .25 sub exch itransform translate
+n
+3719 4799 503 1002 B
+1 g
+f
+1 j
+1 setlinecap
+8 sl
+0 g
+n
+1789 1608 M
+1789 1477 1584 1371 1331 1371 c
+1078 1371 874 1477 874 1608 c
+874 1738 1078 1845 1331 1845 c
+1584 1845 1789 1738 1789 1608 c
+cp
+CM [1 0 0 1 503 1002] concat
+s
+SM
+%%IncludeFont: Courier-Bold
+[133 0 0 -133 0 0]/Courier-Bold MF
+(E)1251 1586 MS (q)1331 1586 MS
+%%IncludeFont: Times-Roman
+[100 0 0 -100 0 0]/Times-Roman MF
+(A)956 1724 MS (l)1028 1724 MS (l)1056 1724 MS ( )1084 1724 MS (e)1109 1724 MS (x)1154 1724 MS (c)1204 1724 MS (e)1249 1724 MS (p)1294 1724 MS (t)1344 1724 MS ( )1372 1724 MS (I)1397 1724 MS (O)1430 1724 MS (,)1502 1724 MS ( )1527 1724 MS (\()1552 1724 MS
+(-)1585 1724 MS (>)1619 1724 MS (\))1675 1724 MS
+n
+1834 2279 M
+1834 2145 1619 2037 1354 2037 c
+1088 2037 874 2145 874 2279 c
+874 2412 1088 2521 1354 2521 c
+1619 2521 1834 2412 1834 2279 c
+cp
+CM [1 0 0 1 503 1002] concat
+s
+SM
+[133 0 0 -133 0 0]/Courier-Bold MF
+(O)1233 2198 MS (r)1313 2198 MS (d)1393 2198 MS
+[100 0 0 -100 0 0]/Times-Roman MF
+(A)1056 2335 MS (l)1128 2335 MS (l)1156 2335 MS ( )1184 2335 MS (e)1209 2335 MS (x)1254 2335 MS (c)1304 2335 MS (e)1349 2335 MS (p)1394 2335 MS (t)1444 2335 MS ( )1472 2335 MS (\()1497 2335 MS (-)1530 2335 MS (>)1563 2335 MS (\))1620 2335 MS
+(I)1105 2455 MS (O)1138 2455 MS (,)1210 2455 MS ( )1235 2455 MS ( )1260 2455 MS
+(I)1285 2455 MS (O)1319 2455 MS (E)1390 2455 MS (r)1452 2455 MS (r)1485 2455 MS (o)1519 2455 MS (r)1569 2455 MS
+n
+2923 2280 M
+2923 2147 2707 2040 2440 2040 c
+2174 2040 1958 2147 1958 2280 c
+1958 2412 2174 2520 2440 2520 c
+2707 2520 2923 2412 2923 2280 c
+cp
+CM [1 0 0 1 503 1002] concat
+s
+SM
+[133 0 0 -133 0 0]/Courier-Bold MF
+(N)2320 2199 MS (u)2400 2199 MS (m)2480 2199 MS
+[100 0 0 -100 0 0]/Times-Roman MF
+(I)2193 2336 MS (n)2226 2336 MS (t)2276 2336 MS
+(,)2304 2336 MS ( )2329 2336 MS (I)2354 2336 MS (n)2388 2336 MS (t)2438 2336 MS (e)2466 2336 MS (g)2511 2336 MS (e)2561 2336 MS (r)2606 2336 MS (,)2639 2336 MS ( )2664 2336 MS
+(F)2165 2456 MS (l)2220 2456 MS (o)2248 2456 MS (a)2298 2456 MS (t)2343 2456 MS (,)2371 2456 MS ( )2396 2456 MS (D)2421 2456 MS (o)2493 2456 MS (u)2543 2456 MS (b)2593 2456 MS (l)2643 2456 MS (e)2671 2456 MS
+6 sl
+n
+1332 1845 M
+1347 1974 L
+CM [1 0 0 1 503 1002] concat
+s
+SM
+n
+1314 1976 M
+1354 2037 L
+1379 1969 L
+cp
+e
+n
+1332 1845 M
+2378 2028 L
+CM [1 0 0 1 503 1002] concat
+s
+SM
+n
+2370 2061 M
+2440 2039 L
+2381 1996 L
+cp
+e
+8 sl
+n
+2847 1608 M
+2847 1483 2658 1383 2425 1383 c
+2191 1383 2003 1483 2003 1608 c
+2003 1732 2191 1833 2425 1833 c
+2658 1833 2847 1732 2847 1608 c
+cp
+CM [1 0 0 1 503 1002] concat
+s
+SM
+[133 0 0 -133 0 0]/Courier-Bold MF
+(S)2265 1527 MS (h)2345 1527 MS (o)2425 1527 MS (w)2506 1527 MS
+[100 0 0 -100 0 0]/Times-Roman MF
+(A)2217 1665 MS (l)2289 1665 MS (l)2317 1665 MS ( )2345 1665 MS (e)2370 1665 MS (x)2415 1665 MS (c)2465 1665 MS (e)2510 1665 MS (p)2555 1665 MS (t)2605 1665 MS
+(I)2269 1784 MS (O)2302 1784 MS (,)2374 1784 MS ( )2399 1784 MS (\()2424 1784 MS (-)2458 1784 MS (>)2491 1784 MS (\))2547 1784 MS
+n
+2862 3007 M
+2862 2881 2656 2780 2403 2780 c
+2150 2780 1945 2881 1945 3007 c
+1945 3133 2150 3235 2403 3235 c
+2656 3235 2862 3133 2862 3007 c
+cp
+CM [1 0 0 1 503 1002] concat
+s
+SM
+[133 0 0 -133 0 0]/Courier-Bold MF
+(R)2243 2927 MS (e)2323 2927 MS (a)2403 2927 MS (l)2484 2927 MS
+[100 0 0 -100 0 0]/Times-Roman MF
+(I)2155 3065 MS (n)2188 3065 MS (t)2238 3065 MS
+(,)2266 3065 MS ( )2291 3065 MS (I)2316 3065 MS (n)2350 3065 MS (t)2400 3065 MS (e)2428 3065 MS (g)2473 3065 MS (e)2523 3065 MS (r)2568 3065 MS (,)2601 3065 MS ( )2626 3065 MS
+(F)2128 3184 MS (l)2183 3184 MS (o)2211 3184 MS (a)2261 3184 MS (t)2306 3184 MS (,)2334 3184 MS ( )2359 3184 MS (D)2384 3184 MS (o)2456 3184 MS (u)2506 3184 MS (b)2556 3184 MS (l)2606 3184 MS (e)2634 3184 MS
+n
+3896 3007 M
+3896 2884 3678 2785 3409 2785 c
+3140 2785 2922 2884 2922 3007 c
+2922 3130 3140 3230 3409 3230 c
+3678 3230 3896 3130 3896 3007 c
+cp
+CM [1 0 0 1 503 1002] concat
+s
+SM
+[133 0 0 -133 0 0]/Courier-Bold MF
+(F)3008 2986 MS (r)3088 2986 MS (a)3168 2986 MS (c)3249 2986 MS (t)3329 2986 MS (i)3409 2986 MS (o)3489 2986 MS (n)3569 2986 MS (a)3650 2986 MS (l)3730 2986 MS
+[100 0 0 -100 0 0]/Times-Roman MF
+(F)3133 3124 MS (l)3188 3124 MS (o)3216 3124 MS (a)3266 3124 MS (t)3311 3124 MS (,)3339 3124 MS ( )3364 3124 MS (D)3389 3124 MS (o)3461 3124 MS (u)3511 3124 MS (b)3561 3124 MS (l)3611 3124 MS (e)3639 3124 MS
+n
+1880 3007 M
+1880 2838 1638 2702 1341 2702 c
+1044 2702 803 2838 803 3007 c
+803 3175 1044 3312 1341 3312 c
+1638 3312 1880 3175 1880 3007 c
+cp
+CM [1 0 0 1 503 1002] concat
+s
+SM
+[133 0 0 -133 0 0]/Courier-Bold MF
+(E)1181 2867 MS (n)1261 2867 MS (u)1341 2867 MS (m)1422 2867 MS
+[100 0 0 -100 0 0]/Times-Roman MF
+(\()846 3004 MS (\))879 3004 MS (,)913 3004 MS ( )938 3004 MS
+(B)963 3004 MS (o)1029 3004 MS (o)1079 3004 MS (l)1129 3004 MS
+(,)1157 3004 MS ( )1182 3004 MS (C)1207 3004 MS (h)1274 3004 MS (a)1324 3004 MS (r)1369 3004 MS (,)1402 3004 MS ( )1427 3004 MS (O)1452 3004 MS (r)1524 3004 MS (d)1557 3004 MS (e)1607 3004 MS (r)1652 3004 MS (i)1686 3004 MS (n)1714 3004 MS (g)1764 3004 MS
+(,)1814 3004 MS
+(I)978 3124 MS (n)1011 3124 MS (t)1061 3124 MS
+(,)1089 3124 MS ( )1114 3124 MS (I)1139 3124 MS (n)1173 3124 MS (t)1223 3124 MS (e)1251 3124 MS (g)1296 3124 MS (e)1346 3124 MS (r)1391 3124 MS (,)1424 3124 MS ( )1449 3124 MS (F)1474 3124 MS (l)1529 3124 MS (o)1557 3124 MS (a)1607 3124 MS (t)1652 3124 MS
+(,)1680 3124 MS
+(D)1193 3244 MS (o)1265 3244 MS (u)1315 3244 MS (b)1365 3244 MS (l)1415 3244 MS (e)1443 3244 MS
+n
+2762 3755 M
+2762 3633 2583 3535 2362 3535 c
+2141 3535 1963 3633 1963 3755 c
+1963 3877 2141 3976 2362 3976 c
+2583 3976 2762 3877 2762 3755 c
+cp
+CM [1 0 0 1 503 1002] concat
+s
+SM
+[133 0 0 -133 0 0]/Courier-Bold MF
+(R)2043 3734 MS (e)2123 3734 MS (a)2203 3734 MS (l)2284 3734 MS (F)2364 3734 MS (r)2444 3734 MS (a)2524 3734 MS (c)2604 3734 MS
+[100 0 0 -100 0 0]/Times-Roman MF
+(F)2087 3872 MS (l)2142 3872 MS (o)2170 3872 MS (a)2220 3872 MS (t)2265 3872 MS (,)2293 3872 MS ( )2318 3872 MS (D)2343 3872 MS (o)2415 3872 MS (u)2465 3872 MS (b)2515 3872 MS (l)2565 3872 MS (e)2593 3872 MS
+n
+3727 3755 M
+3727 3633 3529 3535 3285 3535 c
+3040 3535 2843 3633 2843 3755 c
+2843 3877 3040 3976 3285 3976 c
+3529 3976 3727 3877 3727 3755 c
+cp
+CM [1 0 0 1 503 1002] concat
+s
+SM
+[133 0 0 -133 0 0]/Courier-Bold MF
+(F)2965 3734 MS (l)3045 3734 MS (o)3125 3734 MS (a)3206 3734 MS (t)3286 3734 MS (i)3366 3734 MS (n)3446 3734 MS (g)3526 3734 MS
+[100 0 0 -100 0 0]/Times-Roman MF
+(F)3010 3872 MS (l)3065 3872 MS (o)3093 3872 MS (a)3143 3872 MS (t)3188 3872 MS (,)3216 3872 MS ( )3241 3872 MS (D)3266 3872 MS (o)3338 3872 MS (u)3388 3872 MS (b)3438 3872 MS (l)3488 3872 MS (e)3516 3872 MS
+n
+1838 3755 M
+1838 3633 1662 3535 1445 3535 c
+1227 3535 1052 3633 1052 3755 c
+1052 3877 1227 3976 1445 3976 c
+1662 3976 1838 3877 1838 3755 c
+cp
+CM [1 0 0 1 503 1002] concat
+s
+SM
+[133 0 0 -133 0 0]/Courier-Bold MF
+(I)1124 3734 MS (n)1204 3734 MS (t)1284 3734 MS (e)1365 3734 MS (g)1445 3734 MS (r)1525 3734 MS (a)1605 3734 MS (l)1685 3734 MS
+[100 0 0 -100 0 0]/Times-Roman MF
+(I)1221 3872 MS (n)1254 3872 MS (t)1304 3872 MS
+(,)1332 3872 MS ( )1357 3872 MS (I)1382 3872 MS (n)1416 3872 MS (t)1466 3872 MS (e)1494 3872 MS (g)1539 3872 MS (e)1589 3872 MS (r)1634 3872 MS
+n
+3163 4375 M
+3163 4264 2956 4175 2702 4175 c
+2447 4175 2241 4264 2241 4375 c
+2241 4485 2447 4575 2702 4575 c
+2956 4575 3163 4485 3163 4375 c
+cp
+CM [1 0 0 1 503 1002] concat
+s
+SM
+[133 0 0 -133 0 0]/Courier-Bold MF
+(R)2342 4354 MS (e)2422 4354 MS (a)2502 4354 MS (l)2583 4354 MS (F)2663 4354 MS (l)2743 4354 MS (o)2823 4354 MS (a)2903 4354 MS (t)2984 4354 MS
+[100 0 0 -100 0 0]/Times-Roman MF
+(F)2426 4492 MS (l)2481 4492 MS (o)2509 4492 MS (a)2559 4492 MS (t)2604 4492 MS (,)2632 4492 MS ( )2657 4492 MS (D)2682 4492 MS (o)2754 4492 MS (u)2804 4492 MS (b)2854 4492 MS (l)2904 4492 MS (e)2932 4492 MS
+6 sl
+n
+2425 1833 M
+2435 1976 L
+CM [1 0 0 1 503 1002] concat
+s
+SM
+n
+2402 1977 M
+2440 2039 L
+2467 1972 L
+cp
+e
+n
+1354 2521 M
+2343 2764 L
+CM [1 0 0 1 503 1002] concat
+s
+SM
+n
+2333 2796 M
+2404 2780 L
+2349 2733 L
+cp
+e
+n
+2440 2520 M
+2413 2718 L
+CM [1 0 0 1 503 1002] concat
+s
+SM
+n
+2380 2711 M
+2404 2780 L
+2445 2720 L
+cp
+e
+n
+2404 3235 M
+1506 3516 L
+CM [1 0 0 1 503 1002] concat
+s
+SM
+n
+1498 3484 M
+1446 3535 L
+1518 3547 L
+cp
+e
+n
+2404 3235 M
+2372 3473 L
+CM [1 0 0 1 503 1002] concat
+s
+SM
+n
+2339 3466 M
+2363 3535 L
+2404 3475 L
+cp
+e
+n
+3409 3230 M
+3309 3477 L
+CM [1 0 0 1 503 1002] concat
+s
+SM
+n
+3279 3462 M
+3285 3535 L
+3339 3487 L
+cp
+e
+n
+3409 3230 M
+2423 3517 L
+CM [1 0 0 1 503 1002] concat
+s
+SM
+n
+2416 3485 M
+2363 3535 L
+2434 3548 L
+cp
+e
+n
+3284 3976 M
+2762 4154 L
+CM [1 0 0 1 503 1002] concat
+s
+SM
+n
+2753 4123 M
+2702 4175 L
+2774 4184 L
+cp
+e
+n
+2363 3976 M
+2648 4144 L
+CM [1 0 0 1 503 1002] concat
+s
+SM
+n
+2629 4170 M
+2702 4175 L
+2662 4114 L
+cp
+e
+n
+1342 3312 M
+1419 3478 L
+CM [1 0 0 1 503 1002] concat
+s
+SM
+n
+1389 3490 M
+1446 3535 L
+1448 3463 L
+cp
+e
+8 sl
+n
+3727 1607 M
+3727 1476 3573 1370 3383 1370 c
+3193 1370 3039 1476 3039 1607 c
+3039 1738 3193 1845 3383 1845 c
+3573 1845 3727 1738 3727 1607 c
+cp
+CM [1 0 0 1 503 1002] concat
+s
+SM
+[133 0 0 -133 0 0]/Courier-Bold MF
+(R)3222 1526 MS (e)3302 1526 MS (a)3382 1526 MS (d)3463 1526 MS
+[100 0 0 -100 0 0]/Times-Roman MF
+(A)3176 1663 MS (l)3248 1663 MS (l)3276 1663 MS ( )3304 1663 MS (e)3329 1663 MS (x)3374 1663 MS (c)3424 1663 MS (e)3469 1663 MS (p)3514 1663 MS (t)3564 1663 MS
+(I)3227 1783 MS (O)3260 1783 MS (,)3332 1783 MS ( )3357 1783 MS (\()3382 1783 MS (-)3416 1783 MS (>)3449 1783 MS (\))3505 1783 MS
+n
+3928 2279 M
+3928 2126 3732 2002 3490 2002 c
+3248 2002 3053 2126 3053 2279 c
+3053 2432 3248 2557 3490 2557 c
+3732 2557 3928 2432 3928 2279 c
+cp
+CM [1 0 0 1 503 1002] concat
+s
+SM
+[133 0 0 -133 0 0]/Courier-Bold MF
+(B)3210 2199 MS (o)3290 2199 MS (u)3370 2199 MS (n)3451 2199 MS (d)3531 2199 MS (e)3611 2199 MS (d)3691 2199 MS
+[100 0 0 -100 0 0]/Times-Roman MF
+(I)3132 2336 MS (n)3165 2336 MS (t)3215 2336 MS
+(,)3243 2336 MS ( )3268 2336 MS (C)3293 2336 MS (h)3360 2336 MS (a)3410 2336 MS (r)3455 2336 MS (,)3488 2336 MS ( )3513 2336 MS
+(B)3538 2336 MS (o)3605 2336 MS (o)3655 2336 MS (l)3705 2336 MS
+(,)3733 2336 MS ( )3758 2336 MS (\()3783 2336 MS (\))3816 2336 MS
+(O)3166 2456 MS (r)3238 2456 MS (d)3271 2456 MS (e)3321 2456 MS (r)3366 2456 MS (i)3399 2456 MS (n)3427 2456 MS (g)3477 2456 MS (,)3527 2456 MS ( )3552 2456 MS
+(t)3577 2456 MS (u)3606 2456 MS (p)3656 2456 MS (l)3706 2456 MS (e)3734 2456 MS (s)3779 2456 MS
+n
+1837 4372 M
+1837 4250 1639 4152 1395 4152 c
+1150 4152 953 4250 953 4372 c
+953 4493 1150 4592 1395 4592 c
+1639 4592 1837 4493 1837 4372 c
+cp
+CM [1 0 0 1 503 1002] concat
+s
+SM
+[133 0 0 -133 0 0]/Courier-Bold MF
+(M)1195 4351 MS (o)1275 4351 MS (n)1355 4351 MS (a)1436 4351 MS (d)1516 4351 MS
+[100 0 0 -100 0 0]/Times-Roman MF
+(I)1121 4488 MS (O)1154 4488 MS (,)1226 4488 MS ( )1251 4488 MS ([)1276 4488 MS (])1310 4488 MS (,)1343 4488 MS ( )1368 4488 MS (M)1393 4488 MS (a)1481 4488 MS (y)1526 4488 MS (b)1576 4488 MS (e)1626 4488 MS
+n
+1837 5171 M
+1837 5049 1639 4951 1395 4951 c
+1150 4951 953 5049 953 5171 c
+953 5293 1150 5392 1395 5392 c
+1639 5392 1837 5293 1837 5171 c
+cp
+CM [1 0 0 1 503 1002] concat
+s
+SM
+[133 0 0 -133 0 0]/Courier-Bold MF
+(M)1034 5150 MS (o)1114 5150 MS (n)1194 5150 MS (a)1275 5150 MS (d)1355 5150 MS (P)1435 5150 MS (l)1515 5150 MS (u)1595 5150 MS (s)1676 5150 MS
+[100 0 0 -100 0 0]/Times-Roman MF
+(I)1121 5287 MS (O)1154 5287 MS (,)1226 5287 MS ( )1251 5287 MS ([)1276 5287 MS (])1310 5287 MS (,)1343 5287 MS ( )1368 5287 MS (M)1393 5287 MS (a)1481 5287 MS (y)1526 5287 MS (b)1576 5287 MS (e)1626 5287 MS
+6 sl
+n
+1395 4592 M
+1395 4888 L
+CM [1 0 0 1 503 1002] concat
+s
+SM
+n
+1362 4886 M
+1395 4951 L
+1427 4886 L
+cp
+e
+8 sl
+n
+3053 5171 M
+3053 5050 2855 4952 2611 4952 c
+2366 4952 2169 5050 2169 5171 c
+2169 5292 2366 5391 2611 5391 c
+2855 5391 3053 5292 3053 5171 c
+cp
+CM [1 0 0 1 503 1002] concat
+s
+SM
+[133 0 0 -133 0 0]/Courier-Bold MF
+(F)2330 5150 MS (u)2410 5150 MS (n)2490 5150 MS (c)2571 5150 MS (t)2651 5150 MS (o)2731 5150 MS (r)2811 5150 MS
+[100 0 0 -100 0 0]/Times-Roman MF
+(I)2337 5287 MS (O)2370 5287 MS (,)2442 5287 MS ( )2467 5287 MS ([)2492 5287 MS (])2526 5287 MS (,)2559 5287 MS ( )2584 5287 MS (M)2609 5287 MS (a)2697 5287 MS (y)2742 5287 MS (b)2792 5287 MS (e)2842 5287 MS
+6 sl
+n
+2440 2520 M
+3348 2768 L
+CM [1 0 0 1 503 1002] concat
+s
+SM
+n
+3338 2800 M
+3409 2785 L
+3355 2737 L
+cp
+e
+8 sl
+n
+1261 1252 M
+953 1252 703 1502 703 1810 c
+703 5044 L
+703 5352 953 5602 1261 5602 c
+3495 5602 L
+3803 5602 4053 5352 4053 5044 c
+4053 1810 L
+4053 1502 3803 1252 3495 1252 c
+cp
+CM [1 0 0 1 503 1002] concat
+s
+SM
+PageSV restore
+%%Trailer
+%%DocumentNeededFonts:
+%%+ Courier-Bold
+%%+ Times-Roman
+%%DocumentSuppliedFonts:
+end
+%%Pages: 1
+%%EOF
diff --git a/report/classes.gif b/report/classes.gif
new file mode 100644 (file)
index 0000000..97dc084
Binary files /dev/null and b/report/classes.gif differ
diff --git a/report/classes.ppt b/report/classes.ppt
new file mode 100644 (file)
index 0000000..b3f3747
Binary files /dev/null and b/report/classes.ppt differ
diff --git a/report/decls.verb b/report/decls.verb
new file mode 100644 (file)
index 0000000..8c6048f
--- /dev/null
@@ -0,0 +1,2139 @@
+%
+% $Header: /home/cvs/root/haskell-report/report/decls.verb,v 1.1 2001/03/28 14:13:42 simonpj Exp $
+%
+%**<title>The Haskell 98 Report: Declarations</title>
+%*section 4
+%**~header
+\section{Declarations and Bindings}
+\index{declaration}
+\index{binding}
+\label{declarations}
+
+In this section, we describe the syntax and informal semantics of \Haskell{}
+{\em declarations}.
+% including their translations into
+% the \Haskell{} kernel where appropriate.
+% (see Appendix~\ref{formal-semantics} for a complete formal semantics).
+
+@@@
+module -> @module@ modid [exports] @where@ body 
+       |  body
+body   -> @{@ impdecls @;@ topdecls @}@
+       | @{@ impdecls  @}@
+       | @{@ topdecls  @}@
+
+topdecls -> topdecl_1 @;@ ... @;@ topdecl_n    & \qquad (n>=1)
+topdecl        -> @type@ simpletype @=@ type
+       |  @data@ [context @=>@] simpletype @=@ constrs [deriving]
+        |  @newtype@ [context @=>@] simpletype @=@ newconstr [deriving]
+       |  @class@ [scontext @=>@] simpleclass [@where@ cdecls]
+       |  @instance@ [scontext @=>@] qtycls inst [@where@ idecls]
+       |  @default@ @(@type_1 @,@ ... @,@ type_n@)@ & \qquad (n>=0)
+       |  decl
+
+decls  -> @{@ decl_1 @;@ ... @;@ decl_n @}@            & \qquad (n>=0)
+decl   -> gendecl
+       |  (funlhs | pat^0) rhs
+
+cdecls -> @{@ cdecl_1 @;@ ... @;@ cdecl_n @}@          & \qquad (n>=0)
+cdecl  -> gendecl
+       |  (funlhs | var) rhs
+
+idecls -> @{@ idecl_1 @;@ ... @;@ idecl_n @}@          & \qquad (n>=0)
+idecl  -> (funlhs | qfunlhs | var | qvar) rhs
+       |                                               & (empty)
+
+gendecl        -> vars @::@ [context @=>@] type        & (type signature)
+       |  fixity [digit] ops                   & (fixity declaration)
+       |                                       & (empty declaration)
+
+ops    -> op_1 @,@ ... @,@ op_n                & \qquad (n>=1)
+vars   -> var_1 @,@ ...@,@ var_n               & \qquad (n>=1)
+fixity -> @infixl@ | @infixr@ | @infix@
+@@@
+\indexsyn{vars}%
+\indexsyn{fixity}%
+\indexsyn{ops}%
+\indexsyn{topdecls}%
+\indexsyn{topdecl}%
+\indexsyn{gendecl}%
+\indexsyn{decls}%
+\indexsyn{decl}%
+\indexsyn{cdecls}%
+\indexsyn{cdecl}%
+\indexsyn{idecls}%
+\indexsyn{idecl}%
+
+The declarations in the syntactic category "topdecls" are only allowed
+at the top level of a \Haskell{} module (see
+Section~\ref{modules}), whereas "decls" may be used either at the top level or
+in nested scopes (i.e.~those within a @let@ or @where@ construct).
+
+For exposition, we divide the declarations into
+three groups: user-defined datatypes, consisting of @type@, @newtype@,
+and @data@ 
+declarations (Section~\ref{user-defined-datatypes}); type classes and
+overloading, consisting of @class@, @instance@, and @default@
+declarations (Section~\ref{overloading}); and nested declarations,
+consisting of value bindings, type signatures, and fixity declarations
+(Section~\ref{nested}).
+
+%The @module@ declaration, along with @import@ and
+%infix declarations, is described in Section~\ref{modules}.
+
+\Haskell{} has several primitive datatypes that are ``hard-wired''
+(such as integers and floating-point numbers), but most ``built-in''
+datatypes are defined with normal \Haskell{} code, using normal @type@
+and @data@ declarations. % (see Section~\ref{user-defined-datatypes}).
+These ``built-in'' datatypes are described in detail in
+Section~\ref{basic-types}.
+
+\subsection{Overview of Types and Classes}
+\label{types-overview}
+
+\Haskell{} uses a traditional
+Hindley-Milner\index{Hindley-Milner type system}
+polymorphic type system to provide a static type semantics
+\cite{damas-milner82,hindley69}, but the type system has been extended with
+{\em type} and {\em constructor} classes (or just {\em
+classes}\index{class}) that provide 
+a structured way to introduce {\em overloaded} functions.\index{type
+class} \index{constructor class} \index{overloaded functions}
+
+A @class@ declaration (Section~\ref{class-decls}) introduces a new
+{\em type class} and the overloaded operations that must be
+supported by any type that is an instance of that class.  An
+@instance@ declaration (Section~\ref{instance-decls}) declares that a
+type is an {\em instance} of a class and includes
+the definitions of the overloaded operations---called {\em
+class methods}---instantiated on the named type.
+\index{class method}
+
+For example, suppose we wish to overload the operations @(+)@ and
+@negate@ on types @Int@ and @Float@.  We introduce a new
+type class called @Num@:\nopagebreak[4]
+\bprog
+@
+  class Num a  where          -- simplified class declaration for Num
+    (+)    :: a -> a -> a
+    negate :: a -> a
+@
+\eprog
+This declaration may be read ``a type @a@ is an instance of the class
+@Num@ if there are (overloaded) class methods @(+)@ and @negate@, of the
+appropriate types, defined on it.''
+
+We may then declare @Int@ and @Float@ to be instances of this class:
+\bprog
+@
+  instance Num Int  where     -- simplified instance of Num Int
+    x + y       =  addInt x y
+    negate x    =  negateInt x
+  
+  instance Num Float  where   -- simplified instance of Num Float
+    x + y       =  addFloat x y
+    negate x    =  negateFloat x
+@
+\eprog
+where @addInt@, @negateInt@, @addFloat@, and @negateFloat@ are assumed
+in this case to be primitive functions, but in general could be any
+user-defined function.  The first declaration above may be read
+``@Int@ is an instance of the class @Num@ as witnessed by these
+definitions (i.e.~class methods)\index{class method} for @(+)@ and @negate@.''
+
+More examples of type and constructor classes can be found in
+the papers by Jones \cite{jones:cclasses} or Wadler and Blott
+\cite{wadler:classes}. 
+The term `type class' was used to describe the original \Haskell{} 1.0
+type system; `constructor class' was used to describe an extension to
+the original type classes.  There is no longer any reason to use two
+different terms: in this report, `type class' includes both the
+original \Haskell{} type classes and the constructor classes
+introduced by Jones.
+
+\subsubsection{Kinds}
+
+To ensure that they are valid, type expressions are classified
+into different {\em kinds}, \index{kind} which take one of two possible
+forms:\nopagebreak[4]
+\begin{itemize}
+
+\item The symbol $\ast$ represents the kind of all nullary type
+constructors.
+
+\item If $\kappa_1$ and $\kappa_2$ are kinds, then $\kappa_1\rightarrow\kappa_2$
+is the kind of types that take a type of kind $\kappa_1$ and return
+a type of kind $\kappa_2$.
+\end{itemize}
+Kind inference checks the validity of type expressions 
+in a similar way that type inference checks the validity of value expressions.  
+However, unlike types, kinds are entirely
+implicit and are not visible part of the language.  Kind inference is discussed
+in Section~\ref{kindinference}.
+
+\subsubsection{Syntax of Types}
+\label{type-syntax}
+\index{type}
+\label{types}
+
+@@@
+type      -> btype [@->@ type]                    & (\tr{function type})
+
+btype    ->  [btype] atype                        & (\tr{type application})
+
+atype    ->  gtycon
+          |  tyvar
+          |  @(@ type_1 @,@ ... @,@ type_k @)@ & (\tr{tuple type}, k>=2)
+          |  @[@ type @]@                      & (\tr{list type})
+          |  @(@ type @)@                      & (\tr{parenthesised constructor})
+
+gtycon    -> qtycon
+          |  @()@                              & (\tr{unit type})
+          |  @[]@                              & (\tr{list constructor})
+          |  @(->)@                            & (\tr{function constructor})
+          |  @(,@\{@,@\}@)@                    & (\tr{tupling constructors})
+@@@
+\indexsyn{type}%
+\indexsyn{atype}%
+\indexsyn{btype}%
+\indexsyn{gtycon}%
+
+\noindent
+The syntax for \Haskell{} type expressions
+\index{type expression}
+\index{constructor expression}
+is given above.  Just as data values are built using data
+constructors, type values are built from "type constructors".  As with
+data constructors, the names of type constructors start with uppercase
+letters.
+Unlike data constructors, infix type constructors are not allowed.
+
+The main forms of type expression are as follows:\nopagebreak[4]
+\begin{enumerate}
+
+\item Type variables, written as identifiers beginning with
+      a lowercase letter.  The kind of a variable is determined implicitly
+      by the context in which it appears.
+
+\item Type constructors.  Most type constructors are written as identifiers
+      beginning with an uppercase letter.  For example:\nopagebreak[4]
+      \begin{itemize}
+      \item @Char@, @Int@, @Integer@, @Float@, @Double@ and @Bool@ are
+            type constants with kind $\ast$.
+      \item @Maybe@ and @IO@ are unary type
+            constructors, and treated as types with
+            kind $\ast\rightarrow\ast$.
+      \item The declarations @data T ...@ or @newtype T ...@ add the type
+            constructor @T@ to
+            the type vocabulary.  The kind of @T@ is determined by
+            kind inference.
+      \end{itemize}
+      Special syntax is provided for some type constructors:\nopagebreak[4]
+      \begin{itemize}
+      \item The {\em trivial type}\index{trivial type} is written as @()@ and
+            has kind $\ast$.
+            It denotes the ``nullary tuple'' type, and has exactly one value,
+            also written @()@ (see Sections~\ref{unit-expression}
+            and~\ref{basic-trivial}).
+      \item The {\em function type} is written as @(->)@ and has\index{function type}
+            kind $\ast\rightarrow\ast\rightarrow\ast$.
+      \item The {\em list type}  is written as @[]@ and has kind
+            $\ast\rightarrow\ast$.\index{list}
+      \item The {\em tuple types} are written as @(,)@,\index{tuple}
+            @(,,)@, and so on.  Their kinds are
+            $\ast\rightarrow\ast\rightarrow\ast$,
+            $\ast\rightarrow\ast\rightarrow\ast\rightarrow\ast$,  and
+            so on.
+      \end{itemize}
+      Use of the @(->)@ and @[]@ constants is described in more detail below.
+
+\item Type application.  If $t_1$ is a type of kind
+      $\kappa_1\rightarrow\kappa_2$ and $t_2$ is a type of kind $\kappa_1$,
+      then $t_1~t_2$ is a type expression of kind $\kappa_2$.
+
+\item A {\em parenthesized type}, having form "@(@t@)@", is identical
+      to the type "t".
+
+\end{enumerate}
+For example, the type expression @IO a@ can be understood as the application
+of a constant, @IO@, to the variable @a@.  Since the @IO@ type
+constructor has kind 
+$\ast\rightarrow\ast$, it follows that both the variable @a@ and the whole
+expression, @IO a@, must have kind $\ast$.
+In general, a process of {\em kind inference}\index{kind}\index{kind inference}
+(see Section~\ref{kindinference})
+is needed to determine appropriate kinds for user-defined datatypes, type
+synonyms, and classes.
+
+Special syntax is provided to allow certain type expressions to be written
+in a more traditional style:\nopagebreak[4]
+\begin{enumerate}
+
+\item A {\em function type}\index{function type} has the form
+"t_1 @->@ t_2", which is equivalent to the type
+"@(->)@ t_1 t_2".  Function arrows associate to the right.
+
+\item A {\em tuple type}\index{tuple type} has the form 
+"@(@t_1@,@...@,@ t_k@)@" where "k>=2", which is equivalent to
+the type "@(,@$\ldots$@,)@ t_1 ... t_k" where there are
+$k-1$ commas between the parenthesis.  It denotes the
+type of "k"-tuples with the first component of type "t_1", the second
+component of type "t_2", and so on (see Sections~\ref{tuples}
+and \ref{basic-tuples}).
+
+\item A {\em list type}\index{list type} has the form "@[@t@]@",
+which is equivalent to the type "@[]@ t".
+It denotes the type of lists with elements of type "t" (see
+Sections~\ref{lists} and \ref{basic-lists}).
+
+\end{enumerate}
+Although the tuple, list, and function types have special syntax, they
+are not different from user-defined types with equivalent
+functionality.
+
+Expressions and types have a consistent syntax.
+If "t_i" is the type of
+expression or pattern "e_i", then the expressions "@(\@ e_1 @->@ e_2@)@",
+"@[@e_1@]@", and "@(@e_1,e_2@)@" have the types "@(@t_1 @->@ t_2@)@",
+"@[@t_1@]@", and "@(@t_1,t_2@)@", respectively.
+
+\index{quantification}
+With one exception, the
+type variables in a \Haskell{} type expression
+are all assumed to be universally quantified; there is no explicit
+syntax for universal quantification~\cite{damas-milner82}.
+% \cite{damas-milner82,reynolds90}.
+For example, the type expression
+@a -> a@ denotes the type "\forall a.~a \rightarrow a".
+For clarity, however, we often write quantification explicitly
+when discussing the types of \Haskell{} programs.
+
+The exception referred to is that of the distinguished type variable
+in a class declaration (Section~\ref{class-decls}).
+
+%Every type variable appearing in a signature
+%is universally quantified over that signature.  This last
+%constraint implies that signatures such as:
+%\bprog
+%@@
+%      \ x -> ([x] :: [a])
+%@@
+%\eprog
+%are not valid, because this declares @[x]@ to be of type 
+%"\forall a.@[@a@]@".  In contrast, this {\em is} a valid signature:
+%@(\ x -> [x]) :: a -> [a]@; it declares that @(\ x -> [x])@ has type
+%"\forall a.a @->@ @[@a@]@".
+
+\subsubsection{Syntax of Class Assertions and Contexts}
+\index{class assertion}
+\index{context}
+\label{classes&contexts}
+
+@@@
+context -> class
+        |  @(@ class_1 @,@ ... @,@ class_n @)@         & (n>=0)
+class  -> qtycls tyvar
+       |  qtycls @(@ tyvar atype_1 ...  atype_n @)@ & (n>=1)
+qtycls  -> [ modid @.@ ] tycls
+tycls  -> conid
+tyvar  -> varid
+@@@
+\indexsyn{context}%
+\indexsyn{class}%
+\indexsyn{simpleclass}%
+\indexsyn{tycls}%
+\indexsyn{tyvar}%
+
+A {\em class assertion} has form "qtycls tyvar", and
+indicates the membership of the parameterized type "tyvar" in the class
+"qtycls".  A class identifier begins with an uppercase
+letter.
+A {\em context} consists of zero or more class assertions,
+and has the general form
+\[
+"@(@ C_1 u_1, ..., C_n u_n @)@"
+\]
+where "C_1, ..., C_n" are class identifiers, and each of the "u_1, ..., u_n" is
+either a type variable, or the application of type variable to one or more types.
+The outer parentheses may be omitted when "n=1".  In
+general, we use "cx" to denote a context and we write "cx @=>@ t" to
+indicate the type "t" restricted by the context "cx".
+The context "cx" must only contain type variables referenced in "t".
+For convenience,
+we write "cx @=>@ t" even if the context "cx" is empty, although in this
+case the concrete syntax contains no @=>@.
+
+\subsubsection{Semantics of Types and Classes}
+\label{type-semantics}
+
+In this subsection, we provide informal details of the type system.
+% the formal semantics is described in Appendix~\ref{static-semantics}
+(Wadler and Blott \cite{wadler:classes} and Jones
+\cite{jones:cclasses} discuss type
+and constructor classes, respectively, in more detail.)
+
+%A type is a {\em monotype\/}\index{monotype} if it contains no type
+%variables, and is {\em monomorphic\/}
+%\index{monomorphic type}
+%if it contains type variables
+%but is not polymorphic (in Milner's original terminology,
+%it is monomorphic if it contains no generic type variables).
+
+The \Haskell{} type system attributes a {\em type} to each
+\index{type}
+expression in the program.  In general, a type is of the form
+"\forall \overline{u}.~cx \Rightarrow t",
+where "\overline{u}" is a set of type variables "u_1, ..., u_n".
+In any such type, any of the universally-quantified type variables "u_i"
+that are free in "cx" must also be free in "t".
+Furthermore, the context "cx" must be of the form given above in
+Section~\ref{classes&contexts}.  For example, here are some
+valid types:
+\bprog
+@
+  (Eq a) => a -> a
+  (Eq a, Show a, Eq b) => [a] -> [b] -> String
+  (Eq (f a), Functor f) => (a -> b) -> f a -> f b -> Bool
+@
+\eprog
+In the third type, the constraint @Eq (f a)@ cannot be made
+simpler because @f@ is universally quantified.
+
+The type of an expression "e"
+depends on a {\em type environment}
+\index{type environment}
+that gives types for the free variables in "e", and a
+{\em class environment}
+\index{class environment}
+that declares which types are instances of which classes (a type becomes
+an instance of a class only via the presence of an
+@instance@ declaration or a @deriving@ clause).
+
+Types are related by a generalization order
+\index{generalization order}
+(specified below);
+the most general type that can be assigned to a particular
+expression (in a given environment) is called its {\em
+principal type}.
+\index{principal type}
+\Haskell{}'s extended Hindley-Milner type system can infer the principal
+type of all expressions, including the proper use of overloaded
+class methods (although certain ambiguous overloadings could arise, as
+described in Section~\ref{default-decls}).  Therefore, explicit typings (called
+{\em type signatures})
+\index{type signature}
+are usually optional (see
+Sections~\ref{expression-type-sigs} and~\ref{type-signatures}).
+
+The type "\forall \overline{u}.~cx_1 \Rightarrow t_1" is
+{\em more general than}
+the type "\forall \overline{w}.~cx_2 \Rightarrow t_2" if and only if there is 
+a substitution "S" whose domain is "\overline{u}" such that:
+\begin{itemize}
+\item "t_2" is identical to "S(t_1)".
+\item Whenever "cx_2" holds in the class environment, "S(cx_1)" also holds.
+\end{itemize}
+
+The main point about contexts above is that, a value of type
+"\forall \overline{u}.~cx \Rightarrow t",
+may be instantiated at types "\overline{s}" if and only if
+the context "cx[\overline{s}/\overline{u}]" holds.
+For example, consider the function @double@:
+\bprog
+@
+  double x = x + x
+@
+\eprog
+The most general type of @double@ is
+"\forall a.~@Num@~a \Rightarrow a \rightarrow a".
+@double@ may be applied to values of type @Int@ (instantiating "a" to
+@Int@), since @Num Int@ holds, because @Int@ is an instance of the class @Num@.
+However, @double@ may not normally be applied to values
+of type @Char@, because @Char@ is not normally an instance of class @Num@.  The
+user may choose to declare such an instance, in which case @double@ may
+indeed be applied to a @Char@.
+
+
+\subsection{User-Defined Datatypes}
+\index{datatype}
+\label{user-defined-datatypes}
+
+In this section, we describe algebraic datatypes (@data@
+declarations), renamed datatypes (@newtype@ declarations), and type
+synonyms (@type@ declarations).  These declarations may only appear at
+the top level of a module.
+
+\subsubsection{Algebraic Datatype Declarations}
+\index{algebraic datatype}
+\label{datatype-decls}
+
+@@@
+topdecl           -> @data@ [context @=>@] simpletype @=@ constrs [deriving]
+
+simpletype -> tycon tyvar_1 ... tyvar_k         & (k>=0) 
+
+constrs           -> constr_1 @|@ ... @|@ constr_n     & (n>=1)
+constr    -> con [@!@] atype_1 ... [@!@] atype_k       & (\tr{arity} con = k, k>=0)
+           |  (btype | @!@ atype) conop (btype | @!@ atype) & (\tr{infix} conop)
+           |  con @{@ fielddecl_1 @,@ ... @,@ fielddecl_n @}@ & (n>=0)
+fielddecl  -> vars @::@ (type | @!@ atype)
+
+deriving   -> @deriving@ (dclass | @(@dclass_1@,@ ... @,@ dclass_n@)@)& (n>=0)
+dclass     -> qtycls
+@@@
+\index{topdecl@@{\em topdecl} (@data@)}%
+\indexsyn{simpletype}%
+\indexsyn{constrs}%
+\indexsyn{constr}%
+\indexsyn{fielddecl}%
+\indexsyn{deriving}%
+\indexsyn{dclass}%
+\index{data declaration@@{\tt data} declaration}
+The precedence\index{precedence} for "constr" is the same as that for
+expressions---normal constructor application has higher precedence
+than infix constructor application (thus @a : Foo a@ parses as 
+@a : (Foo a)@).
+
+An algebraic datatype declaration introduces a new type
+and constructors over that type and has the form:
+\[
+"@data@ cx @=>@ T u_1 ... u_k @=@ K_1 t_{11} ... t_{1k_1} @|@ \cdots @|@ \
+                                K_n t_{n1} ... t_{nk_n}"
+\]
+where "cx" is a context.
+%\index{context!in data declaration@@in {\tt data} declaration}
+This declaration
+introduces a new type constructor "T" with constituent data
+constructors "K_1, ..., K_n" whose types are given by:
+\[
+"K_i :: \forall u_1 ... u_k.~ cx_i \Rightarrow t_{i1} \rightarrow \cdots \rightarrow t_{ik_i} \rightarrow (T u_1 ... u_k)"
+\]
+where "cx_i" is the largest subset of "cx" that constrains only those type
+variables free in the types "t_{i1}, ..., t_{ik_i}".
+The type variables "u_1" through "u_k" must be distinct and may appear
+in "cx" and the "t_{ij}"; it is a static error
+for any other type variable to appear in "cx" or on the right-hand-side.
+The new type constant "T" has a kind of the form
+$\kappa_1\rightarrow\ldots\rightarrow\kappa_k\rightarrow\ast$
+where the kinds "\kappa_i" of the argument variables "u_i" are
+determined by kind inference
+as described in Section~\ref{kindinference}\index{kind}\index{kind inference}.
+This means that "T" may be used in type expressions with anywhere
+between "0" and "k" arguments.
+
+For example, the declaration
+\bprog
+@
+  data Eq a => Set a = NilSet | ConsSet a (Set a)
+@
+\eprog
+introduces a type constructor @Set@ of kind $\ast\rightarrow\ast$, and constructors @NilSet@ and
+@ConsSet@ with types
+\[\ba{ll}
+@NilSet@  & ":: \forall a.~ @Set@~ a" \\
+@ConsSet@ & ":: \forall a.~ @Eq@~ a \Rightarrow a \rightarrow @Set@~ a \rightarrow @Set@~ a"
+\ea\]
+In the example given, the overloaded
+type for @ConsSet@ ensures that @ConsSet@ can only be applied to values whose
+type is an instance of the class @Eq@.  The context in the @data@
+declaration has no other effect whatsoever.
+
+The visibility of a datatype's constructors (i.e.~the ``abstractness''
+\index{abstract datatype}
+of the datatype) outside of the module in which the datatype is
+defined is controlled by the form of the datatype's name in the export
+list as described in Section~\ref{abstract-types}.
+
+The optional "@deriving@" part of a @data@ declaration has to do
+with {\em derived instances}, and is described in
+Section~\ref{derived-decls}.
+
+\paragraph{Labelled Fields}
+\label{field-labels}
+\index{field label}
+A data constructor of arity "k" creates an object with "k" components.
+These components are normally accessed positionally as arguments to the
+constructor in expressions or patterns.  For large datatypes it is
+useful to assign "field labels" to the components of a data object.
+This allows a specific field to be referenced independently of its
+location within the constructor.
+
+A constructor definition in a @data@ declaration using the @{@ @}@
+syntax assigns labels to the components of the constructor.
+Constructors using field labels may be freely mixed with constructors
+without them. 
+A constructor with associated field labels may still be used as an
+ordinary constructor; features using labels are
+simply a shorthand for operations using an underlying positional
+constructor.  The arguments to the positional constructor occur in the
+same order as the labeled fields.  For example, the declaration
+\bprog
+@
+  data C = F { f1,f2 :: Int, f3 :: Bool}
+@
+\eprog
+defines a type and constructor identical to the one produced by
+\bprog
+@
+  data C = F Int Int Bool
+@
+\eprog
+Operations using field labels are described in Section~\ref{field-ops}.
+A @data@ declaration may use the same field label in multiple
+constructors as long as the typing of the field is the same in all
+cases after type synonym expansion.  A label cannot be shared by
+more than one type in scope.  Field names share the top level namespace
+with ordinary variables and class methods and must not conflict with
+other top level names in scope.
+
+\paragraph{Strictness Flags}
+\label{strictness-flags}
+\index{strictness flag}
+Whenever a data constructor is applied, each argument to the
+constructor is evaluated if and only if the corresponding type in the
+algebraic datatype declaration has a strictness flag (@!@).
+\indextt{!}
+
+\outline{
+\paragraph*{Translation:}
+A declaration of the form
+\[
+"@data@ cx @=>@ T u_1 ... u_k @=@ ... @|@ K s_{1} ... s_{n} @|@ ... "
+\]
+where each "s_i" is either of the form @!@" t_i" or&nb