[project @ 1997-05-18 04:33:03 by sof]
authorsof <unknown>
Sun, 18 May 1997 04:33:11 +0000 (04:33 +0000)
committersof <unknown>
Sun, 18 May 1997 04:33:11 +0000 (04:33 +0000)
2.03 updates

ghc/docs/users_guide/2-03-notes.lit [new file with mode: 0644]
ghc/docs/users_guide/glasgow_exts.lit
ghc/docs/users_guide/how_to_run.lit
ghc/docs/users_guide/libraries.lit
ghc/docs/users_guide/release.lit
ghc/docs/users_guide/syslib.lit [new file with mode: 0644]
ghc/docs/users_guide/user.lit

diff --git a/ghc/docs/users_guide/2-03-notes.lit b/ghc/docs/users_guide/2-03-notes.lit
new file mode 100644 (file)
index 0000000..e32b55c
--- /dev/null
@@ -0,0 +1,70 @@
+GHC 2.03 is a minor upgrade of GHC 2.02.  It differs in the following
+ways:
+
+\begin{itemize}
+\item
+    A slew of small bugs are fixed.  You can find the complete list
+    at @http://www.cse.ogi.edu/~simonpj/ghc-bugs.html@.  One
+    bug remains un-fixes, namely the crash when there's an empty
+    comment at the end of file.  It's wierd!
+
+\item
+    Last-minute language changes have been implemented (minor changes
+    to the libraries, and to module export/hiding scope rules)
+
+\item
+    It is only available as a source distribution.  If you want to
+    use it you'll have to build it from source.  Nowadays this is
+    a well-documented process (see the build and installation guide, but
+    note that this release is still not self-booting, you still need
+    to have The Good Old Compiler (0.29) at your disposal).
+\end{itemize}
+
+None of the bugs in GHC 2.02 are show-stoppers, so you'll only want
+to upgrade if you are a build-from-source junkie and the bugs are 
+irritating you.
+
+Apart from bug-fixes, which are itemized elsewhere, 
+the exact language and standard-library changes are as follows:
+\begin{itemize}
+\item
+A hiding clause hides the unqualified name, but not the qualified name.
+\item 
+There's a new @Numeric@ library, containing mostly mildly marginal
+code for showing and reading numbers.  Parts of its exports used to be
+exported by @Prelude@, but now you'll have to import them explicitly.
+It also defines some functions that weren't provided before; have a
+look in the Haskell library report for details of complete interface.
+\item
+The following extra functions are exported from @IO@: 
+@try@, @bracket@, @bracket_@, @hGetLine@, @hWaitForInput@.
+\end{itemize}
+
+In addition, we've made following changes to GHC libraries/GHC's
+implementation of the Haskell standard prelude:
+
+\begin{itemize}
+\item The function @fromRational__@, exported from @PrelNum@, is now called @fromRat@.
+(And it's exported by @Numeric@.)
+\item
+Documentation for the Glasgow specific interfaces plus the system
+libraries have been re-instated. Posix library documentation included also.
+\item
+@maybe@ is now exported from Prelude, as it should have been in 2.02.
+\item
+Equality on @IO.Handle@ is now defined as specified by the library
+report.
+\item
+@Ix.rangeSize@ returns \tr{0} on an empty range;previously it failed.
+\item
+The new interface @GlaExts@ which is meant to be the gateway to the
+various Glasgow extensions has now been documented.
+\item
+@GlaExts@ now exports the representation of @Char@.
+\item
+The mutable variable interface, @MutVar@, has also been documented,
+together with @ByteArray@, @MutableArray@ and @Foreign@.
+\item
+Added documentation on how to compile mutually recursive modules with
+2.03.
+\end{itemize}
index 3b04fba..32fcd01 100644 (file)
@@ -165,7 +165,7 @@ Here's a little example, stolen from Alastair Reid:
 \begin{verbatim}
 module GHCmain ( mainPrimIO ) where
 
-import PreludeGlaST
+import GlaExts
 
 mainPrimIO :: PrimIO ()
 mainPrimIO = do
@@ -195,9 +195,14 @@ and things go, you would be well-advised to keep your C-callery
 corraled in a few modules, rather than sprinkled all over your code.
 It will then be quite easy to update later on.
 
-WARNING AS OF 2.02: Yes, the \tr{_ccall_} stuff probably {\em will
-change}, to something better, of course!  We are still at the
-musing-about-it stage, however...
+WARNING AS OF 2.03: Yes, the \tr{_ccall_} stuff probably {\em will
+change}, to something better, of course!  One step in that direction
+is Green Card, a foreign function interface pre-processor for Haskell
+(``Glasgow'' Haskell in particular) --- check out 
+\begin{verbatim}
+ftp://ftp.dcs.gla.ac.uk/pub/haskell/glasgow/green-card.ANNOUNCE
+ftp://ftp.dcs.gla.ac.uk/pub/haskell/glasgow/green-card-src.tar.gz
+\end{verbatim}
 
 %************************************************************************
 %*                                                                      *
@@ -377,9 +382,14 @@ If you use \tr{Addr}, it is up to you to the programmer to arrange
 allocation and deallocation of the objects.
 
 If you use \tr{ForeignObj}, \tr{ghc}'s garbage collector will
-call the user-supplied C function
+call upon the user-supplied {\em finaliser} function to free
+the object when the Haskell world no longer can access the object.
+(An object is associated with a finaliser function when the abstract
+ Haskell type @ForeignObj@ is created). The finaliser function is
+expressed in C, and is passed as argument the object:
+
 \begin{verbatim}
-void freeForeignObj( StgForeignObj garbageMallocPtr )
+void foreignFinaliser ( StgForeignObj fo )
 \end{verbatim}
 when the Haskell world can no longer access the object.  Since
 \tr{ForeignObj}s only get released when a garbage collection occurs,
@@ -394,7 +404,7 @@ performGC :: PrimIO ()
 %*                                                                      *
 \subsubsection[glasgow-avoiding-monads]{Avoiding monads}
 \index{C calls to `pure C'}
-\index{unsafePerformPrimIO (PreludeGlaST)}
+\index{unsafePerformPrimIO (GlaExts)}
 %*                                                                      *
 %************************************************************************
 
@@ -430,7 +440,7 @@ For example, an imperative implementation of a purely functional
 lookup-table might be accessed using the following functions.
 
 \begin{verbatim}
-empty :: EFS x
+empty  :: EFS x
 update :: EFS x -> Int -> x -> EFS x
 lookup :: EFS a -> Int -> a
 
@@ -631,7 +641,7 @@ A related (and inter-operable-with) monad is the \tr{PrimIO} monad
 yourself.
 
 Should you wish to use the \tr{PrimIO} monad directly, you can import
-\tr{PreludeGlaST}.  It makes available the usual monadic stuff (@>>=@,
+\tr{GlaExts}.  It makes available the usual monadic stuff (@>>=@,
 @>>@, @return@, etc.), as well as these functions:
 \begin{verbatim}
 -- for backward compatibility:
index 34fdd32..7cb45f6 100644 (file)
@@ -1225,7 +1225,59 @@ disappointed if you try to glob etc. inside \tr{OPTIONS}.
 
 It is not recommended to move all the contents of your Makefiles into
 your source files, but in some circumstances, the \tr{OPTIONS} pragma
-is the Right Thing.
+is the Right Thing. (If you use \tr{-keep-hc-file-too} and have OPTION
+flags in your module, the OPTIONS will get put into the generated .hc
+file).
+
+%----------------------------------------------------------------------
+\subsubsection{How to compile mutually recursive modules}
+\index{module system, recursion}
+
+Currently, the compiler does not have proper support for dealing with
+mutually recursive modules:
+
+\begin{verbatim}
+module A where
+
+import B
+
+newtype A = A Int
+
+f :: B -> A
+f (B x) = A x
+--------
+module B where
+
+import A
+
+data B = B !Int
+
+g :: A -> B
+g (A x) = B x
+\end{verbatim}
+
+When compiling either module A and B, the compiler will try (in vain)
+to look for the interface file of the other. So, to get mutually
+recursive modules off the ground, you need to hand write an interface
+file for A or B, so as to break the loop. For the example at hand, the
+boot interface file for A would like the following:
+
+\begin{verbatim}
+_interface_ A 1
+_exports_
+A A(A) f;
+_declarations_
+1 newtype A = A PrelBase.Int ;
+1 f _:_ B.B -> A.A ;;
+\end{verbatim}
+
+To make sure you get the syntax right, tailoring an existing interface
+file is a Good Idea.
+
+\bf{Note:} This is all a temporary solution, a version of the compiler
+that handles mutually recursive properly without the manual
+construction of interface file, is in the works.
+
 
 %----------------------------------------------------------------------
 %\subsubsection[arity-checking]{Options to insert arity-checking code}
index eea3106..0558d5b 100644 (file)
 \end{rawlatex}
 \end{onlystandalone}
 
-\section[syslibs]{Introduction}
+\section[ghc-prelude]{The GHC prelude and libraries}
 
 This document describes GHC's prelude and libraries.  The basic story is that of
-the Haskell 1.3 Report and Libraries document (which we do not reproduce here),
+the Haskell 1.4 Report and Libraries document (which we do not reproduce here),
 but this document describes in addition:
 \begin{itemize}
-\item  GHC's additional non-standard libraries and types, such as state transformers,
-       packed strings, foreign objects, stable pointers, and so on.
+\item  GHC's additional non-standard libraries and types, such as
+        state transformers, packed strings, foreign objects, stable
+       pointers, and so on.
+
+\item  GHC's primitive types and operations.  The standard Haskell
+        functions are implemented on top of these, and it is sometimes
+       useful to use them directly.
+
+\item  The organisation of these libraries into directories.
+\item   Short description of programmer interface to the non-standard,
+        `built-in' libraries provided in addition to the standard
+        prelude and libraries.
+\end{itemize}
 
-\item  GHC's primitive types and operations.  The standard Haskell functions are implemented
-       on top of these, and it is sometimes useful to use them directly.
+In addition to the GHC prelude libraries, GHC comes with a number of
+system libraries, which are presented in \ref{syslibs}.
 
-\item  The organsiation of these libraries into directories.
-\end{itemize}
+\subsection{Prelude library organisation}
 
-\section{Overview}
+{\em Probably only of interest to implementors..}
 
-The libraries are organised into the following three groups, each of which
-is kept in a separate sub-directory of GHC's installed @lib/@ directory:
+The prelude libraries are organised into the following three groups,
+each of which is kept in a separate sub-directory of GHC's source
+@lib/@ directory: 
 \begin{description}
-\item[@lib/required/@]  These are the libraries {\em required} by the Haskell
-definition.  All are defined by the Haskell Report, or by the Haskell Libraries Report.
+\item[@lib/required/@]  These are the libraries {\em required} by the
+Haskell definition.  All are defined by the Haskell Report, or by the
+Haskell Libraries Report. 
 They currently comprise:
 \begin{itemize}
 \item @Prelude@.
 \item @List@: more functions on lists.
 \item @Char@: more functions on characters.
 \item @Maybe@: more functions on @Maybe@ types.
-\item @Complex@: functions on complex numbers.
+\item @Complex@: interface defining complex number type and functions over it.
 \item @Ratio@: functions on rational numbers.
-\item @Monad@: functions on characters.
+\item @Monad@: functions on monads.
 \item @Ix@: the @Ix@ class of indexing operations.
 \item @Array@: monolithic arrays.
-\item @IO@: basic input/output functions.
+\item @IO@: additional input/output functions.
 \item @Directory@: basic functions for accessing the file system.
 \item @System@: basic operating-system interface functions.
+\item @Numeric@: operations for reading and showing number values.
 \end{itemize}
 
 \item[@lib/glaExts@]  GHC extension libraries, currently comprising:
 \begin{itemize}
+\item @GlaExts@: collector interface to the various Glasgow
+extensions, primitive operations.
 \item @PackedString@: functions that manipulate strings packed efficiently, one character per byte.
 \item @ST@: the state transformer monad.
 \item @Foreign@: types and operations for GHC's foreign-language interface.
+\item @ByteArray@: operations over immutable chunks of (heap allocated) bytes.
+\item @MutableArray@: operations over mutable arrays.
+\item @MutVar@: operations over mutable variables.
 \end{itemize}
 
 \item[@lib/concurrent@] GHC extension libraries to support Concurrent Haskell, currently comprising:
 \begin{itemize}
-\item @Concurrent.hs@: main library.
-\item @Parallel.hs@: stuff for multi-processor parallelism.
-\item @Channel.hs@
-\item @ChannelVar.hs@
-\item @Merge.hs@
-\item @SampleVar.hs@
-\item @Semaphore.hs@
+\item @Concurrent@: main library.
+\item @Parallel@: stuff for multi-processor parallelism.
+\item @Channel@
+\item @ChannelVar@
+\item @Merge@
+\item @SampleVar@
+\item @Semaphore@
 \end{itemize}
 
 \item[@lib/ghc@] These libraries are the pieces on which all the others are built.
@@ -93,12 +111,15 @@ The types are: list, @Bool@, @Char@, @Ordering@, @String@, @Int@, @Integer@, @Ma
 \item @PrelList@: defines most of the list operations required by @Prelude@.  (A few are in @PrelBase@,
 to avoid gratuitous mutual recursion between modules.)
 
-\item @PrelNum@ defines: the numeric classes beyond @Num@ (namely @Real@, @Integral@, 
-@Fractional@, @Floating@, @RealFrac@, @RealFloat@; instances for appropriate classes 
-for @Int@ and @Integer@; the types @Float@, @Double@, and @Ratio@ and their instances.
+\item @PrelNum@ defines: the numeric classes beyond @Num@, namely
+@Real@, @Integral@, @Fractional@, @Floating@, @RealFrac@, @RealFloat@;
+instances for appropriate classes for @Int@ and @Integer@; the types
+@Float@, @Double@, and @Ratio@ and their instances.
 
-\item @PrelRead@: the @Read@ class and all its instances.  It's kept separate because many programs
-don't use @Read@ at all, so we don't even want to link in its code.
+\item @PrelRead@: the @Read@ class and all its instances.  It's kept
+separate because many programs don't use @Read@ at all, so we don't
+even want to link in its code. (If the prelude libraries are built by
+splitting the object files, this is all a non-issue)
 
 \item @ConcBase@: substrate stuff for Concurrent Haskell.
 
@@ -120,14 +141,14 @@ is hidden from the public interface.  For example the module @STBase@
 exports the type @ST@ including its representation, whereas the module
 @ST@ exports @ST@ abstractly.
 
-None of these modules are involved in any mutual recursion, with the sole exception that
-many modules import @IOBase.error@.
+None of these modules are involved in any mutual recursion, with the
+sole exception that many modules import @IOBase.error@.
 
-\section{The module @GHC@: really primitive stuff}
+\subsection{The module @GHC@: really primitive stuff}
 \label{sect:ghc}
 
-This section defines all the types which are primitive in Glasgow Haskell, and the
-operations provided for them.
+This section defines all the types which are primitive in Glasgow
+Haskell, and the operations provided for them.
 
 A primitive type is one which cannot be defined in Haskell, and which
 is therefore built into the language and compiler.  Primitive types
@@ -148,7 +169,7 @@ the other end of the pointer than the primitive value.
 This section also describes a few non-primitive types, which are needed 
 to express the result types of some primitive operations.
 
-\subsection{Character and numeric types}
+\subsubsection{Character and numeric types}
 
 There are the following obvious primitive types:
 \begin{verbatim}
@@ -157,8 +178,8 @@ type Int#   -- see also Word# and Addr#, later
 type Float#
 type Double#
 \end{verbatim}
-If you want to know their exact equivalents in C, see
-@ghc/includes/StgTypes.lh@ in the GHC source.
+If you really want to know their exact equivalents in C, see
+@ghc/includes/StgTypes.lh@ in the GHC source tree.
 
 Literals for these types may be written as follows:
 \begin{verbatim}
@@ -169,28 +190,28 @@ Literals for these types may be written as follows:
 "a"#           an Addr# (a `char *')
 \end{verbatim}
 
-\subsubsection{Comparison operations}
+\subsubsubsection{Comparison operations}
 \begin{verbatim}
 {gt,ge,eq,ne,lt,le}Char# :: Char# -> Char# -> Bool
     -- ditto for Int#, Word#, Float#, Double#, and Addr#
 \end{verbatim}
 
-\subsubsection{Unboxed-character operations}
+\subsubsubsection{Unboxed-character operations}
 \begin{verbatim}
 ord# :: Char# -> Int#
 chr# :: Int# -> Char#
 \end{verbatim}
 
 
-\subsubsection{Unboxed-@Int@ operations}
+\subsubsubsection{Unboxed-@Int@ operations}
 \begin{verbatim}
 {plus,minus,times,quot,div,rem}Int# :: Int# -> Int# -> Int#
 negateInt# :: Int# -> Int#
 \end{verbatim}
 
-NB: No error/overflow checking!
+\bf{Note:} No error/overflow checking!
 
-\subsubsection{Unboxed-@Double@ and @Float@ operations}
+\subsubsubsection{Unboxed-@Double@ and @Float@ operations}
 \begin{verbatim}
 {plus,minus,times,divide}Double# :: Double# -> Double# -> Double#
 negateDouble# :: Double# -> Double#
@@ -227,22 +248,21 @@ encodeDouble#     :: Int# -> Int# -> ByteArray#   -- Integer mantissa
                -> Int#                         -- Int exponent
                -> Double#
 
-decodeDouble#  :: Double#
-               -> GHCbase.ReturnIntAndGMP
+decodeDouble#  :: Double# -> PrelNum.ReturnIntAndGMP
 \end{verbatim}
 
 (And the same for @Float#@s.)
 
-\subsection{Operations on/for @Integers@ (interface to GMP)}
+\subsubsection{Operations on/for @Integers@ (interface to GMP)}
 \label{sect:horrid-Integer-pairing-types}
 
 We implement @Integers@ (arbitrary-precision integers) using the GNU
-multiple-precision (GMP) package.
+multiple-precision (GMP) package (version 1.3.2).
 
-NB: some of this might change if we upgrade to using GMP~2.x.
+\bf{Note:} some of this might change when we upgrade to using GMP~2.x.
 
 The data type for @Integer@ must mirror that for @MP_INT@ in @gmp.h@
-(see @gmp.info@).  It comes out as:
+(see @gmp.info@ in \tr{ghc/includes/runtime/gmp}).  It comes out as:
 \begin{verbatim}
 data Integer = J# Int# Int# ByteArray#
 \end{verbatim}
@@ -275,22 +295,20 @@ cmpInteger# :: Int# -> Int# -> ByteArray#
 divModInteger#, quotRemInteger#
        :: Int# -> Int# -> ByteArray#
        -> Int# -> Int# -> ByteArray#
-       -> GHCbase.Return2GMPs
+       -> PrelNum.Return2GMPs
 
-integer2Int# :: Int# -> Int# -> ByteArray#
-            -> Int# 
+integer2Int# :: Int# -> Int# -> ByteArray# -> Int# 
 
 int2Integer#  :: Int#  -> Integer -- NB: no error-checking on these two!
 word2Integer# :: Word# -> Integer
 
 addr2Integer# :: Addr# -> Integer
        -- the Addr# is taken to be a `char *' string
-       -- to be converted into an Integer
+       -- to be converted into an Integer.
 \end{verbatim}
 
 
-
-\subsection{Words and addresses}
+\subsubsection{Words and addresses}
 
 A @Word#@ is used for bit-twiddling operations.  It is the same size as
 an @Int#@, but has no sign nor any arithmetic operations.
@@ -327,7 +345,7 @@ addr2Int#   :: Addr# -> Int#
 Operations for indexing off of C pointers (@Addr#@s) to snatch values
 are listed under ``arrays''.
 
-\subsection{Arrays}
+\subsubsection{Arrays}
 
 The type @Array# elt@ is the type of primitive,
 unboxed arrays of values of type @elt@.  
@@ -335,13 +353,13 @@ unboxed arrays of values of type @elt@.
 type Array# elt
 \end{verbatim}
 
-@Array#@ is more primitive than a Haskell
-array --- indeed, Haskell arrays are implemented using @Array#@ ---
-in that an @Array#@ is indexed only by @Int#@s, starting at zero.  It is also
-more primitive by virtue of being unboxed.  That doesn't mean that it isn't
-a heap-allocated object --- of course, it is.  Rather, being unboxed means
-that it is represented by a pointer to the array itself, and not to a thunk
-which will evaluate to the array (or to bottom).
+@Array#@ is more primitive than a Haskell array --- indeed, the
+Haskell @Array@ interface is implemented using @Array#@ --- in that an
+@Array#@ is indexed only by @Int#@s, starting at zero.  It is also
+more primitive by virtue of being unboxed.  That doesn't mean that it
+isn't a heap-allocated object --- of course, it is.  Rather, being
+unboxed means that it is represented by a pointer to the array itself,
+and not to a thunk which will evaluate to the array (or to bottom).
 The components of an @Array#@ are themselves boxed.
 
 The type @ByteArray#@ is similar to @Array#@, except that it contains
@@ -351,14 +369,15 @@ type ByteArray#
 \end{verbatim}
 
 Arrays of these types are useful when a Haskell program wishes to
-construct a value to pass to a C procedure.  It is also possible to
+construct a value to pass to a C procedure. It is also possible to
 use them to build (say) arrays of unboxed characters for internal use
 in a Haskell program.  Given these uses, @ByteArray#@ is deliberately
 a bit vague about the type of its components.  Operations are provided
 to extract values of type @Char#@, @Int#@, @Float#@, @Double#@, and
-@Addr#@ from arbitrary offsets within a @ByteArray#@.  (For type @Foo#@,
-the $i$th offset gets you the $i$th @Foo#@, not the @Foo#@ at byte-position $i$.  Mumble.)
-(If you want a @Word#@, grab an @Int#@, then coerce it.)
+@Addr#@ from arbitrary offsets within a @ByteArray#@.  (For type
+@Foo#@, the $i$th offset gets you the $i$th @Foo#@, not the @Foo#@ at
+byte-position $i$.  Mumble.)  (If you want a @Word#@, grab an @Int#@,
+then coerce it.)
 
 Lastly, we have static byte-arrays, of type @Addr#@ [mentioned
 previously].  (Remember the duality between arrays and pointers in C.)
@@ -367,7 +386,7 @@ world outside Haskell, so this pointer is not followed by the garbage
 collector.  In other respects they are just like @ByteArray#@.  They
 are only needed in order to pass values from C to Haskell.
 
-\subsubsection{Reading and writing.}
+\subsubsubsection{Reading and writing.}
 
 Primitive arrays are linear, and indexed starting at zero.
 
@@ -385,9 +404,9 @@ uses the primitive operation; the primitive operations themselves do
 {\em not} check for out-of-range indexes. The intention is that the
 primitive ops compile to one machine instruction or thereabouts.
 
-We use the terms ``reading'' and ``writing'' to refer to accessing {\em mutable} 
-arrays (see Section~\ref{sect:mutable}), and ``indexing'' 
-to refer to reading a value from an {\em immutable} 
+We use the terms ``reading'' and ``writing'' to refer to accessing
+{\em mutable} arrays (see Section~\ref{sect:mutable}), and
+``indexing'' to refer to reading a value from an {\em immutable}
 array.
 
 If you want to read/write a @Word#@, read an @Int#@ and coerce.
@@ -404,7 +423,8 @@ indexCharOffAddr#   :: Addr# -> Int# -> Char#
 indexIntOffAddr#    :: Addr# -> Int# -> Int#
 indexFloatOffAddr#  :: Addr# -> Int# -> Float#
 indexDoubleOffAddr# :: Addr# -> Int# -> Double#
-indexAddrOffAddr#   :: Addr# -> Int# -> Addr#  -- Get an Addr# from an Addr# offset
+indexAddrOffAddr#   :: Addr# -> Int# -> Addr#  
+ -- Get an Addr# from an Addr# offset
 \end{verbatim}
 
 The last of these, @indexAddrOffAddr#@, extracts an @Addr#@ using an offset
@@ -418,7 +438,7 @@ object!  This is a pain: primitive ops aren't supposed to do
 complicated things like enter objects.  The current solution is to
 return a lifted value, but I don't like it!
 \begin{verbatim}
-indexArray#       :: Array# elt -> Int# -> GHCbase.Lift elt  -- Yuk!
+indexArray#       :: Array# elt -> Int# -> PrelBase.Lift elt  -- Yuk!
 \end{verbatim}
 
 
@@ -436,7 +456,7 @@ type State# s
 \end{verbatim}
 
 
-The type @GHCbuiltins.RealWorld@ is truly opaque: there are no values defined
+The type @GHC.RealWorld@ is truly opaque: there are no values defined
 of this type, and no operations over it.  It is ``primitive'' in that
 sense---but it is {\em not unboxed!} Its only role in life is to be the type
 which distinguishes the @PrimIO@ state transformer (see
@@ -445,23 +465,24 @@ Section~\ref{sect:io-spec}).
 data RealWorld
 \end{verbatim}
 
-\subsubsection{States}
+\subsubsubsection{States}
 
 A single, primitive, value of type @State# RealWorld@ is provided.
 \begin{verbatim}
-realWorld# :: State# GHCbuiltins.RealWorld
+realWorld# :: State# GHC.RealWorld
 \end{verbatim}
 
-(Note: in the compiler, not a @PrimOp@; just a mucho magic @Id@.)
+(Note: in the compiler, not a @PrimOp@; just a mucho magic
+@Id@. Exported from @GHC@, though).
 
-\subsection{State pairing types}
+\subsubsection{State pairing types}
 \label{sect:horrid-pairing-types}
 
-This subsection defines some types which, while they aren't quite primitive 
-because we can define them in Haskell, are very nearly so.  They define 
-constructors which pair a primitive state with a value of each primitive type.
-They are required to express the result type of the primitive operations in the 
-state monad.
+This subsection defines some types which, while they aren't quite
+primitive because we can define them in Haskell, are very nearly so.
+They define constructors which pair a primitive state with a value of
+each primitive type.  They are required to express the result type of
+the primitive operations in the state monad.
 \begin{verbatim}
 data StateAndPtr#    s elt = StateAndPtr#    (State# s) elt 
 
@@ -482,27 +503,26 @@ data StateAndByteArray#        s = StateAndByteArray#        (State# s) ByteArra
 data StateAndMutableByteArray# s = StateAndMutableByteArray# (State# s) (MutableByteArray# s)
 \end{verbatim}
 
+Hideous.
 
-
-\subsection{Mutable arrays}
+\subsubsection{Mutable arrays}
 \label{sect:mutable}
 
-Corresponding to @Array#@ and @ByteArray#@,
-we have the types of mutable versions of each.  
-In each case, the representation is a pointer
-to a suitable block of (mutable) heap-allocated storage.
+Corresponding to @Array#@ and @ByteArray#@, we have the types of
+mutable versions of each.  In each case, the representation is a
+pointer to a suitable block of (mutable) heap-allocated storage.
 \begin{verbatim}
 type MutableArray# s elt
 type MutableByteArray# s
 \end{verbatim}
 
-\subsubsection{Allocation.}
+\subsubsubsection{Allocation.}
+
+Mutable arrays can be allocated. Only pointer-arrays are initialised;
+arrays of non-pointers are filled in by ``user code'' rather than by
+the array-allocation primitive.  Reason: only the pointer case has to
+worry about GC striking with a partly-initialised array.
 
-Mutable arrays can be allocated.
-Only pointer-arrays are initialised; arrays of non-pointers are filled
-in by ``user code'' rather than by the array-allocation primitive.
-Reason: only the pointer case has to worry about GC striking with a
-partly-initialised array.
 \begin{verbatim}
 newArray#       :: Int# -> elt -> State# s -> StateAndMutableArray# s elt 
 
@@ -515,7 +535,7 @@ newDoubleArray# :: Int# -> State# s -> StateAndMutableByteArray# s
 
 The size of a @ByteArray#@ is given in bytes.
 
-\subsubsection{Reading and writing}
+\subsubsubsection{Reading and writing}
 
 %OLD: Remember, offsets in a @MutableByteArray#@ are in bytes.
 \begin{verbatim}
@@ -535,7 +555,7 @@ writeDoubleArray# :: MutableByteArray# s -> Int# -> Double# -> State# s -> State
 \end{verbatim}
 
 
-\subsubsection{Equality.}
+\subsubsubsection{Equality.}
 
 One can take ``equality'' of mutable arrays.  What is compared is the
 {\em name} or reference to the mutable array, not its contents.
@@ -545,7 +565,7 @@ sameMutableByteArray# :: MutableByteArray# s -> MutableByteArray# s -> Bool
 \end{verbatim}
 
 
-\subsubsection{Freezing mutable arrays}
+\subsubsubsection{Freezing mutable arrays}
 
 Only unsafe-freeze has a primitive.  (Safe freeze is done directly in Haskell 
 by copying the array and then using @unsafeFreeze@.) 
@@ -555,35 +575,27 @@ unsafeFreezeByteArray# :: MutableByteArray# s -> State# s -> StateAndByteArray#
 \end{verbatim}
 
 
-\subsubsection{Stable pointers}
-
-{\em Andy's comment.} \bf{Errors:} The following is not strictly true: the current
-implementation is not as polymorphic as claimed.  The reason for this
-is that the C programmer will have to use a different entry-routine
-for each type of stable pointer.  At present, we only supply a very
-limited number (1) of these routines.  It might be possible to
-increase the range of these routines by providing general purpose
-entry points to apply stable pointers to (stable pointers to)
-arguments and to enter (stable pointers to) boxed primitive values.
-{\em End of Andy's comment.}
+\subsubsubsection{Stable pointers}
 
-A stable pointer is a name for a Haskell object which can be passed to the 
-external world.  It is ``stable'' in the sense that the name does not change when 
-the Haskell garbage collector runs --- in contrast to the address of the object 
-which may well change.
+A stable pointer is a name for a Haskell object which can be passed to
+the external world.  It is ``stable'' in the sense that the name does
+not change when the Haskell garbage collector runs --- in contrast to
+the address of the object which may well change.
 
-The stable pointer type is parameterised by the type of the thing which is named.
+The stable pointer type is parameterised by the type of the thing
+which is named.
 \begin{verbatim}
 type StablePtr# a
 \end{verbatim}
 
-A stable pointer is represented by an index into the (static) 
-@StablePointerTable@.  The Haskell garbage collector treats the 
+A stable pointer is represented by an index into the (static)
+@StablePointerTable@.  The Haskell garbage collector treats the
 @StablePointerTable@ as a source of roots for GC.
 
-The @makeStablePointer@ function converts a value into a stable pointer.
-It is part of the @PrimIO@ monad, because we want to be sure we don't
-allocate one twice by accident, and then only free one of the copies.
+The @makeStablePointer@ function converts a value into a stable
+pointer.  It is part of the @PrimIO@ monad, because we want to be sure
+we don't allocate one twice by accident, and then only free one of the
+copies.
 \begin{verbatim}
 makeStablePointer#  :: a -> State# RealWorld -> StateAndStablePtr# RealWorld a
 freeStablePointer#  :: StablePtr# a -> State# RealWorld -> State# RealWorld
@@ -592,26 +604,36 @@ deRefStablePointer# :: StablePtr# a -> State# RealWorld -> StateAndPtr RealWorld
 
 There is also a C procedure @FreeStablePtr@ which frees a stable pointer.
 
+%{\em Andy's comment.} \bf{Errors:} The following is not strictly true: the current
+%implementation is not as polymorphic as claimed.  The reason for this
+%is that the C programmer will have to use a different entry-routine
+%for each type of stable pointer.  At present, we only supply a very
+%limited number (3) of these routines.  It might be possible to
+%increase the range of these routines by providing general purpose
+%entry points to apply stable pointers to (stable pointers to)
+%arguments and to enter (stable pointers to) boxed primitive values.
+%{\em End of Andy's comment.}
+
+
 %
 % Rewritten and updated for MallocPtr++ -- 4/96 SOF
 %
-\subsubsection{Foreign objects}
+\subsubsubsection{Foreign objects}
 
-A @ForeignObj@ is a reference to an object outside the Haskell
-world (i.e., from the C world, or a reference to an object on another
+A @ForeignObj@ is a reference to an object outside the Haskell world
+(i.e., from the C world, or a reference to an object on another
 machine completely.), where the Haskell world has been told ``Let me
 know when you're finished with this ...''.
 
-The @ForeignObj@ type is just a special @Addr#@ ({\em not} parameterised).
+%OLD:The @ForeignObj@ type is just a special @Addr#@ ({\em not} parameterised).
 \begin{verbatim}
 type ForeignObj#
 \end{verbatim}
 
-
-A typical use of @ForeignObj@ is in constructing Haskell bindings
+A typical use of @ForeignObj#@ is in constructing Haskell bindings
 to external libraries. A good example is that of writing a binding to
 an image-processing library (which was actually the main motivation
-for implementing @ForeignObj@'s precursor, @MallocPtr@). The
+for implementing @ForeignObj#@'s precursor, @MallocPtr#@). The
 images manipulated are not stored in the Haskell heap, either because
 the library insist on allocating them internally or we (sensibly)
 decide to spare the GC from having to heave heavy images around.
@@ -622,7 +644,6 @@ data Image = Image ForeignObj#
 instance CCallable Image
 \end{verbatim}
 
-
 The @ForeignObj#@ type is then used to refer to the externally
 allocated image, and to acheive some type safety, the Haskell binding
 defines the @Image@ data type. So, a value of type @ForeignObj#@ is
@@ -642,7 +663,7 @@ with the @ForeignObj#@, saying `` Thanks, I'm through with this
 now..'' For the image-processing library, the finalisation routine could for
 the images free up memory allocated for them. The finalisation routine has
 currently to be written in C (the finalisation routine can in turn call on
-@FreeStablePtr@ to deallocate a stable pointer.).
+@FreeStablePtr@ to deallocate a stable pointer).
 
 Associating a finalisation routine with an external object is done by 
 @makeForeignObj#@:
@@ -653,51 +674,54 @@ makeForeignObj# :: Addr# -- foreign reference
                -> StateAndForeignObj# RealWorld ForeignObj#
 \end{verbatim}
 
+\bf{Note:} the foreign object value and its finaliser are contained
+in the primitive value @ForeignObj#@, so there's no danger of an
+aggressive optimiser somehow separating the two. (with the result
+that the foreign reference would not be freed).
 
 (Implementation: a linked list of all @ForeignObj#@s is maintained to allow the
  garbage collector to detect when a @ForeignObj#@ becomes garbage.)
 
 Like @Array@, @ForeignObj#@s are represented by heap objects.
 
-\bf{ToDo:} Decide whether @FreeCHeapPointer@ is allowed to call on a
-stable pointer. (I sincerely hope not since we will still be in the
-GC at this point.)
+Upon controlled termination of the Haskell program, all @ForeignObjs@
+are freed, invoking their respective finalisers before terminating.
+
+%\bf{ToDo:} Decide whether @FreeCHeapPointer@ is allowed to call on a
+%stable pointer. (I sincerely hope not since we will still be in the
+%GC at this point.)
 
-\subsubsection{Synchronizing variables (I-vars, M-vars)}
+\subsubsubsection{Synchronizing variables (M-vars)}
 
-ToDo ToDo ToDo
+Synchronising variables are the primitive type used to implement
+Concurrent Haskell's MVars (see the Concurrent Haskell paper for
+the operational behaviour of these operations).
 
 \begin{verbatim}
 type SynchVar# s elt   -- primitive
 
 newSynchVar#:: State# s -> StateAndSynchVar# s elt
-
 takeMVar#   :: SynchVar# s elt -> State# s -> StateAndPtr# s elt
 putMVar#    :: SynchVar# s elt -> State# s -> State# s
-
-readIVar#   :: SynchVar# s elt -> State# s -> StateAndPtr# s elt
-writeIVar#  :: SynchVar# s elt -> State# s -> State# s
 \end{verbatim}
 
+%\subsubsubsection{Controlling the garbage collector}
 
-\subsubsection{Controlling the garbage collector}
-
-The C function {\tt PerformGC\/}, allows the C world to force Haskell
-to do a garbage collection.  It can only be called while Haskell
-is performing a C Call.
+%The C function {\tt PerformGC\/}, allows the C world to force Haskell
+%to do a garbage collection. It can only be called while Haskell is
+%performing a C Call.
 
-Note that this function can be used to define a Haskell IO operation
-with the same effect:
-\begin{verbatim}
->      performGCIO :: PrimIO ()
->      performGCIO = _ccall_gc_ PerformGC
-\end{verbatim}
+%Note that this function can be used to define a Haskell IO operation
+%with the same effect:
+%\begin{verbatim}
+%>     performGCIO :: PrimIO ()
+%>     performGCIO = _ccall_gc_ StgPerformGarbageCollection
+%\end{verbatim}
 
-
-\bf{ToDo:} Is there any need for abnormal/normal termination to force
-a GC too?  Is there any need for a function that provides finer
-control over GC: argument = amount of space required; result = amount
-of space recovered.
+%\bf{ToDo:} Is there any need for abnormal/normal termination to force
+%a GC too?  Is there any need for a function that provides finer
+%control over GC: argument = amount of space required; result = amount
+%of space recovered.
 
 \subsection{@spark#@ primitive operation (for parallel execution)}
 
@@ -705,9 +729,10 @@ of space recovered.
 
 \subsection{The @errorIO#@ primitive operation}
 
-The @errorIO#@ primitive takes an argument much like @PrimIO@.  It aborts execution of
-the current program, and continues instead by performing the given @PrimIO@-like value
-on the current state of the world.
+The @errorIO#@ primitive takes an argument much like @PrimIO@.  It
+aborts execution of the current program, and continues instead by
+performing the given @PrimIO@-like value on the current state of the
+world.
 \begin{verbatim}
 errorIO# :: (State RealWorld -> ((), State RealWorld)) -> a
 \end{verbatim}
@@ -744,14 +769,14 @@ casm#  :: CAsmString -> a1# -> ... -> an# -> State# RealWorld -> StateAndR# Real
 \end{verbatim}
 
 %------------------------------------------------------------
-\section{Library stuff built with the Really Primitive Stuff}
+\subsection{Library stuff built with the Really Primitive Stuff}
 
-\subsection{The state transformer monad}
+\subsubsection{The state transformer monad}
 
-\subsubsection{Types}
+\subsubsubsection{Types}
 
-A state transformer is a function from a state to a pair of a result and a new 
-state.  
+A state transformer is a function from a state to a pair of a result
+and a new state.
 \begin{verbatim}
 newtype ST s a = ST (State s -> (a, State s))
 \end{verbatim}
@@ -774,26 +799,40 @@ with @data@ are all boxed.)
 data State s = S# (State# s)
 \end{verbatim}
 
-
-\subsubsection{The state transformer combinators}
+\subsubsubsection{The state transformer combinators}
 
 Now for the combinators, all of which live inside the @ST@
-abstraction.  Notice that @returnST@ and @thenST@ are lazy in the
-state.
+abstraction.  Notice that @returnST@ and @thenST@ are now strict
+in the state. @ST@ is an instance of the @Monad@ type class.
 \begin{verbatim}
 returnST :: a -> ST s a
-returnST a s = (a, s)
+returnST a = ST (\ s@(S# _) -> (a, s)) -- strict in state.
 
 thenST :: ST s a -> (a -> ST s b) -> ST s b
-thenST m k s = let (r,new_s) = m s
-               in 
-               k r new_s
+thenST m k =
+  = ST $ \ s ->
+    case (m s) of {(r, new_s) ->
+    case (k r) of { ST k2 ->
+    (k2 new_s) }}
+
+instance Monad ST where 
+  return = returnST
+  (>>=)  = thenST
 
 fixST :: (a -> ST s a) -> ST s a
-fixST k s = let ans = k r s
+fixST k s = ST $ \ s ->
+            let (ST k_r)  = k r
+                ans       = k_r s
                 (r,new_s) = ans
             in
             ans
+
+unsafeInterleaveST :: ST s a -> ST s a
+unsafeInterleaveST (ST m) = ST $ \ s ->
+    let
+       (r, new_s) = m s
+    in
+    (r, s)
 \end{verbatim}
 
 The interesting one is, of course, @runST@.  We can't infer its type!
@@ -805,7 +844,7 @@ runST m = case m (S# realWorld#) of
 \end{verbatim}
 
 
-\subsubsection{Other useful combinators}
+\subsubsubsection{Other useful combinators}
 
 There are various other standard combinators, all defined in terms the
 fundamental combinators above. The @seqST@ combinator is like
@@ -816,47 +855,49 @@ seqST :: ST s a -> ST s b -> ST s b
 seqST m1 m2 = m1 `thenST` (\_ -> m2)
 \end{verbatim}
 
-
-We also have {\em strict} (... in the state...) variants of the
+We also have {\em lazy} (... in the state...) variants of the
 then/return combinators (same types as their pals):
 \begin{verbatim}
-returnStrictlyST a s@(S# _) = (a, s)
+returnLazyST a = ST (\ s -> (a, s))
 
-thenStrictlyST m k s@(S# _)
-  = case (m s) of { (r, new_s@(S# _)) ->
-    k r new_s }
+thenLazyST m k
+ = ST $ \ s ->
+   let (r, new_s) = m s
+   in  
+   k r new_s
 
-seqStrictlyST m k = ... ditto, for seqST ...
+seqLazyST m k
+ = ST $ \ s ->
+   let (_, new_s) = m s
+   in  
+   k new_s
 \end{verbatim}
 
-The combinator @listST@ takes a list of state transformers, and
-composes them in sequence, returning a list of their results:
+The combinator @listST@ is provided for backwards compatibility, its
+behavior is captured in Haskell 1.3 (and later) by @Monad.accumulate@:
 \begin{verbatim}
 listST :: [ST s a] -> ST s [a]
-listST []     = returnST []
-listST (m:ms) = m              `thenST` \ r ->
-               listST ms       `thenST` \ rs ->
-               returnST (r:rs)
+listST ls = accumulate ls
 \end{verbatim}
 
-The @mapST@ combinator ``lifts'' a function from a value to state
-transformers to one which works over a list of values:
+Another function provided for backwards compatibility is @mapST@, it
+is just an instance of the more general monad combinator @Monad.mapM@:
 \begin{verbatim}
 mapST :: (a -> ST s b) -> [a] -> ST s [b]
-mapST f ms = listST (map f ms)
+mapST f ms = mapM f ms
 \end{verbatim}
 
 The @mapAndUnzipST@ combinator is similar to @mapST@, except that here the
 function returns a pair:
 \begin{verbatim}
 mapAndUnzipST :: (a -> ST s (b,c)) -> [a] -> ST s ([b],[c])
-mapAndUnzipST f (m:ms)
-  = f m                        `thenST` \ ( r1,  r2) ->
-    mapAndUnzipST f ms `thenST` \ (rs1, rs2) ->
-    returnST (r1:rs1, r2:rs2)
+mapAndUnzipST f ls = mapAndUnzipM f ls
 \end{verbatim}
 
 
+\bf{Note:} all the derived operators over @ST@ are implemented using
+the {\em strict} @ST@ instance of @Monad@.
+
 \subsubsection{The @PrimIO@ monad}
 \label{sect:io-spec}
 
@@ -872,50 +913,52 @@ The type @RealWorld@ and value @realWorld#@ do not need to be hidden (although
 there is no particular point in exposing them).  Even having a value of type 
 @realWorld#@ does not compromise safety, since the type @ST@ is hidden. 
 
-It is type-correct to use @returnST@ in an I/O context, but it is a
-bit more efficient to use @returnPrimIO@.  The latter is strict in the
-state, which propagates backwards to all the earlier combinators
-(provided they are unfolded).  Why is it safe for @returnPrimIO@ to be
-strict in the state?  Because every context in which an I/O state
-transformer is used will certainly evaluate the resulting state; it is
-the state of the real world!
+It is type-correct to use @returnST@ in an @PrimIO@ context, they're
+in effect the same (ditto for the bind combinator):
+
 \begin{verbatim}
 returnPrimIO :: a -> PrimIO a
-returnPrimIO a s@(S# _) = (a, s)
-\end{verbatim}
-We provide strict versions of the other combinators too.
-\begin{verbatim}
-thenPrimIO m k s = case m s of
-                    (r,s) -> k r s
+returnPrimIO v = returnST v
+
+thenPrimIO  :: PrimIO a -> (a -> PrimIO b) -> PrimIO b
+thenPrimIO m k = thenST m k
+
+seqPrimIO   :: PrimIO a -> PrimIO b -> PrimIO b
+seqPrimIO m k = seqST m k
 \end{verbatim}
 
+Why is it safe for @returnPrimIO@ to be strict in the state?  Because
+every context in which an I/O state transformer is used will certainly
+evaluate the resulting state; it is the state of the real world!
+
 @fixPrimIO@ has to be lazy, though!
 \begin{verbatim}
 fixPrimIO  = fixST
 \end{verbatim}
 
-The other combinators are just the same as before, but use the strict
-@thenPrimIO@ and @returnPrimIO@ for efficiency.
-\begin{verbatim}
-foldrPrimIO f z []     = z
-foldrPrimIO f z (m:ms) = foldrPrimIO f z ms `thenPrimIO` \ ms' ->
-                        f m ms'
+\subsubsubsection{@PrimIO@ combinators}
 
-listPrimIO ms = foldrPrimIO (\ a xs -> a `thenPrimIO` \ x -> returnPrimIO (x : xs))
-               (returnPrimIO []) ms
 
-mapPrimIO f ms = listPrimIO (map f ms)
 
-mapAndUnzipPrimIO f (m:ms)
-  = f m                            `thenPrimIO` \ ( r1,  r2) ->
-    mapAndUnzipPrimIO f ms  `thenPrimIO` \ (rs1, rs2) ->
-    returnPrimIO (r1:rs1, r2:rs2)
+\begin{verbatim}
+unsafePerformPrimIO    :: PrimIO a -> a
+unsafeInterleavePrimIO :: PrimIO a -> PrimIO a
+
+unsafePerformPrimIO    = runST
+unsafeInterleavePrimIO = unsafeInterleaveST
+
+listPrimIO       :: [PrimIO a] -> PrimIO [a]
+mapPrimIO        :: (a -> PrimIO b) -> [a] -> PrimIO [b]
+mapAndUnzipPrimIO :: (a -> PrimIO (b,c)) -> [a] -> PrimIO ([b],[c])
 \end{verbatim}
 
+The function @unsafePerformPrimIO@ is as the name suggests, {\em
+unsafe}, placing a burden of proof on the programmer to ensure that
+performing the I/O action does not break referential transparency.
 
-\subsection{Arrays}
+\subsubsection{Arrays}
 
-\subsubsection{Types}
+\subsubsubsection{Types}
 
 \begin{verbatim}
 data Array      ix elt = Array     (ix,ix) (Array# elt)
@@ -926,7 +969,7 @@ data MutableByteArray s ix     = MutableByteArray (ix,ix) (MutableByteArray# s)
 \end{verbatim}
 
 
-\subsubsection{Operations on immutable arrays}
+\subsubsubsection{Operations on immutable arrays}
 
 Ordinary array indexing is straightforward.
 \begin{verbatim}
@@ -959,7 +1002,7 @@ indexStaticArray       :: Addr -> Int -> Addr
 \end{verbatim}
 
 
-\subsubsection{Operations on mutable arrays}
+\subsubsubsection{Operations on mutable arrays}
 \begin{verbatim}
 newArray     :: Ix ix => (ix,ix) -> elt -> ST s (MutableArray s ix elt)
 newCharArray :: Ix ix => (ix,ix) -> ST s (MutableByteArray s ix) 
@@ -1008,19 +1051,20 @@ sameMutableByteArray :: MutableByteArray s ix -> MutableByteArray s ix -> Bool
 \end{verbatim}
 
 
+\subsubsection{Mutable Variables}
 
-\subsection{Variables}
+\subsubsubsection{Types}
 
-\subsubsection{Types}
+Mutable variables are (for now anyway) implemented as arrays.  The
+@MutableVar@ type is opaque, so we can change the implementation later
+if we want.
 
-Mutable variables are (for now anyway) implemented as arrays.  The @MutableVar@ type
-is opaque, so we can change the implementation later if we want.
 \begin{verbatim}
 type MutableVar s a = MutableArray s Int a
 \end{verbatim}
 
 
-\subsubsection{Operations}
+\subsubsubsection{Operations}
 \begin{verbatim}
 newVar   :: a -> ST s (MutableVar s a)
 readVar  :: MutableVar s a -> ST s a
@@ -1029,7 +1073,7 @@ sameVar  :: MutableVar s a -> MutableVar s a -> Bool
 \end{verbatim}
 
 
-\subsection{Stable pointers}
+\subsubsection{Stable pointers}
 
 Nothing exciting here, just simple boxing up.
 \begin{verbatim}
@@ -1039,20 +1083,22 @@ makeStablePointer :: a -> StablePtr a
 freeStablePointer :: StablePtr a -> PrimIO ()
 \end{verbatim}
 
-\subsection{Foreign objects}
+\subsubsection{Foreign objects}
 
 Again, just boxing up.
 \begin{verbatim}
 data ForeignObj = ForeignObj ForeignObj#
 
-makeForeignObj :: Addr -> Addr -> PrimIO ForeignObj
+makeForeignObj :: Addr   -- object to be boxed up as a ForeignObj
+               -> Addr   -- finaliser 
+              -> PrimIO ForeignObj
 \end{verbatim}
 
-\subsection{C calls}
+\subsubsection{C calls}
 
 Everything in this section goes for @_casm_@ too.
 
-{\em ToDo: mention @_ccall_gc_@ and @_casm_gc_@...}
+\bf{ToDo:} {\em mention @_ccall_gc_@ and @_casm_gc_@...}
 
 The @_ccall_@ construct has the following form:
 $$@_ccall_@~croutine~a_1~\ldots~a_n$$
@@ -1109,10 +1155,9 @@ ForeignObj         ForeignObj#         StgForeignObj StgPtr
 
 All of the above are {\em C-returnable} except:
 \begin{verbatim}
-       Array, ByteArray, MutableArray, MutableByteArray
+  Array, ByteArray, MutableArray, MutableByteArray, ForeignObj
 \end{verbatim}
 
-
 \bf{ToDo:} I'm pretty wary of @Array@ and @MutableArray@ being in
 this list, and not too happy about @State@ [WDP].
 
@@ -1133,11 +1178,11 @@ f x = _ccall_ foo x
 \end{verbatim}
 
 
-\subsubsection{Implementation}
+\subsubsubsection{Implementation}
 
-The desugarer unwraps the @_ccall_@ construct by inserting the necessary 
-evaluations etc to unbox the arguments.  For example, the body of the definition 
-of @f@ above would become:
+The desugarer unwraps the @_ccall_@ construct by inserting the
+necessary evaluations etc to unbox the arguments.  For example, the
+body of the definition of @f@ above would become:
 \begin{verbatim}
         (\ s -> case x of { I# x# -> 
                 case s of { S# s# ->
@@ -1148,12 +1193,12 @@ of @f@ above would become:
 
 Notice that the state, too, is unboxed.
 
-The code generator must deal specially with primitive objects which
-are stored on the heap.
-
-\begin{verbatim}
-... details omitted ...
-\end{verbatim}
+%The code generator must deal specially with primitive objects which
+%are stored on the heap.
+%
+%\begin{verbatim}
+%... details omitted ...
+%\end{verbatim}
 
 %
 %More importantly, it must construct a C Heap Pointer heap-object after
@@ -1161,7 +1206,7 @@ are stored on the heap.
 %
 
 %--------------------------------------------------------
-\section{Non-primitive stuff that must be wired into GHC}
+\subsection{Non-primitive stuff that must be wired into GHC}
 
 \begin{verbatim}
 data Char    = C# Char#
@@ -1190,18 +1235,18 @@ type String  = [Char]    -- convenience, only
 
 
 %------------------------------------------------------------
-\section{Programmer interface(s)}
+\subsection{Programmer interface(s)}
 
-\subsection{The bog-standard interface}
+\subsubsection{The bog-standard interface}
 
 If you rely on the implicit @import Prelude@ that GHC normally does
 for you, and if you don't use any weird flags (notably
-@-fglasgow-exts@), and if you don't import one of the fairly-magic
-@PreludeGla*@ interfaces, then GHC should work {\em exactly} as the
+@-fglasgow-exts@), and if you don't import the Glasgow extensions
+interface, @GlaExts@, then GHC should work {\em exactly} as the
 Haskell report says, and the full user namespaces should be available
 to you.
 
-\subsection{If you mess about with @import Prelude@...}
+\subsubsubsection{If you mess about with @import Prelude@...}
 
 Innocent hiding, e.g.,
 \begin{verbatim}
@@ -1218,14 +1263,226 @@ import Prelude hiding ( Eq(..) )
 
 Don't do that.
 
-\subsection{Turning on Glasgow extensions with @-fglasgow-exts@}
+\subsubsection{Turning on Glasgow extensions with @-fglasgow-exts@}
+
+% Updated to tell the 2.02+ story  -- SOF
+
+If you turn on @-fglasgow-exts@, the compiler will recognise and parse
+unboxed values properly. To get at the primitive operations described
+herein, import the interface @GlaExts@.
+
+% 1.3+ module system makes this a non-issue.
+%%It is possible that some name conflicts between your code and the
+%%wired-in things might spring to life (though we doubt it...).
+%%Change your names :-)
 
-If you turn on @-fglasgow-exts@, then all the primitive types and
-operations described herein are available.
+%************************************************************************
+%*                                                                      *
+\subsubsection{The @GlaExts@ interface}
+\index{GlaExts interface (GHC extensions)}
+%*                                                                      *
+%************************************************************************
+
+The @GlaExts@ interface is the programmer gateway to most of the
+programmer extensions GHC implement. Currently on tap:
+
+\begin{verbatim}
+  -- PrimIO monad (state transformer, no exceptions).
+type PrimIO a = ST RealWorld a
+  -- instances of: Monad
+data RealWorld   -- abstract State value
 
-It is possible that some name conflicts between your code and the
-wired-in things might spring to life (though we doubt it...).
-Change your names :-)
+thenPrimIO       :: PrimIO a -> (a -> PrimIO b) -> PrimIO b
+returnPrimIO     :: a -> PrimIO a
+seqPrimIO        :: PrimIO a -> PrimIO b -> PrimIO b
 
+fixPrimIO        :: (a -> PrimIO a) -> PrimIO a
+unsafePerformPrimIO    :: PrimIO a -> a
+unsafeInterleavePrimIO :: PrimIO a -> PrimIO a
+
+-- backwards compatibility
+listPrimIO        :: [PrimIO a] -> PrimIO [a]
+mapPrimIO         :: (a -> PrimIO b) -> [a] -> PrimIO [b]
+mapAndUnzipPrimIO :: (a -> PrimIO (b,c)) -> [a] -> PrimIO ([b],[c])
+
+-- Combining ST and PrimIO monads with IO
+        stToIO,       -- :: ST RealWorld a -> IO a
+       primIOToIO,   -- :: PrimIO a       -> IO a
+       ioToST,       -- :: IO a -> ST RealWorld a
+       ioToPrimIO,   -- :: IO a -> PrimIO       a
+        thenIO_Prim,  -- :: PrimIO a -> (a -> IO b) -> IO b
+        seqIO_Prim,   -- :: PrimIO a -> IO b -> IO b
+
+-- the representation of some basic types:
+data Char    = C# Char#
+data Int     = I# Int#
+data Addr    = A# Addr#
+data Word    = W# Word#
+data Float   = F# Float#
+data Double  = D# Double#
+data Integer = J# Int# Int# ByteArray#
+
+-- misc
+trace :: String -> a -> a
+
+-- re-exported interfaces:
+module ByteArray
+module MutableArray
+module GHC  -- all primops and primitive types.
+\end{verbatim}
+
+
+%************************************************************************
+%*                                                                      *
+\subsubsection{The @MutVar@ interface}
+\index{MutVar interface (GHC extensions)}
+%*                                                                      *
+%************************************************************************
+
+@MutVar@ defines an interface to mutable variables, defining type and
+IO operations:
+
+\begin{verbatim}
+data  MutVar   -- abstract
+
+newVar       :: a -> IO (MutVar a)
+readVar      :: MutVar a -> IO a
+writeVar     :: MutVar a -> a -> IO ()
+sameVar      :: MutVar a -> MutVar a -> Bool
+\end{verbatim}
+
+
+%************************************************************************
+%*                                                                      *
+\subsubsection{The @MutableArray@ interface}
+\index{MutableArray interface (GHC extensions)}
+%*                                                                      *
+%************************************************************************
+
+The @MutableArray@ interface defines a general set of operations over
+mutable arrays (@MutableArray@) and mutable chunks of memory
+(@MutableByteArray@):
+
+\begin{verbatim}
+data MutableArray s ix elt -- abstract
+data MutableByteArray s ix -- abstract
+                           -- instance of : CCallable
+-- Creators:
+newArray           :: Ix ix => (ix,ix) -> elt -> ST s (MutableArray s ix elt)
+newCharArray       :: Ix ix => (ix,ix) -> ST s (MutableByteArray s ix) 
+newAddrArray       :: Ix ix => (ix,ix) -> ST s (MutableByteArray s ix) 
+newIntArray        :: Ix ix => (ix,ix) -> ST s (MutableByteArray s ix) 
+newFloatArray      :: Ix ix => (ix,ix) -> ST s (MutableByteArray s ix) 
+newDoubleArray     :: Ix ix => (ix,ix) -> ST s (MutableByteArray s ix) 
+
+boundsOfArray      :: Ix ix => MutableArray s ix elt -> (ix, ix)  
+boundsOfByteArray  :: Ix ix => MutableByteArray s ix -> (ix, ix)
+
+
+readArray         :: Ix ix => MutableArray s ix elt -> ix -> ST s elt 
+
+readCharArray      :: Ix ix => MutableByteArray s ix -> ix -> ST s Char 
+readIntArray       :: Ix ix => MutableByteArray s ix -> ix -> ST s Int
+readAddrArray      :: Ix ix => MutableByteArray s ix -> ix -> ST s Addr
+readFloatArray     :: Ix ix => MutableByteArray s ix -> ix -> ST s Float
+readDoubleArray    :: Ix ix => MutableByteArray s ix -> ix -> ST s Double
+
+writeArray        :: Ix ix => MutableArray s ix elt -> ix -> elt -> ST s () 
+writeCharArray     :: Ix ix => MutableByteArray s ix -> ix -> Char -> ST s () 
+writeIntArray      :: Ix ix => MutableByteArray s ix -> ix -> Int  -> ST s () 
+writeAddrArray     :: Ix ix => MutableByteArray s ix -> ix -> Addr -> ST s () 
+writeFloatArray    :: Ix ix => MutableByteArray s ix -> ix -> Float -> ST s () 
+writeDoubleArray   :: Ix ix => MutableByteArray s ix -> ix -> Double -> ST s () 
+
+freezeArray       :: Ix ix => MutableArray s ix elt -> ST s (Array ix elt)
+freezeCharArray    :: Ix ix => MutableByteArray s ix -> ST s (ByteArray ix)
+freezeIntArray     :: Ix ix => MutableByteArray s ix -> ST s (ByteArray ix)
+freezeAddrArray    :: Ix ix => MutableByteArray s ix -> ST s (ByteArray ix)
+freezeFloatArray   :: Ix ix => MutableByteArray s ix -> ST s (ByteArray ix)
+freezeDoubleArray  :: Ix ix => MutableByteArray s ix -> ST s (ByteArray ix)
+
+unsafeFreezeArray     :: Ix ix => MutableArray s ix elt -> ST s (Array ix elt)  
+unsafeFreezeByteArray :: Ix ix => MutableByteArray s ix -> ST s (ByteArray ix)
+thawArray             :: Ix ix => Array ix elt -> ST s (MutableArray s ix elt)
+\end{verbatim}
+
+
+%************************************************************************
+%*                                                                      *
+\subsubsection{The @ByteArray@ interface}
+\index{ByteArray interface (GHC extensions)}
+%*                                                                      *
+%************************************************************************
+
+@ByteArray@s are chunks of immutable Haskell heap:
+
+\begin{verbatim}
+data ByteArray ix -- abstract
+                 -- instance of: CCallable
+
+indexCharArray     :: Ix ix => ByteArray ix -> ix -> Char 
+indexIntArray      :: Ix ix => ByteArray ix -> ix -> Int
+indexAddrArray     :: Ix ix => ByteArray ix -> ix -> Addr
+indexFloatArray    :: Ix ix => ByteArray ix -> ix -> Float
+indexDoubleArray   :: Ix ix => ByteArray ix -> ix -> Double
+
+indexCharOffAddr   :: Addr -> Int -> Char
+indexIntOffAddr    :: Addr -> Int -> Int
+indexAddrOffAddr   :: Addr -> Int -> Addr
+indexFloatOffAddr  :: Addr -> Int -> Float
+indexDoubleOffAddr :: Addr -> Int -> Double
+
+\end{verbatim}
+
+%************************************************************************
+%*                                                                      *
+\subsubsection{The @Foreign@ interface}
+\index{Foreign interface (GHC extensions)}
+%*                                                                      *
+%************************************************************************
+
+The @Foreign@ interface define and export operations over @ForeignObj@
+and @StablePtr@s:
+
+\begin{verbatim}
+-- semi-magic classes for pack/unpacking ccall arguments.
+class CCallable a
+ {- Instances defined for : 
+      Char Char# Int Int# Float Float#
+      Double Double# Addr Addr# Word Word#
+      (MutableByteArray s ix) (MutableByteArray# s)
+      (ByteArray ix) ByteArray#
+      ForeignObj ForeignObj# 
+      (StablePtr a)
+      (StablePtr# a)
+      [Char]
+ -}
+class CReturnable a
+ {- Instances defined for : 
+      Char Int Float Double Addr Word 
+      (StablePtr a)
+ -}
+
+data ForeignObj = ForeignObj ForeignObj#
+   -- instances of : CCallable Eq
+
+eqForeignObj    :: ForeignObj  -> ForeignObj -> Bool
+makeForeignObj  :: Addr        -> Addr       -> PrimIO ForeignObj
+writeForeignObj :: ForeignObj  -> Addr       -> PrimIO ()
+
+{- derived op - attaching a free() finaliser to a malloc() allocated reference. -}
+makeMallocPtr   :: Addr        -> PrimIO ForeignObj
+
+data StablePtr a = StablePtr (StablePtr# a)
+  -- instances of : CCallable
+
+makeStablePtr  :: a -> PrimIO (StablePtr a)
+deRefStablePtr :: StablePtr a -> PrimIO a
+freeStablePtr  :: StablePtr a -> PrimIO ()
+performGC      :: PrimIO ()
+\end{verbatim}
+
+\begin{onlystandalone}
 \end{document}
+\end{onlystandalone}
                                                        
index 7346a79..f55c3c4 100644 (file)
@@ -26,6 +26,9 @@ Email: glasgow-haskell-\{users,bugs\}-request\@dcs.gla.ac.uk}
 % pointers to it.  Mentioning something in the release notes is not
 % the same as documenting it.
 
+\section[release-2-03]{Release notes for version~2.03---4/97}
+\input{2-03-notes.lit}
+
 \section[release-2-02]{Release notes for version~2.02---3/97}
 \input{2-02-notes.lit}
 
@@ -37,20 +40,20 @@ Email: glasgow-haskell-\{users,bugs\}-request\@dcs.gla.ac.uk}
 %\input{real-soon-now.lit}
 %\upsection
 
-\section{Versions 0.26 through 0.29}
+%\section{Versions 0.26 through 0.29}
 
-GHC~0.26 (7/95) was the last major release of GHC for Haskell~1.2.
+%GHC~0.26 (7/95) was the last major release of GHC for Haskell~1.2.
 
-GHC~0.27 (12/95) was a `` binary-only from-working-sources
-no-guarantees snapshot ...  for i386-unknown-linuxaout and
-i386-unknown-solaris2 platforms...''
+%GHC~0.27 (12/95) was a `` binary-only from-working-sources
+%no-guarantees snapshot ...  for i386-unknown-linuxaout and
+%i386-unknown-solaris2 platforms...''
 
-GHC~0.28 (5/96) was the same thing, for the i386-unknown-linux (ELF)
-platform.
+%GHC~0.28 (5/96) was the same thing, for the i386-unknown-linux (ELF)
+%platform.
 
-GHC~0.29 (7/96), released at the same time as 2.01, is just ``0.26
-with bug fixes''; i.e., the current state-of-play on the Haskell~1.2
-compiler development.
+%GHC~0.29 (7/96), released at the same time as 2.01, is just ``0.26
+%with bug fixes''; i.e., the current state-of-play on the Haskell~1.2
+%compiler development.
 
 \section{Old release notes}
 
diff --git a/ghc/docs/users_guide/syslib.lit b/ghc/docs/users_guide/syslib.lit
new file mode 100644 (file)
index 0000000..6cc7707
--- /dev/null
@@ -0,0 +1,2490 @@
+%************************************************************************
+%*                                                                      *
+\section[syslibs]{System libraries}
+\index{system libraries}
+\index{libraries, system}
+%*                                                                      *
+
+This section gives an overview of the interfaces provided
+by the different {\em syslibs} that comes bundled with GHC.
+
+At the moment, there four different collections of system libraries:
+
+\begin{itemize}
+\item The GHC system library - collection of interfaces that mainly
+have grown out of abstractions used to implement GHC itself.
+\item Parts of the HBC libraries.
+\item The Posix interface - a quality interface to OS functionality as
+specified by {\tt POSIX 1003.1}. Sadly, this library hasn't made it
+into a standard Haskell library.
+\item The contrib libraries - oodles of numeric codes..
+\end{itemize}
+
+If you provide a \tr{-syslib <name>}\index{-syslib <name> option}
+option on the command line, then the interfaces for that library will
+come into scope (and may be \tr{import}ed), and the code will be added
+in at link time. 
+
+
+%************************************************************************
+%*                                                                      *
+\subsection[GHC-library]{The GHC system library}
+\index{library, GHC}
+\index{GHC library}
+%*                                                                      *
+%************************************************************************
+
+We have started to put together a ``GHC system library.''
+
+At the moment, the library is made of generally-useful bits of the
+compiler itself.
+
+To use this library, just give a \tr{-syslib ghc}\index{-syslib ghc option}
+option to GHC, both for compiling and linking.
+
+%************************************************************************
+%*                                                                      *
+\subsubsection[Bag]{The @Bag@ type}
+\index{Bag module (GHC syslib)}
+%*                                                                      *
+%************************************************************************
+
+A {\em bag} is an unordered collection of elements which may contain
+duplicates.  To use, \tr{import Bag}.
+
+\begin{verbatim}
+data Bag elt    -- abstract
+
+emptyBag        :: Bag elt
+unitBag         :: elt -> Bag elt
+
+consBag         :: elt       -> Bag elt -> Bag elt
+snocBag         :: Bag elt   -> elt     -> Bag elt
+
+unionBags       :: Bag elt   -> Bag elt -> Bag elt
+unionManyBags   :: [Bag elt] -> Bag elt
+
+isEmptyBag      :: Bag elt   -> Bool
+elemBag         :: Eq elt => elt -> Bag elt -> Bool
+
+filterBag       :: (elt -> Bool) -> Bag elt -> Bag elt
+partitionBag    :: (elt -> Bool) -> Bag elt-> (Bag elt, Bag elt)
+        -- returns the elements that do/don't satisfy the predicate
+
+concatBag       :: Bag (Bag a) -> Bag a 
+foldBag         :: (r -> r -> r) -> (a -> r) -> r -> Bag a -> r
+mapBag          :: (a -> b) -> Bag a -> Bag b
+
+listToBag       :: [elt] -> Bag elt
+bagToList       :: Bag elt -> [elt]
+\end{verbatim}
+
+%************************************************************************
+%*                                                                      *
+\subsubsection[FiniteMap]{The @FiniteMap@ type}
+\index{FiniteMap module (GHC syslib)}
+%*                                                                      *
+%************************************************************************
+
+What functional programmers call a {\em finite map}, everyone else
+calls a {\em lookup table}.
+
+Out code is derived from that in this paper:
+\begin{display}
+S Adams
+"Efficient sets: a balancing act"
+Journal of functional programming 3(4) Oct 1993, pages 553-562
+\end{display}
+Guess what?  The implementation uses balanced trees.
+
+\begin{verbatim}
+data FiniteMap key elt  -- abstract
+
+--      BUILDING
+emptyFM         :: FiniteMap key elt
+unitFM          :: key -> elt -> FiniteMap key elt
+listToFM        :: Ord key => [(key,elt)] -> FiniteMap key elt
+                        -- In the case of duplicates, the last is taken
+
+--      ADDING AND DELETING
+                   -- Throws away any previous binding
+                   -- In the list case, the items are added starting with the
+                   -- first one in the list
+addToFM         :: Ord key => FiniteMap key elt -> key -> elt  -> FiniteMap key elt
+addListToFM     :: Ord key => FiniteMap key elt -> [(key,elt)] -> FiniteMap key elt
+
+                 -- Combines with previous binding
+                -- In the combining function, the first argument is
+                -- the "old" element, while the second is the "new" one.
+addToFM_C       :: Ord key => (elt -> elt -> elt)
+                           -> FiniteMap key elt -> key -> elt  
+                           -> FiniteMap key elt
+addListToFM_C   :: Ord key => (elt -> elt -> elt)
+                           -> FiniteMap key elt -> [(key,elt)] 
+                           -> FiniteMap key elt
+
+                 -- Deletion doesn't complain if you try to delete something
+                 -- which isn't there
+delFromFM       :: Ord key => FiniteMap key elt -> key   -> FiniteMap key elt
+delListFromFM   :: Ord key => FiniteMap key elt -> [key] -> FiniteMap key elt
+
+--      COMBINING
+                 -- Bindings in right argument shadow those in the left
+plusFM          :: Ord key => FiniteMap key elt -> FiniteMap key elt
+                           -> FiniteMap key elt
+
+                   -- Combines bindings for the same thing with the given function
+plusFM_C        :: Ord key => (elt -> elt -> elt) 
+                           -> FiniteMap key elt -> FiniteMap key elt -> FiniteMap key elt
+
+minusFM         :: Ord key => FiniteMap key elt -> FiniteMap key elt -> FiniteMap key elt
+                   -- (minusFM a1 a2) deletes from a1 any bindings which are bound in a2
+
+intersectFM     :: Ord key => FiniteMap key elt -> FiniteMap key elt -> FiniteMap key elt 
+intersectFM_C   :: Ord key => (elt -> elt -> elt)
+                           -> FiniteMap key elt -> FiniteMap key elt -> FiniteMap key elt 
+
+--      MAPPING, FOLDING, FILTERING
+foldFM          :: (key -> elt -> a -> a) -> a -> FiniteMap key elt -> a
+mapFM           :: (key -> elt1 -> elt2) -> FiniteMap key elt1 -> FiniteMap key elt2
+filterFM        :: Ord key => (key -> elt -> Bool) 
+                           -> FiniteMap key elt -> FiniteMap key elt
+
+--      INTERROGATING
+sizeFM          :: FiniteMap key elt -> Int
+isEmptyFM      :: FiniteMap key elt -> Bool
+
+elemFM         :: Ord key => key -> FiniteMap key elt -> Bool
+lookupFM        :: Ord key => FiniteMap key elt -> key -> Maybe elt
+lookupWithDefaultFM
+                :: Ord key => FiniteMap key elt -> elt -> key -> elt
+                -- lookupWithDefaultFM supplies a "default" elt
+                -- to return for an unmapped key
+
+--      LISTIFYING
+fmToList        :: FiniteMap key elt -> [(key,elt)]
+keysFM          :: FiniteMap key elt -> [key]
+eltsFM          :: FiniteMap key elt -> [elt]
+\end{verbatim}
+
+%************************************************************************
+%*                                                                      *
+\subsubsection[ListSetOps]{The @ListSetOps@ type}
+\index{ListSetOps module (GHC syslib)}
+%*                                                                      *
+%************************************************************************
+
+Just a few set-sounding operations on lists.  If you want sets, use
+the \tr{Set} module.
+
+\begin{verbatim}
+unionLists          :: Eq a => [a] -> [a] -> [a]
+intersectLists      :: Eq a => [a] -> [a] -> [a]
+minusList           :: Eq a => [a] -> [a] -> [a]
+disjointLists       :: Eq a => [a] -> [a] -> Bool
+intersectingLists   :: Eq a => [a] -> [a] -> Bool
+\end{verbatim}
+
+%************************************************************************
+%*                                                                      *
+\subsubsection[Maybes]{The @Maybes@ type}
+\index{Maybes module (GHC syslib)}
+%*                                                                      *
+%************************************************************************
+
+The \tr{Maybe} type is in the Haskell 1.4 prelude. Moreover, the
+required \tr{Maybe} library provides many useful functions on
+\tr{Maybe}s. This (pre-1.3) module provides some more:
+
+An \tr{Either}-like type called \tr{MaybeErr}:
+\begin{verbatim}
+data MaybeErr val err = Succeeded val | Failed err
+\end{verbatim}
+
+Some operations to do with \tr{Maybe} (some commentary follows):
+\begin{verbatim}
+maybeToBool :: Maybe a -> Bool      -- Nothing => False; Just => True
+allMaybes   :: [Maybe a] -> Maybe [a]
+firstJust   :: [Maybe a] -> Maybe a
+findJust    :: (a -> Maybe b) -> [a] -> Maybe b
+
+assocMaybe  :: Eq a => [(a,b)] -> a -> Maybe b
+mkLookupFun :: (key -> key -> Bool) -- Equality predicate
+            -> [(key,val)]          -- The assoc list
+            -> (key -> Maybe val)   -- A lookup fun to use
+mkLookupFunDef :: (key -> key -> Bool) -- Equality predicate
+              -> [(key,val)]           -- The assoc list
+              -> val                   -- Value to return on failure
+              -> key                   -- The key
+              -> val                   -- The corresponding value
+
+    -- a monad thing
+thenMaybe   :: Maybe a -> (a -> Maybe b) -> Maybe b
+returnMaybe :: a -> Maybe a
+failMaybe   :: Maybe a
+mapMaybe    :: (a -> Maybe b) -> [a] -> Maybe [b]
+\end{verbatim}
+
+NB: @catMaybes@ which used to be here, is now available via the
+standard @Maybe@ interface (@Maybe@ is an instance of @MonadPlus@).
+
+@allMaybes@ collects a list of @Justs@ into a single @Just@, returning
+@Nothing@ if there are any @Nothings@.
+
+@firstJust@ takes a list of @Maybes@ and returns the
+first @Just@ if there is one, or @Nothing@ otherwise.
+
+@assocMaybe@ looks up in an association list, returning
+@Nothing@ if it fails.
+
+Now, some operations to do with \tr{MaybeErr} (comments follow):
+\begin{verbatim}
+    -- a monad thing (surprise, surprise)
+thenMaB   :: MaybeErr a err -> (a -> MaybeErr b err) -> MaybeErr b err
+returnMaB :: val -> MaybeErr val err
+failMaB   :: err -> MaybeErr val err
+
+listMaybeErrs :: [MaybeErr val err] -> MaybeErr [val] [err]
+foldlMaybeErrs :: (acc -> input -> MaybeErr acc err)
+               -> acc
+               -> [input]
+               -> MaybeErr acc [err]
+\end{verbatim}
+
+@listMaybeErrs@ takes a list of @MaybeErrs@ and, if they all succeed,
+returns a @Succeeded@ of a list of their values.  If any fail, it
+returns a @Failed@ of the list of all the errors in the list.
+
+@foldlMaybeErrs@ works along a list, carrying an accumulator; it
+applies the given function to the accumulator and the next list item,
+accumulating any errors that occur.
+
+%************************************************************************
+%*                                                                      *
+\subsubsection[PackedString]{The @PackedString@ type}
+\index{PackedString module (GHC syslib)}
+%*                                                                      *
+%************************************************************************
+
+You need to \tr{import PackedString} and heave in your \tr{-syslib
+ghc} to use \tr{PackedString}s.
+
+The basic type and functions available are:
+\begin{verbatim}
+data PackedString -- abstract
+
+packString          :: [Char] -> PackedString
+packStringST        :: [Char] -> ST s PackedString
+packCBytesST        :: Int -> Addr -> ST s PackedString
+packBytesForCST     :: [Char] -> ST s (ByteArray Int)
+byteArrayToPS       :: ByteArray Int -> PackedString
+unsafeByteArrayToPS :: ByteArray a   -> Int -> PackedString
+psToByteArray       :: PackedString -> ByteArray Int
+psToByteArrayST     :: PackedString -> ST s (ByteArray Int)
+
+unpackPS        :: PackedString -> [Char]
+\end{verbatim}
+
+We also provide a wad of list-manipulation-like functions:
+\begin{verbatim}
+nilPS       :: PackedString
+consPS      :: Char -> PackedString -> PackedString
+
+headPS      :: PackedString -> Char
+tailPS      :: PackedString -> PackedString
+nullPS      :: PackedString -> Bool
+appendPS    :: PackedString -> PackedString -> PackedString
+lengthPS    :: PackedString -> Int
+indexPS     :: PackedString -> Int -> Char
+            -- 0-origin indexing into the string
+mapPS       :: (Char -> Char) -> PackedString -> PackedString
+filterPS    :: (Char -> Bool) -> PackedString -> PackedString
+foldlPS     :: (a -> Char -> a) -> a -> PackedString -> a
+foldrPS     :: (Char -> a -> a) -> a -> PackedString -> a
+takePS      :: Int -> PackedString -> PackedString
+dropPS      :: Int -> PackedString -> PackedString
+splitAtPS   :: Int -> PackedString -> (PackedString, PackedString)
+takeWhilePS :: (Char -> Bool) -> PackedString -> PackedString
+dropWhilePS :: (Char -> Bool) -> PackedString -> PackedString
+spanPS      :: (Char -> Bool) -> PackedString -> (PackedString, PackedString)
+breakPS     :: (Char -> Bool) -> PackedString -> (PackedString, PackedString)
+linesPS     :: PackedString -> [PackedString]
+wordsPS     :: PackedString -> [PackedString]
+reversePS   :: PackedString -> PackedString
+concatPS    :: [PackedString] -> PackedString
+elemPS      :: Char -> PackedString -> Bool
+  -- Perl-style split&join
+splitPS     :: Char -> PackedString -> [PackedString]
+splitWithPS :: (Char -> Bool) -> PackedString -> [PackedString]
+joinPS      :: PackedString -> [PackedString] -> PackedString
+
+substrPS   :: PackedString -> Int -> Int -> PackedString
+           -- pluck out a piece of a PackedString
+           -- start and end chars you want; both 0-origin-specified
+\end{verbatim}
+
+%************************************************************************
+%*                                                                      *
+\subsubsection[Pretty]{The @Pretty@ type}
+\index{Pretty module (GHC syslib)}
+%*                                                                      *
+%************************************************************************
+
+This is the pretty-printer that is currently used in GHC:
+
+\begin{verbatim}
+type Pretty
+
+ppShow          :: Int{-width-} -> Pretty -> [Char]
+
+pp'SP           :: Pretty -- "comma space"
+ppComma         :: Pretty -- ,
+ppEquals        :: Pretty -- =
+ppLbrack        :: Pretty -- [
+ppLparen        :: Pretty -- (
+ppNil           :: Pretty -- nothing
+ppRparen        :: Pretty -- )
+ppRbrack        :: Pretty -- ]
+ppSP            :: Pretty -- space
+ppSemi          :: Pretty -- ;
+
+ppChar          :: Char -> Pretty
+ppDouble        :: Double -> Pretty
+ppFloat         :: Float -> Pretty
+ppInt           :: Int -> Pretty
+ppInteger       :: Integer -> Pretty
+ppRational      :: Rational -> Pretty
+ppStr           :: [Char] -> Pretty
+
+ppAbove         :: Pretty -> Pretty -> Pretty
+ppAboves        :: [Pretty] -> Pretty
+ppBeside        :: Pretty -> Pretty -> Pretty
+ppBesides       :: [Pretty] -> Pretty
+ppCat           :: [Pretty] -> Pretty
+ppHang          :: Pretty -> Int -> Pretty -> Pretty
+ppInterleave    :: Pretty -> [Pretty] -> Pretty -- spacing between
+ppIntersperse   :: Pretty -> [Pretty] -> Pretty -- no spacing between
+ppNest          :: Int -> Pretty -> Pretty
+ppSep           :: [Pretty] -> Pretty
+\end{verbatim}
+
+%************************************************************************
+%*                                                                      *
+\subsubsection[Set]{The @Set@ type}
+\index{Set module (GHC syslib)}
+%*                                                                      *
+%************************************************************************
+
+Our implementation of {\em sets} (key property: no duplicates) is just
+a variant of the \tr{FiniteMap} module.
+
+\begin{verbatim}
+data Set        -- abstract
+                -- instance of: Eq
+
+emptySet        :: Set a
+mkSet           :: Ord a => [a]  -> Set a
+setToList       :: Set a -> [a]
+unitSet         :: a -> Set a
+singletonSet    :: a -> Set a  -- deprecated, use unitSet.
+
+union           :: Ord a => Set a -> Set a -> Set a
+unionManySets   :: Ord a => [Set a] -> Set a
+minusSet        :: Ord a => Set a -> Set a -> Set a
+mapSet          :: Ord a => (b -> a) -> Set b -> Set a
+intersect       :: Ord a => Set a -> Set a -> Set a
+
+elementOf       :: Ord a => a -> Set a -> Bool
+isEmptySet      :: Set a -> Bool
+
+cardinality     :: Set a -> Int
+
+\end{verbatim}
+
+%************************************************************************
+%*                                                                      *
+\subsubsection[BitSet]{The @BitSet@ interface}
+\index{Bitset interface (GHC syslib)}
+%*                                                                      *
+%************************************************************************
+
+Bit sets are a fast implementation of sets of integers ranging from 0
+to one less than the number of bits in a machine word (typically 31).
+If any element exceeds the maximum value for a particular machine
+architecture, the results of these operations are undefined.  You have
+been warned. 
+
+\begin{verbatim}
+data BitSet   -- abstract
+              -- instance of:
+
+emptyBS       :: BitSet
+mkBS          :: [Int] -> BitSet
+unitBS        :: Int -> BitSet
+unionBS       :: BitSet -> BitSet -> BitSet
+minusBS       :: BitSet -> BitSet -> BitSet
+isEmptyBS     :: BitSet -> Bool
+intersectBS   :: BitSet -> BitSet -> BitSet
+elementBS     :: Int -> BitSet -> Bool
+listBS        :: BitSet -> [Int]
+\end{verbatim}
+
+%************************************************************************
+%*                                                                      *
+\subsubsection[Util]{The @Util@ type}
+\index{Util module (GHC syslib)}
+%*                                                                      *
+%************************************************************************
+
+Stuff that has been generally useful to use in writing the compiler.
+Don't be too surprised if this stuff moves/gets-renamed/etc.
+
+\begin{verbatim}
+-- general list processing
+forall          :: (a -> Bool) -> [a] -> Bool
+exists          :: (a -> Bool) -> [a] -> Bool
+
+nOfThem         :: Int -> a -> [a]
+lengthExceeds   :: [a] -> Int -> Bool
+isSingleton     :: [a] -> Bool
+
+--paranoid zip'ing (equal length lists)
+zipEqual        :: [a] -> [b] -> [(a,b)]
+zipWithEqual   :: String -> (a->b->c) -> [a]->[b]->[c]
+zipWith3Equal  :: String -> (a->b->c->d) -> [a]->[b]->[c]->[d]
+zipWith4Equal  :: String -> (a->b->c->d->e) -> [a]->[b]->[c]->[d]->[e]
+-- lazy in second argument
+zipLazy :: [a] -> [b] -> [(a,b)]
+
+mapAndUnzip :: (a -> (b, c)) -> [a] -> ([b], [c])
+mapAndUnzip3 :: (a -> (b, c, d)) -> [a] -> ([b], [c], [d])
+
+-- prefix and suffix matching on lists of characters.
+startsWith :: {-prefix-}String -> String -> Maybe String
+endsWith   :: {-suffix-}String -> String -> Maybe String
+
+-- association lists
+assoc       :: Eq a => String -> [(a, b)] -> a -> b
+
+-- duplicate handling
+hasNoDups    :: Eq a => [a] -> Bool
+equivClasses :: (a -> a -> Ordering) -> [a] -> [[a]]
+runs         :: (a -> a -> Bool)     -> [a] -> [[a]]
+removeDups   :: (a -> a -> Ordering) -> [a] -> ([a], [[a]])
+
+-- sorting (don't complain of no choice...)
+quicksort          :: (a -> a -> Bool)     -> [a] -> [a]
+sortLt             :: (a -> a -> Bool)     -> [a] -> [a]
+stableSortLt       :: (a -> a -> Bool)     -> [a] -> [a]
+mergesort          :: (a -> a -> _CMP_TAG) -> [a] -> [a]
+mergeSort          :: Ord a => [a] -> [a]
+naturalMergeSort   :: Ord a => [a] -> [a]
+mergeSortLe        :: Ord a => [a] -> [a]
+naturalMergeSortLe :: Ord a => [a] -> [a]
+
+-- transitive closures
+transitiveClosure :: (a -> [a])         -- Successor function
+                  -> (a -> a -> Bool)   -- Equality predicate
+                  -> [a] 
+                  -> [a]                -- The transitive closure
+
+-- accumulating (Left, Right, Bi-directional)
+mapAccumL :: (acc -> x -> (acc, y))
+                        -- Function of elt of input list and
+                        -- accumulator, returning new accumulator and
+                        -- elt of result list
+          -> acc        -- Initial accumulator
+          -> [x]        -- Input list
+          -> (acc, [y]) -- Final accumulator and result list
+
+mapAccumR :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
+
+mapAccumB :: (accl -> accr -> x -> (accl, accr,y))
+          -> accl -> accr -> [x]
+          -> (accl, accr, [y])
+
+--list comparison with explicit element comparer.
+cmpList :: (a -> a -> Ordering) -> [a] -> [a] -> Ordering
+
+-- pairs
+applyToPair :: ((a -> c), (b -> d)) -> (a, b) -> (c, d)
+applyToFst  :: (a -> c) -> (a, b) -> (c, b)
+applyToSnd  :: (b -> d) -> (a, b) -> (a, d)
+foldPair    :: (a->a->a, b->b->b) -> (a, b) -> [(a, b)] -> (a, b)
+unzipWith   :: (a -> b -> c) -> [(a, b)] -> [c]
+\end{verbatim}
+
+%************************************************************************
+%*                                                                      *
+\subsection[C-interfaces]{Interfaces to C libraries}
+\index{C library interfaces}
+\index{interfaces, C library}
+%*                                                                      *
+%************************************************************************
+
+The GHC system library (\tr{-syslib ghc}) also provides interfaces to
+several useful C libraries, mostly from the GNU project.
+
+%************************************************************************
+%*                                                                      *
+\subsubsection[Readline]{The @Readline@ interface}
+\index{Readline library (GHC syslib)}
+\index{command-line editing library}
+%*                                                                      *
+%************************************************************************
+
+(Darren Moffat supplied the \tr{Readline} interface.)
+
+The \tr{Readline} module is a straightforward interface to the GNU
+Readline library.  As such, you will need to look at the GNU
+documentation (and have a \tr{libreadline.a} file around somewhere...)
+
+You'll need to link any Readlining program with \tr{-lreadline -ltermcap},
+besides the usual \tr{-syslib ghc} (and \tr{-fhaskell-1.3}).
+
+The main function you'll use is:
+\begin{verbatim}
+readline :: String{-the prompt-} -> IO String
+\end{verbatim}
+
+If you want to mess around with Full Readline G(l)ory, we also
+provide:
+\begin{verbatim}
+rlInitialize, addHistory,
+
+rlBindKey, rlAddDefun, RlCallbackFunction(..),
+
+rlGetLineBuffer, rlSetLineBuffer, rlGetPoint, rlSetPoint, rlGetEnd,
+rlSetEnd, rlGetMark, rlSetMark, rlSetDone, rlPendingInput,
+
+rlPrompt, rlTerminalName, rlSetReadlineName, rlGetReadlineName
+\end{verbatim}
+(All those names are just Haskellised versions of what you
+will see in the GNU readline documentation.)
+
+%************************************************************************
+%*                                                                      *
+\subsubsection[Regexp]{The @Regexp@ and @MatchPS@ interfaces}
+\index{Regex library (GHC syslib)}
+\index{MatchPS library (GHC syslib)}
+\index{regular-expressions library}
+%*                                                                      *
+%************************************************************************
+
+(Sigbjorn Finne supplied the regular-expressions interface.)
+
+The \tr{Regex} library provides quite direct interface to the GNU
+regular-expression library, for doing manipulation on
+\tr{PackedString}s.  You probably need to see the GNU documentation
+if you are operating at this level.
+
+The datatypes and functions that \tr{Regex} provides are:
+\begin{verbatim}
+data PatBuffer # just a bunch of bytes (mutable)
+
+data REmatch
+ = REmatch (Array Int GroupBounds)  -- for $1, ... $n
+          GroupBounds              -- for $` (everything before match)
+          GroupBounds              -- for $& (entire matched string)
+          GroupBounds              -- for $' (everything after)
+          GroupBounds              -- for $+ (matched by last bracket)
+
+-- GroupBounds hold the interval where a group
+-- matched inside a string, e.g.
+--
+-- matching "reg(exp)" "a regexp" returns the pair (5,7) for the
+-- (exp) group. (PackedString indices start from 0)
+
+type GroupBounds = (Int, Int)
+
+re_compile_pattern
+       :: PackedString         -- pattern to compile
+       -> Bool                 -- True <=> assume single-line mode
+       -> Bool                 -- True <=> case-insensitive
+       -> PrimIO PatBuffer
+
+re_match :: PatBuffer          -- compiled regexp
+        -> PackedString        -- string to match
+        -> Int                 -- start position
+        -> Bool                -- True <=> record results in registers
+        -> PrimIO (Maybe REmatch)
+
+-- Matching on 2 strings is useful when you're dealing with multiple
+-- buffers, which is something that could prove useful for
+-- PackedStrings, as we don't want to stuff the contents of a file
+-- into one massive heap chunk, but load (smaller chunks) on demand.
+
+re_match2 :: PatBuffer         -- 2-string version
+         -> PackedString
+         -> PackedString
+         -> Int
+         -> Int
+         -> Bool
+         -> PrimIO (Maybe REmatch)
+
+re_search :: PatBuffer         -- compiled regexp
+         -> PackedString       -- string to search
+         -> Int                -- start index
+         -> Int                -- stop index
+         -> Bool               -- True <=> record results in registers
+         -> PrimIO (Maybe REmatch)
+
+re_search2 :: PatBuffer                -- Double buffer search
+          -> PackedString
+          -> PackedString
+          -> Int               -- start index
+          -> Int               -- range (?)
+          -> Int               -- stop index
+          -> Bool              -- True <=> results in registers
+          -> PrimIO (Maybe REmatch)
+\end{verbatim}
+
+The \tr{MatchPS} module provides Perl-like ``higher-level'' facilities
+to operate on \tr{PackedStrings}.  The regular expressions in
+question are in Perl syntax.  The ``flags'' on various functions can
+include: \tr{i} for case-insensitive, \tr{s} for single-line mode, and
+\tr{g} for global.  (It's probably worth your time to peruse the
+source code...)
+
+\begin{verbatim}
+matchPS :: PackedString    -- regexp
+       -> PackedString    -- string to match
+       -> [Char]          -- flags
+       -> Maybe REmatch   -- info about what matched and where
+
+searchPS :: PackedString    -- regexp
+        -> PackedString    -- string to match
+        -> [Char]          -- flags
+        -> Maybe REmatch
+
+-- Perl-like match-and-substitute:
+substPS :: PackedString     -- regexp
+       -> PackedString     -- replacement
+       -> [Char]           -- flags
+       -> PackedString     -- string
+       -> PackedString
+
+-- same as substPS, but no prefix and suffix:
+replacePS :: PackedString  -- regexp
+         -> PackedString  -- replacement
+         -> [Char]        -- flags
+         -> PackedString  -- string
+         -> PackedString
+
+match2PS :: PackedString   -- regexp
+        -> PackedString   -- string1 to match
+        -> PackedString   -- string2 to match
+        -> [Char]         -- flags
+        -> Maybe REmatch
+
+search2PS :: PackedString  -- regexp
+         -> PackedString  -- string to match
+         -> PackedString  -- string to match
+         -> [Char]        -- flags
+         -> Maybe REmatch
+
+-- functions to pull the matched pieces out of an REmatch:
+
+getMatchesNo    :: REmatch -> Int
+getMatchedGroup :: REmatch -> Int -> PackedString -> PackedString
+getWholeMatch   :: REmatch -> PackedString -> PackedString
+getLastMatch    :: REmatch -> PackedString -> PackedString
+getAfterMatch   :: REmatch -> PackedString -> PackedString
+
+-- (reverse) brute-force string matching;
+-- Perl equivalent is index/rindex:
+findPS, rfindPS :: PackedString -> PackedString -> Maybe Int
+
+-- Equivalent to Perl "chop" (off the last character, if any):
+chopPS :: PackedString -> PackedString
+
+-- matchPrefixPS: tries to match as much as possible of strA starting
+-- from the beginning of strB (handy when matching fancy literals in
+-- parsers):
+matchPrefixPS :: PackedString -> PackedString -> Int
+\end{verbatim}
+
+%************************************************************************
+%*                                                                      *
+\subsubsection[Socket]{Network-interface toolkit---@Socket@ and @SocketPrim@}
+\index{SocketPrim interface (GHC syslib)}
+\index{Socket interface (GHC syslib)}
+\index{network-interface library}
+\index{sockets library}
+\index{BSD sockets library}
+%*                                                                      *
+%************************************************************************
+
+(Darren Moffat supplied the network-interface toolkit.)
+
+Your best bet for documentation is to look at the code---really!--- 
+normally in \tr{hslibs/ghc/src/{BSD,Socket,SocketPrim}.lhs}.
+
+The \tr{BSD} module provides functions to get at system-database info;
+pretty straightforward if you're into this sort of thing:
+\begin{verbatim}
+getHostName        :: IO String
+
+getServiceByName    :: ServiceName -> IO ServiceEntry
+getServicePortNumber:: ServiceName -> IO PortNumber
+getServiceEntry            :: IO ServiceEntry
+setServiceEntry            :: Bool -> IO ()
+endServiceEntry            :: IO ()
+
+getProtocolByName   :: ProtocolName -> IO ProtocolEntry
+getProtocolByNumber :: ProtocolNumber -> IO ProtcolEntry
+getProtocolNumber   :: ProtocolName -> ProtocolNumber
+getProtocolEntry    :: IO ProtocolEntry
+setProtocolEntry    :: Bool -> IO ()
+endProtocolEntry    :: IO ()
+
+getHostByName      :: HostName -> IO HostEntry
+getHostByAddr      :: Family -> HostAddress -> IO HostEntry
+getHostEntry       :: IO HostEntry
+setHostEntry       :: Bool -> IO ()
+endHostEntry       :: IO ()
+\end{verbatim}
+
+The \tr{SocketPrim} interface provides quite direct access to the
+socket facilities in a BSD Unix system, including all the
+complications.  We hope you don't need to use it!  See the source if
+needed...
+
+The \tr{Socket} interface is a ``higher-level'' interface to sockets,
+and it is what we recommend.  Please tell us if the facilities it
+offers are inadequate to your task!
+
+The interface is relatively modest:
+\begin{verbatim}
+connectTo      :: Hostname -> PortID -> IO Handle
+listenOn       :: PortID -> IO Socket
+
+accept         :: Socket -> IO (Handle, HostName)
+sendTo         :: Hostname -> PortID -> String -> IO ()
+
+recvFrom       :: Hostname -> PortID -> IO String
+socketPort     :: Socket -> IO PortID
+
+data PortID    -- PortID is a non-abstract type
+  = Service String     -- Service Name eg "ftp"
+  | PortNumber Int     -- User defined Port Number
+  | UnixSocket String  -- Unix family socket in file system
+
+type Hostname = String
+\end{verbatim}
+
+Various examples of networking Haskell code are provided in
+\tr{ghc/misc/examples/}, notably the \tr{net???/Main.hs} programs.
+
+%************************************************************************
+%*                                                                      *
+\subsection[Posix-library]{The Posix system library}
+\index{Posix system library}
+\index{system library, Posix}
+%*                                                                      *
+%************************************************************************
+
+The @Posix@ interface gives you access to the set of OS services
+standardised by POSIX 1003.1b (or the {\em IEEE Portable Operating System
+Interface for Computing Environments} - IEEE Std. 1003.1). The
+interface is accessed by \tr{import Posix} and adding \tr{-syslib
+posix} on your command-line.
+
+\subsubsection[Posix-data-types]{Posix data types}
+\index{Posix, data types}
+
+
+\begin{verbatim}
+data ByteCount  -- instances of : Eq Ord Num Real Integral Ix Enum Show
+\end{verbatim}
+
+A \tr{ByteCount} is a primitive of type \tr{unsigned}. At a minimum,
+an conforming implementation must support values in the range
+\tr{[0, UINT_MAX]}.
+
+\begin{verbatim}
+data ClockTick  -- instances of : Eq Ord Num Real Integral Ix Enum Show
+\end{verbatim}
+
+A \tr{ClockTick} is a primitive of type \tr{clock_t}, which
+is used to measure intervals of time in fractions of a second.  The 
+resolution is determined by \tr{getSysVar ClockTick}.
+
+\begin{verbatim}
+data DeviceID  -- instances of : Eq Ord Num Real Integral Ix Enum Show
+\end{verbatim}
+
+A \tr{DeviceID} is a primitive of type \tr{dev_t}.  It must
+be an arithmetic type.
+
+\begin{verbatim}
+> data EpochTime -- instances of : Eq Ord Num Real Integral Ix Enum Show
+\end{verbatim}
+
+A \tr{EpochTime} is a primitive of type \tr{time_t}, which is
+used to measure seconds since the Epoch.  At a minimum, the implementation 
+must support values in the range \tr{[0, INT_MAX]}.
+
+\begin{verbatim}
+data FileID -- instances of : Eq Ord Num Real Integral Ix Enum Show
+\end{verbatim}
+
+A \tr{FileID} is a primitive of type \tr{ino_t}.  It must
+be an arithmetic type.
+
+\begin{verbatim}
+data FileMode -- instances of : Eq Ord Num Real Integral Ix Enum Show
+\end{verbatim}
+
+A \tr{FileMode} is a primitive of type \tr{mode_t}.
+It must be an arithmetic type.
+
+\begin{verbatim}
+data FileOffset -- instances of : Eq Ord Num Real Integral Ix Enum Show
+\end{verbatim}
+
+A \tr{FileOffset} is a primitive of type \tr{off_t}.  It must
+be an arithmetic type.
+
+\begin{verbatim}
+data GroupID -- instances of : Eq Ord Num Real Integral Ix Enum Show
+\end{verbatim}
+
+A \tr{GroupID} is a primitive of type \tr{gid_t}.  It must
+be an arithmetic type.
+\begin{verbatim}
+data Limit -- instances of : Eq Ord Num Real Integral Ix Enum Show
+\end{verbatim}
+
+A \tr{Limit} is a primitive of type \tr{long}.
+At a minimum, the implementation must support values in the range 
+\tr{[LONG_MIN, LONG_MAX]}.
+
+\begin{verbatim}
+data LinkCount -- instances of : Eq Ord Num Real Integral Ix Enum Show
+\end{verbatim}
+
+A \tr{LinkCount} is a primitive of type \tr{nlink_t}.  It must
+be an arithmetic type.
+
+\begin{verbatim}
+data ProcessID -- instances of : Eq Ord Num Real Integral Ix Enum Show
+type ProcessGroupID = ProcessID
+\end{verbatim}
+
+A \tr{ProcessID} is a primitive of type \tr{pid_t}.  It
+must be a signed arithmetic type.
+\begin{verbatim}
+data UserID -- instances of : Eq Ord Num Real Integral Ix Enum Show
+\end{verbatim}
+
+A \tr{UserID} is a primitive of type \tr{uid_t}.  It
+must be an arithmetic type.
+
+\begin{verbatim}
+data DirStream
+\end{verbatim}
+A \tr{DirStream} is a primitive of type \tr{DIR *}.
+
+\begin{verbatim}
+data FileStatus
+\end{verbatim}
+A \tr{FileStatus} is a primitive of type \tr{struct stat}.
+
+\begin{verbatim}
+data GroupEntry
+\end{verbatim}
+
+A \tr{GroupEntry} is a primitive of type \tr{struct group}.
+\begin{verbatim}
+data ProcessTimes
+\end{verbatim}
+
+\tr{ProcessTimes} is a primitive structure containing a
+\tr{clock_t} and a \tr{struct tms}.
+
+\begin{verbatim}
+data SignalSet
+\end{verbatim}
+
+An \tr{SignalSet} is a primitive of type \tr{sigset_t}.
+
+\begin{verbatim}
+data SystemID
+\end{verbatim}
+
+A \tr{SystemID} is a primitive of type \tr{struct utsname}.
+
+\begin{verbatim}
+data TerminalAttributes
+\end{verbatim}
+\tr{TerminalAttributes} is a primitive of type \tr{struct termios}.
+
+\begin{verbatim}
+data UserEntry
+\end{verbatim}
+
+A \tr{UserEntry} is a primitive of type \tr{struct passwd}.
+
+\begin{verbatim}
+data BaudRate = B0 | B50 | B75 | B110 | B134 | B150 | B200 | B300 | B600
+              | B1200 | B1800 | B2400 | B4800 | B9600 | B19200 | B38400
+              deriving (Eq, Show)
+
+type Channel = Int
+
+data ChannelOption = AppendOnWrite
+                   | CloseOnExec
+                   | NonBlockingRead
+
+data ControlCharacter = EndOfFile
+                      | EndOfLine
+                      | Erase
+                      | Interrupt
+                      | Kill
+                      | Quit
+                      | Suspend
+                      | Start
+                      | Stop
+
+type ErrorCode = Int
+
+type FileLock = (LockRequest, SeekMode, FileOffset, FileOffset)
+--                            whence    start       length
+
+data FlowAction = SuspendOutput | RestartOutput | TransmitStop | TransmitStart
+
+data Handler = Default | Ignore | Catch (IO ())
+
+data LockRequest = ReadLock | WriteLock | Unlock
+                 deriving (Eq, Show)
+
+data OpenMode = ReadOnly | WriteOnly | ReadWrite
+
+data PathVar = LinkLimit
+             | InputLineLimit
+             | InputQueueLimit
+             | FileNameLimit
+             | PathNameLimit
+             | PipeBufferLimit
+             | SetOwnerAndGroupIsRestricted
+             | FileNamesAreNotTruncated
+
+data QueueSelector = InputQueue | OutputQueue | BothQueues
+
+type Signal = Int
+
+data SysVar = ArgumentLimit
+            | ChildLimit
+            | ClockTick
+            | GroupLimit
+            | OpenFileLimit
+            | PosixVersion
+            | HasSavedIDs
+            | HasJobControl
+
+data TerminalMode = InterruptOnBreak       -- BRKINT
+                | MapCRtoLF                -- ICRNL
+                | IgnoreBreak              -- IGNBRK
+                | IgnoreCR                 -- IGNCR
+                | IgnoreParityErrors       -- IGNPAR
+                | MapLFtoCR                -- INLCR
+                | CheckParity              -- INPCK
+                | StripHighBit             -- ISTRIP
+                | StartStopInput           -- IXOFF
+                | StartStopOutput          -- IXON
+                | MarkParityErrors         -- PARMRK
+                | ProcessOutput            -- OPOST
+                | LocalMode                -- CLOCAL
+                | ReadEnable               -- CREAD
+                | TwoStopBits              -- CSTOPB
+                | HangupOnClose            -- HUPCL
+                | EnableParity             -- PARENB
+                | OddParity                -- PARODD
+                | EnableEcho               -- ECHO
+                | EchoErase                -- ECHOE
+                | EchoKill                 -- ECHOK
+                | EchoLF                   -- ECHONL
+                | ProcessInput             -- ICANON
+                | ExtendedFunctions        -- IEXTEN
+                | KeyboardInterrupts       -- ISIG
+                | NoFlushOnInterrupt       -- NOFLSH
+                | BackgroundWriteInterrupt -- TOSTOP
+
+data TerminalState = Immediately | WhenDrained | WhenFlushed
+
+data ProcessStatus = Exited ExitCode 
+                   | Terminated Signal 
+                   | Stopped Signal
+                   deriving (Eq, Show)
+\end{verbatim}
+
+\subsubsection{posix-process-env}{Posix Process Primitives}
+
+\begin{verbatim}
+forkProcess :: IO (Maybe ProcessID)
+\end{verbatim}
+
+\tr{forkProcess} calls \tr{fork}, returning
+\tr{Just pid} to the parent, where <var>pid</var> is the
+ProcessID of the child, and returning \tr{Nothing} to the
+child.
+
+\begin{verbatim}
+executeFile :: FilePath                   -- Command
+            -> Bool                       -- Search PATH?
+            -> [String]                   -- Arguments
+            -> Maybe [(String, String)]   -- Environment
+            -> IO ()
+\end{verbatim}
+
+\tr{executeFile cmd args env} calls one of the
+\tr{execv*} family, depending on whether or not the current
+PATH is to be searched for the command, and whether or not an
+environment is provided to supersede the process's current
+environment.  The basename (leading directory names suppressed) of
+the command is passed to \tr{execv*} as \tr{arg[0]};
+the argument list passed to \tr{executeFile} therefore begins 
+with \tr{arg[1]}.
+
+\begin{verbatim}
+Search PATH?    Supersede environ?      Call
+~~~~~~~~~~~~    ~~~~~~~~~~~~~~~~~~      ~~~~~~~
+False           False                   execv
+False           True                    execve
+True            False                   execvp
+True            True                    execvpe*
+\end{verbatim}
+
+Note that \tr{execvpe} is not provided by the POSIX standard, and must
+be written by hand.  Care must be taken to ensure that the search path
+is extracted from the original environment, and not from the
+environment to be passed on to the new image.
+
+A successful \tr{executeFile} overlays the current process image with 
+a new one, so it only returns on failure.
+\begin{verbatim}
+runProcess :: FilePath                    -- Command
+           -> [String]                    -- Arguments
+           -> Maybe [(String, String)]    -- Environment (Nothing -> Inherited)
+           -> Maybe FilePath              -- Working directory (Nothing -> inherited)
+           -> Maybe Handle                -- stdin  (Nothing -> inherited)
+           -> Maybe Handle                -- stdout (Nothing -> inherited)
+           -> Maybe Handle                -- stderr (Nothing -> inherited)
+           -> IO ()
+\end{verbatim}
+
+\tr{runProcess} is our candidate for the high-level OS-independent
+primitive.
+
+\tr{runProcess cmd args env wd inhdl outhdl errhdl} runs \tr{cmd}
+(searching the current \tr{PATH}) with arguments \tr{args}.  If
+\tr{env} is \tr{Just pairs}, the command is executed with the
+environment specified by \tr{pairs} of variables and values;
+otherwise, the command is executed with the current environment.  If
+\tr{wd} is \tr{Just dir}, the command is executed with working
+directory \tr{dir}; otherwise, the command is executed in the current
+working directory.  If \tr{{in,out,err}hdl} is \tr{Just handle}, the
+command is executed with the \tr{Channel} for \tr{std{in,out,err}}
+attached to the specified \tr{handle}; otherwise, the \tr{Channel} for
+\tr{std{in,out,err}} is left unchanged.
+
+\begin{verbatim}
+getProcessStatus :: Bool              -- Block?
+                 -> Bool              -- Stopped processes?
+                 -> ProcessID 
+                 -> IO (Maybe ProcessStatus)
+\end{verbatim}
+
+\tr{getProcessStatus blk stopped pid} calls \tr{waitpid}, returning
+\tr{Just tc}, the \tr{ProcessStatus} for process \tr{pid} if it is
+available, \tr{Nothing} otherwise.  If \tr{blk} is \tr{False}, then
+\tr{WNOHANG} is set in the options for \tr{waitpid}, otherwise not.
+If \tr{stopped} is \tr{True}, then \tr{WUNTRACED} is set in the
+options for \tr{waitpid}, otherwise not.
+
+\begin{verbatim}
+getGroupProcessStatus :: Bool         -- Block?
+                      -> Bool         -- Stopped processes?
+                      -> ProcessGroupID 
+                      -> IO (Maybe (ProcessID, ProcessStatus))
+\end{verbatim}
+
+\tr{getGroupProcessStatus blk stopped pgid} calls \tr{waitpid},
+returning \tr{Just (pid, tc)}, the \tr{ProcessID} and
+\tr{ProcessStatus} for any process in group \tr{pgid} if one is
+available, \tr{Nothing} otherwise.  If \tr{blk} is \tr{False}, then
+\tr{WNOHANG} is set in the options for \tr{waitpid}, otherwise not.
+If \tr{stopped} is \tr{True}, then \tr{WUNTRACED} is set in the
+options for \tr{waitpid}, otherwise not.
+
+\begin{verbatim}
+getAnyProcessStatus :: Bool           -- Block?
+                    -> Bool           -- Stopped processes?
+                    -> IO (Maybe (ProcessID, ProcessStatus))
+\end{verbatim}
+
+\tr{getAnyProcessStatus blk stopped} calls \tr{waitpid}, returning
+\tr{Just (pid, tc)}, the \tr{ProcessID} and \tr{ProcessStatus} for any
+child process if one is available, \tr{Nothing} otherwise.  If
+\tr{blk} is \tr{False}, then \tr{WNOHANG} is set in the options for
+\tr{waitpid}, otherwise not.  If \tr{stopped} is \tr{True}, then
+\tr{WUNTRACED} is set in the options for \tr{waitpid}, otherwise not.
+
+\begin{verbatim}
+exitImmediately :: ExitCode -> IO ()
+\end{verbatim}
+
+\tr{exitImmediately status} calls \tr{_exit} to terminate the process
+with the indicated exit \tr{status}.
+The operation never returns.
+
+\begin{verbatim}
+getEnvironment :: IO [(String, String)]
+\end{verbatim}
+
+\tr{getEnvironment} parses the environment variable mapping provided by
+\tr{environ}, returning \tr{(variable, value)} pairs. 
+The operation never fails.
+
+\begin{verbatim}
+setEnvironment :: [(String, String)] -> IO ()
+\end{verbatim}
+
+\tr{setEnvironment} replaces the process environment with the provided
+mapping of \tr{(variable, value)} pairs. 
+
+\begin{verbatim}
+getEnvVar :: String -> IO String
+\end{verbatim}
+
+\tr{getEnvVar var} returns the value associated with variable \tr{var} 
+in the current environment (identical functionality provided through
+standard Haskell library function @System.getEnv@).
+
+The operation may fail with:
+
+\begin{itemize}
+\item[\tr{NoSuchThing}]
+The variable has no mapping in the current environment.
+\end{itemize}
+
+\begin{verbatim}
+setEnvVar :: String -> String -> IO ()
+\end{verbatim}
+
+\tr{setEnvVar var val} sets the value associated with variable \tr{var} 
+in the current environment to be \tr{val}.  Any previous mapping is 
+superseded.
+
+\begin{verbatim}
+removeEnvVar :: String -> IO ()
+\end{verbatim}
+
+\tr{removeEnvVar var} removes any value associated with variable \tr{var} 
+in the current environment.  Deleting a variable for which there is no mapping
+does not generate an error.
+
+\begin{verbatim}
+nullSignal :: Signal
+nullSignal = 0
+
+backgroundRead, sigTTIN        :: Signal
+backgroundWrite, sigTTOU       :: Signal
+continueProcess, sigCONT       :: Signal
+floatingPointException, sigFPE :: Signal
+illegalInstruction, sigILL     :: Signal
+internalAbort, sigABRT         :: Signal
+keyboardSignal, sigINT         :: Signal
+keyboardStop, sigTSTP          :: Signal
+keyboardTermination, sigQUIT   :: Signal
+killProcess, sigKILL           :: Signal
+lostConnection, sigHUP         :: Signal
+openEndedPipe, sigPIPE         :: Signal
+processStatusChanged, sigCHLD  :: Signal
+realTimeAlarm, sigALRM         :: Signal
+segmentationViolation, sigSEGV :: Signal
+softwareStop, sigSTOP          :: Signal
+softwareTermination, sigTERM   :: Signal
+userDefinedSignal1, sigUSR1    :: Signal
+userDefinedSignal2, sigUSR2    :: Signal
+
+signalProcess :: Signal -> ProcessID -> IO ()
+\end{verbatim}
+
+\tr{signalProcess int pid} calls \tr{kill} to signal 
+process \tr{pid} with interrupt signal \tr{int}.
+
+\begin{verbatim}
+raiseSignal :: Signal -> IO ()
+\end{verbatim}
+
+\tr{raiseSignal int} calls \tr{kill} to signal the current process
+with interrupt signal \tr{int}. 
+
+\begin{verbatim}
+signalProcessGroup :: Signal -> ProcessGroupID -> IO ()
+\end{verbatim}
+
+\tr{signalProcessGroup int pgid} calls \tr{kill} to signal 
+all processes in group \tr{pgid} with interrupt signal \tr{int}.
+
+\begin{verbatim}
+setStoppedChildFlag :: Bool -> IO Bool
+\end{verbatim}
+
+\tr{setStoppedChildFlag bool} sets a flag which controls whether or
+not the \tr{NOCLDSTOP} option will be used the next time a signal
+handler is installed for \tr{SIGCHLD}.  If \tr{bool} is \tr{True} (the
+default), \tr{NOCLDSTOP} will not be used; otherwise it will be.  The
+operation never fails.
+
+\begin{verbatim}
+queryStoppedChildFlag :: IO Bool
+\end{verbatim}
+
+\tr{queryStoppedChildFlag} queries the flag which
+controls whether or not the \tr{NOCLDSTOP} option will be used
+the next time a signal handler is installed for \tr{SIGCHLD}.
+If \tr{NOCLDSTOP} will be used, it returns \tr{False}; 
+otherwise (the default) it returns \tr{True}.  
+The operation never fails.
+
+\begin{verbatim}
+emptySignalSet :: SignalSet
+fullSignalSet  :: SignalSet
+addSignal      :: Signal -> SignalSet -> SignalSet
+deleteSignal   :: Signal -> SignalSet -> SignalSet
+inSignalSet    :: Signal -> SignalSet -> Bool
+
+installHandler :: Signal
+               -> Handler 
+               -> Maybe SignalSet       -- other signals to block
+               -> IO Handler            -- old handler
+\end{verbatim}
+
+\tr{installHandler int handler iset} calls \tr{sigaction} to install
+an interrupt handler for signal \tr{int}.  If \tr{handler} is
+\tr{Default}, \tr{SIG_DFL} is installed; if \tr{handler} is
+\tr{Ignore}, \tr{SIG_IGN} is installed; if \tr{handler} is \tr{Catch
+action}, a handler is installed which will invoke \tr{action} as a
+replacement for \tr{main}.  If \tr{iset} is \tr{Just s}, then the
+\tr{sa_mask} of the \tr{sigaction} structure is set to \tr{s};
+otherwise it is cleared.  The previously installed signal handler for
+\tr{int} is returned.
+
+\begin{verbatim}
+getSignalMask :: IO SignalSet
+\end{verbatim}
+
+\tr{getSignalMask} calls \tr{sigprocmask} to determine the
+set of interrupts which are currently being blocked.
+
+\begin{verbatim}
+setSignalMask :: SignalSet -> IO SignalSet
+\end{verbatim}
+
+\tr{setSignalMask mask} calls \tr{sigprocmask} with
+\tr{SIG_SETMASK} to block all interrupts in \tr{mask}.  The
+previous set of blocked interrupts is returned.
+
+\begin{verbatim}
+blockSignals :: SignalSet -> IO SignalSet
+\end{verbatim}
+
+\tr{setSignalMask mask} calls \tr{sigprocmask} with
+\tr{SIG_BLOCK} to add all interrupts in \tr{mask} to the
+set of blocked interrupts.  The previous set of blocked interrupts is returned.
+
+\begin{verbatim}
+unBlockSignals :: SignalSet -> IO SignalSet
+\end{verbatim}
+
+\tr{setSignalMask mask} calls \tr{sigprocmask} with
+\tr{SIG_UNBLOCK} to remove all interrupts in \tr{mask} from the
+set of blocked interrupts.  The previous set of blocked interrupts is returned.
+
+\begin{verbatim}
+getPendingSignals :: IO SignalSet
+\end{verbatim}
+
+\tr{getPendingSignals} calls \tr{sigpending} to obtain
+the set of interrupts which have been received but are currently blocked.
+
+\begin{verbatim}
+awaitSignal :: Maybe SignalSet -> IO ()
+\end{verbatim}
+
+\tr{awaitSignal iset} suspends execution until an interrupt is received.
+If \tr{iset} is \tr{Just s}, \tr{awaitSignal} calls 
+\tr{sigsuspend}, installing \tr{s} as the new signal mask before
+suspending execution; otherwise, it calls \tr{pause}.  If successful,
+\tr{awaitSignal} does not return.
+
+\begin{verbatim}
+scheduleAlarm :: Int -> IO Int
+\end{verbatim}
+
+\tr{scheduleAlarm i} calls \tr{alarm} to schedule a real time
+alarm at least \tr{i} seconds in the future.
+
+\begin{verbatim}
+sleep :: Int -> IO ()
+\end{verbatim}
+
+\tr{sleep i} calls \tr{sleep} to suspend execution of the
+program until at least \tr{i} seconds have elapsed or a signal is
+received.
+
+\subsubsection[posix-proc-env]{Posix Process Environment}
+\index{Posix, process environment}
+
+\begin{verbatim}
+getProcessID :: IO ProcessID
+\end{verbatim}
+
+\tr{getProcessID} calls \tr{getpid} to obtain the \tr{ProcessID} for
+the current process.
+
+\begin{verbatim}
+getParentProcessID :: IO ProcessID
+\end{verbatim}
+
+\tr{getProcessID} calls \tr{getppid} to obtain the \tr{ProcessID} for
+the parent of the current process.
+
+\begin{verbatim}
+getRealUserID :: IO UserID
+\end{verbatim}
+
+\tr{getRealUserID} calls \tr{getuid} to obtain the real \tr{UserID}
+associated with the current process.
+
+\begin{verbatim}
+getEffectiveUserID :: IO UserID
+\end{verbatim}
+
+\tr{getRealUserID} calls \tr{geteuid} to obtain the effective
+\tr{UserID} associated with the current process.
+
+\begin{verbatim}
+setUserID :: UserID -> IO ()
+\end{verbatim}
+
+\tr{setUserID uid} calls \tr{setuid} to set the real, effective, and
+saved set-user-id associated with the current process to \tr{uid}.
+
+\begin{verbatim}
+getLoginName :: IO String
+\end{verbatim}
+
+\tr{getLoginName} calls \tr{getlogin} to obtain the login name
+associated with the current process.
+
+\begin{verbatim}
+getRealGroupID :: IO GroupID
+\end{verbatim}
+
+\tr{getRealGroupID} calls \tr{getgid} to obtain the real \tr{GroupID}
+associated with the current process.
+
+\begin{verbatim}
+getEffectiveGroupID :: IO GroupID
+\end{verbatim}
+
+\tr{getEffectiveGroupID} calls \tr{getegid} to obtain the effective
+\tr{GroupID} associated with the current process.
+
+\begin{verbatim}
+setGroupID :: GroupID -> IO ()
+\end{verbatim}
+
+\tr{setGroupID gid} calls \tr{setgid} to set the real, effective, and
+saved set-group-id associated with the current process to \tr{gid}.
+
+\begin{verbatim}
+getGroups :: IO [GroupID]
+\end{verbatim}
+
+\tr{getGroups} calls \tr{getgroups} to obtain the list of
+supplementary \tr{GroupID}s associated with the current process.
+
+\begin{verbatim}
+getEffectiveUserName :: IO String
+\end{verbatim}
+
+\tr{getEffectiveUserName} calls \tr{cuserid} to obtain a name
+associated with the effective \tr{UserID} of the process.
+
+\begin{verbatim}
+getProcessGroupID :: IO ProcessGroupID
+\end{verbatim}
+
+\tr{getProcessGroupID} calls \tr{getpgrp} to obtain the
+\tr{ProcessGroupID} for the current process.
+
+\begin{verbatim}
+createProcessGroup :: ProcessID -> IO ProcessGroupID
+\end{verbatim}
+
+\tr{createProcessGroup pid} calls \tr{setpgid} to make
+process \tr{pid} a new process group leader.
+
+\begin{verbatim}
+joinProcessGroup :: ProcessGroupID -> IO ProcessGroupID
+\end{verbatim}
+
+\tr{joinProcessGroup pgid} calls \tr{setpgid} to set the
+\tr{ProcessGroupID} of the current process to \tr{pgid}.
+
+\begin{verbatim}
+setProcessGroupID :: ProcessID -> ProcessGroupID -> IO ()
+\end{verbatim}
+
+\tr{setProcessGroupID pid pgid} calls \tr{setpgid} to set the
+\tr{ProcessGroupID} for process \tr{pid} to \tr{pgid}.
+
+\begin{verbatim}
+createSession :: IO ProcessGroupID
+\end{verbatim}
+
+\tr{createSession} calls \tr{setsid} to create a new session
+with the current process as session leader.
+
+\begin{verbatim}
+systemName :: SystemID -> String
+nodeName :: SystemID -> String
+release :: SystemID -> String
+version :: SystemID -> String
+machine :: SystemID -> String
+
+getSystemID :: IO SystemID
+\end{verbatim}
+
+\tr{getSystemID} calls \tr{uname} to obtain information
+about the current operating system.
+
+\begin{verbatim}
+> epochTime :: IO EpochTime
+\end{verbatim}
+
+\tr{epochTime} calls \tr{time} to obtain the number of 
+seconds that have elapsed since the epoch (Jan 01 00:00:00 GMT 1970).
+
+\begin{verbatim}
+elapsedTime     :: ProcessTimes -> ClockTick
+userTime        :: ProcessTimes -> ClockTick
+systemTime      :: ProcessTimes -> ClockTick
+childUserTime   :: ProcessTimes -> ClockTick
+childSystemTime :: ProcessTimes -> ClockTick
+
+getProcessTimes :: IO ProcessTimes
+\end{verbatim}
+
+\tr{getProcessTimes} calls \tr{times} to obtain time-accounting
+information for the current process and its children.
+
+\begin{verbatim}
+getControllingTerminalName :: IO FilePath
+\end{verbatim}
+
+\tr{getControllingTerminalName} calls \tr{ctermid} to obtain
+a name associated with the controlling terminal for the process.  If a
+controlling terminal exists,
+\tr{getControllingTerminalName} returns the name of the
+controlling terminal.
+
+The operation may fail with:
+
+\begin{itemize}
+\item[\tr{NoSuchThing}]
+There is no controlling terminal, or its name cannot be determined.
+\item[\tr{SystemError}]
+Various other causes.
+\end{itemize}
+
+\begin{verbatim}
+getTerminalName :: Channel -> IO FilePath
+\end{verbatim}
+
+\tr{getTerminalName fd} calls \tr{ttyname} to obtain a name associated
+with the terminal for \tr{Channel} \tr{fd}. If \tr{fd} is associated
+with a terminal, \tr{getTerminalName} returns the name of the
+terminal.
+
+The operation may fail with:
+
+\begin{itemize}
+\item[\tr{InappropriateType}]
+The channel is not associated with a terminal.
+\item[\tr{NoSuchThing}]
+The channel is associated with a terminal, but it has no name.
+\item[\tr{SystemError}]
+Various other causes.
+\end{itemize}
+
+\begin{verbatim}
+queryTerminal :: Channel -> IO Bool
+\end{verbatim}
+
+\tr{queryTerminal fd} calls \tr{isatty} to determine whether or
+not \tr{Channel} \tr{fd} is associated with a terminal.
+
+\begin{verbatim}
+getSysVar :: SysVar -> IO Limit
+\end{verbatim}
+
+\tr{getSysVar var} calls \tr{sysconf} to obtain the
+dynamic value of the requested configurable system limit or option.
+For defined system limits, \tr{getSysVar} returns the associated
+value.  For defined system options, the result of \tr{getSysVar}
+is undefined, but not failure.
+
+The operation may fail with:
+
+\begin{itemize}
+\item[\tr{NoSuchThing}]
+The requested system limit or option is undefined.
+\end{itemize}
+
+\subsubsection[posix-files-dir]{Files and Directories}
+\index{Posix, files and directories}
+
+\begin{verbatim}
+openDirStream :: FilePath -> IO DirStream
+\end{verbatim}
+
+\tr{openDirStream dir} calls \tr{opendir} to obtain a
+directory stream for \tr{dir}.
+
+\begin{verbatim}
+readDirStream :: DirStream -> IO String
+\end{verbatim}
+
+\tr{readDirStream dp} calls \tr{readdir} to obtain the
+next directory entry (\tr{struct dirent}) for the open directory
+stream \tr{dp}, and returns the \tr{d_name} member of that
+structure.
+
+The operation may fail with:
+
+\begin{itemize}
+\item[\tr{EOF}]
+End of file has been reached.
+\item[\tr{SystemError}]
+Various other causes.
+\end{itemize}
+
+\begin{verbatim}
+rewindDirStream :: DirStream -> IO ()
+\end{verbatim}
+
+\tr{rewindDirStream dp} calls \tr{rewinddir} to reposition
+the directory stream \tr{dp} at the beginning of the directory.
+
+\begin{verbatim}
+closeDirStream :: DirStream -> IO ()
+\end{verbatim}
+
+\tr{closeDirStream dp} calls \tr{closedir} to close
+the directory stream \tr{dp}.
+
+\begin{verbatim}
+getWorkingDirectory :: IO FilePath
+\end{verbatim}
+
+\tr{getWorkingDirectory} calls \tr{getcwd} to obtain the name
+of the current working directory.
+
+\begin{verbatim}
+changeWorkingDirectory :: FilePath -> IO ()
+\end{verbatim}
+
+\tr{changeWorkingDirectory dir} calls \tr{chdir} to change
+the current working directory to \tr{dir}.
+
+\begin{verbatim}
+nullFileMode       :: FileMode       -- ---------
+ownerReadMode      :: FileMode       -- r--------
+ownerWriteMode     :: FileMode       -- -w-------
+ownerExecuteMode   :: FileMode       -- --x------
+groupReadMode      :: FileMode       -- ---r-----
+groupWriteMode     :: FileMode       -- ----w----
+groupExecuteMode   :: FileMode       -- -----x---
+otherReadMode      :: FileMode       -- ------r--
+otherWriteMode     :: FileMode       -- -------w-
+otherExecuteMode   :: FileMode       -- --------x
+setUserIDMode      :: FileMode       -- --S------
+setGroupIDMode     :: FileMode       -- -----S---
+                              
+stdFileMode        :: FileMode       -- rw-rw-rw-
+                              
+ownerModes         :: FileMode       -- rwx------
+groupModes         :: FileMode       -- ---rwx---
+otherModes         :: FileMode       -- ------rwx
+accessModes        :: FileMode       -- rwxrwxrwx
+
+unionFileModes     :: FileMode -> FileMode -> FileMode
+intersectFileModes :: FileMode -> FileMode -> FileMode
+
+stdInput  :: Channel
+stdInput  = 0
+
+stdOutput :: Channel
+stdOutput = 1
+
+stdError  :: Channel
+stdError  = 2
+
+openChannel :: FilePath
+            -> OpenMode
+            -> Maybe FileMode  -- Just x => O_CREAT, Nothing => must exist
+            -> Bool            -- O_APPEND
+            -> Bool            -- O_EXCL
+            -> Bool            -- O_NOCTTY
+            -> Bool            -- O_NONBLOCK
+            -> Bool            -- O_TRUNC
+            -> IO Channel
+\end{verbatim}
+
+\tr{openChannel path acc mode app excl noctty nonblock trunc} calls
+\tr{open} to obtain a \tr{Channel} for the file \tr{path} with access
+mode \tr{acc}.  If \tr{mode} is \tr{Just m}, the \tr{O_CREAT} flag is
+set and the file's permissions will be based on \tr{m} if it does not
+already exist; otherwise, the \tr{O_CREAT} flag is not set.  The
+arguments \tr{app}, \tr{excl}, \tr{noctty}, \tr{nonblock}, and
+\tr{trunc} control whether or not the flags \tr{O_APPEND},
+\tr{O_EXCL}, \tr{O_NOCTTY}, \tr{O_NONBLOCK}, and \tr{O_TRUNC} are set,
+respectively.
+
+\begin{verbatim}
+createFile :: FilePath -> FileMode -> IO Channel
+\end{verbatim}
+
+\tr{createFile path mode} calls \tr{creat} to obtain a \tr{Channel}
+for file \tr{path}, which will be created with permissions based on
+\tr{mode} if it does not already exist.
+
+\begin{verbatim}
+setFileCreationMask :: FileMode -> IO FileMode
+\end{verbatim}
+
+\tr{setFileCreationMask mode} calls \tr{umask} to set
+the process's file creation mask to \tr{mode}.  The previous file
+creation mask is returned.
+
+\begin{verbatim}
+createLink :: FilePath -> FilePath -> IO ()
+\end{verbatim}
+
+\tr{createLink old new} calls \tr{link} to create a 
+new path, \tr{new}, linked to an existing file, \tr{old}.
+\begin{verbatim}
+createDirectory :: FilePath -> FileMode -> IO ()
+\end{verbatim}
+
+\tr{createDirectory dir mode} calls \tr{mkdir} to 
+create a new directory, \tr{dir}, with permissions based on
+\tr{mode}.
+
+\begin{verbatim}
+createNamedPipe :: FilePath -> FileMode -> IO ()
+\end{verbatim}
+
+\tr{createNamedPipe fifo mode} calls \tr{mkfifo} to 
+create a new named pipe, \tr{fifo}, with permissions based on
+\tr{mode}.
+
+\begin{verbatim}
+removeLink :: FilePath -> IO ()
+\end{verbatim}
+
+\tr{removeLink path} calls \tr{unlink} to remove the link
+named \tr{path}.
+
+\begin{verbatim}
+removeDirectory :: FilePath -> IO ()
+\end{verbatim}
+
+\tr{removeDirectory dir} calls \tr{rmdir} to remove the 
+directory named \tr{dir}.
+
+\begin{verbatim}
+rename :: FilePath -> FilePath -> IO ()
+\end{verbatim}
+
+\tr{rename old new} calls \tr{rename} to rename a 
+file or directory from \tr{old} to \tr{new}.
+
+\begin{verbatim}
+fileMode          :: FileStatus -> FileMode
+                  
+fileID            :: FileStatus -> FileID
+deviceID          :: FileStatus -> DeviceID
+                  
+linkCount         :: FileStatus -> LinkCount
+                  
+fileOwner         :: FileStatus -> UserID
+fileGroup         :: FileStatus -> GroupID
+fileSize          :: FileStatus -> FileOffset
+
+accessTime        :: FileStatus -> EpochTime
+modificationTime  :: FileStatus -> EpochTime
+statusChangeTime  :: FileStatus -> EpochTime
+
+isDirectory       :: FileStatus -> Bool
+isCharacterDevice :: FileStatus -> Bool
+isBlockDevice     :: FileStatus -> Bool
+isRegularFile     :: FileStatus -> Bool
+isNamedPipe       :: FileStatus -> Bool
+
+getFileStatus     :: FilePath -> IO FileStatus
+\end{verbatim}
+
+\tr{getFileStatus path} calls \tr{stat} to get the
+\tr{FileStatus} information for the file \tr{path}.
+
+\begin{verbatim}
+getChannelStatus :: Channel -> IO FileStatus
+\end{verbatim}
+
+\tr{getChannelStatus fd} calls \tr{fstat} to get the
+\tr{FileStatus} information for the file associated with
+\tr{Channel} \tr{fd}.
+
+\begin{verbatim}
+queryAccess :: FilePath -> Bool -> Bool -> Bool -> IO Bool
+\end{verbatim}
+
+\tr{queryAccess path r w x} calls \tr{access} to test the access
+permissions for file \tr{path}.  The three arguments, \tr{r}, \tr{w},
+and \tr{x} control whether or not \tr{access} is called with
+\tr{R_OK}, \tr{W_OK}, and \tr{X_OK} respectively.
+
+\begin{verbatim}
+queryFile :: FilePath -> IO Bool
+\end{verbatim}
+
+\tr{queryFile path} calls \tr{access} with \tr{F_OK} to test for the
+existence for file \tr{path}.
+
+\begin{verbatim}
+setFileMode :: FilePath -> FileMode -> IO ()
+\end{verbatim}
+
+\tr{setFileMode path mode} calls \tr{chmod} to set the
+permission bits associated with file \tr{path} to \tr{mode}.
+
+\begin{verbatim}
+setOwnerAndGroup :: FilePath -> UserID -> GroupID -> IO ()
+\end{verbatim}
+
+\tr{setOwnerAndGroup path uid gid} calls \tr{chown} to
+set the \tr{UserID} and \tr{GroupID} associated with file
+\tr{path} to \tr{uid} and \tr{gid}, respectively.
+
+\begin{verbatim}
+setFileTimes :: FilePath -> EpochTime -> EpochTime -> IO ()
+\end{verbatim}
+
+\tr{setFileTimes path atime mtime} calls \tr{utime} to
+set the access and modification times associated with file
+\tr{path} to \tr{atime} and \tr{mtime}, respectively.
+
+\begin{verbatim}
+touchFile :: FilePath -> IO ()
+\end{verbatim}
+
+\tr{touchFile path} calls \tr{utime} to
+set the access and modification times associated with file
+\tr{path} to the current time.
+
+\begin{verbatim}
+getPathVar :: PathVar -> FilePath -> IO Limit
+\end{verbatim}
+
+\tr{getPathVar var path} calls \tr{pathconf} to obtain the
+dynamic value of the requested configurable file limit or option associated
+with file or directory \tr{path}.  For
+defined file limits, \tr{getPathVar} returns the associated
+value.  For defined file options, the result of \tr{getPathVar}
+is undefined, but not failure.
+The operation may fail with:
+\begin{itemize}
+\item[\tr{NoSuchThing}]
+The requested file limit or option is undefined.
+\item[\tr{SystemError}]
+Various other causes.
+\end{itemize}
+
+
+\begin{verbatim}
+getChannelVar :: PathVar -> Channel -> IO Limit
+\end{verbatim}
+
+\tr{getChannelVar var fd} calls \tr{fpathconf} to obtain the
+dynamic value of the requested configurable file limit or option associated
+with the file or directory attached to the open channel \tr{fd}.
+For defined file limits, \tr{getChannelVar} returns the associated
+value.  For defined file options, the result of \tr{getChannelVar}
+is undefined, but not failure.
+
+The operation may fail with:
+
+\begin{itemize}
+\item[\tr{NoSuchThing}]
+The requested file limit or option is undefined.
+\item[\tr{SystemError}]
+Various other causes.
+\end{itemize}
+
+\subsubsection[posix-input-output]{Posix Input and Output Primitives}
+\index{Posix, input/output}
+
+\begin{verbatim}
+createPipe :: IO (Channel, Channel)
+\end{verbatim}
+
+\tr{createPipe} calls \tr{pipe} to create a pipe and returns a pair of
+\tr{Channels}, the first for writing and the second for reading.
+
+\begin{verbatim}
+dupChannel :: Channel -> IO Channel
+\end{verbatim}
+
+\tr{dupChannel fd} calls \tr{dup} to duplicate \tr{Channel} \tr{fd} to
+another \tr{Channel}.
+
+\begin{verbatim}
+dupChannelTo :: Channel -> Channel -> IO ()
+\end{verbatim}
+
+\tr{dupChannelTo src dst} calls \tr{dup2} to duplicate \tr{Channel}
+\tr{src} to \tr{Channel} \tr{dst}.
+
+\begin{verbatim}
+closeChannel :: Channel -> IO ()
+\end{verbatim}
+
+\tr{closeChannel fd} calls \tr{close} to close \tr{Channel} \tr{fd}.
+
+\begin{verbatim}
+readChannel :: Channel -> ByteCount -> IO (String, ByteCount)
+\end{verbatim}
+
+\tr{readChannel fd nbytes} calls \tr{read} to read at most \tr{nbytes}
+bytes from \tr{Channel} \tr{fd}, and returns the result as a string
+paired with the number of bytes actually read.
+
+The operation may fail with:
+
+\begin{itemize}
+\item[\tr{EOF}]
+End of file has been reached.
+\item[\tr{SystemError}]
+Various other causes.
+\end{itemize}
+
+\begin{verbatim}
+writeChannel :: Channel -> String -> IO ByteCount
+\end{verbatim}
+
+\tr{writeChannel fd s} calls \tr{write} to write
+the string \tr{s} to \tr{Channel} \tr{fd} as a
+contiguous sequence of bytes.  It returns the number of bytes successfully
+written.
+
+\begin{verbatim}
+queryChannelOption :: ChannelOption -> Channel -> IO Bool
+\end{verbatim}
+
+\tr{getChannelOption opt fd} calls \tr{fcntl} to determine whether or
+not the flag associated with \tr{ChannelOption} \tr{opt} is set for
+\tr{Channel} \tr{fd}.
+
+\begin{verbatim}
+setChannelOption :: ChannelOption -> Bool -> Channel -> IO ()
+\end{verbatim}
+
+\tr{setChannelOption opt val fd} calls \tr{fcntl} to set the flag
+associated with \tr{ChannelOption} \tr{opt} on \tr{Channel} \tr{fd} to
+\tr{val}.
+
+\begin{verbatim}
+getLock :: Channel -> FileLock -> IO (Maybe (ProcessID, FileLock))
+\end{verbatim}
+
+\tr{getLock fd lock} calls \tr{fcntl} to get the first \tr{FileLock}
+for \tr{Channel} \tr{fd} which blocks the \tr{FileLock} \tr{lock}.  If
+no such \tr{FileLock} exists, \tr{getLock} returns \tr{Nothing}.
+Otherwise, it returns \tr{Just (pid, block)}, where \tr{block} is the
+blocking \tr{FileLock} and \tr{pid} is the \tr{ProcessID} of the
+process holding the blocking \tr{FileLock}.
+
+
+\begin{verbatim}
+setLock :: Channel -> FileLock -> IO ()
+\end{verbatim}
+
+\tr{setLock fd lock} calls \tr{fcntl} with \tr{F_SETLK} to set or
+clear a lock segment for \tr{Channel} \tr{fd} as indicated by the
+\tr{FileLock} \tr{lock}.  \tr{setLock} does not block, but fails with
+\tr{SystemError} if the request cannot be satisfied immediately.
+
+\begin{verbatim}
+waitToSetLock :: Channel -> FileLock -> IO ()
+\end{verbatim}
+
+\tr{waitToSetLock fd lock} calls \tr{fcntl} with \tr{F_SETLKW} to set
+or clear a lock segment for \tr{Channel} \tr{fd} as indicated by the
+\tr{FileLock} \tr{lock}. If the request cannot be satisfied
+immediately, \tr{waitToSetLock} blocks until the request can be
+satisfied.
+
+
+\begin{verbatim}
+seekChannel :: Channel -> SeekMode -> FileOffset -> IO FileOffset
+\end{verbatim}
+
+\tr{seekChannel fd whence offset} calls \tr{lseek} to position the
+\tr{Channel} at the given \tr{offset} from the starting location
+indicated by \tr{whence}.  It returns the resulting offset from the
+start of the file in bytes.
+
+\subsubsection[posix-device-class]{Posix, Device- and Class-Specific Functions}
+\index{Posix, device and class-specific functions}
+
+\begin{verbatim}
+terminalMode    :: TerminalMode -> TerminalAttributes -> Bool
+withMode        :: TerminalAttributes -> TerminalMode -> TerminalAttributes
+withoutMode     :: TerminalAttributes -> TerminalMode -> TerminalAttributes
+
+bitsPerByte     :: TerminalAttributes -> Int
+withBits        :: TerminalAttributes -> Int -> TerminalAttributes
+
+controlChar     :: TerminalAttributes -> ControlCharacter -> Maybe Char
+withCC          :: TerminalAttributes
+                -> (ControlCharacter, Char)
+                -> TerminalAttributes 
+withoutCC       :: TerminalAttributes 
+                -> ControlCharacter 
+                -> TerminalAttributes
+                 
+inputTime       :: TerminalAttributes -> Int
+withTime        :: TerminalAttributes -> Int -> TerminalAttributes
+                 
+minInput        :: TerminalAttributes -> Int
+withMinInput    :: TerminalAttributes -> Int -> TerminalAttributes
+                 
+inputSpeed      :: TerminalAttributes -> BaudRate
+withInputSpeed  :: TerminalAttributes -> BaudRate -> TerminalAttributes
+                 
+outputSpeed     :: TerminalAttributes -> BaudRate
+withOutputSpeed :: TerminalAttributes -> BaudRate -> TerminalAttributes
+
+getTerminalAttributes :: Channel -> IO TerminalAttributes
+\end{verbatim}
+
+\tr{getTerminalAttributes fd} calls \tr{tcgetattr} to obtain
+the \tr{TerminalAttributes} associated with \tr{Channel}
+\tr{fd}.
+
+\begin{verbatim}
+setTerminalAttributes :: Channel 
+                      -> TerminalAttributes 
+                      -> TerminalState
+                      -> IO ()
+\end{verbatim}
+
+\tr{setTerminalAttributes fd attr ts} calls \tr{tcsetattr} to change
+the \tr{TerminalAttributes} associated with \tr{Channel} \tr{fd} to
+\tr{attr}, when the terminal is in the state indicated by \tr{ts}.
+
+\begin{verbatim}
+sendBreak :: Channel -> Int -> IO ()
+\end{verbatim}
+
+\tr{sendBreak fd duration} calls \tr{tcsendbreak} to transmit a
+continuous stream of zero-valued bits on \tr{Channel} \tr{fd} for the
+specified implementation-dependent \tr{duration}.
+
+\begin{verbatim}
+drainOutput :: Channel -> IO ()
+\end{verbatim}
+
+\tr{drainOutput fd} calls \tr{tcdrain} to block until all output
+written to \tr{Channel} \tr{fd} has been transmitted.
+
+\begin{verbatim}
+discardData :: Channel -> QueueSelector -> IO ()
+\end{verbatim}
+
+\tr{discardData fd queues} calls \tr{tcflush} to discard
+pending input and/or output for \tr{Channel} \tr{fd},
+as indicated by the \tr{QueueSelector} \tr{queues}.
+
+\begin{verbatim}
+controlFlow :: Channel -> FlowAction -> IO ()
+\end{verbatim}
+
+\tr{controlFlow fd action} calls \tr{tcflow} to control the 
+flow of data on \tr{Channel} \tr{fd}, as indicated by
+\tr{action}.
+
+\begin{verbatim}
+getTerminalProcessGroupID :: Channel -> IO ProcessGroupID
+\end{verbatim}
+
+\tr{getTerminalProcessGroupID fd} calls \tr{tcgetpgrp} to
+obtain the \tr{ProcessGroupID} of the foreground process group 
+associated with the terminal attached to \tr{Channel} 
+\tr{fd}.
+
+\begin{verbatim}
+setTerminalProcessGroupID :: Channel -> ProcessGroupID -> IO ()
+\end{verbatim}
+
+\tr{setTerminalProcessGroupID fd pgid} calls \tr{tcsetpgrp} to
+set the \tr{ProcessGroupID} of the foreground process group 
+associated with the terminal attached to \tr{Channel} 
+\tr{fd} to \tr{pgid}.
+
+\subsubsection[posix-system-db]{Posix System Databases}
+\index{Posix, system databases}
+
+\begin{verbatim}
+groupName    :: GroupEntry -> String
+groupID      :: GroupEntry -> GroupID
+groupMembers :: GroupEntry -> [String]
+
+getGroupEntryForID :: GroupID -> IO GroupEntry
+\end{verbatim}
+
+\tr{getGroupEntryForID gid} calls \tr{getgrgid} to obtain
+the \tr{GroupEntry} information associated with \tr{GroupID}
+\tr{gid}.
+
+The operation may fail with:
+
+\begin{itemize}
+\item[\tr{NoSuchThing}]
+There is no group entry for the GroupID.
+\end{itemize}
+
+\begin{verbatim}
+getGroupEntryForName :: String -> IO GroupEntry
+\end{verbatim}
+
+\tr{getGroupEntryForName name} calls \tr{getgrnam} to obtain
+the \tr{GroupEntry} information associated with the group called
+\tr{name}.
+
+The operation may fail with:
+
+\begin{itemize}
+\item[\tr{NoSuchThing}]
+There is no group entry for the name.
+\end{itemize}
+
+\begin{verbatim}
+userName      :: UserEntry -> String
+userID        :: UserEntry -> UserID
+userGroupID   :: UserEntry -> GroupID
+homeDirectory :: UserEntry -> String
+userShell     :: UserEntry -> String
+
+getUserEntryForID :: UserID -> IO UserEntry
+\end{verbatim}
+
+\tr{getUserEntryForID gid} calls \tr{getpwuid} to obtain
+the \tr{UserEntry} information associated with \tr{UserID}
+\tr{uid}.
+The operation may fail with:
+
+\begin{itemize}
+\item[\tr{NoSuchThing}]
+There is no user entry for the UserID.
+\end{itemize}
+
+\begin{verbatim}
+getUserEntryForName :: String -> IO UserEntry
+\end{verbatim}
+
+\tr{getUserEntryForName name} calls \tr{getpwnam} to obtain
+the \tr{UserEntry} information associated with the user login
+\tr{name}.
+
+The operation may fail with:
+
+\begin{itemize}
+\item[\tr{NoSuchThing}]
+There is no user entry for the name.
+\end{itemize}
+
+\subsubsection[posix-errors]{POSIX Errors}
+\index{Posix, errors}
+
+\begin{verbatim}
+getErrorCode :: IO ErrorCode
+\end{verbatim}
+
+\tr{getErrorCode} returns the current value of the external
+variable \tr{errno}.  It never fails.
+
+\begin{verbatim}
+setErrorCode :: ErrorCode -> IO ()
+\end{verbatim}
+
+\tr{setErrorCode err} sets the external
+variable \tr{errno} to \tr{err}.  It never fails.
+
+\begin{verbatim}
+noError :: ErrorCode
+noError = 0
+
+argumentListTooLong, e2BIG              :: ErrorCode
+badChannel, eBADF                       :: ErrorCode
+brokenPipe, ePIPE                       :: ErrorCode
+directoryNotEmpty, eNOTEMPTY            :: ErrorCode
+execFormatError, eNOEXEC                :: ErrorCode
+fileAlreadyExists, eEXIST               :: ErrorCode
+fileTooLarge, eFBIG                     :: ErrorCode
+filenameTooLong, eNAMETOOLONG           :: ErrorCode
+improperLink, eXDEV                     :: ErrorCode
+inappropriateIOControlOperation, eNOTTY :: ErrorCode
+inputOutputError, eIO                   :: ErrorCode
+interruptedOperation, eINTR             :: ErrorCode
+invalidArgument, eINVAL                 :: ErrorCode
+invalidSeek, eSPIPE                     :: ErrorCode
+isADirectory, eISDIR                    :: ErrorCode
+noChildProcess, eCHILD                  :: ErrorCode
+noLocksAvailable, eNOLCK                :: ErrorCode
+noSpaceLeftOnDevice, eNOSPC             :: ErrorCode
+noSuchOperationOnDevice, eNODEV         :: ErrorCode
+noSuchDeviceOrAddress, eNXIO            :: ErrorCode
+noSuchFileOrDirectory, eNOENT           :: ErrorCode
+noSuchProcess, eSRCH                    :: ErrorCode
+notADirectory, eNOTDIR                  :: ErrorCode
+notEnoughMemory, eNOMEM                 :: ErrorCode
+operationNotImplemented, eNOSYS         :: ErrorCode
+operationNotPermitted, ePERM            :: ErrorCode
+permissionDenied, eACCES                :: ErrorCode
+readOnlyFileSystem, eROFS               :: ErrorCode
+resourceBusy, eBUSY                     :: ErrorCode
+resourceDeadlockAvoided, eDEADLK        :: ErrorCode
+resourceTemporarilyUnavailable, eAGAIN  :: ErrorCode
+tooManyLinks, eMLINK                    :: ErrorCode
+tooManyOpenFiles, eMFILE                :: ErrorCode
+tooManyOpenFilesInSystem, eNFILE        :: ErrorCode
+
+\end{verbatim}
+
+%************************************************************************
+%*                                                                      *
+\subsection[HBC-library]{The HBC system library}
+\index{HBC system library}
+\index{system library, HBC}
+%*                                                                      *
+%************************************************************************
+
+This documentation is stolen directly from the HBC distribution.  The
+modules that GHC does not support (because they require HBC-specific
+extensions) are omitted.
+
+\begin{description}
+\item[\tr{Either}:]
+\index{Either module (HBC library)}%
+A binary sum data type:
+\begin{verbatim}
+data Either a b = Left a | Right b
+\end{verbatim}
+The constructor \tr{Left} is typically used for errors; it can be
+renamed to \tr{Wrong} on import.
+
+\item[\tr{Maybe}:]
+\index{Maybe module (HBC library)}%
+A type for failure or success:
+\begin{verbatim}
+data Maybe a = Nothing | Just a
+thenM :: Maybe a -> (a -> Maybe b) -> Maybe b
+    -- apply a function that may fail
+\end{verbatim}
+
+\item[\tr{Option}:]
+\index{Option module (HBC library)}%
+An alias for \tr{Maybe}:
+\begin{verbatim}
+data Option a = None | Some a
+thenO :: Option a -> (a -> Option b) -> Option b
+\end{verbatim}
+
+\item[\tr{ListUtil}:]
+\index{ListUtil module (HBC library)}%
+Various useful functions involving lists that are missing from the
+\tr{Prelude}:
+\begin{verbatim}
+assoc :: (Eq c) => (a -> b) -> b -> [(c, a)] -> c -> b
+        -- assoc f d l k looks for k in the association list l, if it
+        -- is found f is applied to the value, otherwise d is returned.
+concatMap :: (a -> [b]) -> [a] -> [b]
+        -- flattening map (LML's concmap)
+unfoldr :: (a -> (b, a)) -> (a -> Bool) -> a -> [b]
+        -- unfoldr f p x repeatedly applies f to x until (p x) holds.
+        -- (f x) should give a list element and a new x.
+mapAccuml :: (a -> b -> (a, c)) -> a -> [b] -> (a, [c])
+        -- mapAccuml f s l maps f over l, but also threads the state s
+        -- through (LML's mapstate).
+union :: (Eq a) => [a] -> [a] -> [a]
+        -- union of two lists
+intersection :: (Eq a) => [a] -> [a] -> [a]
+        -- intersection of two lists
+chopList :: ([a] -> (b, [a])) -> [a] -> [b]
+        -- LMLs choplist
+assocDef :: (Eq a) => [(a, b)] -> b -> a -> b
+        -- LMLs assocdef
+lookup :: (Eq a) => [(a, b)] -> a -> Option b
+        -- lookup l k looks for the key k in the association list l
+        -- and returns an optional value
+tails :: [a] -> [[a]]
+        -- return all the tails of a list
+rept :: (Integral a) => a -> b -> [b]
+        -- repeat a value a number of times
+groupEq :: (a->a->Bool) -> [a] -> [[a]]
+        -- group list elements according to an equality predicate
+group :: (Eq a) => [a] -> [[a]]
+        -- group according to} ==
+readListLazily :: (Text a) => String -> [a]
+        -- read a list in a lazy fashion
+\end{verbatim}
+
+\item[\tr{Pretty}:]
+\index{Pretty module (HBC library)}%
+John Hughes's pretty printing library.  
+\begin{verbatim}
+type Context = (Bool, Int, Int, Int)
+type IText = Context -> [String]
+text :: String -> IText                 -- just text
+(~.) :: IText -> IText -> IText         -- horizontal composition
+(^.) :: IText -> IText -> IText         -- vertical composition
+separate :: [IText] -> IText            -- separate by spaces
+nest :: Int -> IText -> IText           -- indent
+pretty :: Int -> Int -> IText -> String -- format it
+\end{verbatim}
+
+\item[\tr{QSort}:]
+\index{QSort module (HBC library)}%
+A sort function using quicksort.
+\begin{verbatim}
+sortLe :: (a -> a -> Bool) -> [a] -> [a]
+        -- sort le l  sorts l with le as less than predicate
+sort :: (Ord a) => [a] -> [a]
+        -- sort l  sorts l using the Ord class
+\end{verbatim}
+
+\item[\tr{Random}:]
+\index{Random module (HBC library)}%
+Random numbers.
+\begin{verbatim}
+randomInts :: Int -> Int -> [Int]
+        -- given two seeds gives a list of random Int
+randomDoubles :: Int -> Int -> [Double]
+        -- random Double with uniform distribution in (0,1)
+normalRandomDoubles :: Int -> Int -> [Double]
+        -- random Double with normal distribution, mean 0, variance 1
+\end{verbatim}
+
+\item[\tr{Trace}:]
+Simple tracing.  (Note: This comes with GHC anyway.)
+\begin{verbatim}
+trace :: String -> a -> a       -- trace x y  prints x and returns y
+\end{verbatim}
+
+\item[\tr{Miranda}:]
+\index{Miranda module (HBC library)}%
+Functions found in the Miranda library.
+(Note: Miranda is a registered trade mark of Research Software Ltd.)
+
+\item[\tr{Word}:]
+\index{Word module (HBC library)}
+Bit manipulation.  (GHC doesn't implement absolutely all of this.
+And don't count on @Word@ being 32 bits on a Alpha...)
+\begin{verbatim}
+class Bits a where
+    bitAnd :: a -> a -> a       -- bitwise and
+    bitOr :: a -> a -> a        -- bitwise or
+    bitXor :: a -> a -> a       -- bitwise xor
+    bitCompl :: a -> a          -- bitwise negation
+    bitRsh :: a -> Int -> a     -- bitwise right shift
+    bitLsh :: a -> Int -> a     -- bitwise left shift
+    bitSwap :: a -> a           -- swap word halves
+    bit0 :: a                   -- word with least significant bit set
+    bitSize :: a -> Int         -- number of bits in a word
+
+data Byte                       -- 8  bit quantity
+data Short                      -- 16 bit quantity
+data Word                       -- 32 bit quantity
+
+instance Bits Byte, Bits Short, Bits Word
+instance Eq Byte, Eq Short, Eq Word
+instance Ord Byte, Ord Short, Ord Word
+instance Text Byte, Text Short, Text Word
+instance Num Byte, Num Short, Num Word
+wordToShorts :: Word -> [Short]   -- convert a Word to two Short
+wordToBytes :: Word -> [Byte]     -- convert a Word to four Byte
+bytesToString :: [Byte] -> String -- convert a list of Byte to a String (bit by bit)
+wordToInt :: Word -> Int          -- convert a Word to Int
+shortToInt :: Short -> Int        -- convert a Short to Int
+byteToInt :: Byte -> Int          -- convert a Byte to Int
+\end{verbatim}
+
+\item[\tr{Time}:]
+\index{Time module (HBC library)}%
+Manipulate time values (a Double with seconds since 1970).
+\begin{verbatim}
+--               year mon  day  hour min  sec  dec-sec  weekday
+data Time = Time Int  Int  Int  Int  Int  Int  Double  Int
+dblToTime :: Double -> Time     -- convert a Double to a Time
+timeToDbl :: Time -> Double     -- convert a Time to a Double
+timeToString :: Time -> String  -- convert a Time to a readable String
+\end{verbatim}
+
+\item[\tr{Hash}:]
+\index{Hash module (HBC library)}%
+Hashing functions.
+\begin{verbatim}
+class Hashable a where
+    hash :: a -> Int                            -- hash a value, return an Int
+-- instances for all Prelude types
+hashToMax :: (Hashable a) => Int -> a -> Int    -- hash into interval [0..x-1]
+\end{verbatim}
+
+\item[\tr{NameSupply}:]
+\index{NameSupply module (HBC library)}%
+Functions to generate unique names (Int).
+\begin{verbatim}
+type Name = Int
+initialNameSupply :: NameSupply
+        -- The initial name supply (may be different every
+        -- time the program is run.
+splitNameSupply :: NameSupply -> (NameSupply,NameSupply)
+        -- split the namesupply into two
+getName :: NameSupply -> Name
+        -- get the name associated with a name supply
+\end{verbatim}
+
+\item[\tr{Parse}:]
+\index{Parse module (HBC library)}%
+Higher order functions to build parsers.  With a little care these
+combinators can be used to build efficient parsers with good error
+messages.
+\begin{verbatim}
+infixr 8 +.+ , ..+ , +.. 
+infix  6 `act` , >>> , `into` , .> 
+infixr 4 ||| , ||! , |!! 
+data ParseResult a b 
+type Parser a b = a -> Int -> ParseResult a b 
+(|||) :: Parser a b -> Parser a b -> Parser a b
+        -- Alternative
+(||!) :: Parser a b -> Parser a b -> Parser a b
+        -- Alternative, but with committed choice
+(|!!) :: Parser a b -> Parser a b -> Parser a b
+        -- Alternative, but with committed choice
+(+.+) :: Parser a b -> Parser a c -> Parser a (b,c)
+        -- Sequence
+(..+) :: Parser a b -> Parser a c -> Parser a c
+        -- Sequence, throw away first part
+(+..) :: Parser a b -> Parser a c -> Parser a b
+        -- Sequence, throw away second part
+act   :: Parser a b -> (b->c) -> Parser a c
+        -- Action
+(>>>) :: Parser a (b,c) -> (b->c->d) -> Parser a d
+        -- Action on two items
+(.>) :: Parser a b -> c -> Parse a c
+        -- Action ignoring value
+into :: Parser a b -> (b -> Parser a c) -> Parser a c
+        -- Use a produced value in a parser.
+succeed b :: Parser a b
+        -- Always succeeds without consuming a token
+failP :: Parser a b
+        -- Always fails.
+many :: Parser a b -> Parser a [b]
+        -- Kleene star
+many1 :: Parser a b -> Parser a [b]
+        -- Kleene plus
+count :: Parser a b -> Int -> Parser a [b]
+        -- Parse an exact number of items
+sepBy1 :: Parser a b -> Parser a c -> Parser a [b]
+        -- Non-empty sequence of items separated by something
+sepBy :: Parser a b -> Parser a c -> Parser a [b]
+        -- Sequence of items separated by something
+lit :: (Eq a, Text a) => a -> Parser [a] a
+        -- Recognise a literal token from a list of tokens
+litp :: String -> (a->Bool) -> Parser [a] a
+        -- Recognise a token with a predicate.
+        -- The string is a description for error messages.
+testp :: String -> (a -> Bool) -> (Parser b a) -> Parser b a
+        -- Test a semantic value. 
+token :: (a -> Either String (b, a)) -> Parser a b
+        -- General token recogniser.
+parse :: Parser a b -> a -> Either ([String], a) [(b, a)]
+        -- Do a parse.  Return either error (possible tokens and rest
+        -- of tokens) or all possible parses.
+sParse :: (Text a) => (Parser [a] b) -> [a] -> Either String b
+        -- Simple parse.  Return error message or result.
+\end{verbatim}
+
+%%%simpleLex :: String -> [String]              -- A simple (but useful) lexical analyzer
+
+\item[\tr{Native}:]
+\index{Native module (HBC library)}%
+Functions to convert the primitive types \tr{Int}, \tr{Float}, and \tr{Double} to
+their native representation as a list of bytes (\tr{Char}).  If such a list
+is read/written to a file it will have the same format as when, e.g.,
+C read/writes the same kind of data.
+\begin{verbatim}
+type Bytes = [Char] -- A byte stream is just a list of characters
+
+class Native a where 
+    showBytes     :: a -> Bytes -> Bytes
+        -- prepend the representation of an item the a byte stream
+    listShowBytes :: [a] -> Bytes -> Bytes
+        -- prepend the representation of a list of items to a stream
+        -- (may be more efficient than repeating showBytes).
+    readBytes     :: Bytes -> Maybe (a, Bytes)
+        -- get an item from the stream and return the rest,
+        -- or fail if the stream is to short.
+    listReadBytes :: Int -> Bytes -> Maybe ([a], Bytes)
+        -- read n items from a stream.
+
+instance Native Int 
+instance Native Float 
+instance Native Double 
+instance (Native a, Native b) => Native (a,b)
+        -- juxtaposition of the two items
+instance (Native a, Native b, Native c) => Native (a, b, c)
+        -- juxtaposition of the three items
+instance (Native a) => Native [a]
+        -- an item count in an Int followed by the items
+
+shortIntToBytes :: Int -> Bytes -> Bytes
+        -- Convert an Int to what corresponds to a short in C.
+bytesToShortInt :: Bytes -> Maybe (Int, Bytes)
+        -- Get a short from a byte stream and convert to an Int.
+
+showB :: (Native a) => a -> Bytes       -- Simple interface to showBytes.
+readB :: (Native a) => Bytes -> a       -- Simple interface to readBytes.
+\end{verbatim}
+
+\item[\tr{Number}:]
+\index{Number module (HBC library)}%
+Simple numbers that belong to all numeric classes and behave like
+a naive user would expect (except that printing is still ugly).
+(NB: GHC does not provide a magic way to use \tr{Numbers} everywhere,
+but you should be able to do it with normal \tr{import}ing and
+\tr{default}ing.)
+\begin{verbatim}
+data Number                     -- The type itself.
+instance ...                    -- All reasonable instances.
+isInteger :: Number -> Bool     -- Test if a Number is an integer.
+\end{verbatim}
+\end{description}
index 8144e82..c3fc158 100644 (file)
@@ -24,6 +24,7 @@ Email: glasgow-haskell-\{bugs,users\}-request\@dcs.gla.ac.uk}
 \input{profiling.lit}
 \input{glasgow_exts.lit}
 \input{libraries.lit}
+\input{syslib.lit}
 \input{parallel.lit}
 \input{gone_wrong.lit}
 \input{backwards.lit}