%
-% $Id: libraries.vsgml,v 1.2 1998/08/25 18:07:57 sof Exp $
+% $Id: libraries.vsgml,v 1.3 1998/12/02 13:20:40 simonm Exp $
%
% GHC Prelude and Libraries.
%
<tag>@fromInt@ method in class @Num@:</tag> It's there. Converts from
an @Int@ to the type.
-<tag>@toInt@ method in class @Integral@:</tag> Converts from type type
-to an @Int@.
+<tag>@toInt@ method in class @Integral@:</tag> Converts from Integral
+type to an @Int@.
</descrip>
GHC also internally uses a number of modules that begin with the
-string @Prel@: for this reason, we don't recommend that you use any
-module names beginning with @Prel@ in your own programs. The @Prel@
-modules are always available: in fact, you can get access to several
-extensions this way (for some you might need to give the
-@-fglasgow-exts@<nidx>-fglasgow-exts option</nidx> flag).
+string @Prel@<nidx>Prel module prefix</nidx>: for this reason, we
+don't recommend that you use any module names beginning with @Prel@ in
+your own programs. The @Prel@ modules are always available: in fact,
+you can get access to several extensions this way (for some you might
+need to give the @-fglasgow-exts@<nidx>-fglasgow-exts option</nidx>
+flag).
<sect1>The module @PrelGHC@: really primitive stuff
<label id="ghc-libs-ghc">
<p>
+<nidx>PrelGHC module</nidx>
-This section defines all the types which are primitive in Glasgow
+This module defines all the types which are primitive in Glasgow
Haskell, and the operations provided for them.
A primitive type is one which cannot be defined in Haskell, and which
is therefore built into the language and compiler. Primitive types
-are always unboxed; that is, a value of primitive type cannot be
-bottom.
+are always unlifted; that is, a value of primitive type cannot be
+bottom. We use the convention that primitive types, values, and
+operations have a @#@ suffix.
Primitive values are often represented by a simple bit-pattern, such
as @Int#@, @Float#@, @Double#@. But this is not necessarily the case:
a primitive value might be represented by a pointer to a
heap-allocated object. Examples include @Array#@, the type of
-primitive arrays. You might think this odd: doesn't being
-heap-allocated mean that it has a box? No, it does not. 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.
-
-This section also describes a few non-primitive types, which are needed
-to express the result types of some primitive operations.
+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.
+
+<sect2>Unboxed Tuples
+<label id="unboxed-tuples">
+<p>
+
+Unboxed tuples aren't really exported by @PrelGHC@, they're available
+by default with @-fglasgow-exts@. An unboxed tuple looks like this:
+
+<tscreen><verb>
+(# e_1, ..., e_n #)
+</verb></tscreen>
+
+where @e_1..e_n@ are expressions of any type (primitive or
+non-primitive). The type of an unboxed tuple looks the same.
+
+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.
+
+There are some pretty stringent restrictions on the use of unboxed tuples:
+
+<itemize>
+
+<item> 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.
+
+<item> Unboxed tuples may only be constructed as the direct result of
+a function, and may only be deconstructed with a @case@ expression.
+eg. the following are valid:
+
+<tscreen><verb>
+f x y = (# x+1, y-1 #)
+g x = case f x x of { (# a, b #) -> a + b }
+</verb></tscreen>
+
+but the following are invalid:
+
+<tscreen><verb>
+f x y = g (# x, y #)
+g (# x, y #) = x + y
+</verb></tscreen>
+
+<item> No variable can have an unboxed tuple type. This is illegal:
+
+<tscreen><verb>
+f :: (# Int, Int #) -> (# Int, Int #)
+f x = x
+</verb></tscreen>
+
+because @x@ has an unboxed tuple type.
+
+</itemize>
+
+Note: we may relax some of these restrictions in the future.
+
+The @IO@ and @ST@ monads use unboxed tuples to avoid unnecessary
+allocation during sequences of operations.
<sect2>Character and numeric types
<p>
<ncdx>Double#</ncdx>
If you really want to know their exact equivalents in C, see
-@ghc/includes/StgTypes.lh@ in the GHC source tree.
+@ghc/includes/StgTypes.h@ in the GHC source tree.
Literals for these types may be written as follows:
<sect2> Primitive-character operations
<p>
-<nidx>characters, primitive</nidx>
+<nidx>characters, primitive operations</nidx>
<nidx>operators, primitive character</nidx>
<tscreen><verb>
<sect2> Primitive-@Int@ operations
<p>
-<nidx>integers, primitive</nidx>
+<nidx>integers, primitive operations</nidx>
<nidx>operators, primitive integer</nidx>
<tscreen><verb>
(And the same for @Float#@s.)
<sect2>Operations on/for @Integers@ (interface to GMP)
-<label id="horrid-Integer-pairing-types">
+<label id="integer-operations">
<p>
<nidx>arbitrary precision integers</nidx>
<nidx>Integer, operations on</nidx>
We implement @Integers@ (arbitrary-precision integers) using the GNU
-multiple-precision (GMP) package (version 1.3.2).
-
-<bf>Note:</bf> some of this might change when we upgrade to using
-GMP~2.x.
+multiple-precision (GMP) package (version 2.0.2).
The data type for @Integer@ must mirror that for @MP_INT@ in @gmp.h@
(see @gmp.info@ in @ghc/includes/runtime/gmp@). It comes out as:
So, @Integer@ is really just a ``pairing'' type for a particular
collection of primitive types.
-The operations in the GMP return other combinations of
-GMP-plus-something, so we need ``pairing'' types for those, too:
-
-<tscreen><verb>
-data Return2GMPs = Return2GMPs Int# Int# ByteArray# Int# Int# ByteArray#
-data ReturnIntAndGMP = ReturnIntAndGMP Int# Int# Int# ByteArray#
-
--- ????? something to return a string of bytes (in the heap?)
-</verb></tscreen>
-<ncdx>Return2GMPs</ncdx>
-<ncdx>ReturnIntAndGMP</ncdx>
-
The primitive ops to support @Integers@ use the ``pieces'' of the
representation, and are as follows:
not# :: Word# -> Word#
-shiftL#, shiftRL# :: Word# -> Int# -> Word#
- -- shift left, right logical
+shiftL#, shiftRA#, shiftRL# :: Word# -> Int# -> Word#
+ -- shift left, right arithmetic, right logical
int2Word# :: Int# -> Word# -- just a cast, really
word2Int# :: Word# -> Int#
<ncdx>quotWord#</ncdx>
<ncdx>remWord#</ncdx>
<ncdx>shiftL#</ncdx>
+<ncdx>shiftRA#</ncdx>
<ncdx>shiftRL#</ncdx>
<ncdx>int2Word#</ncdx>
<ncdx>word2Int#</ncdx>
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 lifted value, but I don't like it!
+return a single element unboxed tuple (see Section <ref name="Unboxed
+Tuples" id="unboxed-tuples">).
<tscreen><verb>
-indexArray# :: Array# elt -> Int# -> PrelBase.Lift elt -- Yuk!
+indexArray# :: Array# elt -> Int# -> (# elt #)
</verb></tscreen>
<ncdx>indexArray#</ncdx>
The type @GHC.RealWorld@ is truly opaque: there are no values defined
of this type, and no operations over it. It is ``primitive'' in that
-sense - but it is <em>not unboxed!</em> Its only role in life is to be
+sense - but it is <em>not unlifted!</em> Its only role in life is to be
the type which distinguishes the @IO@ state transformer.
<tscreen><verb>
A single, primitive, value of type @State# RealWorld@ is provided.
<tscreen><verb>
-realWorld# :: State# GHC.RealWorld
+realWorld# :: State# RealWorld
</verb></tscreen>
<nidx>realWorld# state object</nidx>
(Note: in the compiler, not a @PrimOp@; just a mucho magic
@Id@. Exported from @GHC@, though).
-<sect2>State pairing types
-<p>
-<label id="horrid-pairing-types">
-
-This subsection defines some types which, while they aren't quite
-primitive because we can define them in Haskell, are very nearly so.
-They define constructors which pair a primitive state with a value of
-each primitive type. They are required to express the result type of
-the primitive operations in the state monad.
-<tscreen><verb>
-data StateAndPtr# s elt = StateAndPtr# (State# s) elt
-
-data StateAndChar# s = StateAndChar# (State# s) Char#
-data StateAndInt# s = StateAndInt# (State# s) Int#
-data StateAndWord# s = StateAndWord# (State# s) Word#
-data StateAndFloat# s = StateAndFloat# (State# s) Float#
-data StateAndDouble# s = StateAndDouble# (State# s) Double#
-data StateAndAddr# s = StateAndAddr# (State# s) Addr#
-
-data StateAndStablePtr# s a = StateAndStablePtr# (State# s) (StablePtr# a)
-data StateAndForeignObj# s = StateAndForeignObj# (State# s) ForeignObj#
-data StateAndSynchVar# s a = StateAndSynchVar# (State# s) (SynchVar# a)
-
-data StateAndArray# s elt = StateAndArray# (State# s) (Array# elt)
-data StateAndMutableArray# s elt = StateAndMutableArray# (State# s) (MutableArray# s elt)
-data StateAndByteArray# s = StateAndByteArray# (State# s) ByteArray#
-data StateAndMutableByteArray# s = StateAndMutableByteArray# (State# s) (MutableByteArray# s)
-</verb></tscreen>
-
-Hideous.
-
<sect2>Mutable arrays
<p>
<label id="sect:mutable">
worry about GC striking with a partly-initialised array.
<tscreen><verb>
-newArray# :: Int# -> elt -> State# s -> StateAndMutableArray# s elt
+newArray# :: Int# -> elt -> State# s -> (# State# s, MutableArray# s elt #)
-newCharArray# :: Int# -> State# s -> StateAndMutableByteArray# s
-newIntArray# :: Int# -> State# s -> StateAndMutableByteArray# s
-newAddrArray# :: Int# -> State# s -> StateAndMutableByteArray# s
-newFloatArray# :: Int# -> State# s -> StateAndMutableByteArray# s
-newDoubleArray# :: Int# -> State# s -> StateAndMutableByteArray# s
+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 #)
</verb></tscreen>
<ncdx>newArray#</ncdx>
<ncdx>newCharArray#</ncdx>
<nidx>arrays, reading and writing</nidx>
<tscreen><verb>
-readArray# :: MutableArray# s elt -> Int# -> State# s -> StateAndPtr# s elt
-readCharArray# :: MutableByteArray# s -> Int# -> State# s -> StateAndChar# s
-readIntArray# :: MutableByteArray# s -> Int# -> State# s -> StateAndInt# s
-readAddrArray# :: MutableByteArray# s -> Int# -> State# s -> StateAndAddr# s
-readFloatArray# :: MutableByteArray# s -> Int# -> State# s -> StateAndFloat# s
-readDoubleArray# :: MutableByteArray# s -> Int# -> State# s -> StateAndDouble# s
+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
by copying the array and then using @unsafeFreeze@.)
<tscreen><verb>
-unsafeFreezeArray# :: MutableArray# s elt -> State# s -> StateAndArray# s elt
-unsafeFreezeByteArray# :: MutableByteArray# s -> State# s -> StateAndByteArray# s
+unsafeFreezeArray# :: MutableArray# s elt -> State# s -> (# State# s, Array# s elt #)
+unsafeFreezeByteArray# :: MutableByteArray# s -> State# s -> (# State# s, ByteArray# #)
</verb></tscreen>
<ncdx>unsafeFreezeArray#</ncdx>
<ncdx>unsafeFreezeByteArray#</ncdx>
copies.
<tscreen><verb>
-makeStablePointer# :: a -> State# RealWorld -> StateAndStablePtr# RealWorld a
+makeStablePointer# :: a -> State# RealWorld -> (# State# RealWord, StablePtr# a #)
freeStablePointer# :: StablePtr# a -> State# RealWorld -> State# RealWorld
-deRefStablePointer# :: StablePtr# a -> State# RealWorld -> StateAndPtr RealWorld a
+deRefStablePointer# :: StablePtr# a -> State# RealWorld -> (# State# RealWorld, a #)
</verb></tscreen>
<ncdx>makeStablePointer#</ncdx>
<ncdx>freeStablePointer#</ncdx>
makeForeignObj#
:: Addr# -- foreign reference
-> Addr# -- pointer to finalisation routine
- -> StateAndForeignObj# RealWorld ForeignObj#
+ -> (# State# RealWorld, ForeignObj# )
writeForeignObj
:: ForeignObj# -- foreign object
-> Addr# -- datum
the operational behaviour of these operations).
<tscreen><verb>
-type SynchVar# s elt -- primitive
+type MVar# s elt -- primitive
-newSynchVar#:: State# s -> StateAndSynchVar# s elt
-takeMVar# :: SynchVar# s elt -> State# s -> StateAndPtr# s elt
+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
</verb></tscreen>
<ncdx>SynchVar#</ncdx>
<ncdx>takeMVar</ncdx>
<ncdx>putMVar</ncdx>
-<sect2>@spark#@ primitive operation (for parallel execution)
-<p>
-<nidx>spark primitive operation</nidx>
-
-<em>ToDo: say something</em> It's used in the unfolding for @par@.
-
-<sect2>The @errorIO#@ primitive operation
-<p>
-<nidx>errors, primitive</nidx>
-
-The @errorIO#@ primitive takes an argument much like @IO@. It aborts
-execution of the current program, and continues instead by performing
-the given @IO@-like value on the current state of the world.
-
-<tscreen><verb>
-errorIO# :: (State# RealWorld# -> a) -> a
-</verb></tscreen>
-<ncdx>errorIO#</ncdx>
-
<sect1>GHC/Hugs Extension Libraries
<p>
newIntArray :: Ix ix => (ix,ix) -> ST s (MutableByteArray s ix)
newFloatArray :: Ix ix => (ix,ix) -> ST s (MutableByteArray s ix)
newDoubleArray :: Ix ix => (ix,ix) -> ST s (MutableByteArray s ix)
-
+
boundsOfArray :: Ix ix => MutableArray s ix elt -> (ix, ix)
boundsOfByteArray :: Ix ix => MutableByteArray s ix -> (ix, ix)
-
-
-readArray :: Ix ix => MutableArray s ix elt -> ix -> ST s elt
-
+
+
+readArray :: Ix ix => MutableArray s ix elt -> ix -> ST s elt
+
readCharArray :: Ix ix => MutableByteArray s ix -> ix -> ST s Char
readIntArray :: Ix ix => MutableByteArray s ix -> ix -> ST s Int
readAddrArray :: Ix ix => MutableByteArray s ix -> ix -> ST s Addr
readFloatArray :: Ix ix => MutableByteArray s ix -> ix -> ST s Float
readDoubleArray :: Ix ix => MutableByteArray s ix -> ix -> ST s Double
-
-writeArray :: Ix ix => MutableArray s ix elt -> ix -> elt -> ST s ()
+
+writeArray :: Ix ix => MutableArray s ix elt -> ix -> elt -> ST s ()
writeCharArray :: Ix ix => MutableByteArray s ix -> ix -> Char -> ST s ()
writeIntArray :: Ix ix => MutableByteArray s ix -> ix -> Int -> ST s ()
writeAddrArray :: Ix ix => MutableByteArray s ix -> ix -> Addr -> ST s ()
writeFloatArray :: Ix ix => MutableByteArray s ix -> ix -> Float -> ST s ()
writeDoubleArray :: Ix ix => MutableByteArray s ix -> ix -> Double -> ST s ()
-
-freezeArray :: Ix ix => MutableArray s ix elt -> ST s (Array ix elt)
+
+freezeArray :: Ix ix => MutableArray s ix elt -> ST s (Array ix elt)
freezeCharArray :: Ix ix => MutableByteArray s ix -> ST s (ByteArray ix)
freezeIntArray :: Ix ix => MutableByteArray s ix -> ST s (ByteArray ix)
freezeAddrArray :: Ix ix => MutableByteArray s ix -> ST s (ByteArray ix)
thawArray :: Ix ix => Array ix elt -> ST s (MutableArray s ix elt)
</verb></tscreen>
-%ToDo: index these.
+<nidx>newArray</nidx>
+<nidx>newCharArray</nidx>
+<nidx>newAddrArray</nidx>
+<nidx>newIntArray</nidx>
+<nidx>newFloatArray</nidx>
+<nidx>newDoubleArray</nidx>
+<nidx>boundsOfArray</nidx>
+<nidx>boundsOfByteArray</nidx>
+<nidx>readArray</nidx>
+<nidx>readCharArray</nidx>
+<nidx>readIntArray</nidx>
+<nidx>readAddrArray</nidx>
+<nidx>readFloatArray</nidx>
+<nidx>readDoubleArray</nidx>
+<nidx>writeArray</nidx>
+<nidx>writeCharArray</nidx>
+<nidx>writeIntArray</nidx>
+<nidx>writeAddrArray</nidx>
+<nidx>writeFloatArray</nidx>
+<nidx>writeDoubleArray</nidx>
+<nidx>freezeArray</nidx>
+<nidx>freezeCharArray</nidx>
+<nidx>freezeIntArray</nidx>
+<nidx>freezeAddrArray</nidx>
+<nidx>freezeFloatArray</nidx>
+<nidx>freezeDoubleArray</nidx>
+<nidx>unsafeFreezeArray</nidx>
+<nidx>unsafeFreezeByteArray</nidx>
+<nidx>thawArray</nidx>
<sect2>The @ByteArray@ interface
<label id="sec:byte-array">