<Para>
Before you get too carried away working at the lowest level (e.g.,
-sloshing <Literal>MutableByteArray#</Literal>s around your program), you may wish to
-check if there are system libraries that provide a “Haskellised
-veneer” over the features you want. See <XRef LinkEnd="ghc-prelude">.
+sloshing <Literal>MutableByteArray#</Literal>s around your
+program), you may wish to check if there are libraries that provide a
+“Haskellised veneer” over the features you want. See the
+accompanying library documentation.
</Para>
-<Sect1 id="glasgow-unboxed">
+<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>
<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 “raw machine” types you
+would use in C: <Literal>Int#</Literal> (long int),
+<Literal>Double#</Literal> (double), <Literal>Addr#</Literal>
+(void *), etc. The <Emphasis>primitive operations</Emphasis>
+(PrimOps) on these types are what you might expect; e.g.,
+<Literal>(+#)</Literal> is addition on
+<Literal>Int#</Literal>s, and is the machine-addition that we all
+know and love—usually one instruction.
+</Para>
+
+<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>#</Literal> suffix.
+</Para>
+
+<Para>
+Primitive values are often represented by a simple bit-pattern, such
+as <Literal>Int#</Literal>, <Literal>Float#</Literal>,
+<Literal>Double#</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#</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…nothing can be at the
+other end of the pointer than the primitive value.
+</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#]</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#</Literal> for instance).
+</Para>
+
<Para>
-These types correspond to the “raw machine” types you would use in
-C: <Literal>Int#</Literal> (long int), <Literal>Double#</Literal> (double), <Literal>Addr#</Literal> (void *), etc. The
-<Emphasis>primitive operations</Emphasis> (PrimOps) on these types are what you
-might expect; e.g., <Literal>(+#)</Literal> is addition on <Literal>Int#</Literal>s, and is the
-machine-addition that we all know and love—usually one instruction.
+Nevertheless, A numerically-intensive program using unboxed types can
+go a <Emphasis>lot</Emphasis> faster than its “standard”
+counterpart—we saw a threefold speedup on one example.
</Para>
+</sect2>
+
+<Sect2 id="unboxed-tuples">
+<Title>Unboxed Tuples
+</Title>
+
<Para>
-There are some restrictions on the use of unboxed types, the main one
-being that you can't pass an unboxed value to a polymorphic function
-or store one in a polymorphic data type. This rules out things like
-<Literal>[Int#]</Literal> (i.e. lists of unboxed 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#</Literal> for instance).
+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>
-Nevertheless, A numerically-intensive program using unboxed types can
-go a <Emphasis>lot</Emphasis> faster than its “standard” counterpart—we saw a
-threefold speedup on one example.
+
+<ProgramListing>
+(# e_1, ..., e_n #)
+</ProgramListing>
+
+</Para>
+
+<Para>
+where <Literal>e_1..e_n</Literal> are expressions of any
+type (primitive or non-primitive). The type of an unboxed tuple looks
+the same.
+</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.
+</Para>
+
+<Para>
+There are some pretty stringent restrictions on the use of unboxed tuples:
+</Para>
+
+<Para>
+
+<ItemizedList>
+<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.
+
+</Para>
+</ListItem>
+<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 #) -> a + b }
+</ProgramListing>
+
+
+but the following are invalid:
+
+
+<ProgramListing>
+f x y = g (# x, y #)
+g (# x, y #) = x + y
+</ProgramListing>
+
+
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+ No variable can have an unboxed tuple type. This is illegal:
+
+
+<ProgramListing>
+f :: (# Int, Int #) -> (# Int, Int #)
+f x = x
+</ProgramListing>
+
+
+because <VarName>x</VarName> has an unboxed tuple type.
+
+</Para>
+</ListItem>
+
+</ItemizedList>
+
+</Para>
+
+<Para>
+Note: we may relax some of these restrictions in the future.
+</Para>
+
+<Para>
+The <Literal>IO</Literal> and <Literal>ST</Literal> monads use unboxed tuples to avoid unnecessary
+allocation during sequences of operations.
+</Para>
+
+</Sect2>
+
+<Sect2>
+<Title>Character and numeric types</Title>
+
+<Para>
+<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>
+There are the following obvious primitive types:
+</Para>
+
+<Para>
+
+<ProgramListing>
+type Char#
+type Int#
+type Word#
+type Addr#
+type Float#
+type Double#
+type Int64#
+type Word64#
+</ProgramListing>
+
+<IndexTerm><Primary><literal>Char#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>Int#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>Word#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>Addr#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>Float#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>Double#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>Int64#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>Word64#</literal></Primary></IndexTerm>
+</Para>
+
+<Para>
+If you really want to know their exact equivalents in C, see
+<Filename>ghc/includes/StgTypes.h</Filename> in the GHC source tree.
+</Para>
+
+<Para>
+Literals for these types may be written as follows:
+</Para>
+
+<Para>
+
+<ProgramListing>
+1# an Int#
+1.2# a Float#
+1.34## a Double#
+'a'# a Char#; for weird characters, use '\o<octal>'#
+"a"# an Addr# (a `char *')
+</ProgramListing>
+
+<IndexTerm><Primary>literals, primitive</Primary></IndexTerm>
+<IndexTerm><Primary>constants, primitive</Primary></IndexTerm>
+<IndexTerm><Primary>numbers, primitive</Primary></IndexTerm>
+</Para>
+
+</Sect2>
+
+<Sect2>
+<Title>Comparison operations</Title>
+
+<Para>
+<IndexTerm><Primary>comparisons, primitive</Primary></IndexTerm>
+<IndexTerm><Primary>operators, comparison</Primary></IndexTerm>
+</Para>
+
+<Para>
+
+<ProgramListing>
+{>,>=,==,/=,<,<=}# :: Int# -> Int# -> Bool
+
+{gt,ge,eq,ne,lt,le}Char# :: Char# -> Char# -> Bool
+ -- ditto for Word# and Addr#
+</ProgramListing>
+
+<IndexTerm><Primary><literal>>#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>>=#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>==#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>/=#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal><#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal><=#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>gt{Char,Word,Addr}#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>ge{Char,Word,Addr}#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>eq{Char,Word,Addr}#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>ne{Char,Word,Addr}#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>lt{Char,Word,Addr}#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>le{Char,Word,Addr}#</literal></Primary></IndexTerm>
+</Para>
+
+</Sect2>
+
+<Sect2>
+<Title>Primitive-character operations</Title>
+
+<Para>
+<IndexTerm><Primary>characters, primitive operations</Primary></IndexTerm>
+<IndexTerm><Primary>operators, primitive character</Primary></IndexTerm>
+</Para>
+
+<Para>
+
+<ProgramListing>
+ord# :: Char# -> Int#
+chr# :: Int# -> Char#
+</ProgramListing>
+
+<IndexTerm><Primary><literal>ord#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>chr#</literal></Primary></IndexTerm>
+</Para>
+
+</Sect2>
+
+<Sect2>
+<Title>Primitive-<Literal>Int</Literal> operations</Title>
+
+<Para>
+<IndexTerm><Primary>integers, primitive operations</Primary></IndexTerm>
+<IndexTerm><Primary>operators, primitive integer</Primary></IndexTerm>
+</Para>
+
+<Para>
+
+<ProgramListing>
+{+,-,*,quotInt,remInt,gcdInt}# :: Int# -> Int# -> Int#
+negateInt# :: Int# -> Int#
+
+iShiftL#, iShiftRA#, iShiftRL# :: Int# -> Int# -> Int#
+ -- shift left, right arithmetic, right logical
+
+addIntC#, subIntC#, mulIntC# :: Int# -> Int# -> (# Int#, Int# #)
+ -- add, subtract, multiply with carry
+</ProgramListing>
+
+<IndexTerm><Primary><literal>+#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>-#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>*#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>quotInt#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>remInt#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>gcdInt#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>iShiftL#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>iShiftRA#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>iShiftRL#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>addIntC#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>subIntC#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>mulIntC#</literal></Primary></IndexTerm>
+<IndexTerm><Primary>shift operations, integer</Primary></IndexTerm>
+</Para>
+
+<Para>
+<Emphasis>Note:</Emphasis> No error/overflow checking!
+</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>
+</Para>
+
+<Para>
+
+<ProgramListing>
+{+,-,*,/}## :: Double# -> Double# -> Double#
+{<,<=,==,/=,>=,>}## :: Double# -> Double# -> Bool
+negateDouble# :: Double# -> Double#
+double2Int# :: Double# -> Int#
+int2Double# :: Int# -> Double#
+
+{plus,minux,times,divide}Float# :: Float# -> Float# -> Float#
+{gt,ge,eq,ne,lt,le}Float# :: Float# -> Float# -> Bool
+negateFloat# :: Float# -> Float#
+float2Int# :: Float# -> Int#
+int2Float# :: Int# -> Float#
+</ProgramListing>
+
+</Para>
+
+<Para>
+<IndexTerm><Primary><literal>+##</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>-##</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>*##</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>/##</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal><##</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal><=##</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>==##</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>=/##</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>>=##</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>>##</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>negateDouble#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>double2Int#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>int2Double#</literal></Primary></IndexTerm>
+</Para>
+
+<Para>
+<IndexTerm><Primary><literal>plusFloat#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>minusFloat#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>timesFloat#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>divideFloat#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>gtFloat#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>geFloat#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>eqFloat#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>neFloat#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>ltFloat#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>leFloat#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>negateFloat#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>float2Int#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>int2Float#</literal></Primary></IndexTerm>
+</Para>
+
+<Para>
+And a full complement of trigonometric functions:
+</Para>
+
+<Para>
+
+<ProgramListing>
+expDouble# :: Double# -> Double#
+logDouble# :: Double# -> Double#
+sqrtDouble# :: Double# -> Double#
+sinDouble# :: Double# -> Double#
+cosDouble# :: Double# -> Double#
+tanDouble# :: Double# -> Double#
+asinDouble# :: Double# -> Double#
+acosDouble# :: Double# -> Double#
+atanDouble# :: Double# -> Double#
+sinhDouble# :: Double# -> Double#
+coshDouble# :: Double# -> Double#
+tanhDouble# :: Double# -> Double#
+powerDouble# :: Double# -> Double# -> Double#
+</ProgramListing>
+
+<IndexTerm><Primary>trigonometric functions, primitive</Primary></IndexTerm>
+</Para>
+
+<Para>
+similarly for <Literal>Float#</Literal>.
+</Para>
+
+<Para>
+There are two coercion functions for <Literal>Float#</Literal>/<Literal>Double#</Literal>:
+</Para>
+
+<Para>
+
+<ProgramListing>
+float2Double# :: Float# -> Double#
+double2Float# :: Double# -> Float#
+</ProgramListing>
+
+<IndexTerm><Primary><literal>float2Double#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>double2Float#</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# -> PrelNum.ReturnIntAndGMP
+</ProgramListing>
+
+<IndexTerm><Primary><literal>encodeDouble#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>decodeDouble#</literal></Primary></IndexTerm>
+</Para>
+
+<Para>
+(And the same for <Literal>Float#</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_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
+“pieces” of the representation, and are as follows:
+</Para>
+
+<Para>
+
+<ProgramListing>
+negateInteger# :: Int# -> ByteArray# -> Integer
+
+{plus,minus,times}Integer#, gcdInteger#,
+ quotInteger#, remInteger#, divExactInteger#
+ :: Int# -> ByteArray#
+ -> Int# -> ByteArray#
+ -> (# Int#, ByteArray# #)
+
+cmpInteger#
+ :: Int# -> ByteArray#
+ -> Int# -> ByteArray#
+ -> Int# -- -1 for <; 0 for ==; +1 for >
+
+cmpIntegerInt#
+ :: Int# -> ByteArray#
+ -> Int#
+ -> Int# -- -1 for <; 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#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>plusInteger#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>minusInteger#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>timesInteger#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>quotInteger#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>remInteger#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>gcdInteger#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>gcdIntegerInt#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>divExactInteger#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>cmpInteger#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>divModInteger#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>quotRemInteger#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>integer2Int#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>int2Integer#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>word2Integer#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>addr2Integer#</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>
-Please see <XRef LinkEnd="ghc-libs-ghc"> for the details of unboxed types and the
-operations on them.
+A <Literal>Word#</Literal> is used for bit-twiddling operations.
+It is the same size as an <Literal>Int#</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#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>Addr#</literal></Primary></IndexTerm>
+</Para>
+
+<Para>
+<Literal>Word#</Literal>s and <Literal>Addr#</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#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>geWord#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>eqWord#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>neWord#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>ltWord#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>leWord#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>and#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>or#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>xor#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>not#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>quotWord#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>remWord#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>shiftL#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>shiftRA#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>shiftRL#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>int2Word#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>word2Int#</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#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>geAddr#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>eqAddr#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>neAddr#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>ltAddr#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>leAddr#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>int2Addr#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>addr2Int#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>addr2Integer#</literal></Primary></IndexTerm>
+</Para>
+
+<Para>
+The casts between <Literal>Int#</Literal>,
+<Literal>Word#</Literal> and <Literal>Addr#</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#</Literal>s) to snatch values are listed under
+“arrays”.
+</Para>
+
+</Sect2>
+
+<Sect2>
+<Title>Arrays</Title>
+
+<Para>
+<IndexTerm><Primary>arrays, primitive</Primary></IndexTerm>
+</Para>
+
+<Para>
+The type <Literal>Array# 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#</literal></Primary></IndexTerm>
+</Para>
+
+<Para>
+<Literal>Array#</Literal> is more primitive than a Haskell
+array—indeed, the Haskell <Literal>Array</Literal> interface is
+implemented using <Literal>Array#</Literal>—in that an
+<Literal>Array#</Literal> is indexed only by
+<Literal>Int#</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—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#</Literal> are themselves boxed.
+</Para>
+
+<Para>
+The type <Literal>ByteArray#</Literal> is similar to
+<Literal>Array#</Literal>, except that it contains just a string
+of (non-pointer) bytes.
+</Para>
+
+<Para>
+
+<ProgramListing>
+type ByteArray#
+</ProgramListing>
+
+<IndexTerm><Primary><literal>ByteArray#</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#</Literal>
+is deliberately a bit vague about the type of its components.
+Operations are provided to extract values of type
+<Literal>Char#</Literal>, <Literal>Int#</Literal>,
+<Literal>Float#</Literal>, <Literal>Double#</Literal>, and
+<Literal>Addr#</Literal> from arbitrary offsets within a
+<Literal>ByteArray#</Literal>. (For type
+<Literal>Foo#</Literal>, the $i$th offset gets you the $i$th
+<Literal>Foo#</Literal>, not the <Literal>Foo#</Literal> at
+byte-position $i$. Mumble.) (If you want a
+<Literal>Word#</Literal>, grab an <Literal>Int#</Literal>,
+then coerce it.)
+</Para>
+
+<Para>
+Lastly, we have static byte-arrays, of type
+<Literal>Addr#</Literal> [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#</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#</Literal>, <Literal>Addr#</Literal>, and
+<Literal>MutableByteArray#</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#</Literal> to contain a mixture of values of different
+type, which is often needed when preparing data for and unpicking
+results from C. (Umm…not true of indices…WDP 95/09)
+</Para>
+
+<Para>
+<Emphasis>Should we provide some <Literal>sizeOfDouble#</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 “reading” and “writing” to refer to accessing
+<Emphasis>mutable</Emphasis> arrays (see <XRef LinkEnd="sect-mutable">), and
+“indexing” 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#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>indexIntArray#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>indexAddrArray#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>indexFloatArray#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>indexDoubleArray#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>indexCharOffAddr#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>indexIntOffAddr#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>indexFloatOffAddr#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>indexDoubleOffAddr#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>indexAddrOffAddr#</literal></Primary></IndexTerm>
+</Para>
+
+<Para>
+The last of these, <Function>indexAddrOffAddr#</Function>, extracts an <Literal>Addr#</Literal> using an offset
+from another <Literal>Addr#</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—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#</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#</literal></Primary></IndexTerm>
+</Para>
+
+<Para>
+The primitive type <Literal>State#</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#</Literal> are represented in the same way.
+Indeed, they are all represented by nothing at all! The code
+generator “knows” 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 “primitive” 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# RealWorld</Literal> is provided.
+</Para>
+
+<Para>
+
+<ProgramListing>
+realWorld# :: State# RealWorld
+</ProgramListing>
+
+<IndexTerm><Primary>realWorld# 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#</Literal> and <Literal>ByteArray#</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#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>MutableByteArray#</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 “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.
+</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#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>newCharArray#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>newIntArray#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>newAddrArray#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>newFloatArray#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>newDoubleArray#</literal></Primary></IndexTerm>
+</Para>
+
+<Para>
+The size of a <Literal>ByteArray#</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#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>readCharArray#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>readIntArray#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>readAddrArray#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>readFloatArray#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>readDoubleArray#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>writeArray#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>writeCharArray#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>writeIntArray#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>writeAddrArray#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>writeFloatArray#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>writeDoubleArray#</literal></Primary></IndexTerm>
+</Para>
+
+</Sect3>
+
+<Sect3>
+<Title>Equality</Title>
+
+<Para>
+<IndexTerm><Primary>arrays, testing for equality</Primary></IndexTerm>
+</Para>
+
+<Para>
+One can take “equality” 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#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>sameMutableByteArray#</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#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>unsafeFreezeByteArray#</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#</literal></Primary></IndexTerm>
+<IndexTerm><Primary><literal>newSynchVar#</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">
</Para>
<Para>
-The libraries section gives more details on all these “primitive
-array” types and the operations on them, <XRef LinkEnd="ghc-prelude">. Some of these extensions
-are also supported by Hugs, and the supporting libraries are described
-in the <ULink
-URL="libs.html"
->GHC/Hugs Extension Libraries</ULink
->
-document.
+The libraries documentatation gives more details on all these
+“primitive array” types and the operations on them.
</Para>
</Sect1>
<Para>
<ProgramListing>
-fooH :: Char -> Int -> Double -> Word -> IO Double
+fooH :: Char -> Int -> Double -> Word -> IO Double
fooH c i d w = _ccall_ fooC (“stdin”::Addr) c i d w
</ProgramListing>
import CString
oldGetEnv name
- = _casm_ “%r = getenv((char *) %0);” name >>= \ litstring ->
+ = _casm_ “%r = getenv((char *) %0);” name >>= \ litstring ->
return (
if (litstring == nullAddr) then
Left ("Fail:oldGetEnv:"++name)
<Para>
<ProgramListing>
-fooH :: Char -> Int -> Double -> Word -> IO Double
+fooH :: Char -> Int -> Double -> Word -> IO Double
fooH c i d w = _ccall_ fooC (“stdin”::Addr) c i d w
</ProgramListing>
<Para>
<ProgramListing>
-storeH :: Int -> IO ()
-storeH x = makeStablePtr x >>= \ stable_x ->
+storeH :: Int -> IO ()
+storeH x = makeStablePtr x >>= \ stable_x ->
_ccall_ storeC stable_x
fetchH :: IO Int
-fetchH x = _ccall_ fetchC >>= \ stable_x ->
- deRefStablePtr stable_x >>= \ x ->
- freeStablePtr stable_x >>
+fetchH x = _ccall_ fetchC >>= \ stable_x ->
+ deRefStablePtr stable_x >>= \ x ->
+ freeStablePtr stable_x >>
return x
</ProgramListing>
<ProgramListing>
void freeStablePointer( StgStablePtr stablePtrToToss )
-freeStablePtr :: StablePtr a -> IO ()
+freeStablePtr :: StablePtr a -> IO ()
</ProgramListing>
</Para>
Calling a function with no side-effects:
<ProgramListing>
-atan2d :: Double -> Double -> Double
+atan2d :: Double -> Double -> Double
atan2d y x = unsafePerformIO (_ccall_ atan2d y x)
-sincosd :: Double -> (Double, Double)
+sincosd :: Double -> (Double, Double)
sincosd x = unsafePerformIO $ do
da <- newDoubleArray (0, 1)
_casm_ “sincosd( %0, &((double *)%1[0]), &((double *)%1[1]) );” x da
<ProgramListing>
empty :: EFS x
-update :: EFS x -> Int -> x -> EFS x
-lookup :: EFS a -> Int -> a
+update :: EFS x -> Int -> x -> EFS x
+lookup :: EFS a -> Int -> a
empty = unsafePerformIO (_ccall_ emptyEFS)
update a i x = unsafePerformIO $
- makeStablePtr x >>= \ stable_x ->
+ makeStablePtr x >>= \ stable_x ->
_ccall_ updateEFS a i stable_x
lookup a i = unsafePerformIO $
- _ccall_ lookupEFS a i >>= \ stable_x ->
+ _ccall_ lookupEFS a i >>= \ stable_x ->
deRefStablePtr stable_x
</ProgramListing>
<ProgramListing>
-trace :: String -> a -> a
+trace :: String -> a -> a
trace string expr
= unsafePerformIO (
- ((_ccall_ PreTraceHook sTDERR{-msg-}):: IO ()) >>
- fputs sTDERR string >>
- ((_ccall_ PostTraceHook sTDERR{-msg-}):: IO ()) >>
+ ((_ccall_ PreTraceHook sTDERR{-msg-}):: IO ()) >>
+ fputs sTDERR string >>
+ ((_ccall_ PostTraceHook sTDERR{-msg-}):: IO ()) >>
return expr )
where
sTDERR = (“stderr” :: Addr)
<ProgramListing>
-f :: Int -> IO Double
+f :: Int -> IO Double
f x = _ccall_ foo x
</ProgramListing>
<Para>
<ProgramListing>
- forall tv1..tvn (c1, ...,cn) => type
+ forall tv1..tvn (c1, ...,cn) => type
</ProgramListing>
</Para>
<ProgramListing>
- forall a. Eq a => Int
+ forall a. Eq a => Int
</ProgramListing>
<ProgramListing>
- forall a. C a b => burble
+ forall a. C a b => burble
</ProgramListing>
<ProgramListing>
- forall a. Eq b => burble
+ forall a. Eq b => burble
</ProgramListing>
<Para>
<ProgramListing>
- f :: Eq (m a) => [m a] -> [m a]
- g :: Eq [a] => ...
+ f :: Eq (m a) => [m a] -> [m a]
+ g :: Eq [a] => ...
</ProgramListing>
</Para>
<ProgramListing>
class Collection c a where
- union :: c a -> c a -> c a
+ union :: c a -> c a -> c a
...etc.
</ProgramListing>
<ProgramListing>
class C a where {
- op :: D b => a -> b -> b
+ op :: D b => a -> b -> b
}
- class C a => D a where { ... }
+ class C a => D a where { ... }
</ProgramListing>
<ProgramListing>
- class Functor (m k) => FiniteMap m k where
+ class Functor (m k) => FiniteMap m k where
...
- class (Monad m, Monad (t m)) => Transform t m where
- lift :: m a -> (t m) a
+ class (Monad m, Monad (t m)) => Transform t m where
+ lift :: m a -> (t m) a
</ProgramListing>
<ProgramListing>
class Collection c a where
- mapC :: Collection c b => (a->b) -> c a -> c b
+ mapC :: Collection c b => (a->b) -> c a -> c b
</ProgramListing>
<ProgramListing>
class C a where
- op :: Eq a => (a,b) -> (a,b)
+ op :: Eq a => (a,b) -> (a,b)
</ProgramListing>
<ProgramListing>
- class Eq a => C a where
- op ::(a,b) -> (a,b)
+ class Eq a => C a where
+ op ::(a,b) -> (a,b)
</ProgramListing>
<ProgramListing>
class Coll s a where
empty :: s
- insert :: s -> a -> s
+ insert :: s -> a -> s
</ProgramListing>
<ProgramListing>
class Coll s a where
empty :: s a
- insert :: s a -> a -> s a
+ insert :: s a -> a -> s a
</ProgramListing>
class CollE s where
empty :: s
- class CollE s => Coll s a where
- insert :: s -> a -> s
+ class CollE s => Coll s a where
+ insert :: s -> a -> s
</ProgramListing>
<ProgramListing>
- instance context1 => C type1 where ...
- instance context2 => C type2 where ...
+ instance context1 => C type1 where ...
+ instance context2 => C type2 where ...
</ProgramListing>
<Para>
<Emphasis>There are no restrictions on the type in an instance
<Emphasis>head</Emphasis>, except that at least one must not be a type variable</Emphasis>.
-The instance "head" is the bit after the "=>" in an instance decl. For
+The instance "head" is the bit after the "=>" in an instance decl. For
example, these are OK:
<ProgramListing>
- instance C a => C a where ...
+ instance C a => C a where ...
</ProgramListing>
<ProgramListing>
- class (C1 a, C2 a, C3 a) => C a where { }
+ class (C1 a, C2 a, C3 a) => C a where { }
- instance (C1 a, C2 a, C3 a) => C a where { }
+ instance (C1 a, C2 a, C3 a) => C a where { }
</ProgramListing>
<ProgramListing>
- f :: C a => ...
+ f :: C a => ...
</ProgramListing>
<ProgramListing>
- f :: (C1 a, C2 a, C3 a) => ...
+ f :: (C1 a, C2 a, C3 a) => ...
</ProgramListing>
<ProgramListing>
-instance C a b => Eq (a,b) where ...
+instance C a b => Eq (a,b) where ...
</ProgramListing>
<ProgramListing>
-instance C Int b => Foo b where ...
+instance C Int b => Foo b where ...
</ProgramListing>
<Para>
<ProgramListing>
- forall a b. (Ord a, Eq b) => a -> b -> a
+ forall a b. (Ord a, Eq b) => a -> b -> a
</ProgramListing>
</Para>
<Para>
<ProgramListing>
- g :: b -> b
+ g :: b -> b
</ProgramListing>
</Para>
<Para>
<ProgramListing>
- g :: forall b. (b -> b)
+ g :: forall b. (b -> b)
</ProgramListing>
</Para>
<Para>
<ProgramListing>
-data T a = T1 (forall b. b -> b -> b) a
+data T a = T1 (forall b. b -> b -> b) a
-data MonadT m = MkMonad { return :: forall a. a -> m a,
- bind :: forall a b. m a -> (a -> m b) -> m b
+data MonadT m = MkMonad { return :: forall a. a -> m a,
+ bind :: forall a b. m a -> (a -> m b) -> m b
}
-newtype Swizzle = MkSwizzle (Ord a => [a] -> [a])
+newtype Swizzle = MkSwizzle (Ord a => [a] -> [a])
</ProgramListing>
</Para>
<Para>
<ProgramListing>
-T1 :: forall a. (forall b. b -> b -> b) -> a -> T a
-MkMonad :: forall m. (forall a. a -> m a)
- -> (forall a b. m a -> (a -> m b) -> m b)
- -> MonadT m
-MkSwizzle :: (Ord a => [a] -> [a]) -> Swizzle
+T1 :: forall a. (forall b. b -> b -> b) -> a -> T a
+MkMonad :: forall m. (forall a. a -> m a)
+ -> (forall a b. m a -> (a -> m b) -> m b)
+ -> MonadT m
+MkSwizzle :: (Ord a => [a] -> [a]) -> Swizzle
</ProgramListing>
</Para>
types too. So if you write this:
<ProgramListing>
- data T a = MkT (Either a b) (b -> b)
+ data T a = MkT (Either a b) (b -> b)
</ProgramListing>
it's just as if you had written this:
<ProgramListing>
- data T a = MkT (forall b. Either a b) (forall b. b -> b)
+ data T a = MkT (forall b. Either a b) (forall b. b -> b)
</ProgramListing>
That is, since the type variable <Literal>b</Literal> isn't in scope, it's
<Para>
<ProgramListing>
-(T1 (\xy->x) 3) :: T Int
+(T1 (\xy->x) 3) :: T Int
(MkSwizzle sort) :: Swizzle
(MkSwizzle reverse) :: Swizzle
(let r x = Just x
b m k = case m of
- Just y -> k y
- Nothing -> Nothing
+ Just y -> k y
+ Nothing -> Nothing
in
MkMonad r b) :: MonadT Maybe
</ProgramListing>
<Para>
<ProgramListing>
- f :: T a -> a -> (a, Char)
+ f :: T a -> a -> (a, Char)
f (T1 f k) x = (f k x, f 'c' 'd')
- g :: (Ord a, Ord b) => Swizzle -> [a] -> (a -> b) -> [b]
+ g :: (Ord a, Ord b) => Swizzle -> [a] -> (a -> b) -> [b]
g (MkSwizzle s) xs f = s (map f (s xs))
- h :: MonadT m -> [m a] -> m [a]
+ h :: MonadT m -> [m a] -> m [a]
h m [] = return m []
- h m (x:xs) = bind m x $ \y ->
- bind m (h m xs) $ \ys ->
+ h m (x:xs) = bind m x $ \y ->
+ bind m (h m xs) $ \ys ->
return m (y:ys)
</ProgramListing>
<ProgramListing>
newtype TIM s a = TIM (ST s (Maybe a))
- runTIM :: (forall s. TIM s a) -> Maybe a
+ runTIM :: (forall s. TIM s a) -> Maybe a
runTIM (TIM m) = runST m
</ProgramListing>
must bind the variable and pattern match in the right hand side:
<ProgramListing>
- runTIM :: (forall s. TIM s a) -> Maybe a
- runTIM tm = case tm of { TIM m -> runST m }
+ runTIM :: (forall s. TIM s a) -> Maybe a
+ runTIM tm = case tm of { TIM m -> runST m }
</ProgramListing>
The <Literal>tm</Literal> on the right hand side is (invisibly) instantiated, like
<Para>
In the illegal example, the sub-expression <Literal>MkSwizzle</Literal> has the
-polymorphic type <Literal>(Ord b => [b] -> [b]) -> Swizzle</Literal> and is not
+polymorphic type <Literal>(Ord b => [b] -> [b]) -> Swizzle</Literal> and is not
a sub-expression of an enclosing application. On the other hand, this
expression is OK:
</Para>
<Para>
<ProgramListing>
- map (T1 (\a b -> a)) [1,2,3]
+ map (T1 (\a b -> a)) [1,2,3]
</ProgramListing>
</Para>
<Para>
even though it involves a partial application of <Function>T1</Function>, because
-the sub-expression <Literal>T1 (\a b -> a)</Literal> has type <Literal>Int -> T
+the sub-expression <Literal>T1 (\a b -> a)</Literal> has type <Literal>Int -> T
Int</Literal>.
</Para>
<Para>
<ProgramListing>
- mkTs :: (forall b. b -> b -> b) -> a -> [T a]
+ mkTs :: (forall b. b -> b -> b) -> a -> [T a]
mkTs f x y = [T1 f x, T1 f y]
</ProgramListing>
<Para>
This type signature tells the compiler to attribute <Literal>f</Literal> with
-the polymorphic type <Literal>(forall b. b -> b -> b)</Literal> when type
+the polymorphic type <Literal>(forall b. b -> b -> b)</Literal> when type
checking the body of <Function>mkTs</Function>, so now the application of
<Function>T1</Function> is fine.
</Para>
<ProgramListing>
-rank2type ::= [forall tyvars .] [context =>] funty
-funty ::= ([forall tyvars .] [context =>] ty) -> funty
+rank2type ::= [forall tyvars .] [context =>] funty
+funty ::= ([forall tyvars .] [context =>] ty) -> funty
| ty
ty ::= ...current Haskell monotype syntax...
</ProgramListing>
<ProgramListing>
-mkTs :: (forall b. b -> b -> b) -> a -> [T a]
-mkTs = \ f x y -> [T1 f x, T1 f y]
+mkTs :: (forall b. b -> b -> b) -> a -> [T a]
+mkTs = \ f x y -> [T1 f x, T1 f y]
</ProgramListing>
<Para>
<ProgramListing>
- data Foo = forall a. MkFoo a (a -> Bool)
+ data Foo = forall a. MkFoo a (a -> Bool)
| Nil
</ProgramListing>
<Para>
<ProgramListing>
- MkFoo :: forall a. a -> (a -> Bool) -> Foo
+ MkFoo :: forall a. a -> (a -> Bool) -> Foo
Nil :: Foo
</ProgramListing>
<Para>
<ProgramListing>
- f :: Foo -> Bool
+ f :: Foo -> Bool
f (MkFoo val fn) = fn val
</ProgramListing>
<Para>
<ProgramListing>
- MkFoo :: (exists a . (a, a -> Bool)) -> Foo
+ MkFoo :: (exists a . (a, a -> Bool)) -> Foo
</ProgramListing>
</Para>
<Para>
<ProgramListing>
-data Baz = forall a. Eq a => Baz1 a a
- | forall b. Show b => Baz2 b (b -> b)
+data Baz = forall a. Eq a => Baz1 a a
+ | forall b. Show b => Baz2 b (b -> b)
</ProgramListing>
</Para>
<Para>
<ProgramListing>
-Baz1 :: forall a. Eq a => a -> a -> Baz
-Baz2 :: forall b. Show b => b -> (b -> b) -> Baz
+Baz1 :: forall a. Eq a => a -> a -> Baz
+Baz2 :: forall b. Show b => b -> (b -> b) -> Baz
</ProgramListing>
</Para>
<Para>
<ProgramListing>
- f :: Baz -> String
+ f :: Baz -> String
f (Baz1 p q) | p == q = "Yes"
| otherwise = "No"
f (Baz1 v fn) = show (fn v)
<ProgramListing>
- f1 :: Foo -> a -- Weird!
+ f1 :: Foo -> a -- Weird!
</ProgramListing>
<ProgramListing>
- f1 :: forall a. Foo -> a -- Wrong!
+ f1 :: forall a. Foo -> a -- Wrong!
</ProgramListing>
<ProgramListing>
- newtype T = forall a. Ord a => MkT a
+ newtype T = forall a. Ord a => MkT a
</ProgramListing>
<Para>
<ProgramListing>
-assert :: Bool -> a -> a
+assert :: Bool -> a -> a
assert False x = error "assertion failed!"
assert _ x = x
</ProgramListing>
<Para>
<ProgramListing>
-kelvinToC :: Double -> Double
+kelvinToC :: Double -> Double
kelvinToC k = assert (k &gt;= 0.0) (k+273.15)
</ProgramListing>
<Para>
<ProgramListing>
-assert pred val ==> assertError "Main.hs|15" pred val
+assert pred val ==> assertError "Main.hs|15" pred val
</ProgramListing>
</Para>
<ProgramListing>
- f :: a -> a
+ f :: a -> a
f x = x::a
</ProgramListing>
<ProgramListing>
class C a where
- op :: [a] -> a
+ op :: [a] -> a
op xs = let ys::[a]
ys = reverse xs
<ProgramListing>
- f :: [a] -> [a]
+ f :: [a] -> [a]
f (xs::[b]) = reverse xs
</ProgramListing>
k (x::a) True = ... -- a unifies with Int
k (x::Int) False = ...
- w :: [b] -> [b]
+ w :: [b] -> [b]
w (x::a) = x -- a unifies with [b]
</ProgramListing>
<ProgramListing>
- f :: Int -> [a] -> [a]
- f n :: ([a] -> [a]) = let g (x::a, y::a) = (y,x)
- in \xs -> map g (reverse xs `zip` xs)
+ f :: Int -> [a] -> [a]
+ f n :: ([a] -> [a]) = let g (x::a, y::a) = (y,x)
+ in \xs -> map g (reverse xs `zip` xs)
</ProgramListing>
<ProgramListing>
- (\ (x::a, y) :: a -> x)
+ (\ (x::a, y) :: a -> x)
</ProgramListing>
<ProgramListing>
f1 (x::c) = f1 x -- ok
- f2 = \(x::c) -> f2 x -- not ok
+ f2 = \(x::c) -> f2 x -- not ok
</ProgramListing>
<ProgramListing>
- case e of { (x::a, y) :: a -> x }
+ case e of { (x::a, y) :: a -> x }
</ProgramListing>
<ProgramListing>
- case (True,False) of { (x::a, y) -> x }
+ case (True,False) of { (x::a, y) -> x }
</ProgramListing>
<ProgramListing>
- case (True,False) of { (x::Bool, y) -> x }
+ case (True,False) of { (x::Bool, y) -> x }
</ProgramListing>
<ProgramListing>
- \ x :: a -> b -> x
+ \ x :: a -> b -> x
</ProgramListing>
<ProgramListing>
- f :: (b->b) = \(x::b) -> x
+ f :: (b->b) = \(x::b) -> x
</ProgramListing>
<Para>
<ProgramListing>
- g :: a -> a -> Bool = \x y. x==y
+ g :: a -> a -> Bool = \x y. x==y
</ProgramListing>
</Para>
<ProgramListing>
data T = forall a. MkT [a]
- f :: T -> T
+ f :: T -> T
f (MkT [t::a]) = MkT t3
where
t3::[a] = [t,t,t]
<Literal>INLINE</Literal><IndexTerm><Primary>INLINE pragma</Primary></IndexTerm> pragma, used thusly:
<ProgramListing>
-key_function :: Int -> String -> (Bool, Double)
+key_function :: Int -> String -> (Bool, Double)
#ifdef __GLASGOW_HASKELL__
{-# INLINE key_function #-}
<Para>
<ProgramListing>
-hammeredLookup :: Ord key => [(key, value)] -> key -> value
+hammeredLookup :: Ord key => [(key, value)] -> key -> value
</ProgramListing>
</Para>
specialise it as follows:
<ProgramListing>
-{-# SPECIALIZE hammeredLookup :: [(Widget, value)] -> Widget -> value #-}
+{-# SPECIALIZE hammeredLookup :: [(Widget, value)] -> Widget -> value #-}
</ProgramListing>
</Para>
An example in which the <Literal>= blah</Literal> form will Win Big:
<ProgramListing>
-toDouble :: Real a => a -> Double
+toDouble :: Real a => a -> Double
toDouble = fromRational . toRational
-{-# SPECIALIZE toDouble :: Int -> Double = i2d #-}
+{-# SPECIALIZE toDouble :: Int -> Double = i2d #-}
i2d (I# i) = D# (int2Double# i) -- uses Glasgow prim-op directly
</ProgramListing>
Same idea, except for instance declarations. For example:
<ProgramListing>
-instance (Eq a) => Eq (Foo a) where { ... usual stuff ... }
+instance (Eq a) => Eq (Foo a) where { ... usual stuff ... }
{-# SPECIALIZE instance Eq (Foo [(Int, Bar)] #-}
</ProgramListing>
For example, here is the <Literal>foldr/build</Literal> rule:
<ProgramListing>
-"fold/build" forall k z (g::forall b. (a->b->b) -> b -> b) .
+"fold/build" forall k z (g::forall b. (a->b->b) -> b -> b) .
foldr k z (build g) = g k z
</ProgramListing>
to arbitrary expressions. For example, this is <Emphasis>not</Emphasis> OK:
<ProgramListing>
-"wrong1" forall e1 e2. case True of { True -> e1; False -> e2 } = e1
+"wrong1" forall e1 e2. case True of { True -> e1; False -> e2 } = e1
"wrong2" forall f. f True = True
</ProgramListing>
present in earlier version of GHC:
<ProgramListing>
- {-# SPECIALIZE fromIntegral :: Int8 -> Int16 = int8ToInt16 #-}
+ {-# SPECIALIZE fromIntegral :: Int8 -> Int16 = int8ToInt16 #-}
</ProgramListing>
This told GHC to use <Function>int8ToInt16</Function> instead of <Function>fromIntegral</Function> whenever
The defintion of (say) <Function>build</Function> in <FileName>PrelBase.lhs</FileName> looks llike this:
<ProgramListing>
- build :: forall a. (forall b. (a -> b -> b) -> b -> b) -> [a]
+ build :: forall a. (forall b. (a -> b -> b) -> b -> b) -> [a]
{-# INLINE build #-}
build g = g (:) []
</ProgramListing>