<!-- UNBOXED TYPES AND PRIMITIVE OPERATIONS -->

<sect1 id="primitives">
  <title>Unboxed types and primitive operations</title>
  <indexterm><primary>GHC.Exts module</primary></indexterm>

  <para>This chapter defines all the types which are primitive in
  Glasgow Haskell, and the operations provided for them. You bring
  them into scope by importing module <literal>GHC.Exts</literal>.</para>

  <para>Note: while you really can use this stuff to write fast code,
  we generally find it a lot less painful, and more satisfying in the
  long run, to use higher-level language features and libraries.  With
  any luck, the code you write will be optimised to the efficient
  unboxed version in any case.  And if it isn't, we'd like to know
  about it.</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>

<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>

<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.
</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).
</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.
</para>

</sect2>

<sect2 id="unboxed-tuples">
<title>Unboxed Tuples
</title>

<para>
Unboxed tuples aren't really exported by <literal>GHC.Exts</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.
</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 #) -&#62; 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 #) -&#62; (# Int, Int #)
f x = x
</programlisting>


because <literal>x</literal> 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>

<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>
<para>
There are the following obvious primitive types:
</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.
</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 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>
</para>

</sect2>

<sect2>
<title>Comparison operations</title>

<para>
<indexterm><primary>comparisons, primitive</primary></indexterm>
<indexterm><primary>operators, comparison</primary></indexterm>
</para>

<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#
</programlisting>

<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>

<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# -&#62; Int#
chr# :: Int# -&#62; Char#
</programlisting>

<indexterm><primary><literal>ord&num;</literal></primary></indexterm>
<indexterm><primary><literal>chr&num;</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# -&#62; Int# -&#62; Int#
negateInt# :: Int# -&#62; Int#

iShiftL#, iShiftRA#, iShiftRL# :: Int# -&#62; Int# -&#62; Int#
        -- shift left, right arithmetic, right logical

addIntC#, subIntC#, mulIntC# :: Int# -> Int# -> (# Int#, Int# #)
	-- add, subtract, multiply with carry
</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!
</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# -&#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#
</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>
</para>

<para>
And a full complement of trigonometric functions:
</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#
</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 are in
units of the size of the object being read):

<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>

<sect2 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 the module <literal>Foreign.StablePtr</literal> in the
library documentation 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 module <literal>Foreign.ForeignPtr</literal> in the library
documentatation 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>

</sect2>

</sect1>

<!-- Emacs stuff:
     ;;; Local Variables: ***
     ;;; mode: sgml ***
     ;;; sgml-parent-document: ("users_guide.sgml" "book" "chapter" "sect1") ***
     ;;; End: ***
 -->
