The GHC prelude and libraries
This document describes GHC's prelude and libraries. The basic story is that of the Haskell 1.4 Report and Libraries document (which we do not reproduce here), but this document describes in addition:
GHC's additional non-standard libraries and types, such as state
transformers, packed strings, foreign objects, stable pointers, and so on.
GHC's primitive types and operations. The standard Haskell functions are
implemented on top of these, and it is sometimes useful to use them
directly.
The organisation of these libraries into directories.
Short description of programmer interface to the non-standard
libraries provided in addition to the standard prelude.
A number of the libraries that provide access to GHC's language
extensions are shared by Hugs, and are described in the GHC/Hugs Extension Libraries document.
Prelude extensions
GHC's prelude contains the following non-standard extensions:
fromInt method in class Num:
It's there. Converts from
an Int to the type.
toInt method in class Integral:
Converts from Integral
type to an Int.
GHC also internally uses a number of modules that begin with the
string PrelPrel module prefix: 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 option
flag).
GHC-only Extension Librarieslibraries, ghc-onlyextension libraries, ghc-only
If you rely on the implicit import Prelude that GHC normally does
for you, and if you don't use any weird flags (notably
), and if you don't import the Glasgow extensions
interface, GlaExts, then GHC should work exactly as the
Haskell report says (modulo a few minor issues, see ).
If you turn on , a new world opens up to you and the compiler
will recognise and parse unboxed values properly, and provide access to the
various interfaces libraries described here (and piles of other goodies.)
The module PrelGHC: really primitive stuff
PrelGHC module
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 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. 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.
Unboxed Tuples
Unboxed tuples aren't really exported by PrelGHC, they're available
by default with . An unboxed tuple looks like this:
(# e_1, ..., e_n #)
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:
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.
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:
f x y = (# x+1, y-1 #)
g x = case f x x of { (# a, b #) -> a + b }
but the following are invalid:
f x y = g (# x, y #)
g (# x, y #) = x + y
No variable can have an unboxed tuple type. This is illegal:
f :: (# Int, Int #) -> (# Int, Int #)
f x = x
because x has an unboxed tuple type.
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.
Character and numeric typescharacter types, primitivenumeric types, primitiveinteger types, primitivefloating point types, primitive
There are the following obvious primitive types:
type Char#
type Int# -- see also Word# and Addr#, later
type Float#
type Double#
Char#Int#Float#Double#
If you really want to know their exact equivalents in C, see
ghc/includes/StgTypes.h in the GHC source tree.
Literals for these types may be written as follows:
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 *')
literals, primitiveconstants, primitivenumbers, primitiveComparison operationscomparisons, primitiveoperators, comparison
{>,>=,==,/=,<,<=}# :: Int# -> Int# -> Bool
{gt,ge,eq,ne,lt,le}Char# :: Char# -> Char# -> Bool
-- ditto for Word# and Addr#
>#>=#==#/=#<#<=#gt{Char,Word,Addr}#ge{Char,Word,Addr}#eq{Char,Word,Addr}#ne{Char,Word,Addr}#lt{Char,Word,Addr}#le{Char,Word,Addr}#Primitive-character operationscharacters, primitive operationsoperators, primitive character
ord# :: Char# -> Int#
chr# :: Int# -> Char#
ord#chr#Primitive-Int operationsintegers, primitive operationsoperators, primitive integer
{+,-,*,quotInt,remInt}# :: Int# -> Int# -> Int#
negateInt# :: Int# -> Int#
iShiftL#, iShiftRA#, iShiftRL# :: Int# -> Int# -> Int#
-- shift left, right arithmetic, right logical
+#-#*#quotInt#remInt#iShiftL#iShiftRA#iShiftRL#shift operations, integerNote: No error/overflow checking!
Primitive-Double and Float operationsfloating point numbers, primitiveoperators, primitive floating point
{+,-,*,/}## :: 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#
+##-##*##/##<##<=##==##=/##>=##>##negateDouble#double2Int#int2Double#plusFloat#minusFloat#timesFloat#divideFloat#gtFloat#geFloat#eqFloat#neFloat#ltFloat#leFloat#negateFloat#float2Int#int2Float#
And a full complement of trigonometric functions:
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#
trigonometric functions, primitive
similarly for Float#.
There are two coercion functions for Float#/Double#:
float2Double# :: Float# -> Double#
double2Float# :: Double# -> Float#
float2Double#double2Float#
The primitive versions of encodeDouble/decodeDouble:
encodeDouble# :: Int# -> Int# -> ByteArray# -- Integer mantissa
-> Int# -- Int exponent
-> Double#
decodeDouble# :: Double# -> PrelNum.ReturnIntAndGMP
encodeDouble#decodeDouble#
(And the same for Float#s.)
Operations on/for Integers (interface to GMP)
arbitrary precision integersInteger, operations on
We implement Integers (arbitrary-precision integers) using the GNU
multiple-precision (GMP) package (version 2.0.2).
The data type for Integer is either a small integer,
represented by an Int, or a large integer represented
using the pieces required by GMP's MP_INT in gmp.h
(see gmp.info in ghc/includes/runtime/gmp). It comes out as:
data Integer = S# Int# -- small integers
| J# Int# ByteArray# -- large integers
Integer type
The primitive ops to support large Integers use the “pieces” of the
representation, and are as follows:
negateInteger# :: Int# -> ByteArray# -> Integer
{plus,minus,times}Integer# :: Int# -> ByteArray#
-> Int# -> ByteArray#
-> Integer
cmpInteger# :: Int# -> ByteArray#
-> Int# -> ByteArray#
-> Int# -- -1 for <; 0 for ==; +1 for >
divModInteger#, quotRemInteger#
:: Int# -> ByteArray#
-> Int# -> ByteArray#
-> PrelNum.Return2GMPs
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.
negateInteger#plusInteger#minusInteger#timesInteger#cmpInteger#divModInteger#quotRemInteger#integer2Int#int2Integer#word2Integer#addr2Integer#Words and addressesword, primitive typeaddress, primitive typeunsigned integer, primitive typepointer, primitive type
A Word# is used for bit-twiddling operations. It is the same size as
an Int#, but has no sign nor any arithmetic operations.
type Word# -- Same size/etc as Int# but *unsigned*
type Addr# -- A pointer from outside the "Haskell world" (from C, probably);
-- described under "arrays"
Word#Addr#Word#s and Addr#s have the usual comparison operations.
Other unboxed-Word ops (bit-twiddling and coercions):
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#, shiftRA#, shiftRL# :: Word# -> Int# -> Word#
-- shift left, right arithmetic, right logical
int2Word# :: Int# -> Word# -- just a cast, really
word2Int# :: Word# -> Int#
bit operations, Word and Addrand#or#xor#not#quotWord#remWord#shiftL#shiftRA#shiftRL#int2Word#word2Int#
Unboxed-Addr ops (C casts, really):
int2Addr# :: Int# -> Addr#
addr2Int# :: Addr# -> Int#
int2Addr#addr2Int#
The casts between Int#, Word# and Addr# correspond to null
operations at the machine level, but are required to keep the Haskell
type checker happy.
Operations for indexing off of C pointers (Addr#s) to snatch values
are listed under “arrays”.
Arraysarrays, primitive
The type Array# elt is the type of primitive, unpointed arrays of
values of type elt.
type Array# elt
Array#Array# is more primitive than a Haskell array—indeed, the
Haskell Array interface is implemented using Array#—in that an
Array# is indexed only by Int#s, starting at zero. It is also
more primitive by virtue of being unboxed. That doesn't mean that it
isn't a heap-allocated object—of course, it is. Rather, being
unboxed means that it is represented by a pointer to the array itself,
and not to a thunk which will evaluate to the array (or to bottom).
The components of an Array# are themselves boxed.
The type ByteArray# is similar to Array#, except that it contains
just a string of (non-pointer) bytes.
type ByteArray#
ByteArray#
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, ByteArray# is deliberately
a bit vague about the type of its components. Operations are provided
to extract values of type Char#, Int#, Float#, Double#, and
Addr# from arbitrary offsets within a ByteArray#. (For type
Foo#, the $i$th offset gets you the $i$th Foo#, not the Foo# at
byte-position $i$. Mumble.) (If you want a Word#, grab an Int#,
then coerce it.)
Lastly, we have static byte-arrays, of type Addr# [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 ByteArray#. They
are only needed in order to pass values from C to Haskell.
Reading and writing
Primitive arrays are linear, and indexed starting at zero.
The size and indices of a ByteArray#, Addr#, and
MutableByteArray# 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 ByteArray# 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)
Should we provide some sizeOfDouble# constants?
Out-of-range errors on indexing should be caught by the code which
uses the primitive operation; the primitive operations themselves do
not check for out-of-range indexes. The intention is that the
primitive ops compile to one machine instruction or thereabouts.
We use the terms “reading” and “writing” to refer to accessing
mutable arrays (see ), and
“indexing” to refer to reading a value from an immutable
array.
Immutable byte arrays are straightforward to index (all indices in bytes):
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
indexCharArray#indexIntArray#indexAddrArray#indexFloatArray#indexDoubleArray#indexCharOffAddr#indexIntOffAddr#indexFloatOffAddr#indexDoubleOffAddr#indexAddrOffAddr#
The last of these, indexAddrOffAddr#, extracts an Addr# using an offset
from another Addr#, thereby providing the ability to follow a chain of
C pointers.
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 ).
indexArray# :: Array# elt -> Int# -> (# elt #)
indexArray#The state typestate, primitive typeState#
The primitive type State# 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 only effect of this parameterisation is in the type
system: all values of type State# 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.
type State# s
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 not unlifted! Its only role in life is to be
the type which distinguishes the IO state transformer.
data RealWorld
State of the world
A single, primitive, value of type State# RealWorld is provided.
realWorld# :: State# RealWorld
realWorld# state object
(Note: in the compiler, not a PrimOp; just a mucho magic
Id. Exported from GHC, though).
Mutable arraysmutable arraysarrays, mutable
Corresponding to Array# and ByteArray#, we have the types of
mutable versions of each. In each case, the representation is a
pointer to a suitable block of (mutable) heap-allocated storage.
type MutableArray# s elt
type MutableByteArray# s
MutableArray#MutableByteArray#Allocationmutable arrays, allocationarrays, allocationallocation, of mutable arrays
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.
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 #)
newArray#newCharArray#newIntArray#newAddrArray#newFloatArray#newDoubleArray#
The size of a ByteArray# is given in bytes.
Reading and writingarrays, reading and writing
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
readArray#readCharArray#readIntArray#readAddrArray#readFloatArray#readDoubleArray#writeArray#writeCharArray#writeIntArray#writeAddrArray#writeFloatArray#writeDoubleArray#Equalityarrays, testing for equality
One can take “equality” of mutable arrays. What is compared is the
name or reference to the mutable array, not its contents.
sameMutableArray# :: MutableArray# s elt -> MutableArray# s elt -> Bool
sameMutableByteArray# :: MutableByteArray# s -> MutableByteArray# s -> Bool
sameMutableArray#sameMutableByteArray#Freezing mutable arraysarrays, freezing mutablefreezing mutable arraysmutable arrays, freezing
Only unsafe-freeze has a primitive. (Safe freeze is done directly in Haskell
by copying the array and then using unsafeFreeze.)
unsafeFreezeArray# :: MutableArray# s elt -> State# s -> (# State# s, Array# s elt #)
unsafeFreezeByteArray# :: MutableByteArray# s -> State# s -> (# State# s, ByteArray# #)
unsafeFreezeArray#unsafeFreezeByteArray#Synchronizing variables (M-vars)synchronising variables (M-vars)M-Vars
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).
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
SynchVar#newSynchVar#takeMVarputMVar