[project @ 2001-08-27 11:45:23 by simonmar]
[ghc-hetmet.git] / ghc / docs / users_guide / glasgow_exts.sgml
index 824a007..5c80925 100644 (file)
@@ -96,6 +96,22 @@ Executive summary of our extensions:
     </varlistentry>
 
     <varlistentry>
+      <term>Data types with no constructors</term>
+      <listitem>
+       <para>See <xref LinkEnd="nullary-types">.</para>
+      </listitem>
+    </varlistentry>
+
+    <varlistentry>
+      <term>Parallel list comprehensions</term>
+      <listitem>
+       <para>An extension to the list comprehension syntax to support
+       <literal>zipWith</literal>-like functionality.  See <xref
+       linkend="parallel-list-comprehensions">.</para>
+      </listitem>
+    </varlistentry>
+
+    <varlistentry>
       <term>Foreign calling:</term>
       <listitem>
        <para>Just what it sounds like.  We provide
@@ -126,6 +142,9 @@ Executive summary of our extensions:
     <varlistentry>
       <term>Generic classes:</term>
       <listitem>
+       <para>(Note: support for generic classes is currently broken
+        in GHC 5.02).</para>
+
        <para>Generic class declarations allow you to define a class
         whose methods say how to work over an arbitrary data type.
         Then it's really easy to make any new type into an instance of
@@ -240,8 +259,8 @@ program), you may wish to check if there are libraries that provide a
             "<literal>Prelude.fromInteger 1</literal>", which is what
             the Haskell Report specifies.  So the
             <option>-fno-implicit-prelude</option> flag causes the
-            following pieces of built-in syntax to refer to whatever
-            is in scope, not the Prelude versions:</para>
+            following pieces of built-in syntax to refer to <emphasis>whatever
+            is in scope</emphasis>, not the Prelude versions:</para>
 
            <itemizedlist>
              <listitem>
@@ -260,1347 +279,277 @@ program), you may wish to check if there are libraries that provide a
 
              <listitem>
                <para>In an n+k pattern, the standard Prelude
-                <literal>Ord</literal> class is used for comparison,
+                <literal>Ord</literal> class is still used for comparison,
                 but the necessary subtraction uses whatever
                 "<literal>(-)</literal>" is in scope (not
                 "<literal>Prelude.(-)</literal>").</para>
              </listitem>
            </itemizedlist>
 
+            <para>Note: Negative literals, such as <literal>-3</literal>, are
+             specified by (a careful reading of) the Haskell Report as 
+             meaning <literal>Prelude.negate (Prelude.fromInteger 3)</literal>.
+             However, GHC deviates from this slightly, and treats them as meaning
+             <literal>fromInteger (-3)</literal>.  One particular effect of this
+             slightly-non-standard reading is that there is no difficulty with
+             the literal <literal>-2147483648</literal> at type <literal>Int</literal>;
+             it means <literal>fromInteger (-2147483648)</literal>.  The strict interpretation
+             would be <literal>negate (fromInteger 2147483648)</literal>,
+             and the call to <literal>fromInteger</literal> would overflow
+             (at type <literal>Int</literal>, remember).
+             </para>
+
          </listitem>
        </varlistentry>
 
     </variablelist>
   </sect1>
 
-<sect1 id="primitives">
-<title>Unboxed types and primitive operations
-</title>
-<indexterm><primary>PrelGHC module</primary></indexterm>
-
-<para>
-This module defines all the types which are primitive in Glasgow
-Haskell, and the operations provided for them.
-</para>
-
-<sect2 id="glasgow-unboxed">
-<title>Unboxed types
-</title>
-
-<para>
-<indexterm><primary>Unboxed types (Glasgow extension)</primary></indexterm>
-</para>
-
-<para>Most types in GHC are <firstterm>boxed</firstterm>, which means
-that values of that type are represented by a pointer to a heap
-object.  The representation of a Haskell <literal>Int</literal>, for
-example, is a two-word heap object.  An <firstterm>unboxed</firstterm>
-type, however, is represented by the value itself, no pointers or heap
-allocation are involved.
-</para>
-
-<para>
-Unboxed types correspond to the &ldquo;raw machine&rdquo; types you
-would use in C: <literal>Int&num;</literal> (long int),
-<literal>Double&num;</literal> (double), <literal>Addr&num;</literal>
-(void *), etc.  The <emphasis>primitive operations</emphasis>
-(PrimOps) on these types are what you might expect; e.g.,
-<literal>(+&num;)</literal> is addition on
-<literal>Int&num;</literal>s, and is the machine-addition that we all
-know and love&mdash;usually one instruction.
-</para>
+<!-- UNBOXED TYPES AND PRIMITIVE OPERATIONS -->
+&primitives;
 
-<para>
-Primitive (unboxed) types cannot be defined in Haskell, and are
-therefore built into the language and compiler.  Primitive types are
-always unlifted; that is, a value of a primitive type cannot be
-bottom.  We use the convention that primitive types, values, and
-operations have a <literal>&num;</literal> suffix.
-</para>
+<sect1 id="glasgow-ST-monad">
+<title>Primitive state-transformer monad</title>
 
 <para>
-Primitive values are often represented by a simple bit-pattern, such
-as <literal>Int&num;</literal>, <literal>Float&num;</literal>,
-<literal>Double&num;</literal>.  But this is not necessarily the case:
-a primitive value might be represented by a pointer to a
-heap-allocated object.  Examples include
-<literal>Array&num;</literal>, the type of primitive arrays.  A
-primitive array is heap-allocated because it is too big a value to fit
-in a register, and would be too expensive to copy around; in a sense,
-it is accidental that it is represented by a pointer.  If a pointer
-represents a primitive value, then it really does point to that value:
-no unevaluated thunks, no indirections&hellip;nothing can be at the
-other end of the pointer than the primitive value.
+<indexterm><primary>state transformers (Glasgow extensions)</primary></indexterm>
+<indexterm><primary>ST monad (Glasgow extension)</primary></indexterm>
 </para>
 
 <para>
-There are some restrictions on the use of primitive types, the main
-one being that you can't pass a primitive value to a polymorphic
-function or store one in a polymorphic data type.  This rules out
-things like <literal>[Int&num;]</literal> (i.e. lists of primitive
-integers).  The reason for this restriction is that polymorphic
-arguments and constructor fields are assumed to be pointers: if an
-unboxed integer is stored in one of these, the garbage collector would
-attempt to follow it, leading to unpredictable space leaks.  Or a
-<function>seq</function> operation on the polymorphic component may
-attempt to dereference the pointer, with disastrous results.  Even
-worse, the unboxed value might be larger than a pointer
-(<literal>Double&num;</literal> for instance).
+This monad underlies our implementation of arrays, mutable and
+immutable, and our implementation of I/O, including &ldquo;C calls&rdquo;.
 </para>
 
 <para>
-Nevertheless, A numerically-intensive program using unboxed types can
-go a <emphasis>lot</emphasis> faster than its &ldquo;standard&rdquo;
-counterpart&mdash;we saw a threefold speedup on one example.
+The <literal>ST</literal> library, which provides access to the
+<function>ST</function> monad, is described in <xref
+linkend="sec-ST">.
 </para>
 
-</sect2>
+</sect1>
 
-<sect2 id="unboxed-tuples">
-<title>Unboxed Tuples
+<sect1 id="glasgow-prim-arrays">
+<title>Primitive arrays, mutable and otherwise
 </title>
 
 <para>
-Unboxed tuples aren't really exported by <literal>PrelGHC</literal>,
-they're available by default with <option>-fglasgow-exts</option>.  An
-unboxed tuple looks like this:
-</para>
-
-<para>
-
-<programlisting>
-(# e_1, ..., e_n #)
-</programlisting>
-
-</para>
-
-<para>
-where <literal>e&lowbar;1..e&lowbar;n</literal> are expressions of any
-type (primitive or non-primitive).  The type of an unboxed tuple looks
-the same.
+<indexterm><primary>primitive arrays (Glasgow extension)</primary></indexterm>
+<indexterm><primary>arrays, primitive (Glasgow extension)</primary></indexterm>
 </para>
 
 <para>
-Unboxed tuples are used for functions that need to return multiple
-values, but they avoid the heap allocation normally associated with
-using fully-fledged tuples.  When an unboxed tuple is returned, the
-components are put directly into registers or on the stack; the
-unboxed tuple itself does not have a composite representation.  Many
-of the primitive operations listed in this section return unboxed
-tuples.
+GHC knows about quite a few flavours of Large Swathes of Bytes.
 </para>
 
 <para>
-There are some pretty stringent restrictions on the use of unboxed tuples:
+First, GHC distinguishes between primitive arrays of (boxed) Haskell
+objects (type <literal>Array&num; obj</literal>) and primitive arrays of bytes (type
+<literal>ByteArray&num;</literal>).
 </para>
 
 <para>
+Second, it distinguishes between&hellip;
+<variablelist>
 
-<itemizedlist>
+<varlistentry>
+<term>Immutable:</term>
 <listitem>
-
 <para>
- Unboxed tuple types are subject to the same restrictions as
-other unboxed types; i.e. they may not be stored in polymorphic data
-structures or passed to polymorphic functions.
-
+Arrays that do not change (as with &ldquo;standard&rdquo; Haskell arrays); you
+can only read from them.  Obviously, they do not need the care and
+attention of the state-transformer monad.
 </para>
 </listitem>
+</varlistentry>
+<varlistentry>
+<term>Mutable:</term>
 <listitem>
-
 <para>
- Unboxed tuples may only be constructed as the direct result of
-a function, and may only be deconstructed with a <literal>case</literal> expression.
-eg. the following are valid:
-
-
-<programlisting>
-f x y = (# x+1, y-1 #)
-g x = case f x x of { (# a, b #) -&#62; a + b }
-</programlisting>
-
-
-but the following are invalid:
-
-
-<programlisting>
-f x y = g (# x, y #)
-g (# x, y #) = x + y
-</programlisting>
-
-
+Arrays that may be changed or &ldquo;mutated.&rdquo;  All the operations on them
+live within the state-transformer monad and the updates happen
+<emphasis>in-place</emphasis>.
 </para>
 </listitem>
+</varlistentry>
+<varlistentry>
+<term>&ldquo;Static&rdquo; (in C land):</term>
 <listitem>
-
 <para>
- No variable can have an unboxed tuple type.  This is illegal:
-
-
-<programlisting>
-f :: (# Int, Int #) -&#62; (# Int, Int #)
-f x = x
-</programlisting>
-
-
-because <literal>x</literal> has an unboxed tuple type.
-
+A C routine may pass an <literal>Addr&num;</literal> pointer back into Haskell land.  There
+are then primitive operations with which you may merrily grab values
+over in C land, by indexing off the &ldquo;static&rdquo; pointer.
 </para>
 </listitem>
-
-</itemizedlist>
-
-</para>
-
+</varlistentry>
+<varlistentry>
+<term>&ldquo;Stable&rdquo; pointers:</term>
+<listitem>
 <para>
-Note: we may relax some of these restrictions in the future.
+If, for some reason, you wish to hand a Haskell pointer (i.e.,
+<emphasis>not</emphasis> an unboxed value) to a C routine, you first make the
+pointer &ldquo;stable,&rdquo; so that the garbage collector won't forget that it
+exists.  That is, GHC provides a safe way to pass Haskell pointers to
+C.
 </para>
 
 <para>
-The <literal>IO</literal> and <literal>ST</literal> monads use unboxed
-tuples to avoid unnecessary allocation during sequences of operations.
+Please see <xref LinkEnd="sec-stable-pointers"> for more details.
 </para>
-
-</sect2>
-
-<sect2>
-<title>Character and numeric types</title>
-
-<indexterm><primary>character types, primitive</primary></indexterm>
-<indexterm><primary>numeric types, primitive</primary></indexterm>
-<indexterm><primary>integer types, primitive</primary></indexterm>
-<indexterm><primary>floating point types, primitive</primary></indexterm>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>&ldquo;Foreign objects&rdquo;:</term>
+<listitem>
 <para>
-There are the following obvious primitive types:
+A &ldquo;foreign object&rdquo; is a safe way to pass an external object (a
+C-allocated pointer, say) to Haskell and have Haskell do the Right
+Thing when it no longer references the object.  So, for example, C
+could pass a large bitmap over to Haskell and say &ldquo;please free this
+memory when you're done with it.&rdquo;
 </para>
 
-<programlisting>
-type Char#
-type Int#
-type Word#
-type Addr#
-type Float#
-type Double#
-type Int64#
-type Word64#
-</programlisting>
-
-<indexterm><primary><literal>Char&num;</literal></primary></indexterm>
-<indexterm><primary><literal>Int&num;</literal></primary></indexterm>
-<indexterm><primary><literal>Word&num;</literal></primary></indexterm>
-<indexterm><primary><literal>Addr&num;</literal></primary></indexterm>
-<indexterm><primary><literal>Float&num;</literal></primary></indexterm>
-<indexterm><primary><literal>Double&num;</literal></primary></indexterm>
-<indexterm><primary><literal>Int64&num;</literal></primary></indexterm>
-<indexterm><primary><literal>Word64&num;</literal></primary></indexterm>
-
 <para>
-If you really want to know their exact equivalents in C, see
-<filename>ghc/includes/StgTypes.h</filename> in the GHC source tree.
+Please see <xref LinkEnd="sec-ForeignObj"> for more details.
 </para>
-
-<para>
-Literals for these types may be written as follows:
+</listitem>
+</varlistentry>
+</variablelist>
 </para>
 
 <para>
-
-<programlisting>
-1#              an Int#
-1.2#            a Float#
-1.34##          a Double#
-'a'#            a Char#; for weird characters, use e.g. '\o&#60;octal&#62;'#
-"a"#            an Addr# (a `char *'); only characters '\0'..'\255' allowed
-</programlisting>
-
-<indexterm><primary>literals, primitive</primary></indexterm>
-<indexterm><primary>constants, primitive</primary></indexterm>
-<indexterm><primary>numbers, primitive</primary></indexterm>
+The libraries documentatation gives more details on all these
+&ldquo;primitive array&rdquo; types and the operations on them.
 </para>
 
-</sect2>
-
-<sect2>
-<title>Comparison operations</title>
+</sect1>
 
-<para>
-<indexterm><primary>comparisons, primitive</primary></indexterm>
-<indexterm><primary>operators, comparison</primary></indexterm>
-</para>
 
-<para>
+<sect1 id="nullary-types">
+<title>Data types with no constructors</title>
 
+<para>With the <option>-fglasgow-exts</option> flag, GHC lets you declare
+a data type with no constructors.  For example:</para>
 <programlisting>
-{&#62;,&#62;=,==,/=,&#60;,&#60;=}# :: Int# -&#62; Int# -&#62; Bool
-
-{gt,ge,eq,ne,lt,le}Char# :: Char# -&#62; Char# -&#62; Bool
-    -- ditto for Word# and Addr#
+  data S      -- S :: *
+  data T a    -- T :: * -> *
 </programlisting>
+<para>Syntactically, the declaration lacks the "= constrs" part.  The 
+type can be parameterised, but only over ordinary types, of kind *; since
+Haskell does not have kind signatures, you cannot parameterise over higher-kinded
+types.</para>
 
-<indexterm><primary><literal>&#62;&num;</literal></primary></indexterm>
-<indexterm><primary><literal>&#62;=&num;</literal></primary></indexterm>
-<indexterm><primary><literal>==&num;</literal></primary></indexterm>
-<indexterm><primary><literal>/=&num;</literal></primary></indexterm>
-<indexterm><primary><literal>&#60;&num;</literal></primary></indexterm>
-<indexterm><primary><literal>&#60;=&num;</literal></primary></indexterm>
-<indexterm><primary><literal>gt&lcub;Char,Word,Addr&rcub;&num;</literal></primary></indexterm>
-<indexterm><primary><literal>ge&lcub;Char,Word,Addr&rcub;&num;</literal></primary></indexterm>
-<indexterm><primary><literal>eq&lcub;Char,Word,Addr&rcub;&num;</literal></primary></indexterm>
-<indexterm><primary><literal>ne&lcub;Char,Word,Addr&rcub;&num;</literal></primary></indexterm>
-<indexterm><primary><literal>lt&lcub;Char,Word,Addr&rcub;&num;</literal></primary></indexterm>
-<indexterm><primary><literal>le&lcub;Char,Word,Addr&rcub;&num;</literal></primary></indexterm>
-</para>
-
-</sect2>
+<para>Such data types have only one value, namely bottom.
+Nevertheless, they can be useful when defining "phantom types".</para>
+</sect1>
 
-<sect2>
-<title>Primitive-character operations</title>
+<sect1 id="pattern-guards">
+<title>Pattern guards</title>
 
 <para>
-<indexterm><primary>characters, primitive operations</primary></indexterm>
-<indexterm><primary>operators, primitive character</primary></indexterm>
+<indexterm><primary>Pattern guards (Glasgow extension)</primary></indexterm>
+The discussion that follows is an abbreviated version of Simon Peyton Jones's original <ULink URL="http://research.microsoft.com/~simonpj/Haskell/guards.html">proposal</ULink>. (Note that the proposal was written before pattern guards were implemented, so refers to them as unimplemented.)
 </para>
 
 <para>
+Suppose we have an abstract data type of finite maps, with a
+lookup operation:
 
 <programlisting>
-ord# :: Char# -&#62; Int#
-chr# :: Int# -&#62; Char#
+lookup :: FiniteMap -> Int -> Maybe Int
 </programlisting>
 
-<indexterm><primary><literal>ord&num;</literal></primary></indexterm>
-<indexterm><primary><literal>chr&num;</literal></primary></indexterm>
+The lookup returns <function>Nothing</function> if the supplied key is not in the domain of the mapping, and <function>(Just v)</function> otherwise,
+where <VarName>v</VarName> is the value that the key maps to.  Now consider the following definition:
 </para>
 
-</sect2>
-
-<sect2>
-<title>Primitive-<literal>Int</literal> operations</title>
+<programlisting>
+clunky env var1 var2 | ok1 && ok2 = val1 + val2
+| otherwise  = var1 + var2
+where
+  m1 = lookup env var1
+  m2 = lookup env var2
+  ok1 = maybeToBool m1
+  ok2 = maybeToBool m2
+  val1 = expectJust m1
+  val2 = expectJust m2
+</programlisting>
 
 <para>
-<indexterm><primary>integers, primitive operations</primary></indexterm>
-<indexterm><primary>operators, primitive integer</primary></indexterm>
+The auxiliary functions are 
 </para>
 
-<para>
-
 <programlisting>
-{+,-,*,quotInt,remInt,gcdInt}# :: Int# -&#62; Int# -&#62; Int#
-negateInt# :: Int# -&#62; Int#
-
-iShiftL#, iShiftRA#, iShiftRL# :: Int# -&#62; Int# -&#62; Int#
-        -- shift left, right arithmetic, right logical
+maybeToBool :: Maybe a -&gt; Bool
+maybeToBool (Just x) = True
+maybeToBool Nothing  = False
 
-addIntC#, subIntC#, mulIntC# :: Int# -> Int# -> (# Int#, Int# #)
-       -- add, subtract, multiply with carry
+expectJust :: Maybe a -&gt; a
+expectJust (Just x) = x
+expectJust Nothing  = error "Unexpected Nothing"
 </programlisting>
 
-<indexterm><primary><literal>+&num;</literal></primary></indexterm>
-<indexterm><primary><literal>-&num;</literal></primary></indexterm>
-<indexterm><primary><literal>*&num;</literal></primary></indexterm>
-<indexterm><primary><literal>quotInt&num;</literal></primary></indexterm>
-<indexterm><primary><literal>remInt&num;</literal></primary></indexterm>
-<indexterm><primary><literal>gcdInt&num;</literal></primary></indexterm>
-<indexterm><primary><literal>iShiftL&num;</literal></primary></indexterm>
-<indexterm><primary><literal>iShiftRA&num;</literal></primary></indexterm>
-<indexterm><primary><literal>iShiftRL&num;</literal></primary></indexterm>
-<indexterm><primary><literal>addIntC&num;</literal></primary></indexterm>
-<indexterm><primary><literal>subIntC&num;</literal></primary></indexterm>
-<indexterm><primary><literal>mulIntC&num;</literal></primary></indexterm>
-<indexterm><primary>shift operations, integer</primary></indexterm>
-</para>
-
 <para>
-<emphasis>Note:</emphasis> No error/overflow checking!
+What is <function>clunky</function> doing? The guard <literal>ok1 &&
+ok2</literal> checks that both lookups succeed, using
+<function>maybeToBool</function> to convert the <function>Maybe</function>
+types to booleans. The (lazily evaluated) <function>expectJust</function>
+calls extract the values from the results of the lookups, and binds the
+returned values to <VarName>val1</VarName> and <VarName>val2</VarName>
+respectively.  If either lookup fails, then clunky takes the
+<literal>otherwise</literal> case and returns the sum of its arguments.
 </para>
 
-</sect2>
-
-<sect2>
-<title>Primitive-<literal>Double</literal> and <literal>Float</literal> operations</title>
-
 <para>
-<indexterm><primary>floating point numbers, primitive</primary></indexterm>
-<indexterm><primary>operators, primitive floating point</primary></indexterm>
+This is certainly legal Haskell, but it is a tremendously verbose and
+un-obvious way to achieve the desired effect.  Arguably, a more direct way
+to write clunky would be to use case expressions:
 </para>
 
-<para>
-
 <programlisting>
-{+,-,*,/}##         :: Double# -&#62; Double# -&#62; Double#
-{&#60;,&#60;=,==,/=,&#62;=,&#62;}## :: Double# -&#62; Double# -&#62; Bool
-negateDouble#       :: Double# -&#62; Double#
-double2Int#         :: Double# -&#62; Int#
-int2Double#         :: Int#    -&#62; Double#
-
-{plus,minux,times,divide}Float# :: Float# -&#62; Float# -&#62; Float#
-{gt,ge,eq,ne,lt,le}Float# :: Float# -&#62; Float# -&#62; Bool
-negateFloat#        :: Float# -&#62; Float#
-float2Int#          :: Float# -&#62; Int#
-int2Float#          :: Int#   -&#62; Float#
+clunky env var1 var1 = case lookup env var1 of
+  Nothing -&gt; fail
+  Just val1 -&gt; case lookup env var2 of
+    Nothing -&gt; fail
+    Just val2 -&gt; val1 + val2
+where
+  fail = val1 + val2
 </programlisting>
 
-</para>
-
 <para>
-<indexterm><primary><literal>+&num;&num;</literal></primary></indexterm>
-<indexterm><primary><literal>-&num;&num;</literal></primary></indexterm>
-<indexterm><primary><literal>*&num;&num;</literal></primary></indexterm>
-<indexterm><primary><literal>/&num;&num;</literal></primary></indexterm>
-<indexterm><primary><literal>&#60;&num;&num;</literal></primary></indexterm>
-<indexterm><primary><literal>&#60;=&num;&num;</literal></primary></indexterm>
-<indexterm><primary><literal>==&num;&num;</literal></primary></indexterm>
-<indexterm><primary><literal>=/&num;&num;</literal></primary></indexterm>
-<indexterm><primary><literal>&#62;=&num;&num;</literal></primary></indexterm>
-<indexterm><primary><literal>&#62;&num;&num;</literal></primary></indexterm>
-<indexterm><primary><literal>negateDouble&num;</literal></primary></indexterm>
-<indexterm><primary><literal>double2Int&num;</literal></primary></indexterm>
-<indexterm><primary><literal>int2Double&num;</literal></primary></indexterm>
-</para>
-
-<para>
-<indexterm><primary><literal>plusFloat&num;</literal></primary></indexterm>
-<indexterm><primary><literal>minusFloat&num;</literal></primary></indexterm>
-<indexterm><primary><literal>timesFloat&num;</literal></primary></indexterm>
-<indexterm><primary><literal>divideFloat&num;</literal></primary></indexterm>
-<indexterm><primary><literal>gtFloat&num;</literal></primary></indexterm>
-<indexterm><primary><literal>geFloat&num;</literal></primary></indexterm>
-<indexterm><primary><literal>eqFloat&num;</literal></primary></indexterm>
-<indexterm><primary><literal>neFloat&num;</literal></primary></indexterm>
-<indexterm><primary><literal>ltFloat&num;</literal></primary></indexterm>
-<indexterm><primary><literal>leFloat&num;</literal></primary></indexterm>
-<indexterm><primary><literal>negateFloat&num;</literal></primary></indexterm>
-<indexterm><primary><literal>float2Int&num;</literal></primary></indexterm>
-<indexterm><primary><literal>int2Float&num;</literal></primary></indexterm>
+This is a bit shorter, but hardly better.  Of course, we can rewrite any set
+of pattern-matching, guarded equations as case expressions; that is
+precisely what the compiler does when compiling equations! The reason that
+Haskell provides guarded equations is because they allow us to write down
+the cases we want to consider, one at a time, independently of each other. 
+This structure is hidden in the case version.  Two of the right-hand sides
+are really the same (<function>fail</function>), and the whole expression
+tends to become more and more indented. 
 </para>
 
 <para>
-And a full complement of trigonometric functions:
+Here is how I would write clunky:
 </para>
 
-<para>
-
 <programlisting>
-expDouble#      :: Double# -&#62; Double#
-logDouble#      :: Double# -&#62; Double#
-sqrtDouble#     :: Double# -&#62; Double#
-sinDouble#      :: Double# -&#62; Double#
-cosDouble#      :: Double# -&#62; Double#
-tanDouble#      :: Double# -&#62; Double#
-asinDouble#     :: Double# -&#62; Double#
-acosDouble#     :: Double# -&#62; Double#
-atanDouble#     :: Double# -&#62; Double#
-sinhDouble#     :: Double# -&#62; Double#
-coshDouble#     :: Double# -&#62; Double#
-tanhDouble#     :: Double# -&#62; Double#
-powerDouble#    :: Double# -&#62; Double# -&#62; Double#
+clunky env var1 var1
+  | Just val1 &lt;- lookup env var1
+  , Just val2 &lt;- lookup env var2
+  = val1 + val2
+...other equations for clunky...
 </programlisting>
 
-<indexterm><primary>trigonometric functions, primitive</primary></indexterm>
-</para>
-
-<para>
-similarly for <literal>Float&num;</literal>.
-</para>
-
 <para>
-There are two coercion functions for <literal>Float&num;</literal>/<literal>Double&num;</literal>:
-</para>
-
-<para>
-
-<programlisting>
-float2Double#   :: Float# -&#62; Double#
-double2Float#   :: Double# -&#62; Float#
-</programlisting>
-
-<indexterm><primary><literal>float2Double&num;</literal></primary></indexterm>
-<indexterm><primary><literal>double2Float&num;</literal></primary></indexterm>
-</para>
-
-<para>
-The primitive version of <function>decodeDouble</function>
-(<function>encodeDouble</function> is implemented as an external C
-function):
-</para>
-
-<para>
-
-<programlisting>
-decodeDouble#   :: Double# -&#62; PrelNum.ReturnIntAndGMP
-</programlisting>
-
-<indexterm><primary><literal>encodeDouble&num;</literal></primary></indexterm>
-<indexterm><primary><literal>decodeDouble&num;</literal></primary></indexterm>
-</para>
-
-<para>
-(And the same for <literal>Float&num;</literal>s.)
-</para>
-
-</sect2>
-
-<sect2 id="integer-operations">
-<title>Operations on/for <literal>Integers</literal> (interface to GMP)
-</title>
-
-<para>
-<indexterm><primary>arbitrary precision integers</primary></indexterm>
-<indexterm><primary>Integer, operations on</primary></indexterm>
-</para>
-
-<para>
-We implement <literal>Integers</literal> (arbitrary-precision
-integers) using the GNU multiple-precision (GMP) package (version
-2.0.2).
-</para>
-
-<para>
-The data type for <literal>Integer</literal> is either a small
-integer, represented by an <literal>Int</literal>, or a large integer
-represented using the pieces required by GMP's
-<literal>MP&lowbar;INT</literal> in <filename>gmp.h</filename> (see
-<filename>gmp.info</filename> in
-<filename>ghc/includes/runtime/gmp</filename>).  It comes out as:
-</para>
-
-<para>
-
-<programlisting>
-data Integer = S# Int#             -- small integers
-             | J# Int# ByteArray#  -- large integers
-</programlisting>
-
-<indexterm><primary>Integer type</primary></indexterm> The primitive
-ops to support large <literal>Integers</literal> use the
-&ldquo;pieces&rdquo; of the representation, and are as follows:
-</para>
-
-<para>
-
-<programlisting>
-negateInteger#  :: Int# -&#62; ByteArray# -&#62; Integer
-
-{plus,minus,times}Integer#, gcdInteger#, 
-  quotInteger#, remInteger#, divExactInteger#
-       :: Int# -> ByteArray#
-        -> Int# -> ByteArray#
-        -> (# Int#, ByteArray# #)
-
-cmpInteger# 
-       :: Int# -> ByteArray#
-        -> Int# -> ByteArray#
-        -> Int# -- -1 for &#60;; 0 for ==; +1 for >
-
-cmpIntegerInt# 
-       :: Int# -> ByteArray#
-        -> Int#
-        -> Int# -- -1 for &#60;; 0 for ==; +1 for >
-
-gcdIntegerInt# :: 
-       :: Int# -> ByteArray#
-        -> Int#
-        -> Int#
-
-divModInteger#, quotRemInteger#
-        :: Int# -> ByteArray#
-        -> Int# -> ByteArray#
-        -> (# Int#, ByteArray#,
-                  Int#, ByteArray# #)
-
-integer2Int# :: 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.
-</programlisting>
-
-<indexterm><primary><literal>negateInteger&num;</literal></primary></indexterm>
-<indexterm><primary><literal>plusInteger&num;</literal></primary></indexterm>
-<indexterm><primary><literal>minusInteger&num;</literal></primary></indexterm>
-<indexterm><primary><literal>timesInteger&num;</literal></primary></indexterm>
-<indexterm><primary><literal>quotInteger&num;</literal></primary></indexterm>
-<indexterm><primary><literal>remInteger&num;</literal></primary></indexterm>
-<indexterm><primary><literal>gcdInteger&num;</literal></primary></indexterm>
-<indexterm><primary><literal>gcdIntegerInt&num;</literal></primary></indexterm>
-<indexterm><primary><literal>divExactInteger&num;</literal></primary></indexterm>
-<indexterm><primary><literal>cmpInteger&num;</literal></primary></indexterm>
-<indexterm><primary><literal>divModInteger&num;</literal></primary></indexterm>
-<indexterm><primary><literal>quotRemInteger&num;</literal></primary></indexterm>
-<indexterm><primary><literal>integer2Int&num;</literal></primary></indexterm>
-<indexterm><primary><literal>int2Integer&num;</literal></primary></indexterm>
-<indexterm><primary><literal>word2Integer&num;</literal></primary></indexterm>
-<indexterm><primary><literal>addr2Integer&num;</literal></primary></indexterm>
-</para>
-
-</sect2>
-
-<sect2>
-<title>Words and addresses</title>
-
-<para>
-<indexterm><primary>word, primitive type</primary></indexterm>
-<indexterm><primary>address, primitive type</primary></indexterm>
-<indexterm><primary>unsigned integer, primitive type</primary></indexterm>
-<indexterm><primary>pointer, primitive type</primary></indexterm>
-</para>
-
-<para>
-A <literal>Word&num;</literal> is used for bit-twiddling operations.
-It is the same size as an <literal>Int&num;</literal>, but has no sign
-nor any arithmetic operations.
-
-<programlisting>
-type Word#      -- Same size/etc as Int# but *unsigned*
-type Addr#      -- A pointer from outside the "Haskell world" (from C, probably);
-                -- described under "arrays"
-</programlisting>
-
-<indexterm><primary><literal>Word&num;</literal></primary></indexterm>
-<indexterm><primary><literal>Addr&num;</literal></primary></indexterm>
-</para>
-
-<para>
-<literal>Word&num;</literal>s and <literal>Addr&num;</literal>s have
-the usual comparison operations.  Other
-unboxed-<literal>Word</literal> ops (bit-twiddling and coercions):
-</para>
-
-<para>
-
-<programlisting>
-{gt,ge,eq,ne,lt,le}Word# :: Word# -> Word# -> Bool
-
-and#, or#, xor# :: Word# -> Word# -> Word#
-        -- standard bit ops.
-
-quotWord#, remWord# :: Word# -> Word# -> Word#
-        -- word (i.e. unsigned) versions are different from int
-        -- versions, so we have to provide these explicitly.
-
-not# :: Word# -> Word#
-
-shiftL#, shiftRL# :: Word# -> Int# -> Word#
-        -- shift left, right logical
-
-int2Word#       :: Int#  -> Word# -- just a cast, really
-word2Int#       :: Word# -> Int#
-</programlisting>
-
-<indexterm><primary>bit operations, Word and Addr</primary></indexterm>
-<indexterm><primary><literal>gtWord&num;</literal></primary></indexterm>
-<indexterm><primary><literal>geWord&num;</literal></primary></indexterm>
-<indexterm><primary><literal>eqWord&num;</literal></primary></indexterm>
-<indexterm><primary><literal>neWord&num;</literal></primary></indexterm>
-<indexterm><primary><literal>ltWord&num;</literal></primary></indexterm>
-<indexterm><primary><literal>leWord&num;</literal></primary></indexterm>
-<indexterm><primary><literal>and&num;</literal></primary></indexterm>
-<indexterm><primary><literal>or&num;</literal></primary></indexterm>
-<indexterm><primary><literal>xor&num;</literal></primary></indexterm>
-<indexterm><primary><literal>not&num;</literal></primary></indexterm>
-<indexterm><primary><literal>quotWord&num;</literal></primary></indexterm>
-<indexterm><primary><literal>remWord&num;</literal></primary></indexterm>
-<indexterm><primary><literal>shiftL&num;</literal></primary></indexterm>
-<indexterm><primary><literal>shiftRA&num;</literal></primary></indexterm>
-<indexterm><primary><literal>shiftRL&num;</literal></primary></indexterm>
-<indexterm><primary><literal>int2Word&num;</literal></primary></indexterm>
-<indexterm><primary><literal>word2Int&num;</literal></primary></indexterm>
-</para>
-
-<para>
-Unboxed-<literal>Addr</literal> ops (C casts, really):
-
-<programlisting>
-{gt,ge,eq,ne,lt,le}Addr# :: Addr# -> Addr# -> Bool
-
-int2Addr#       :: Int#  -> Addr#
-addr2Int#       :: Addr# -> Int#
-addr2Integer#   :: Addr# -> (# Int#, ByteArray# #)
-</programlisting>
-
-<indexterm><primary><literal>gtAddr&num;</literal></primary></indexterm>
-<indexterm><primary><literal>geAddr&num;</literal></primary></indexterm>
-<indexterm><primary><literal>eqAddr&num;</literal></primary></indexterm>
-<indexterm><primary><literal>neAddr&num;</literal></primary></indexterm>
-<indexterm><primary><literal>ltAddr&num;</literal></primary></indexterm>
-<indexterm><primary><literal>leAddr&num;</literal></primary></indexterm>
-<indexterm><primary><literal>int2Addr&num;</literal></primary></indexterm>
-<indexterm><primary><literal>addr2Int&num;</literal></primary></indexterm>
-<indexterm><primary><literal>addr2Integer&num;</literal></primary></indexterm>
-</para>
-
-<para>
-The casts between <literal>Int&num;</literal>,
-<literal>Word&num;</literal> and <literal>Addr&num;</literal>
-correspond to null operations at the machine level, but are required
-to keep the Haskell type checker happy.
-</para>
-
-<para>
-Operations for indexing off of C pointers
-(<literal>Addr&num;</literal>s) to snatch values are listed under
-&ldquo;arrays&rdquo;.
-</para>
-
-</sect2>
-
-<sect2>
-<title>Arrays</title>
-
-<para>
-<indexterm><primary>arrays, primitive</primary></indexterm>
-</para>
-
-<para>
-The type <literal>Array&num; elt</literal> is the type of primitive,
-unpointed arrays of values of type <literal>elt</literal>.
-</para>
-
-<para>
-
-<programlisting>
-type Array# elt
-</programlisting>
-
-<indexterm><primary><literal>Array&num;</literal></primary></indexterm>
-</para>
-
-<para>
-<literal>Array&num;</literal> is more primitive than a Haskell
-array&mdash;indeed, the Haskell <literal>Array</literal> interface is
-implemented using <literal>Array&num;</literal>&mdash;in that an
-<literal>Array&num;</literal> is indexed only by
-<literal>Int&num;</literal>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&mdash;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 <literal>Array&num;</literal> are themselves boxed.
-</para>
-
-<para>
-The type <literal>ByteArray&num;</literal> is similar to
-<literal>Array&num;</literal>, except that it contains just a string
-of (non-pointer) bytes.
-</para>
-
-<para>
-
-<programlisting>
-type ByteArray#
-</programlisting>
-
-<indexterm><primary><literal>ByteArray&num;</literal></primary></indexterm>
-</para>
-
-<para>
-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 use
-them to build (say) arrays of unboxed characters for internal use in a
-Haskell program.  Given these uses, <literal>ByteArray&num;</literal>
-is deliberately a bit vague about the type of its components.
-Operations are provided to extract values of type
-<literal>Char&num;</literal>, <literal>Int&num;</literal>,
-<literal>Float&num;</literal>, <literal>Double&num;</literal>, and
-<literal>Addr&num;</literal> from arbitrary offsets within a
-<literal>ByteArray&num;</literal>.  (For type
-<literal>Foo&num;</literal>, the $i$th offset gets you the $i$th
-<literal>Foo&num;</literal>, not the <literal>Foo&num;</literal> at
-byte-position $i$.  Mumble.)  (If you want a
-<literal>Word&num;</literal>, grab an <literal>Int&num;</literal>,
-then coerce it.)
-</para>
-
-<para>
-Lastly, we have static byte-arrays, of type
-<literal>Addr&num;</literal> &lsqb;mentioned previously].  (Remember
-the duality between arrays and pointers in C.)  Arrays of this types
-are represented by a pointer to an array in the world outside Haskell,
-so this pointer is not followed by the garbage collector.  In other
-respects they are just like <literal>ByteArray&num;</literal>.  They
-are only needed in order to pass values from C to Haskell.
-</para>
-
-</sect2>
-
-<sect2>
-<title>Reading and writing</title>
-
-<para>
-Primitive arrays are linear, and indexed starting at zero.
-</para>
-
-<para>
-The size and indices of a <literal>ByteArray&num;</literal>, <literal>Addr&num;</literal>, and
-<literal>MutableByteArray&num;</literal> are all in bytes.  It's up to the program to
-calculate the correct byte offset from the start of the array.  This
-allows a <literal>ByteArray&num;</literal> to contain a mixture of values of different
-type, which is often needed when preparing data for and unpicking
-results from C.  (Umm&hellip;not true of indices&hellip;WDP 95/09)
-</para>
-
-<para>
-<emphasis>Should we provide some <literal>sizeOfDouble&num;</literal> constants?</emphasis>
-</para>
-
-<para>
-Out-of-range errors on indexing should be caught by the code which
-uses the primitive operation; the primitive operations themselves do
-<emphasis>not</emphasis> check for out-of-range indexes. The intention is that the
-primitive ops compile to one machine instruction or thereabouts.
-</para>
-
-<para>
-We use the terms &ldquo;reading&rdquo; and &ldquo;writing&rdquo; to refer to accessing
-<emphasis>mutable</emphasis> arrays (see <xref LinkEnd="sect-mutable">), and
-&ldquo;indexing&rdquo; to refer to reading a value from an <emphasis>immutable</emphasis>
-array.
-</para>
-
-<para>
-Immutable byte arrays are straightforward to index (all indices in bytes):
-
-<programlisting>
-indexCharArray#   :: ByteArray# -> Int# -> Char#
-indexIntArray#    :: ByteArray# -> Int# -> Int#
-indexAddrArray#   :: ByteArray# -> Int# -> Addr#
-indexFloatArray#  :: ByteArray# -> Int# -> Float#
-indexDoubleArray# :: ByteArray# -> Int# -> Double#
-
-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
-</programlisting>
-
-<indexterm><primary><literal>indexCharArray&num;</literal></primary></indexterm>
-<indexterm><primary><literal>indexIntArray&num;</literal></primary></indexterm>
-<indexterm><primary><literal>indexAddrArray&num;</literal></primary></indexterm>
-<indexterm><primary><literal>indexFloatArray&num;</literal></primary></indexterm>
-<indexterm><primary><literal>indexDoubleArray&num;</literal></primary></indexterm>
-<indexterm><primary><literal>indexCharOffAddr&num;</literal></primary></indexterm>
-<indexterm><primary><literal>indexIntOffAddr&num;</literal></primary></indexterm>
-<indexterm><primary><literal>indexFloatOffAddr&num;</literal></primary></indexterm>
-<indexterm><primary><literal>indexDoubleOffAddr&num;</literal></primary></indexterm>
-<indexterm><primary><literal>indexAddrOffAddr&num;</literal></primary></indexterm>
-</para>
-
-<para>
-The last of these, <function>indexAddrOffAddr&num;</function>, extracts an <literal>Addr&num;</literal> using an offset
-from another <literal>Addr&num;</literal>, thereby providing the ability to follow a chain of
-C pointers.
-</para>
-
-<para>
-Something a bit more interesting goes on when indexing arrays of boxed
-objects, because the result is simply the boxed object. So presumably
-it should be entered&mdash;we never usually return an unevaluated
-object!  This is a pain: primitive ops aren't supposed to do
-complicated things like enter objects.  The current solution is to
-return a single element unboxed tuple (see <xref LinkEnd="unboxed-tuples">).
-</para>
-
-<para>
-
-<programlisting>
-indexArray#       :: Array# elt -> Int# -> (# elt #)
-</programlisting>
-
-<indexterm><primary><literal>indexArray&num;</literal></primary></indexterm>
-</para>
-
-</sect2>
-
-<sect2>
-<title>The state type</title>
-
-<para>
-<indexterm><primary><literal>state, primitive type</literal></primary></indexterm>
-<indexterm><primary><literal>State&num;</literal></primary></indexterm>
-</para>
-
-<para>
-The primitive type <literal>State&num;</literal> represents the state of a state
-transformer.  It is parameterised on the desired type of state, which
-serves to keep states from distinct threads distinct from one another.
-But the <emphasis>only</emphasis> effect of this parameterisation is in the type
-system: all values of type <literal>State&num;</literal> are represented in the same way.
-Indeed, they are all represented by nothing at all!  The code
-generator &ldquo;knows&rdquo; to generate no code, and allocate no registers
-etc, for primitive states.
-</para>
-
-<para>
-
-<programlisting>
-type State# s
-</programlisting>
-
-</para>
-
-<para>
-The type <literal>GHC.RealWorld</literal> is truly opaque: there are no values defined
-of this type, and no operations over it.  It is &ldquo;primitive&rdquo; in that
-sense - but it is <emphasis>not unlifted!</emphasis> Its only role in life is to be
-the type which distinguishes the <literal>IO</literal> state transformer.
-</para>
-
-<para>
-
-<programlisting>
-data RealWorld
-</programlisting>
-
-</para>
-
-</sect2>
-
-<sect2>
-<title>State of the world</title>
-
-<para>
-A single, primitive, value of type <literal>State&num; RealWorld</literal> is provided.
-</para>
-
-<para>
-
-<programlisting>
-realWorld# :: State# RealWorld
-</programlisting>
-
-<indexterm><primary>realWorld&num; state object</primary></indexterm>
-</para>
-
-<para>
-(Note: in the compiler, not a <literal>PrimOp</literal>; just a mucho magic
-<literal>Id</literal>. Exported from <literal>GHC</literal>, though).
-</para>
-
-</sect2>
-
-<sect2 id="sect-mutable">
-<title>Mutable arrays</title>
-
-<para>
-<indexterm><primary>mutable arrays</primary></indexterm>
-<indexterm><primary>arrays, mutable</primary></indexterm>
-Corresponding to <literal>Array&num;</literal> and <literal>ByteArray&num;</literal>, 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.
-</para>
-
-<para>
-
-<programlisting>
-type MutableArray# s elt
-type MutableByteArray# s
-</programlisting>
-
-<indexterm><primary><literal>MutableArray&num;</literal></primary></indexterm>
-<indexterm><primary><literal>MutableByteArray&num;</literal></primary></indexterm>
-</para>
-
-<sect3>
-<title>Allocation</title>
-
-<para>
-<indexterm><primary>mutable arrays, allocation</primary></indexterm>
-<indexterm><primary>arrays, allocation</primary></indexterm>
-<indexterm><primary>allocation, of mutable arrays</primary></indexterm>
-</para>
-
-<para>
-Mutable arrays can be allocated. Only pointer-arrays are initialised;
-arrays of non-pointers are filled in by &ldquo;user code&rdquo; rather than by
-the array-allocation primitive.  Reason: only the pointer case has to
-worry about GC striking with a partly-initialised array.
-</para>
-
-<para>
-
-<programlisting>
-newArray#       :: Int# -> elt -> State# s -> (# State# s, MutableArray# s elt #)
-
-newCharArray#   :: Int# -> State# s -> (# State# s, MutableByteArray# s elt #)
-newIntArray#    :: Int# -> State# s -> (# State# s, MutableByteArray# s elt #)
-newAddrArray#   :: Int# -> State# s -> (# State# s, MutableByteArray# s elt #)
-newFloatArray#  :: Int# -> State# s -> (# State# s, MutableByteArray# s elt #)
-newDoubleArray# :: Int# -> State# s -> (# State# s, MutableByteArray# s elt #)
-</programlisting>
-
-<indexterm><primary><literal>newArray&num;</literal></primary></indexterm>
-<indexterm><primary><literal>newCharArray&num;</literal></primary></indexterm>
-<indexterm><primary><literal>newIntArray&num;</literal></primary></indexterm>
-<indexterm><primary><literal>newAddrArray&num;</literal></primary></indexterm>
-<indexterm><primary><literal>newFloatArray&num;</literal></primary></indexterm>
-<indexterm><primary><literal>newDoubleArray&num;</literal></primary></indexterm>
-</para>
-
-<para>
-The size of a <literal>ByteArray&num;</literal> is given in bytes.
-</para>
-
-</sect3>
-
-<sect3>
-<title>Reading and writing</title>
-
-<para>
-<indexterm><primary>arrays, reading and writing</primary></indexterm>
-</para>
-
-<para>
-
-<programlisting>
-readArray#       :: MutableArray# s elt -> Int# -> State# s -> (# State# s, elt #)
-readCharArray#   :: MutableByteArray# s -> Int# -> State# s -> (# State# s, Char# #)
-readIntArray#    :: MutableByteArray# s -> Int# -> State# s -> (# State# s, Int# #)
-readAddrArray#   :: MutableByteArray# s -> Int# -> State# s -> (# State# s, Addr# #)
-readFloatArray#  :: MutableByteArray# s -> Int# -> State# s -> (# State# s, Float# #)
-readDoubleArray# :: MutableByteArray# s -> Int# -> State# s -> (# State# s, Double# #)
-
-writeArray#       :: MutableArray# s elt -> Int# -> elt     -> State# s -> State# s
-writeCharArray#   :: MutableByteArray# s -> Int# -> Char#   -> State# s -> State# s
-writeIntArray#    :: MutableByteArray# s -> Int# -> Int#    -> State# s -> State# s
-writeAddrArray#   :: MutableByteArray# s -> Int# -> Addr#   -> State# s -> State# s
-writeFloatArray#  :: MutableByteArray# s -> Int# -> Float#  -> State# s -> State# s
-writeDoubleArray# :: MutableByteArray# s -> Int# -> Double# -> State# s -> State# s
-</programlisting>
-
-<indexterm><primary><literal>readArray&num;</literal></primary></indexterm>
-<indexterm><primary><literal>readCharArray&num;</literal></primary></indexterm>
-<indexterm><primary><literal>readIntArray&num;</literal></primary></indexterm>
-<indexterm><primary><literal>readAddrArray&num;</literal></primary></indexterm>
-<indexterm><primary><literal>readFloatArray&num;</literal></primary></indexterm>
-<indexterm><primary><literal>readDoubleArray&num;</literal></primary></indexterm>
-<indexterm><primary><literal>writeArray&num;</literal></primary></indexterm>
-<indexterm><primary><literal>writeCharArray&num;</literal></primary></indexterm>
-<indexterm><primary><literal>writeIntArray&num;</literal></primary></indexterm>
-<indexterm><primary><literal>writeAddrArray&num;</literal></primary></indexterm>
-<indexterm><primary><literal>writeFloatArray&num;</literal></primary></indexterm>
-<indexterm><primary><literal>writeDoubleArray&num;</literal></primary></indexterm>
-</para>
-
-</sect3>
-
-<sect3>
-<title>Equality</title>
-
-<para>
-<indexterm><primary>arrays, testing for equality</primary></indexterm>
-</para>
-
-<para>
-One can take &ldquo;equality&rdquo; of mutable arrays.  What is compared is the
-<emphasis>name</emphasis> or reference to the mutable array, not its contents.
-</para>
-
-<para>
-
-<programlisting>
-sameMutableArray#     :: MutableArray# s elt -> MutableArray# s elt -> Bool
-sameMutableByteArray# :: MutableByteArray# s -> MutableByteArray# s -> Bool
-</programlisting>
-
-<indexterm><primary><literal>sameMutableArray&num;</literal></primary></indexterm>
-<indexterm><primary><literal>sameMutableByteArray&num;</literal></primary></indexterm>
-</para>
-
-</sect3>
-
-<sect3>
-<title>Freezing mutable arrays</title>
-
-<para>
-<indexterm><primary>arrays, freezing mutable</primary></indexterm>
-<indexterm><primary>freezing mutable arrays</primary></indexterm>
-<indexterm><primary>mutable arrays, freezing</primary></indexterm>
-</para>
-
-<para>
-Only unsafe-freeze has a primitive.  (Safe freeze is done directly in Haskell
-by copying the array and then using <function>unsafeFreeze</function>.)
-</para>
-
-<para>
-
-<programlisting>
-unsafeFreezeArray#     :: MutableArray# s elt -> State# s -> (# State# s, Array# s elt #)
-unsafeFreezeByteArray# :: MutableByteArray# s -> State# s -> (# State# s, ByteArray# #)
-</programlisting>
-
-<indexterm><primary><literal>unsafeFreezeArray&num;</literal></primary></indexterm>
-<indexterm><primary><literal>unsafeFreezeByteArray&num;</literal></primary></indexterm>
-</para>
-
-</sect3>
-
-</sect2>
-
-<sect2>
-<title>Synchronizing variables (M-vars)</title>
-
-<para>
-<indexterm><primary>synchronising variables (M-vars)</primary></indexterm>
-<indexterm><primary>M-Vars</primary></indexterm>
-</para>
-
-<para>
-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).
-</para>
-
-<para>
-
-<programlisting>
-type MVar# s elt        -- primitive
-
-newMVar#    :: State# s -> (# State# s, MVar# s elt #)
-takeMVar#   :: SynchVar# s elt -> State# s -> (# State# s, elt #)
-putMVar#    :: SynchVar# s elt -> State# s -> State# s
-</programlisting>
-
-<indexterm><primary><literal>SynchVar&num;</literal></primary></indexterm>
-<indexterm><primary><literal>newSynchVar&num;</literal></primary></indexterm>
-<indexterm><primary><literal>takeMVar</literal></primary></indexterm>
-<indexterm><primary><literal>putMVar</literal></primary></indexterm>
-</para>
-
-</sect2>
-
-</sect1>
-
-<sect1 id="glasgow-ST-monad">
-<title>Primitive state-transformer monad
-</title>
-
-<para>
-<indexterm><primary>state transformers (Glasgow extensions)</primary></indexterm>
-<indexterm><primary>ST monad (Glasgow extension)</primary></indexterm>
-</para>
-
-<para>
-This monad underlies our implementation of arrays, mutable and
-immutable, and our implementation of I/O, including &ldquo;C calls&rdquo;.
-</para>
-
-<para>
-The <literal>ST</literal> library, which provides access to the
-<function>ST</function> monad, is described in <xref
-linkend="sec-ST">.
-</para>
-
-</sect1>
-
-<sect1 id="glasgow-prim-arrays">
-<title>Primitive arrays, mutable and otherwise
-</title>
-
-<para>
-<indexterm><primary>primitive arrays (Glasgow extension)</primary></indexterm>
-<indexterm><primary>arrays, primitive (Glasgow extension)</primary></indexterm>
-</para>
-
-<para>
-GHC knows about quite a few flavours of Large Swathes of Bytes.
-</para>
-
-<para>
-First, GHC distinguishes between primitive arrays of (boxed) Haskell
-objects (type <literal>Array&num; obj</literal>) and primitive arrays of bytes (type
-<literal>ByteArray&num;</literal>).
-</para>
-
-<para>
-Second, it distinguishes between&hellip;
-<variablelist>
-
-<varlistentry>
-<term>Immutable:</term>
-<listitem>
-<para>
-Arrays that do not change (as with &ldquo;standard&rdquo; Haskell arrays); you
-can only read from them.  Obviously, they do not need the care and
-attention of the state-transformer monad.
-</para>
-</listitem>
-</varlistentry>
-<varlistentry>
-<term>Mutable:</term>
-<listitem>
-<para>
-Arrays that may be changed or &ldquo;mutated.&rdquo;  All the operations on them
-live within the state-transformer monad and the updates happen
-<emphasis>in-place</emphasis>.
-</para>
-</listitem>
-</varlistentry>
-<varlistentry>
-<term>&ldquo;Static&rdquo; (in C land):</term>
-<listitem>
-<para>
-A C routine may pass an <literal>Addr&num;</literal> pointer back into Haskell land.  There
-are then primitive operations with which you may merrily grab values
-over in C land, by indexing off the &ldquo;static&rdquo; pointer.
-</para>
-</listitem>
-</varlistentry>
-<varlistentry>
-<term>&ldquo;Stable&rdquo; pointers:</term>
-<listitem>
-<para>
-If, for some reason, you wish to hand a Haskell pointer (i.e.,
-<emphasis>not</emphasis> an unboxed value) to a C routine, you first make the
-pointer &ldquo;stable,&rdquo; so that the garbage collector won't forget that it
-exists.  That is, GHC provides a safe way to pass Haskell pointers to
-C.
-</para>
-
-<para>
-Please see <xref LinkEnd="sec-stable-pointers"> for more details.
-</para>
-</listitem>
-</varlistentry>
-<varlistentry>
-<term>&ldquo;Foreign objects&rdquo;:</term>
-<listitem>
-<para>
-A &ldquo;foreign object&rdquo; is a safe way to pass an external object (a
-C-allocated pointer, say) to Haskell and have Haskell do the Right
-Thing when it no longer references the object.  So, for example, C
-could pass a large bitmap over to Haskell and say &ldquo;please free this
-memory when you're done with it.&rdquo;
-</para>
-
-<para>
-Please see <xref LinkEnd="sec-ForeignObj"> for more details.
-</para>
-</listitem>
-</varlistentry>
-</variablelist>
-</para>
-
-<para>
-The libraries documentatation gives more details on all these
-&ldquo;primitive array&rdquo; types and the operations on them.
-</para>
-
-</sect1>
-
-
-<sect1 id="pattern-guards">
-<title>Pattern guards</title>
-
-<para>
-<indexterm><primary>Pattern guards (Glasgow extension)</primary></indexterm>
-The discussion that follows is an abbreviated version of Simon Peyton Jones's original <ULink URL="http://research.microsoft.com/~simonpj/Haskell/guards.html">proposal</ULink>. (Note that the proposal was written before pattern guards were implemented, so refers to them as unimplemented.)
-</para>
-
-<para>
-Suppose we have an abstract data type of finite maps, with a
-lookup operation:
-
-<programlisting>
-lookup :: FiniteMap -> Int -> Maybe Int
-</programlisting>
-
-The lookup returns <function>Nothing</function> if the supplied key is not in the domain of the mapping, and <function>(Just v)</function> otherwise,
-where <VarName>v</VarName> is the value that the key maps to.  Now consider the following definition:
-</para>
-
-<programlisting>
-clunky env var1 var2 | ok1 && ok2 = val1 + val2
-| otherwise  = var1 + var2
-where
-  m1 = lookup env var1
-  m2 = lookup env var2
-  ok1 = maybeToBool m1
-  ok2 = maybeToBool m2
-  val1 = expectJust m1
-  val2 = expectJust m2
-</programlisting>
-
-<para>
-The auxiliary functions are 
-</para>
-
-<programlisting>
-maybeToBool :: Maybe a -&gt; Bool
-maybeToBool (Just x) = True
-maybeToBool Nothing  = False
-
-expectJust :: Maybe a -&gt; a
-expectJust (Just x) = x
-expectJust Nothing  = error "Unexpected Nothing"
-</programlisting>
-
-<para>
-What is <function>clunky</function> doing? The guard <literal>ok1 &&
-ok2</literal> checks that both lookups succeed, using
-<function>maybeToBool</function> to convert the <function>Maybe</function>
-types to booleans. The (lazily evaluated) <function>expectJust</function>
-calls extract the values from the results of the lookups, and binds the
-returned values to <VarName>val1</VarName> and <VarName>val2</VarName>
-respectively.  If either lookup fails, then clunky takes the
-<literal>otherwise</literal> case and returns the sum of its arguments.
-</para>
-
-<para>
-This is certainly legal Haskell, but it is a tremendously verbose and
-un-obvious way to achieve the desired effect.  Arguably, a more direct way
-to write clunky would be to use case expressions:
-</para>
-
-<programlisting>
-clunky env var1 var1 = case lookup env var1 of
-  Nothing -&gt; fail
-  Just val1 -&gt; case lookup env var2 of
-    Nothing -&gt; fail
-    Just val2 -&gt; val1 + val2
-where
-  fail = val1 + val2
-</programlisting>
-
-<para>
-This is a bit shorter, but hardly better.  Of course, we can rewrite any set
-of pattern-matching, guarded equations as case expressions; that is
-precisely what the compiler does when compiling equations! The reason that
-Haskell provides guarded equations is because they allow us to write down
-the cases we want to consider, one at a time, independently of each other. 
-This structure is hidden in the case version.  Two of the right-hand sides
-are really the same (<function>fail</function>), and the whole expression
-tends to become more and more indented. 
-</para>
-
-<para>
-Here is how I would write clunky:
-</para>
-
-<programlisting>
-clunky env var1 var1
-  | Just val1 &lt;- lookup env var1
-  , Just val2 &lt;- lookup env var2
-  = val1 + val2
-...other equations for clunky...
-</programlisting>
-
-<para>
-The semantics should be clear enough.  The qualifers are matched in order. 
-For a <literal>&lt;-</literal> qualifier, which I call a pattern guard, the
-right hand side is evaluated and matched against the pattern on the left. 
-If the match fails then the whole guard fails and the next equation is
-tried.  If it succeeds, then the appropriate binding takes place, and the
-next qualifier is matched, in the augmented environment.  Unlike list
-comprehensions, however, the type of the expression to the right of the
-<literal>&lt;-</literal> is the same as the type of the pattern to its
-left.  The bindings introduced by pattern guards scope over all the
-remaining guard qualifiers, and over the right hand side of the equation.
+The semantics should be clear enough.  The qualifers are matched in order. 
+For a <literal>&lt;-</literal> qualifier, which I call a pattern guard, the
+right hand side is evaluated and matched against the pattern on the left. 
+If the match fails then the whole guard fails and the next equation is
+tried.  If it succeeds, then the appropriate binding takes place, and the
+next qualifier is matched, in the augmented environment.  Unlike list
+comprehensions, however, the type of the expression to the right of the
+<literal>&lt;-</literal> is the same as the type of the pattern to its
+left.  The bindings introduced by pattern guards scope over all the
+remaining guard qualifiers, and over the right hand side of the equation.
 </para>
 
 <para>
@@ -1608,120 +557,68 @@ Just as with list comprehensions, boolean expressions can be freely mixed
 with among the pattern guards.  For example:
 </para>
 
-<programlisting>
-f x | [y] <- x
-    , y > 3
-    , Just z <- h y
-    = ...
-</programlisting>
-
-<para>
-Haskell's current guards therefore emerge as a special case, in which the
-qualifier list has just one element, a boolean expression.
-</para>
-</sect1>
-
-  <sect1 id="sec-ffi">
-    <title>The foreign interface</title>
-
-    <para>The foreign interface consists of the following components:</para>
-
-    <itemizedlist>
-      <listitem>
-       <para>The Foreign Function Interface language specification
-       (included in this manual, in <xref linkend="ffi">).</para>
-      </listitem>
-
-      <listitem>
-       <para>The <literal>Foreign</literal> module (see <xref
-       linkend="sec-Foreign">) collects together several interfaces
-       which are useful in specifying foreign language
-       interfaces, including the following:</para>
-
-       <itemizedlist>
-         <listitem>
-           <para>The <literal>ForeignObj</literal> module (see <xref
-           linkend="sec-ForeignObj">), for managing pointers from
-           Haskell into the outside world.</para>
-         </listitem>
-      
-         <listitem>
-           <para>The <literal>StablePtr</literal> module (see <xref
-           linkend="sec-stable-pointers">), for managing pointers
-           into Haskell from the outside world.</para>
-         </listitem>
-      
-         <listitem>
-           <para>The <literal>CTypes</literal> module (see <xref
-           linkend="sec-CTypes">) gives Haskell equivalents for the
-           standard C datatypes, for use in making Haskell bindings
-           to existing C libraries.</para>
-         </listitem>
-      
-         <listitem>
-           <para>The <literal>CTypesISO</literal> module (see <xref
-           linkend="sec-CTypesISO">) gives Haskell equivalents for C
-           types defined by the ISO C standard.</para>
-         </listitem>
-      
-         <listitem>
-           <para>The <literal>Storable</literal> library, for
-           primitive marshalling of data types between Haskell and
-           the foreign language.</para>
-         </listitem>
-       </itemizedlist>
-
-      </listitem>
-    </itemizedlist>
-
-<para>The following sections also give some hints and tips on the use
-of the foreign function interface in GHC.</para>
-
-<sect2 id="glasgow-foreign-headers">
-<title>Using function headers
-</title>
-
-<para>
-<indexterm><primary>C calls, function headers</primary></indexterm>
-</para>
-
-<para>
-When generating C (using the <option>-fvia-C</option> directive), one can assist the
-C compiler in detecting type errors by using the <Command>-&num;include</Command> directive
-to provide <filename>.h</filename> files containing function headers.
-</para>
+<programlisting>
+f x | [y] <- x
+    , y > 3
+    , Just z <- h y
+    = ...
+</programlisting>
 
 <para>
-For example,
+Haskell's current guards therefore emerge as a special case, in which the
+qualifier list has just one element, a boolean expression.
 </para>
+</sect1>
 
-<para>
+  <sect1 id="parallel-list-comprehensions">
+    <title>Parallel List Comprehensions</title>
+    <indexterm><primary>list comprehensions</primary><secondary>parallel</secondary>
+    </indexterm>
+    <indexterm><primary>parallel list comprehensions</primary>
+    </indexterm>
+
+    <para>Parallel list comprehensions are a natural extension to list
+    comprehensions.  List comprehensions can be thought of as a nice
+    syntax for writing maps and filters.  Parallel comprehensions
+    extend this to include the zipWith family.</para>
+
+    <para>A parallel list comprehension has multiple independent
+    branches of qualifier lists, each separated by a `|' symbol.  For
+    example, the following zips together two lists:</para>
 
 <programlisting>
-#include "HsFFI.h"
+   [ (x, y) | x <- xs | y <- ys ] 
+</programlisting>
+
+    <para>The behavior of parallel list comprehensions follows that of
+    zip, in that the resulting list will have the same length as the
+    shortest branch.</para>
+
+    <para>We can define parallel list comprehensions by translation to
+    regular comprehensions.  Here's the basic idea:</para>
+
+    <para>Given a parallel comprehension of the form: </para>
 
-void         initialiseEFS (HsInt size);
-HsInt        terminateEFS (void);
-HsForeignObj emptyEFS(void);
-HsForeignObj updateEFS (HsForeignObj a, HsInt i, HsInt x);
-HsInt        lookupEFS (HsForeignObj a, HsInt i);
+<programlisting>
+   [ e | p1 <- e11, p2 <- e12, ... 
+       | q1 <- e21, q2 <- e22, ... 
+       ... 
+   ] 
 </programlisting>
-</para>
 
-      <para>The types <literal>HsInt</literal>,
-      <literal>HsForeignObj</literal> etc. are described in <xref
-      linkend="sec-mapping-table">.</para>
+    <para>This will be translated to: </para>
 
-      <para>Note that this approach is only
-      <emphasis>essential</emphasis> for returning
-      <literal>float</literal>s (or if <literal>sizeof(int) !=
-      sizeof(int *)</literal> on your architecture) but is a Good
-      Thing for anyone who cares about writing solid code.  You're
-      crazy not to do it.</para>
+<programlisting>
+   [ e | ((p1,p2), (q1,q2), ...) <- zipN [(p1,p2) | p1 <- e11, p2 <- e12, ...] 
+                                         [(q1,q2) | q1 <- e21, q2 <- e22, ...] 
+                                         ... 
+   ] 
+</programlisting>
 
-</sect2>
+    <para>where `zipN' is the appropriate zip for the given number of
+    branches.</para>
 
-</sect1>
+  </sect1>
 
 <sect1 id="multi-param-type-classes">
 <title>Multi-parameter type classes
@@ -3186,6 +2083,8 @@ In particular, it is in scope at the type signature for <VarName>y</VarName>.
 </para>
 
 <para>
+ Pattern type signatures are completely orthogonal to ordinary, separate
+type signatures.  The two can be used independently or together.
 At ordinary type signatures, such as that for <VarName>ys</VarName>, any type variables
 mentioned in the type signature <emphasis>that are not in scope</emphasis> are
 implicitly universally quantified.  (If there are no type variables in
@@ -3208,6 +2107,46 @@ So much for the basic idea.  Here are the details.
 </para>
 
 <sect2>
+<title>What a pattern type signature means</title>
+<para>
+A type variable brought into scope by a pattern type signature is simply
+the name for a type.   The restriction they express is that all occurrences
+of the same name mean the same type.  For example:
+<programlisting>
+  f :: [Int] -> Int -> Int
+  f (xs::[a]) (y::a) = (head xs + y) :: a
+</programlisting>
+The pattern type signatures on the left hand side of
+<literal>f</literal> express the fact that <literal>xs</literal>
+must be a list of things of some type <literal>a</literal>; and that <literal>y</literal>
+must have this same type.  The type signature on the expression <literal>(head xs)</literal>
+specifies that this expression must have the same type <literal>a</literal>.
+<emphasis>There is no requirement that the type named by "<literal>a</literal>" is
+in fact a type variable</emphasis>.  Indeed, in this case, the type named by "<literal>a</literal>" is
+<literal>Int</literal>.  (This is a slight liberalisation from the original rather complex
+rules, which specified that a pattern-bound type variable should be universally quantified.)
+For example, all of these are legal:</para>
+
+<programlisting>
+  t (x::a) (y::a) = x+y*2
+
+  f (x::a) (y::b) = [x,y]       -- a unifies with b
+
+  g (x::a) = x + 1::Int         -- a unifies with Int
+
+  h x = let k (y::a) = [x,y]    -- a is free in the
+        in k x                  -- environment
+
+  k (x::a) True    = ...        -- a unifies with Int
+  k (x::Int) False = ...
+
+  w :: [b] -> [b]
+  w (x::a) = x                  -- a unifies with [b]
+</programlisting>
+
+</sect2>
+
+<sect2>
 <title>Scope and implicit quantification</title>
 
 <para>
@@ -3216,15 +2155,25 @@ So much for the basic idea.  Here are the details.
 <listitem>
 
 <para>
- All the type variables mentioned in the patterns for a single
-function definition equation, that are not already in scope,
-are brought into scope by the patterns.  We describe this set as
-the <emphasis>type variables bound by the equation</emphasis>.
-
+All the type variables mentioned in a pattern,
+that are not already in scope,
+are brought into scope by the pattern.  We describe this set as
+the <emphasis>type variables bound by the pattern</emphasis>.
+For example:
+<programlisting>
+  f (x::a) = let g (y::(a,b)) = fst y
+             in
+             g (x,True)
+</programlisting>
+The pattern <literal>(x::a)</literal> brings the type variable
+<literal>a</literal> into scope, as well as the term 
+variable <literal>x</literal>.  The pattern <literal>(y::(a,b))</literal>
+contains an occurrence of the already-in-scope type variable <literal>a</literal>,
+and brings into scope the type variable <literal>b</literal>.
 </para>
 </listitem>
-<listitem>
 
+<listitem>
 <para>
  The type variables thus brought into scope may be mentioned
 in ordinary type signatures or pattern type signatures anywhere within
@@ -3232,35 +2181,34 @@ their scope.
 
 </para>
 </listitem>
-<listitem>
 
+<listitem>
 <para>
  In ordinary type signatures, any type variable mentioned in the
 signature that is in scope is <emphasis>not</emphasis> universally quantified.
 
 </para>
 </listitem>
+
 <listitem>
 
 <para>
  Ordinary type signatures do not bring any new type variables
 into scope (except in the type signature itself!). So this is illegal:
 
-
 <programlisting>
   f :: a -> a
   f x = x::a
 </programlisting>
 
-
 It's illegal because <VarName>a</VarName> is not in scope in the body of <function>f</function>,
 so the ordinary signature <literal>x::a</literal> is equivalent to <literal>x::forall a.a</literal>;
 and that is an incorrect typing.
 
 </para>
 </listitem>
-<listitem>
 
+<listitem>
 <para>
  There is no implicit universal quantification on pattern type
 signatures, nor may one write an explicit <literal>forall</literal> type in a pattern
@@ -3268,8 +2216,8 @@ type signature.  The pattern type signature is a monotype.
 
 </para>
 </listitem>
-<listitem>
 
+<listitem>
 <para>
 
 The type variables in the head of a <literal>class</literal> or <literal>instance</literal> declaration
@@ -3298,103 +2246,6 @@ scope over the methods defined in the <literal>where</literal> part.  For exampl
 </sect2>
 
 <sect2>
-<title>Polymorphism</title>
-
-<para>
-
-<itemizedlist>
-<listitem>
-
-<para>
- Pattern type signatures are completely orthogonal to ordinary, separate
-type signatures.  The two can be used independently or together.  There is
-no scoping associated with the names of the type variables in a separate type signature.
-
-
-<programlisting>
-   f :: [a] -> [a]
-   f (xs::[b]) = reverse xs
-</programlisting>
-
-
-</para>
-</listitem>
-<listitem>
-
-<para>
- The function must be polymorphic in the type variables
-bound by all its equations.  Operationally, the type variables bound
-by one equation must not:
-
-
-<itemizedlist>
-<listitem>
-
-<para>
- Be unified with a type (such as <literal>Int</literal>, or <literal>[a]</literal>).
-</para>
-</listitem>
-<listitem>
-
-<para>
- Be unified with a type variable free in the environment.
-</para>
-</listitem>
-<listitem>
-
-<para>
- Be unified with each other.  (They may unify with the type variables
-bound by another equation for the same function, of course.)
-</para>
-</listitem>
-
-</itemizedlist>
-
-
-For example, the following all fail to type check:
-
-
-<programlisting>
-  f (x::a) (y::b) = [x,y]       -- a unifies with b
-
-  g (x::a) = x + 1::Int         -- a unifies with Int
-
-  h x = let k (y::a) = [x,y]    -- a is free in the
-        in k x                  -- environment
-
-  k (x::a) True    = ...        -- a unifies with Int
-  k (x::Int) False = ...
-
-  w :: [b] -> [b]
-  w (x::a) = x                  -- a unifies with [b]
-</programlisting>
-
-
-</para>
-</listitem>
-<listitem>
-
-<para>
- The pattern-bound type variable may, however, be constrained
-by the context of the principal type, thus:
-
-
-<programlisting>
-  f (x::a) (y::a) = x+y*2
-</programlisting>
-
-
-gets the inferred type: <literal>forall a. Num a =&gt; a -&gt; a -&gt; a</literal>.
-</para>
-</listitem>
-
-</itemizedlist>
-
-</para>
-
-</sect2>
-
-<sect2>
 <title>Result type signatures</title>
 
 <para>
@@ -3438,16 +2289,17 @@ Result type signatures are not yet implemented in Hugs.
 </sect2>
 
 <sect2>
-<title>Pattern signatures on other constructs</title>
+<title>Where a pattern type signature can occur</title>
 
 <para>
-
+A pattern type signature can occur in any pattern, but there
+are restrictions on pattern bindings:
 <itemizedlist>
-<listitem>
 
+<listitem>
 <para>
- A pattern type signature can be on an arbitrary sub-pattern, not
-just on a variable:
+A pattern type signature can be on an arbitrary sub-pattern, not
+ust on a variable:
 
 
 <programlisting>
@@ -3463,28 +2315,9 @@ just on a variable:
  Pattern type signatures, including the result part, can be used
 in lambda abstractions:
 
-
 <programlisting>
   (\ (x::a, y) :: a -> x)
 </programlisting>
-
-
-Type variables bound by these patterns must be polymorphic in
-the sense defined above.
-For example:
-
-
-<programlisting>
-  f1 (x::c) = f1 x      -- ok
-  f2 = \(x::c) -> f2 x  -- not ok
-</programlisting>
-
-
-Here, <function>f1</function> is OK, but <function>f2</function> is not, because <VarName>c</VarName> gets unified
-with a type variable free in the environment, in this
-case, the type of <function>f2</function>, which is in the environment when
-the lambda abstraction is checked.
-
 </para>
 </listitem>
 <listitem>
@@ -3498,50 +2331,50 @@ in <literal>case</literal> expressions:
   case e of { (x::a, y) :: a -> x }
 </programlisting>
 
+</para>
+</listitem>
 
-The pattern-bound type variables must, as usual,
-be polymorphic in the following sense: each case alternative,
-considered as a lambda abstraction, must be polymorphic.
-Thus this is OK:
-
-
-<programlisting>
-  case (True,False) of { (x::a, y) -> x }
-</programlisting>
-
-
-Even though the context is that of a pair of booleans,
-the alternative itself is polymorphic.  Of course, it is
-also OK to say:
+<listitem>
+<para>
+To avoid ambiguity, the type after the &ldquo;<literal>::</literal>&rdquo; in a result
+pattern signature on a lambda or <literal>case</literal> must be atomic (i.e. a single
+token or a parenthesised type of some sort).  To see why,
+consider how one would parse this:
 
 
 <programlisting>
-  case (True,False) of { (x::Bool, y) -> x }
+  \ x :: a -> b -> x
 </programlisting>
 
 
 </para>
 </listitem>
+
 <listitem>
 
 <para>
-To avoid ambiguity, the type after the &ldquo;<literal>::</literal>&rdquo; in a result
-pattern signature on a lambda or <literal>case</literal> must be atomic (i.e. a single
-token or a parenthesised type of some sort).  To see why,
-consider how one would parse this:
+ Pattern type signatures can bind existential type variables.
+For example:
 
 
 <programlisting>
-  \ x :: a -> b -> x
+  data T = forall a. MkT [a]
+
+  f :: T -> T
+  f (MkT [t::a]) = MkT t3
+                 where
+                   t3::[a] = [t,t,t]
 </programlisting>
 
 
 </para>
 </listitem>
+
+
 <listitem>
 
 <para>
- Pattern type signatures that bind new type variables
+Pattern type signatures that bind new type variables
 may not be used in pattern bindings at all.
 So this is illegal:
 
@@ -3595,49 +2428,31 @@ would get a monomorphic type.
 
 </sect2>
 
-<sect2>
-<title>Existentials</title>
-
-<para>
-
-<itemizedlist>
-<listitem>
-
-<para>
- Pattern type signatures can bind existential type variables.
-For example:
-
-
-<programlisting>
-  data T = forall a. MkT [a]
-
-  f :: T -> T
-  f (MkT [t::a]) = MkT t3
-                 where
-                   t3::[a] = [t,t,t]
-</programlisting>
-
 
-</para>
-</listitem>
+</sect1>
 
-</itemizedlist>
+  <sect1 id="pragmas">
+    <title>Pragmas</title>
 
-</para>
+    <indexterm><primary>pragma</primary></indexterm>
 
-</sect2>
+    <para>GHC supports several pragmas, or instructions to the
+    compiler placed in the source code.  Pragmas don't normally affect
+    the meaning of the program, but they might affect the efficiency
+    of the generated code.</para>
 
-</sect1>
+    <para>Pragmas all take the form
 
-<sect1 id="pragmas">
-<title>Pragmas
-</title>
+<literal>{-# <replaceable>word</replaceable> ... #-}</literal>  
 
-<para>
-GHC supports several pragmas, or instructions to the compiler placed
-in the source code.  Pragmas don't affect the meaning of the program,
-but they might affect the efficiency of the generated code.
-</para>
+    where <replaceable>word</replaceable> indicates the type of
+    pragma, and is followed optionally by information specific to that
+    type of pragma.  Case is ignored in
+    <replaceable>word</replaceable>.  The various values for
+    <replaceable>word</replaceable> that GHC understands are described
+    in the following sections; any pragma encountered with an
+    unrecognised <replaceable>word</replaceable> is (silently)
+    ignored.</para>
 
 <sect2 id="inline-pragma">
 <title>INLINE pragma
@@ -3709,17 +2524,23 @@ For example, in GHC's own <literal>UniqueSupply</literal> monad code, we have:
 <title>NOINLINE pragma
 </title>
 
-<para>
 <indexterm><primary>NOINLINE pragma</primary></indexterm>
-<indexterm><primary>pragma, NOINLINE</primary></indexterm>
-</para>
+<indexterm><primary>pragma</primary><secondary>NOINLINE</secondary></indexterm>
+<indexterm><primary>NOTINLINE pragma</primary></indexterm>
+<indexterm><primary>pragma</primary><secondary>NOTINLINE</secondary></indexterm>
 
 <para>
-The <literal>NOINLINE</literal> pragma does exactly what you'd expect: it stops the
-named function from being inlined by the compiler.  You shouldn't ever
-need to do this, unless you're very cautious about code size.
+The <literal>NOINLINE</literal> pragma does exactly what you'd expect:
+it stops the named function from being inlined by the compiler.  You
+shouldn't ever need to do this, unless you're very cautious about code
+size.
 </para>
 
+<para><literal>NOTINLINE</literal> is a synonym for
+<literal>NOINLINE</literal> (<literal>NOTINLINE</literal> is specified
+by Haskell 98 as the standard way to disable inlining, so it should be
+used if you want your code to be portable).</para>
+
 </sect2>
 
     <sect2 id="specialize-pragma">
@@ -3849,6 +2670,42 @@ The RULES pragma lets you specify rewrite rules.  It is described in
 
 </sect2>
 
+<sect2 id="deprecated-pragma">
+<title>DEPRECATED pragma</title>
+
+<para>
+The DEPRECATED pragma lets you specify that a particular function, class, or type, is deprecated.  
+There are two forms.  
+</para>
+<itemizedlist>
+<listitem><para>
+You can deprecate an entire module thus:</para>
+<programlisting>
+   module Wibble {-# DEPRECATED "Use Wobble instead" #-} where
+     ...
+</programlisting>
+<para>
+When you compile any module that import <literal>Wibble</literal>, GHC will print
+the specified message.</para>
+</listitem>
+
+<listitem>
+<para>
+You can deprecate a function, class, or type, with the following top-level declaration:
+</para>
+<programlisting>
+   {-# DEPRECATED f, C, T "Don't use these" #-}
+</programlisting>
+<para>
+When you compile any module that imports and uses any of the specifed entities, 
+GHC will print the specified message.
+</para>
+</listitem>
+</itemizedlist>
+<para>You can suppress the warnings with the flag <option>-fno-warn-deprecations</option>.</para>
+
+</sect2>
+
 </sect1>
 
 <sect1 id="rewrite-rules">
@@ -4154,14 +3011,14 @@ The following are good producers:
  <function>++</function>
 </para>
 </listitem>
-<listitem>
 
+<listitem>
 <para>
  <function>map</function>
 </para>
 </listitem>
-<listitem>
 
+<listitem>
 <para>
  <function>filter</function>
 </para>
@@ -4211,8 +3068,14 @@ The following are good consumers:
  <function>++</function> (on its first argument)
 </para>
 </listitem>
+
 <listitem>
+<para>
+ <function>foldr</function>
+</para>
+</listitem>
 
+<listitem>
 <para>
  <function>map</function>
 </para>
@@ -4406,6 +3269,9 @@ program even if fusion doesn't happen.  More rules in <filename>PrelList.lhs</fi
 <sect1 id="generic-classes">
 <title>Generic classes</title>
 
+    <para>(Note: support for generic classes is currently broken in
+    GHC 5.02).</para>
+
 <para>
 The ideas behind this extension are described in detail in "Derivable type classes",
 Ralf Hinze and Simon Peyton Jones, Haskell Workshop, Montreal Sept 2000, pp94-105.
@@ -4455,7 +3321,10 @@ where clause and over-ride whichever methods you please.
       <para>To use generics you need to</para>
       <itemizedlist>
        <listitem>
-         <para>Use the <option>-fgenerics</option> flag.</para>
+         <para>Use the flags <option>-fglasgow-exts</option> (to enable the extra syntax), 
+                <option>-fgenerics</option> (to generate extra per-data-type code),
+                and <option>-package lang</option> (to make the <literal>Generics</literal> library
+                available.  </para>
        </listitem>
        <listitem>
          <para>Import the module <literal>Generics</literal> from the
@@ -4476,7 +3345,7 @@ can be written infix (indeed, you can now use
 any operator starting in a colon as an infix type constructor).  Also note that
 the type constructors are not exactly as in the paper (Unit instead of 1, etc).
 Finally, note that the syntax of the type patterns in the class declaration
-uses "<literal>{|</literal>" and "<literal>{|</literal>" brackets; curly braces
+uses "<literal>{|</literal>" and "<literal>|}</literal>" brackets; curly braces
 alone would ambiguous when they appear on right hand sides (an extension we 
 anticipate wanting).
 </para>
@@ -4558,10 +3427,10 @@ So this too is illegal:
 <programlisting>
   class Foo a where
     op1 :: a -> Bool
-    op {| a :*: b |} (Inl x) = True
+    op1 {| a :*: b |} (x :*: y) = True
 
     op2 :: a -> Bool
-    op {| p :*: q |} (Inr y) = False
+    op2 {| p :*: q |} (x :*: y) = False
 </programlisting>
 (The reason for this restriction is that we gather all the equations for a particular type consructor
 into a single generic instance declaration.)