The Glorious Glasgow Haskell Compilation System Version 0.26 User's Guide

The AQUA Team Department of Computing Science University of Glasgow Glasgow, Scotland G12 8QQ Email: glasgow-haskell-{bugs,users}-request@dcs.glasgow.ac.uk

Introduction to GHC

This is a guide to using the Glasgow Haskell compilation (GHC) system. It is a batch compiler for the Haskell 1.2 language, with support for various extensions, including the DRAFT 1.3 I/O proposal.

Many people will use GHC very simply: compile some modules -- ghc -c -O Foo.hs Bar.hs; and link them -- ghc -o wiggle -O Foo.o Bar.o.

But if you need to do something more complicated, GHC can do that, too:

ghc -c -O -fno-foldr-build -dcore-lint -fvia-C -ddump-simpl Foo.lhs

Stay tuned -- all will be revealed!

In this document, we assume that GHC has been installed at your site as ghc. If you are unfamiliar with the conventions of UNIX compilers, the material in part compiler-tutorial may help.

Knowing us, knowing you: Web sites, mailing lists, etc.

On the World-Wide Web, there are several URLs of likely interest:

GHC home page -- http://www.dcs.glasgow.ac.uk/fp/software/ghc/
Glasgow FP group page -- http://www.dcs.glasgow.ac.uk/fp/
comp.lang.functional FAQ -- http://www.cs.nott.ac.uk/Department/Staff/mpj/faq.html
programming language research page --
   http://www.cs.cmu.edu/afs/cs.cmu.edu/user/mleone/web/language-research.html



We run two mailing lists about Glasgow Haskell. We encourage you to join, as you feel is appropriate.

glasgow-haskell-users:
This list is for GHC users to chat among themselves. Subscribe by sending mail to majordomo@dcs.gla.ac.uk, with a message body (not header) like this:
subscribe glasgow-haskell-users My Name <m.y.self@bigbucks.com>

(The last bit is your all-important e-mail address, of course.)

To communicate with your fellow users, send mail to glasgow-haskell-users.

To contact the list administrator, send mail to glasgow-haskell-users-request.

glasgow-haskell-bugs:
Send bug reports for GHC to this address! The sad and lonely people who subscribe to this list will muse upon what's wrong and what you might do about it.

Subscribe via majordomo@dcs.gla.ac.uk with:

subscribe glasgow-haskell-bugs My Name <m.y.self@hackers.r.us>

Again, you may contact the list administrator at glasgow-haskell-bugs-request.

There is also the general Haskell mailing list. Subscribe by sending email to majordomo@dcs.gla.ac.uk, with the usual message body:

subscribe haskell My Name <m.y.self@fp.rules.ok.org>

Some Haskell-related discussion takes place in the Usenet newsgroup comp.lang.functional. (But note: news propagation to Glasgow can be terrible. That's one reason Glaswegians aren't too active in c.f.l.)

The main anonymous-FTP site for Glasgow Haskell is ftp.dcs.glasgow.ac.uk, in pub/haskell/glasgow/. "Important" bits are mirrored at other Haskell archive sites (and we have their stuff, too).

Invoking GHC: Command-line options

Command-line arguments are either options or file names.

Command-line options begin with -. They may not be grouped: -vO is different from -v -O. Options need not precede filenames: e.g., ghc *.o -o foo. All options are processed and then apply to all files; you cannot, for example, invoke ghc -c -O1 Foo.hs -O2 Bar.hs to apply different optimisation levels to the files Foo.hs and Bar.hs. For conflicting options, e.g., -c -S, we reserve the right to do anything we want. (Usually, the last one applies.)

Options related to profiling, Glasgow extensions to Haskell (e.g., unboxed values), Concurrent and Parallel Haskell are described in part profiling}, part \ref{glasgow-exts, and part concurrent-and-parallel, respectively.

Meaningful file suffixes

File names with "meaningful" suffixes (e.g., .lhs or .o) cause the "right thing" to happen to those files.

.lhs:

A "literate Haskell" module.

.hs:
A not-so-literate Haskell module.

.hi:
A Haskell interface file, probably compiler-generated.

.hc:
Intermediate C file produced by the Haskell compiler.

.c:
A C file not produced by the Haskell compiler.

.s:
An assembly-language source file, usually produced by the compiler.

.o:
An object file, produced by an assembler.

Files with other suffixes (or without suffixes) are passed straight to the linker.

Help and verbosity options

A good option to start with is the -help (or -?) option.

GHC spews a long message to standard output and then exits.

The -v option makes GHC verbose: it reports its version number and shows (on stderr) exactly how it invokes each phase of the compilation system. Moreover, it passes the -v flag to most phases; each reports its version number (and possibly some other information).

Please, oh please, use the -v option when reporting bugs! Knowing that you ran the right bits in the right order is always the first thing we want to verify.

Running the right phases in the right order

The basic task of the ghc driver is to run each input file through the right phases (parsing, linking, etc.).

The first phase to run is determined by the input-file suffix, and the last phase is determined by a flag. If no relevant flag is present, then go all the way through linking. This table summarises:

phase of the                     suffix saying  flag saying   (suffix of)  
compilation system               "start here"   "stop after"  output file  
\hline

literate pre-processor .lhs - - C pre-processor (opt.) - - - Haskell parser .hs - - Haskell compiler - -C, -S .hc, .s C compiler (opt.) .hc or .c -S .s assembler .s -c .o linker other - a.out

Thus, a common invocation would be: ghc -c Foo.hs

Note: What the Haskell compiler proper produces depends on whether a native-code generator is used (producing assembly language) or not (producing C).

The option -cpp must be given for the C pre-processor phase to be run.

The option -E runs just the C-preprocessor part of the C-compiling phase, sending the result to stdout [I think]. (For debugging, usually.)

Optimisation (code improvement)

The -O* options specify convenient "packages" of optimisation flags; the -f* options described later on specify individual optimisations to be turned on/off; the -m* options specify machine-specific optimisations to be turned on/off.

-O*: convenient "packages" of optimisation flags.

There are many options that affect the quality of code produced by GHC. Most people only have a general goal, something like "Compile quickly" or "Make my program run like greased lightning." The following "packages" of optimisations (or lack thereof) should suffice.

Once you choose a -O* "package," stick with it -- don't chop and change. Modules' interfaces will change with a shift to a new -O* option, and you will have to recompile all importing modules before your program can again be run safely.

No -O*-type option specified:

This is taken to mean: "Please compile quickly; I'm not over-bothered about compiled-code quality." So, for example: ghc -c Foo.hs

-O or -O1:

Means: "Generate good-quality code without taking too long about it." Thus, for example: ghc -c -O Main.lhs

-O2:

Means: "Apply every non-dangerous optimisation, even if it means significantly longer compile times."

The avoided "dangerous" optimisations are those that can make runtime or space worse if you're unlucky. They are normally turned on or off individually.

As of version 0.26, -O2 is unlikely to produce better code than -O.

-fvia-C:

Compile via C, and don't use the native-code generator. (There are many cases when GHC does this on its own.) You might pick up a little bit of speed by compiling via C. If you use _ccall_s or _casm_s, you probably have to use -fvia-C.

-O2-for-C:

Says to run GCC with -O2, which may be worth a few percent in execution speed. Don't forget -fvia-C, lest you use the native-code generator and bypass GCC altogether!

-Onot:

This option will make GHC "forget" any -Oish options it has seen so far. Sometimes useful; for example: make all EXTRA_HC_OPTS=-Onot.

-Ofile <file>:

For those who need absolute control over exactly what options are used (e.g., compiler writers, sometimes :-), a list of options can be put in a file and then slurped in with -Ofile.

In that file, comments are of the #-to-end-of-line variety; blank lines and most whitespace is ignored.

Please ask if you are baffled and would like an example of -Ofile!

At Glasgow, we don't use a -O* flag for day-to-day work. We use -O to get respectable speed; e.g., when we want to measure something. When we want to go for broke, we tend to use -O -fvia-C -O2-for-C (and we go for lots of coffee breaks).

The easiest way to see what -O (etc) "really mean" is to run with -v, then stand back in amazement. Alternatively, just look at the @HsC_minus<blah> lists in the ghc driver script.

-f*: platform-independent flags

Flags can be turned off individually. (NB: I hope you have a good reason for doing this....) To turn off the -ffoo flag, just use the -fno-foo flag.

So, for example, you can say -O2 -fno-strictness, which will then drop out any running of the strictness analyser.

The options you are most likely to want to turn off are: -fno-update-analysis [because it is sometimes slow], -fno-strictness (strictness analyser [because it is sometimes slow]), -fno-specialise (automatic specialisation of overloaded functions [because it makes your code bigger]) [US spelling also accepted], and -fno-foldr-build [because no-one knows what Andy Gill made it do].

Should you wish to turn individual flags on, you are advised to use the -Ofile option, described above. Because the order in which optimisation passes are run is sometimes crucial, it's quite hard to do with command-line options.

Here are some "dangerous" optimisations you might want to try:

-funfolding-creation-threshold<n>:
(Default: 30) By raising or lowering this number, you can raise or lower the amount of pragmatic junk that gets spewed into interface files. (An unfolding has a "size" that reflects the cost in terms of "code bloat" of expanding that unfolding in another module. A bigger Core expression would be assigned a bigger cost.)

-funfolding-use-threshold<n>:
(Default: 3) By raising or lowering this number, you can make the compiler more or less keen to expand unfoldings.

OK, folks, these magic numbers `30' and `3' are mildly arbitrary; they are of the "seem to be OK" variety. The `3' is the more critical one; it's what determines how eager GHC is about expanding unfoldings.

-funfolding-override-threshold<n>:
(Default: 8) [Pretty obscure] When deciding what unfoldings from a module should be made available to the rest of the world (via this module's interface), the compiler normally likes "small" expressions.

For example, if it sees foo = bar, it will decide that the very small expression bar is a great unfolding for foo. But if bar turns out to be (True,False,True), we would probably prefer that for the unfolding for foo.

Should we "override" the initial small unfolding from foo=bar with the bigger-but-better one? Yes, if the bigger one's "size" is still under the "override threshold." You can use this flag to adjust this threshold (why, I'm not sure).

-fliberated-case-threshold<n>:
(Default: 12) [Vastly obscure: NOT IMPLEMENTED YET] "Case liberation" lifts evaluation out of recursive functions; it does this by duplicating code. Done without constraint, you can get serious code bloat; so we only do it if the "size" of the duplicated code is smaller than some "threshold." This flag can fiddle that threshold.

-fsemi-tagging:
This option (which does not work with the native-code generator) tells the compiler to add extra code to test for already-evaluated values. You win if you have lots of such values during a run of your program, you lose otherwise. (And you pay in extra code space.)

We have not played with -fsemi-tagging enough to recommend it. (For all we know, it doesn't even work in 0.26. Sigh.)

-m*: platform-specific flags

Some flags only make sense for particular target platforms.

-mlong-calls:
(HPPA machines)

Means to pass the like-named option to GCC. Required for Very Big modules, maybe. (Probably means you're in trouble...)

-monly-[432]-regs:
(iX86 machines)

GHC tries to "steal" five registers from GCC, for performance reasons; it almost always works. However, when GCC is compiling some modules with five stolen registers, it will crash, probably saying:

Foo.hc:533: fixed or forbidden register was spilled.
This may be due to a compiler bug or to impossible asm
statements or clauses.

Just give some registers back with -monly-N-regs. Try `4' first, then `3', then `2'. If `2' doesn't work, please report the bug to us.

Code improvement by the C compiler.

The C compiler, normally GCC, is run with -O turned on. (It has to be, actually.)

If you want to run GCC with -O2 -- which may be worth a few percent in execution speed -- you can give a -O2-for-C option.

Sanity-checking options

If you would like GHC to check that every top-level value has a type signature, use the -fsignatures-required option.

If you would like to disallow "name shadowing," i.e., an inner-scope value has the same name as an outer-scope value, then use the -fname-shadowing-not-ok option.

This option catches typographical errors that turn into hard-to-find bugs, e.g., in the inadvertent cyclic definition let x = ... x ... in.

Consequently, this option does not allow cyclic recursive definitions.

If you're feeling really paranoid, the -dcore-lint option is a good choice. It turns on heavyweight intra-pass sanity-checking within GHC. (It checks GHC's sanity, not yours.)

Re-directing the compilation output(s)

When compiling a Haskell module, GHC may produce several files of output (usually two).

One file is usually an interface file. If compiling bar/Foo.hs, the interface file would normally be bar/Foo.hi. The interface output may be directed to another file bar2/Wurble.iface with the option -ohi bar2/Wurble.iface .

To avoid generating an interface file at all, use a -nohi option.

The compiler does not overwrite an existing .hi interface file if the new one is byte-for-byte the same as the old one; this is friendly to make. When an interface does change, it is often enlightening to be informed. The -hi-diffs option will make ghc run diff on the old and new .hi files.

GHC's non-interface output normally goes into a .hc, .o, etc., file, depending on the last-run compilation phase. The option -o foo re-directs the output of that last-run phase to file foo.

Note: this "feature" can be counterintuitive: ghc -C -o foo.o foo.hs will put the intermediate C code in the file foo.o, name notwithstanding!

EXOTICA: But the -o option isn't much use if you have several input files... Non-interface output files are normally put in the same directory as their corresponding input file came from. You may specify that they be put in another directory using the -odir <dir> (the "Oh, dear" option). For example:

% ghc -c parse/Foo.hs parse/Bar.hs gurgle/Bumble.hs -odir `arch`

The output files, Foo.o, Bar.o, and Bumble.o would be put into a subdirectory named after the architecture of the executing machine (sun4, mips, etc). The directory must already exist; it won't be created.

Note that the -odir option does not affect where the interface files are put. In the above example, they would still be put in parse/Foo.hi, parse/Bar.hi, and gurgle/Bumble.hi.

MORE EXOTICA: The -osuf <suffix>

will change the .o file suffix for object files to whatever you specify. (We use this in compiling the prelude.)

Similarly, the -hisuf <suffix> will change the .hi file suffix for non-system interface files. This can be useful when you are trying to compile a program several ways, all in the same directory. The suffix given is used for all interfaces files written, and for all non-system interface files that your read.

The -hisuf/-osuf game is useful if you want to compile a program with both GHC and HBC (say) in the same directory. Let HBC use the standard .hi/.o suffixes; add -hisuf _g.hi -osuf _g.o to your make rule for GHC compiling...

FURTHER EXOTICA: If you are doing a normal .hs-to-.o compilation but would like to hang onto the intermediate .hc C file, just throw in a -keep-hc-file-too option . If you would like to look at the assembler output, toss in a -keep-s-file-too, too.

SAVING GHC STDERR OUTPUT: Sometimes, you may cause GHC to be rather chatty on standard error; with -fshow-import-specs, for example. You can instruct GHC to append this output to a particular log file with a -odump <blah> option.

TEMPORARY FILES: If you have trouble because of running out of space in /tmp/ (or wherever your installation thinks temporary files should go), you may use the -tmpdir <dir>

option to specify an alternate directory. For example, -tmpdir . says to put temporary files in the current working directory.

BETTER IDEA FOR TEMPORARY FILES: Use your TMPDIR environment variable. Set it to the name of the directory where temporary files should be put. GCC and other programs will honour the TMPDIR variable as well.

EVEN BETTER IDEA: Configure GHC with --with-tmpdir=<mumble> when you build it, and never worry about TMPDIR again.

For finding interface files, etc.

In your program, you import a module Foo by saying import Foo. GHC goes looking for an interface file, Foo.hi. It has a builtin list of directories (notably including .) where it looks.

The -i<dirs> option prepends a colon-separated list of dirs to the "import directories" list.

A plain -i resets the "import directories" list back to nothing.

GHC normally imports PreludeCore.hi and Prelude.hi files for you. If you'd rather it didn't, then give it a -fno-implicit-prelude option . (Sadly, it still has to find a PreludeNull_.hi file; it just won't feed it into the compiler proper.) You are unlikely to get very far without a Prelude, but, hey, it's a free country.

If you are using a system-supplied non-Prelude library (e.g., the HBC library), just use a -syslib hbc

option (for example). The right interface files should then be available.

Once a Haskell module has been compiled to C (.hc file), you may wish to specify where GHC tells the C compiler to look for .h files. (Or, if you are using the -cpp option , where it tells the C pre-processor to look...) For this purpose, use a -I<dir> in the usual C-ish way.

Pragmas: Interface files are normally jammed full of compiler-produced pragmas, which record arities, strictness info, etc. If you think these pragmas are messing you up (or you are doing some kind of weird experiment), you can tell GHC to ignore them with the -fignore-interface-pragmas

option.

See also chapter options-linker, which describes how the linker finds standard Haskell libraries.

Related to the C pre-processor

The C pre-processor cpp is run over your Haskell code only if the -cpp option is given. Unless you are building a large system with significant doses of conditional compilation, you really shouldn't need it.

-D<foo>:

Define macro <foo> in the usual way. NB: does not affect -D macros passed to the C compiler when compiling via C! For those, use the -optc-Dfoo hack...

-U<foo>:

Undefine macro <foo> in the usual way.

-I<dir>:

Specify a directory in which to look for #include files, in the usual UNIX/C way.

The ghc driver pre-defines several macros:

__HASKELL1__:

If defined to n, that means GHC supports the Haskell language defined in the Haskell report version 1.n. Currently 2.

NB: This macro is set both when pre-processing Haskell source and when pre-processing generated C (.hc) files.

If you give the -fhaskell-1.3 flag , then __HASKELL1__ is set to 3. Obviously.

__GLASGOW_HASKELL__:

For version n of the GHC system, this will be #defined to 100 \times n. So, for version 0.26, it is 26.

This macro is only set when pre-processing Haskell source. (Not when pre-processing generated C.)

With any luck, __GLASGOW_HASKELL__ will be undefined in all other implementations that support C-style pre-processing.

(For reference: the comparable symbols for other systems are: __YALE_HASKELL__ for Yale Haskell, __HBC__ for Chalmers HBC, and __GOFER__ for Gofer [I think].)

__CONCURRENT_HASKELL__:

Only defined when -concurrent is in use! This symbol is defined when pre-processing Haskell (input) and pre-processing C (GHC output).

__PARALLEL_HASKELL__:

Only defined when -parallel is in use! This symbol is defined when pre-processing Haskell (input) and pre-processing C (GHC output).

Options other than the above can be forced through to the C pre-processor with the -opt flags (see section forcing-options-through).

A small word of warning: -cpp is not friendly to "string gaps".

Options affecting the C compiler (if applicable)

At the moment, quite a few common C-compiler options are passed on quietly to the C compilation of Haskell-compiler-generated C files. THIS MAY CHANGE. Meanwhile, options so sent are:

phase of the                     suffix saying  flag saying   (suffix of)  
compilation system               "start here"   "stop after"  output file  
\hline

literate pre-processor .lhs - - C pre-processor (opt.) - - - Haskell parser .hs - - Haskell compiler - -C, -S .hc, .s C compiler (opt.) .hc or .c -S .s assembler .s -c .o linker other - a.out -Wall get all warnings from GCC -ansi do ANSI C (not K\&R) -pedantic be so -dgcc-lint (hack) short for "make GCC very paranoid"

If you are compiling with lots of ccalls, etc., you may need to tell the C compiler about some #include files. There is no pretty way to do this, but you can use this hack from the command-line:

% ghc -c '-#include <X/Xlib.h>' Xstuff.lhs

Linking and consistency-checking

GHC has to link your code with various libraries, possibly including: user-supplied, GHC-supplied, and system-supplied (-lm math library, for example).

-l<FOO>:

Link in a library named lib<FOO>.a which resides somewhere on the library directories path.

Because of the sad state of most UNIX linkers, the order of such options does matter. Thus: ghc -lbar *.o is almost certainly wrong, because it will search libbar.a before it has collected unresolved symbols from the *.o files. ghc *.o -lbar is probably better.

The linker will of course be informed about some GHC-supplied libraries automatically; these are:

phase of the                     suffix saying  flag saying   (suffix of)  
compilation system               "start here"   "stop after"  output file  
\hline

literate pre-processor .lhs - - C pre-processor (opt.) - - - Haskell parser .hs - - Haskell compiler - -C, -S .hc, .s C compiler (opt.) .hc or .c -S .s assembler .s -c .o linker other - a.out -Wall get all warnings from GCC -ansi do ANSI C (not K\&R) -pedantic be so -dgcc-lint (hack) short for "make GCC very paranoid" -l equivalent description \hline

-lHSrts,-lHSclib basic runtime libraries -lHS standard Prelude library -lgmp GNU multi-precision library (for Integers)

-syslib <name>:

If you are using an optional GHC-supplied library (e.g., the HBC library), just use the -syslib hbc option, and the correct code should be linked in.

Please see part syslibs for information about optional GHC-supplied libraries.

-L<dir>:

Where to find user-supplied libraries... Prepend the directory <dir> to the library directories path.

-static:

Tell the linker to avoid shared libraries.

-no-link-chk and -link-chk:

By default, immediately after linking an executable, GHC verifies that the pieces that went into it were compiled with compatible flags; a "consistency check". (This is to avoid mysterious failures caused by non-meshing of incompatibly-compiled programs; e.g., if one .o file was compiled for a parallel machine and the others weren't.) You may turn off this check with -no-link-chk. You can turn it (back) on with -link-chk (the default).

For the compiler's RTS: heap, stack sizes, etc.

The compiler is itself a Haskell program, so it has a tweakable runtime-system (RTS), just like any other Haskell program.

-H<size> or -Rmax-heapsize <size>:

Don't use more than <size> bytes for heap space. If more than one of these arguments is given, the largest will be taken.

A size of zero can be used to reset the heap size downwards. For example, to run GHC with a heap of 250KB (the default is 6MB), do -H0 -H250k.

-K<size> or -Rmax-stksize <size>:

Set the stack space to <size> bytes. If you have to set it very high [a megabyte or two, say], the compiler is probably looping, which is a BUG (please report).

A size of zero can be used to rest the stack size downwards, as above.

-Rscale-sizes<factor>:

Multiply the given (or default) heap and stack sizes by <factor>. For example, on a DEC Alpha (a 64-bit machine), you might want to double those space sizes; just use -Rscale-sizes2.

A non-integral factor is OK, too: -Rscale-sizes1.2.

-Rghc-timing:

Reports a one-line useful collection of time- and space- statistics for a module's compilation.

-Rgc-stats:

Report garbage-collection statistics. It will create a <foo>.stat file, in some obvious place (I hope).

Alternatively, if you'd rather the GC stats went straight to standard error, you can "cheat" by using, instead: -optCrts-Sstderr.

-Rhbc:

Tell the compiler it has an HBC-style RTS; i.e., it was compiled with HBC. Not used in Real Life.

-Rghc:

Tell the compiler it has a GHC-style RTS; i.e., it was compiled with GHC. Not used in Real Life.

For all <size>s: If the last character of size is a K, multiply by 1000; if an M, by 1,000,000; if a G, by 1,000,000,000. Sizes are always in bytes, not words. Good luck on the G's (I think the counter is still only 32-bits [WDP])!

For Concurrent and Parallel Haskell

For the full story on using GHC for concurrent \& parallel Haskell programming, please see Part concurrent-and-parallel.

For experimental purposes

From time to time, we provide GHC options for "experimenting." Easy come, easy go. In version 0.26, the "experimental" options are:

-firrefutable-tuples option:

Pretend that every tuple pattern is irrefutable; i.e., has a "twiddle" ( ) in front of it.

Some parts of the GHC system depend on strictness properties which -firrefutable-tuples may undo, notably the low-level state-transformer stuff, which includes I/O (!). You're on your own...

-fall-strict option:

(DOESN'T REALLY WORK, I THINK) Changes the strictness analyser so that, when it asks the question "Is this function argument certain to be evaluated?", the answer is always "yes".

Compilation is changed in no other way.

For debugging the compiler

HACKER TERRITORY. HACKER TERRITORY. (You were warned.)

Replacing the program for one or more phases.

You may specify that a different program be used for one of the phases of the compilation system, in place of whatever the driver ghc has wired into it. For example, you might want to test a replacement parser. The -pgm<phase-code><program-name> option to ghc will cause it to use <program-name> for phase <phase-code>, where the codes to indicate the phases are:

phase of the                     suffix saying  flag saying   (suffix of)  
compilation system               "start here"   "stop after"  output file  
\hline

literate pre-processor .lhs - - C pre-processor (opt.) - - - Haskell parser .hs - - Haskell compiler - -C, -S .hc, .s C compiler (opt.) .hc or .c -S .s assembler .s -c .o linker other - a.out -Wall get all warnings from GCC -ansi do ANSI C (not K\&R) -pedantic be so -dgcc-lint (hack) short for "make GCC very paranoid" -l equivalent description \hline

-lHSrts,-lHSclib basic runtime libraries -lHS standard Prelude library -lgmp GNU multi-precision library (for Integers) code phase \hlineL literate pre-processor P C pre-processor (if -cpp only) p parser C Haskell compiler cO C compiler for `optimised' (normal) compiling c C compiler for `unregisterised' compiling a assembler l linker

If you use the ambiguous -pgmcOle, it will take it to mean "use program le for optimised C compiling."

Forcing options to a particular phase.

The preceding sections describe driver options that are mostly applicable to one particular phase. You may also force a specific option <option> to be passed to a particular phase <phase-code> by feeding the driver the option -opt<phase-code><option>. The codes to indicate the phases are the same as in the previous section.

So, for example, to force an -Ewurble option to the assembler, you would tell the driver -opta-Ewurble (the dash before the E is required).

Besides getting options to the Haskell compiler with -optC<blah>, you can get options through to its runtime system with -optCrts<blah> .

So, for example: when I want to use my normal driver but with my profiled compiler binary, I use this script:

#! /bin/sh
exec /local/grasp_tmp3/partain/ghc-BUILDS/working-alpha/ghc/driver/ghc \
     -pgmC/local/grasp_tmp3/partain/ghc-BUILDS/working-hsc-prof/hsc \
     -optCrts-i0.5 \
     -optCrts-PT \
     "$@"

Dumping out compiler intermediate structures

-noC:

Don't bother generating C output or an interface file. Usually used in conjunction with one or more of the -ddump-* options; for example: ghc -noC -ddump-simpl Foo.hs

-hi:

Do generate an interface file. This would normally be used in conjunction with -noC, which turns off interface generation; thus: -noC -hi.

-ddump-parser:

This debugging option shows the exact prefix-form Haskell that is fed into the Haskell compiler proper.

-ddump-<pass>:

Make a debugging dump after pass <pass> (may be common enough to need a short form...). Some of the most useful ones are:

phase of the                     suffix saying  flag saying   (suffix of)  
compilation system               "start here"   "stop after"  output file  
\hline

literate pre-processor .lhs - - C pre-processor (opt.) - - - Haskell parser .hs - - Haskell compiler - -C, -S .hc, .s C compiler (opt.) .hc or .c -S .s assembler .s -c .o linker other - a.out -Wall get all warnings from GCC -ansi do ANSI C (not K\&R) -pedantic be so -dgcc-lint (hack) short for "make GCC very paranoid" -l equivalent description \hline

-lHSrts,-lHSclib basic runtime libraries -lHS standard Prelude library -lgmp GNU multi-precision library (for Integers) code phase \hlineL literate pre-processor P C pre-processor (if -cpp only) p parser C Haskell compiler cO C compiler for `optimised' (normal) compiling c C compiler for `unregisterised' compiling a assembler l linker -ddump-rif2hs reader output (earliest stuff in the compiler) -ddump-rn4 renamer output -ddump-tc typechecker output -ddump-deriv derived instances -ddump-ds desugarer output -ddump-simpl simplifer output (Core-to-Core passes) (and don't forget -O, too!) -ddump-stranal strictness analyser output (only works in conjunction with -ddump-simpl) -ddump-occur-anal `occurrence analysis' output (only works in conjunction with -ddump-simpl) -ddump-spec dump specialisation info -ddump-stg output of STG-to-STG passes -ddump-absC unflattened Abstract C -ddump-flatC flattened Abstract C -ddump-realC same as what goes to the C compiler -ddump-asm assembly language from the native-code generator

-dverbose-simpl and -dverbose-stg:

Show the output of the intermediate Core-to-Core and STG-to-STG passes, respectively. (Lots of output!) So: when we're really desperate:

% ghc -noC -O -ddump-simpl -dverbose-simpl -dcore-lint Foo.hs

-dppr-\{user,debug,all\}:

Debugging output is in one of several "styles." Take the printing of types, for example. In the "user" style, the compiler's internal ideas about types are presented in Haskell source-level syntax, insofar as possible. In the "debug" style (which is the default for debugging output), the types are printed in the most-often-desired form, with explicit foralls, etc. In the "show all" style, very verbose information about the types (e.g., the Uniques on the individual type variables) is displayed.

-ddump-raw-asm:

Dump out the assembly-language stuff, before the "mangler" gets it.

-dgc-debug:

Enables some debugging code related to the garbage-collector.

How to read Core syntax (from some -ddump-* flags)

Let's do this by commenting an example. It's from doing -ddump-ds on this code:

skip2 m = m : skip2 (m+2)

Before we jump in, a word about names of things. Within GHC, variables, type constructors, etc., are identified by their "Uniques." These are of the form `letter' plus `number' (both loosely interpreted). The `letter' gives some idea of where the Unique came from; e.g., _ means "built-in type variable"; t means "from the typechecker"; s means "from the simplifier"; and so on. The `number' is printed fairly compactly in a `base-62' format, which everyone hates except me (WDP).

Remember, everything has a "Unique" and it is usually printed out when debugging, in some form or another. So here we go...

Desugared:
Main.skip2{-r1L6-} :: _forall_ a$_4 =>{{Num a$_4}} -> a$_4 -> [a$_4]

--# `r1L6' is the Unique for Main.skip2;
--# `_4' is the Unique for the type-variable (template) `a'
--# `{{Num a$_4}}' is a dictionary argument

_NI_

--# `_NI_' means "no (pragmatic) information" yet; it will later
--# evolve into the GHC_PRAGMA info that goes into interface files.

Main.skip2{-r1L6-} =
    /\ _4 -> \ d.Num.t4Gt ->
        let {
          {- CoRec -}
          +.t4Hg :: _4 -> _4 -> _4
          _NI_
          +.t4Hg = (+{-r3JH-} _4) d.Num.t4Gt

          fromInt.t4GS :: Int{-2i-} -> _4
          _NI_
          fromInt.t4GS = (fromInt{-r3JX-} _4) d.Num.t4Gt

--# The `+' class method (Unique: r3JH) selects the addition code
--# from a `Num' dictionary (now an explicit lamba'd argument).
--# Because Core is 2nd-order lambda-calculus, type applications
--# and lambdas (/\) are explicit.  So `+' is first applied to a
--# type (`_4'), then to a dictionary, yielding the actual addition
--# function that we will use subsequently...

--# We play the exact same game with the (non-standard) class method
--# `fromInt'.  Unsurprisingly, the type `Int' is wired into the
--# compiler.

          lit.t4Hb :: _4
          _NI_
          lit.t4Hb =
              let {
                ds.d4Qz :: Int{-2i-}
                _NI_
                ds.d4Qz = I#! 2#
              } in  fromInt.t4GS ds.d4Qz

--# `I# 2#' is just the literal Int `2'; it reflects the fact that
--# GHC defines `data Int = I# Int#', where Int# is the primitive
--# unboxed type.  (see relevant info about unboxed types elsewhere...)

--# The `!' after `I#' indicates that this is a *saturated*
--# application of the `I#' data constructor (i.e., not partially
--# applied).

          skip2.t3Ja :: _4 -> [_4]
          _NI_
          skip2.t3Ja =
              \ m.r1H4 ->
                  let { ds.d4QQ :: [_4]
                        _NI_
                        ds.d4QQ =
                    let {
                      ds.d4QY :: _4
                      _NI_
                      ds.d4QY = +.t4Hg m.r1H4 lit.t4Hb
                    } in  skip2.t3Ja ds.d4QY
                  } in
                  :! _4 m.r1H4 ds.d4QQ

          {- end CoRec -}
        } in  skip2.t3Ja

("It's just a simple functional language" is an unregisterised trademark of Peyton Jones Enterprises, plc.)

Options to insert arity-checking code

The -darity-checks option inserts code to check for arity violations. Unfortunately, it's not that simple: you have to link with a prelude that was also built with arity checks. If you have one, then great; otherwise...

The -darity-checks-C-only

option inserts the self-same arity checking code into .hc files, but doesn't compile it into the .o files. We use this flag with the -keep-hc-file-too , where we are keeping .hc files around for debugging purposes.

Options to omit checking code

By default, the GHC system emits all possible not-too-expensive runtime checking code. If you are brave or experimenting, you might want to turn off some of this (not recommended):

phase of the                     suffix saying  flag saying   (suffix of)  
compilation system               "start here"   "stop after"  output file  
\hline

literate pre-processor .lhs - - C pre-processor (opt.) - - - Haskell parser .hs - - Haskell compiler - -C, -S .hc, .s C compiler (opt.) .hc or .c -S .s assembler .s -c .o linker other - a.out -Wall get all warnings from GCC -ansi do ANSI C (not K\&R) -pedantic be so -dgcc-lint (hack) short for "make GCC very paranoid" -l equivalent description \hline

-lHSrts,-lHSclib basic runtime libraries -lHS standard Prelude library -lgmp GNU multi-precision library (for Integers) code phase \hlineL literate pre-processor P C pre-processor (if -cpp only) p parser C Haskell compiler cO C compiler for `optimised' (normal) compiling c C compiler for `unregisterised' compiling a assembler l linker -ddump-rif2hs reader output (earliest stuff in the compiler) -ddump-rn4 renamer output -ddump-tc typechecker output -ddump-deriv derived instances -ddump-ds desugarer output -ddump-simpl simplifer output (Core-to-Core passes) (and don't forget -O, too!) -ddump-stranal strictness analyser output (only works in conjunction with -ddump-simpl) -ddump-occur-anal `occurrence analysis' output (only works in conjunction with -ddump-simpl) -ddump-spec dump specialisation info -ddump-stg output of STG-to-STG passes -ddump-absC unflattened Abstract C -ddump-flatC flattened Abstract C -ddump-realC same as what goes to the C compiler -ddump-asm assembly language from the native-code generator -dno-black-holing won't buy you much (even if it works) -dno-updates you're crazy if you do this -dno-stk-stubbing omit stack stubbing (NOT DONE YET)

Warning: all very lightly tested, if at all...

Controlling the run-time behaviour of your programs

To make an executable program, the GHC system compiles your code and then links it with a non-trivial runtime system (RTS), which handles storage management, profiling, etc.

You have some control over the behaviour of the RTS, by giving special command-line arguments to your program.

When your Haskell program starts up, its RTS extracts command-line arguments bracketed between +RTS

and -RTS as its own. For example:

% ./a.out -f +RTS -p -S -RTS -h foo bar

The RTS will snaffle -p -S for itself, and the remaining arguments -f -h foo bar will be handed to your program when it does a GetArgs I/O request.

No -RTS option is required if the runtime-system options extend to the end of the command line, as in this example:

% hls -ltr /usr/etc +RTS -H5m

If you absolutely positively want all the rest of the options in a command line to go to the program (and not the RTS), use a --RTS .

As always, for RTS options that take <size>s: If the last character of size is a K or k, multiply by 1000; if an M or m, by 1,000,000; if a G or G, by 1,000,000,000. (And any wraparound in the counters is your fault!)

Giving a +RTS -f option will print out the RTS options actually available in your program (which vary, depending on how you compiled).

Generally-available RTS options

The most important RTS options are:

-H<size>:

Set the heap size to <size> bytes [default: 4M].

-K<size>:

Set the stack size to <size> bytes [default: 64K]. For concurrent/parallel programs, it is the stack size of the main thread; generally speaking, c/p stacks are in heap.

Note: if your program seems to be consuming infinite stack space, it is probably in a loop :-) Of course, if stacks are in the heap, make that infinite heap space...

-s<file> or -S<file>:

Write modest (-s) or verbose (-S) garbage-collector statistics into file <file>. The default <file> is <program>.stat. The <file> stderr is treated specially, with the output really being sent to stderr.

The amount of heap allocation will typically increase as the total heap size is reduced. The reason for this odd behaviour is that updates of promoted-to-old-generation objects may require the extra allocation of a new-generation object to ensure that there are never any pointers from the old generation to the new generation.

For some garbage collectors (not including the default one, sadly), you can convert the -S output into a residency graph (in PostScript), using the stat2resid utility in the GHC distribution (ghc/utils/stat2resid).

-N:

Normally, the garbage collector black-holes closures which are being evaluated, as a space-saving measure. That's exactly what you want for ordinary Haskell programs.

When signal handlers are present, however, a computation may be abandoned prematurely, leaving black holes behind. If the signal handler shares one of these black-holed closures, disaster can result. Use the -N option to prevent black-holing by the garbage collector if you suspect that your signal handlers may share any subexpressions with the top-level computation. Expect your heap usage to increase, since the lifetimes of some closures may be extended.

RTS options to control the garbage-collector

Besides the -H (set heap size) and -S/-s (GC stats) RTS options, there are several options to give you precise control over garbage collection.

-M<n>:

Minimum % <n> of heap which must be available for allocation. The default is 3%.

-A<size>:

Sets a limit on the size of the allocation area for generational garbage collection to <size> bytes (-A gives default of 64k). If a negative size is given the size of the allocation is fixed to -<size>. For non-generational collectors, it fixes the minimum heap which must be available after a collection, overriding the -M<n> RTS option.

-G<size>:

Sets the percentage of free space to be promoted before a major collection is invoked to <size>%. The default is 66%. If a negative size is given it fixes the size of major generation threshold to -<size> bytes.

-F2s:

Forces a program compiled for generational GC to use two-space copying collection. The two-space collector may outperform the generational collector for programs which have a very low heap residency. It can also be used to generate a statistics file from which a basic heap residency profile can be produced (see Section stat2resid).

There will still be a small execution overhead imposed by the generational compilation as the test for old generation updates will still be executed (of course none will actually happen). This overhead is typically less than 1%.

-j<size>:

Force a major garbage collection every <size> bytes. (Normally used because you're keen on getting major-GC stats, notably heap residency info.)

RTS options for profiling and Concurrent/Parallel Haskell

The RTS options related to profiling are described in Chapter prof-rts-options; and those for concurrent/parallel stuff, in Section parallel-rts-opts.

RTS options for hackers, debuggers, and over-interested souls

These RTS options might be used (a) to avoid a GHC bug, (b) to see "what's really happening", or (c) because you feel like it. Not recommended for everyday use!

-B:

Sound the bell at the start of each (major) garbage collection.

Oddly enough, people really do use this option! Our pal in Durham (England), PaulCallaghan, writes: "Some people here use it for a variety of purposes -- honestly! -- e.g., confirmation that the code/machine is doing something, infinite loop detection, gauging cost of recently added code. Certain people can even tell what stage [the program] is in by the beep pattern. But the major use is for annoying others in the same office..."

-I:
Use the "debugging mini-interpreter" with sanity-checking; you have to have an appropriately-compiled version of the prelude, etc. Goes together nicely with GDB (GNU debugger)... (OLD, REALLY)

-r<file>:

Produce "ticky-ticky" statistics at the end of the program run. The <file> business works just like on the -S RTS option (above).

"Ticky-ticky" statistics are counts of various program actions (updates, enters, etc.) The program must have been compiled using -fstg-reduction-counts

(a.k.a. "ticky-ticky profiling"), and, for it to be really useful, linked with suitable system libraries. Not a trivial undertaking: consult the installation guide on how to set things up for easy "ticky-ticky" profiling.

-T<num>:

An RTS debugging flag; varying quantities of output depending on which bits are set in <num>.

-Z:

Turn off "update-frame squeezing" at garbage-collection time. (There's no particularly good reason to turn it off.)

"Hooks" to change RTS failure messages

GHC lets you exercise rudimentary control over the messages printed when the runtime system "blows up," e.g., on stack overflow.

Simply write some of the following procedures in C and then make sure they get linked in, in preference to those in the RTS library:

void ErrorHdrHook (FILE *):

What's printed out before the message from error.

void OutOfHeapHook (unsigned long, unsigned long):

The heap-overflow message.

void StackOverflowHook (long int):

The stack-overflow message.

void MallocFailHook (long int):

The message printed if malloc fails.

void PatErrorHdrHook (FILE *):

The message printed if a pattern-match fails (the failures that were not handled by the Haskell programmer).

void PreTraceHook (FILE *):

What's printed out before a trace message.

void PostTraceHook (FILE *):

What's printed out after a trace message.

For example, here is the "hooks" code used by GHC itself:

#include <stdio.h>
#define W_ unsigned long int
#define I_ long int

void
ErrorHdrHook (where)
  FILE *where;
{
    fprintf(where, "\n"); /* no "Fail: " */
}

void
OutOfHeapHook (request_size, heap_size)
  W_ request_size; /* in bytes */
  W_ heap_size;    /* in bytes */
{
    fprintf(stderr, "GHC's heap exhausted;\nwhile trying to 
        allocate %lu bytes in a %lu-byte heap;\nuse the `-H<size>'
        option to increase the total heap size.\n",
        request_size,
        heap_size);
}

void
StackOverflowHook (stack_size)
  I_ stack_size;    /* in bytes */
{
    fprintf(stderr, "GHC stack-space overflow: current size
        %ld bytes.\nUse the `-K<size>' option to increase it.\n",
        stack_size);
}

void
PatErrorHdrHook (where)
  FILE *where;
{
    fprintf(where, "\n*** Pattern-matching error within GHC!\n\n
        This is a compiler bug; please report it to
        glasgow-haskell-bugs@dcs.glasgow.ac.uk.\n\nFail: ");
}

void
PreTraceHook (where)
  FILE *where;
{
    fprintf(where, "\n"); /* not "Trace On" */
}

void
PostTraceHook (where)
  FILE *where;
{
    fprintf(where, "\n"); /* not "Trace Off" */
}

Advice on: sooner, faster, smaller, stingier

Please advise us of other "helpful hints" that should go here!

Sooner: producing a program more quickly

Don't use -O or (especially) -O2:
By using them, you are telling GHC that you are willing to suffer longer compilation times for better-quality code.

GHC is surprisingly zippy for normal compilations without -O!

Use more memory:
Within reason, more memory for heap space means less garbage collection for GHC, which means less compilation time. If you use the -Rgc-stats option, you'll get a garbage-collector report. (Again, you can use the cheap-and-nasty -optCrts-Sstderr option to send the GC stats straight to standard error.)

If it says you're using more than 20% of total time in garbage collecting, then more memory would help.

You ask for more heap with the -H<size>

option; e.g.: ghc -c -O -H16m Foo.hs.

If GHC persists in being a bad memory citizen, please report it as a bug.

Don't use too much memory!
As soon as GHC plus its "fellow citizens" (other processes on your machine) start using more than the real memory on your machine, and the machine starts "thrashing," the party is over. Compile times will be worse than terrible! Use something like the csh-builtin time command to get a report on how many page faults you're getting.

If you don't know what virtual memory, thrashing, and page faults are, or you don't know the memory configuration of your machine, don't try to be clever about memory use: you'll just make your life a misery (and for other people, too, probably).

Try to use local disks when linking:
Because Haskell objects and libraries tend to be large, it can take many real seconds to slurp the bits to/from an NFS filesystem (say).

It would be quite sensible to compile on a fast machine using remotely-mounted disks; then link on a slow machine that had your disks directly mounted.

Don't derive read for Text unnecessarily:
When doing deriving Text, use -fomit-derived-read

to derive only the showsPrec method. Quicker, smaller code.

Don't re-export instance declarations:
(Note: This recommendation totally violates the Haskell language standard.)

The Haskell module system dictates that instance declarations are exported and re-exported into interface files with considerable gusto. In a large system, especially one with mutually-recursive modules, this tendency makes your interface files bigger (bad) and decreases the chances that changes will be propagated incorrectly (bad).

If you wish, you may use a language-violating option, -fomit-reexported-instances,

to get just the effect you might expect. It can't help but speed things up.

GHC compiles some program constructs slowly:
Deeply-nested list comprehensions seem to be one such; in the past, very large constant tables were bad, too.

We'd rather you reported such behaviour as a bug, so that we can try to correct it.

The parts of the compiler that seem most prone to wandering off for a long time are the abstract interpreters (strictness and update analysers). You can turn these off individually with -fno-strictness and -fno-update-analysis.

If -ddump-simpl produces output after a reasonable time, but -ddump-stg doesn't, then it's probably the update analyser slowing you down.

If your module has big wads of constant data, GHC may produce a huge basic block that will cause the native-code generator's register allocator to founder.

If -ddump-absC produces output after a reasonable time, but nothing after that -- it's probably the native-code generator. Bring on -fvia-C (not that GCC will be that quick about it, either).

Avoid the consistency-check on linking:
Use -no-link-chk ; saves effort. This is probably safe in a I-only-compile-things-one-way setup.

Explicit import declarations:
Instead of saying import Foo, say import Foo (...stuff I want...).

Truthfully, the reduction on compilation time will be very small. However, judicious use of import declarations can make a program easier to understand, so it may be a good idea anyway.

Faster: producing a program that runs quicker

The key tool to use in making your Haskell program run faster are GHC's profiling facilities, described separately in part profiling. There is no substitute for finding where your program's time/space is really going, as opposed to where you imagine it is going.

Another point to bear in mind: By far the best way to improve a program's performance dramatically is to use better algorithms. Once profiling has thrown the spotlight on the guilty time-consumer(s), it may be better to re-think your program than to try all the tweaks listed below.

Another extremely efficient way to make your program snappy is to use library code that has been Seriously Tuned By Someone Else. You might be able to write a better quicksort than the one in the HBC library, but it will take you much longer than typing import QSort. (Incidentally, it doesn't hurt if the Someone Else is Lennart Augustsson.)

Please report any overly-slow GHC-compiled programs. The current definition of "overly-slow" is "the HBC-compiled version ran faster"...

Optimise, using -O or -O2:
This is the most basic way to make your program go faster. Compilation time will be slower, especially with -O2.

At version 0.26, -O2 is nearly indistinguishable from -O.

Compile via C and crank up GCC:
Even with -O, GHC tries to use a native-code generator, if available. But the native code-generator is designed to be quick, not mind-bogglingly clever. Better to let GCC have a go, as it tries much harder on register allocation, etc.

So, when we want very fast code, we use: -O -fvia-C -O2-for-C.

Overloaded functions are not your friend:
Haskell's overloading (using type classes) is elegant, neat, etc., etc., but it is death to performance if left to linger in an inner loop. How can you squash it?

Give explicit type signatures:
Signatures are the basic trick; putting them on exported, top-level functions is good software-engineering practice, anyway.

The automatic specialisation of overloaded functions should take care of overloaded local and/or unexported functions.

Use SPECIALIZE pragmas:

(UK spelling also accepted.) For key overloaded functions, you can create extra versions (NB: more code space) specialised to particular types. Thus, if you have an overloaded function:

hammeredLookup :: Ord key => [(key, value)] -> key -> value

If it is heavily used on lists with Widget keys, you could specialise it as follows:

{-# SPECIALIZE hammeredLookup :: [(Widget, value)] -> Widget -> value #-}

To get very fancy, you can also specify a named function to use for the specialised value, by adding = blah, as in:

{-# SPECIALIZE hammeredLookup :: ...as before... = blah #-}

It's Your Responsibility to make sure that blah really behaves as a specialised version of hammeredLookup!!!

An example in which the = blah form will Win Big:

toDouble :: Real a => a -> Double
toDouble = fromRational . toRational

{-# SPECIALIZE toDouble :: Int -> Double = i2d #-}
i2d (I# i) = D# (int2Double# i) -- uses Glasgow prim-op directly

The i2d function is virtually one machine instruction; the default conversion -- via an intermediate Rational -- is obscenely expensive by comparison.

By using the US spelling, your SPECIALIZE pragma will work with HBC, too. Note that HBC doesn't support the = blah form.

A SPECIALIZE pragma for a function can be put anywhere its type signature could be put.

Use SPECIALIZE instance pragmas:
Same idea, except for instance declarations. For example:
instance (Eq a) => Eq (Foo a) where { ... usual stuff ... }

{-# SPECIALIZE instance Eq (Foo [(Int, Bar)] #-}

Compatible with HBC, by the way.

See also: overlapping instances, in Chapter glasgow-hbc-exts. They are to SPECIALIZE instance pragmas what = blah hacks are to SPECIALIZE (value) pragmas...

"How do I know what's happening with specialisations?":
The -fshow-specialisations

will show the specialisations that actually take place.

The -fshow-import-specs will show the specialisations that GHC wished were available, but were not. You can add the relevant pragmas to your code if you wish.

You're a bit stuck if the desired specialisation is of a Prelude function. If it's Really Important, you can just snap a copy of the Prelude code, rename it, and then SPECIALIZE that to your heart's content.

"But how do I know where overloading is creeping in?":
A low-tech way: grep (search) your interface files for overloaded type signatures; e.g.,:
% egrep '^[a-z].*::.*=>' *.hi

Note: explicit export lists sometimes "mask" overloaded top-level functions; i.e., you won't see anything about them in the interface file. I sometimes remove my export list temporarily, just to see what pops out.

Strict functions are your dear friends:
and, among other things, lazy pattern-matching is your enemy.

(If you don't know what a "strict function" is, please consult a functional-programming textbook. A sentence or two of explanation here probably would not do much good.)

Consider these two code fragments:

f (Wibble x y) =  ... # strict

f arg = let { (Wibble x y) = arg } in ... # lazy

The former will result in far better code.

A less contrived example shows the use of cases instead of lets to get stricter code (a good thing):

f (Wibble x y)  # beautiful but slow
  = let
        (a1, b1, c1) = unpackFoo x
        (a2, b2, c2) = unpackFoo y
    in ...

f (Wibble x y)  # ugly, and proud of it
  = case (unpackFoo x) of { (a1, b1, c1) ->
    case (unpackFoo y) of { (a2, b2, c2) ->
    ...
    }}

GHC loves single-constructor data-types:
It's all the better if a function is strict in a single-constructor type (a type with only one data-constructor; for example, tuples are single-constructor types).

"How do I find out a function's strictness?"
Don't guess -- look it up.

Look for your function in the interface file, then for the third field in the pragma; it should say _S_ <string>. The <string> gives the strictness of the function's arguments. L is lazy (bad), S and E are strict (good), P is "primitive" (good), U(...) is strict and "unpackable" (very good), and A is absent (very good).

For an "unpackable" U(...) argument, the info inside tells the strictness of its components. So, if the argument is a pair, and it says U(AU(LSS)), that means "the first component of the pair isn't used; the second component is itself unpackable, with three components (lazy in the first, strict in the second \& third)."

If the function isn't exported, just compile with the extra flag -ddump-simpl; next to the signature for any binder, it will print the self-same pragmatic information as would be put in an interface file. (Besides, Core syntax is fun to look at!)

Force key functions to be INLINEd (esp. monads):
GHC (with -O, as always) tries to inline (or "unfold") functions/values that are "small enough," thus avoiding the call overhead and possibly exposing other more-wonderful optimisations.

You will probably see these unfoldings (in Core syntax) in your interface files.

Normally, if GHC decides a function is "too expensive" to inline, it will not do so, nor will it export that unfolding for other modules to use.

The sledgehammer you can bring to bear is the INLINE pragma, used thusly:

key_function :: Int -> String -> (Bool, Double) 

#ifdef __GLASGOW_HASKELL__
{-# INLINE key_function #-}
#endif

(You don't need to do the C pre-processor carry-on unless you're going to stick the code through HBC -- it doesn't like INLINE pragmas.)

The major effect of an INLINE pragma is to declare a function's "cost" to be very low. The normal unfolding machinery will then be very keen to inline it.

An INLINE pragma for a function can be put anywhere its type signature could be put.

INLINE pragmas are a particularly good idea for the then/return (or bind/unit) functions in a monad. For example, in GHC's own UniqueSupply monad code, we have:

#ifdef __GLASGOW_HASKELL__
{-# INLINE thenUs #-}
{-# INLINE returnUs #-}
#endif

GHC reserves the right to disallow any unfolding, even if you explicitly asked for one. That's because a function's body may become unexportable, because it mentions a non-exported value, to which any importing module would have no access.

If you want to see why candidate unfoldings are rejected, use the -freport-disallowed-unfoldings

option.

Don't let GHC ignore pragmatic information:
Sort-of by definition, GHC is allowed to ignore pragmas in interfaces. Your program should still work, if not as well.

Normally, GHC will ignore an unfolding pragma in an interface if it cannot figure out all the names mentioned in the unfolding. (A very much hairier implementation could make sure This Never Happens, but life is too short to wage constant battle with Haskell's module system.)

If you want to prevent such ignorings, give GHC a -fshow-pragma-name-errs option.

It will then treat any unresolved names in pragmas as errors, rather than inconveniences.

Explicit export list:
If you do not have an explicit export list in a module, GHC must assume that everything in that module will be exported. This has various pessimising effect. For example, if a bit of code is actually unused (perhaps because of unfolding effects), GHC will not be able to throw it away, because it is exported and some other module may be relying on its existence.

GHC can be quite a bit more aggressive with pieces of code if it knows they are not exported.

Look at the Core syntax!
(The form in which GHC manipulates your code.) Just run your compilation with -ddump-simpl (don't forget the -O).

If profiling has pointed the finger at particular functions, look at their Core code. lets are bad, cases are good, dictionaries (d.<Class>.<Unique>) [or anything overloading-ish] are bad, nested lambdas are bad, explicit data constructors are good, primitive operations (e.g., eqInt#) are good, ...

Use unboxed types (a GHC extension):
When you are really desperate for speed, and you want to get right down to the "raw bits." Please see chapter glasgow-unboxed for some information about using unboxed types.

Use _ccall_s (a GHC extension) to plug into fast libraries:
This may take real work, but... There exist piles of massively-tuned library code, and the best thing is not to compete with it, but link with it.

Chapter glasgow-ccalls says a little about how to use C calls.

Don't use Floats:
We don't provide specialisations of Prelude functions for Float (but we do for Double). If you end up executing overloaded code, you will lose on performance, perhaps badly.

Floats (probably 32-bits) are almost always a bad idea, anyway, unless you Really Know What You Are Doing. Use Doubles. There's rarely a speed disadvantage -- modern machines will use the same floating-point unit for both. With Doubles, you are much less likely to hang yourself with numerical errors.

Use a bigger heap!
If your program's GC stats (-S RTS option) indicate that it's doing lots of garbage-collection (say, more than 20% of execution time), more memory might help -- with the -H<size> RTS option.

Use a smaller heap!
Some programs with a very small heap residency (toy programs, usually) actually benefit from running the heap size way down. The -H<size> RTS option, as above.

Use a smaller "allocation area":
If you can get the garbage-collector's youngest generation to fit entirely in your machine's cache, it may make quite a difference. The effect is very machine dependent. But, for example, a +RTS -A128k option on one of our DEC Alphas was worth an immediate 5% performance boost.

Smaller: producing a program that is smaller

Decrease the "go-for-it" threshold for unfolding smallish expressions. Give a -funfolding-use-threshold0

option for the extreme case. ("Only unfoldings with zero cost should proceed.")

(Note: I have not been too successful at producing code smaller than that which comes out with -O. WDP 94/12)

Use -fomit-derived-read if you are using a lot of derived instances of Text (and don't need the read methods).

Use strip on your executables.

Stingier: producing a program that gobbles less heap space

"I think I have a space leak..." Re-run your program with +RTS -Sstderr, and remove all doubt! (You'll see the heap usage get bigger and bigger...) [Hmmm... this might be even easier with the -F2s RTS option; so... ./a.out +RTS -Sstderr -F2s...]

Once again, the profiling facilities (part profiling) are the basic tool for demystifying the space behaviour of your program.

Strict functions are good to space usage, as they are for time, as discussed in the previous section. Strict functions get right down to business, rather than filling up the heap with closures (the system's notes to itself about how to evaluate something, should it eventually be required).

If you have a true blue "space leak" (your program keeps gobbling up memory and never "lets go"), then 7 times out of 10 the problem is related to a CAF (constant applicative form). Real people call them "top-level values that aren't functions." Thus, for example:

x = (1 :: Int)
f y = x
ones = [ 1, (1 :: Float), .. ]

x and ones are CAFs; f is not.

The GHC garbage collectors are not clever about CAFs. The part of the heap reachable from a CAF is never collected. In the case of ones in the example above, it's disastrous. For this reason, the GHC "simplifier" tries hard to avoid creating CAFs, but it cannot subvert the will of a determined CAF-writing programmer (as in the case above).

Profiling Haskell programs

Glasgow Haskell comes with a time and space profiling system. Its purpose is to help you improve your understanding of your program's execution behaviour, so you can improve it.

Any comments, suggestions and/or improvements you have to are welcome. Recommended "profiling tricks" would be especially cool!

How to profile a Haskell program

The GHC approach to profiling is very simple: annotate the expressions you consider "interesting" with cost centre labels (strings); so, for example, you might have:

f x y
  = let
        output1 = _scc_ "Pass1" ( pass1 x )
        output2 = _scc_ "Pass2" ( pass2 output1 y )
        output3 = _scc_ "Pass3" ( pass3 (output2 `zip` [1 .. ]) )
    in concat output3

The costs of the evaluating the expressions bound to output1, output2 and output3 will be attributed to the "cost centres" Pass1, Pass2 and Pass3, respectively.

The costs of evaluating other expressions, e.g., concat output4, will be inherited by the scope which referenced the function f.

You can put in cost-centres via _scc_ constructs by hand, as in the example above. Perfectly cool. That's probably what you would do if your program divided into obvious "passes" or "phases", or whatever.

If your program is large or you have no clue what might be gobbling all the time, you can get GHC to mark all functions with _scc_ constructs, automagically. Add an -auto compilation flag to the usual -prof option.

Once you start homing in on the Guilty Suspects, you may well switch from automagically-inserted cost-centres to a few well-chosen ones of your own.

To use profiling, you must compile and run with special options. (We usually forget the "run" magic! -- Do as we say, not as we do...) Details follow.

If you're serious about this profiling game, you should probably read one or more of the Sansom/Peyton Jones papers about the GHC profiling system. Just visit the Glasgow FP Web page...

Compiling programs for profiling

To make use of the cost centre profiling system all modules must be compiled and linked with the -prof option.

Any _scc_ constructs you've put in your source will spring to life.

Without a -prof option, your _scc_s are ignored; so you can compiled _scc_-laden code without changing it.

There are a few other profiling-related compilation options. Use them in addition to -prof. These do not have to be used consistently for all modules in a program.

-auto:

GHC will automatically add _scc_ constructs for all top-level, exported functions.

-auto-all:

All top-level functions, exported or not, will be automatically _scc_'d.

-ignore-scc:

Ignore any _scc_ constructs, so a module which already has _scc_s can be compiled for profiling with the annotations ignored.

-G<group>:

Specifies the <group> to be attached to all the cost-centres declared in the module. If no group is specified it defaults to the module name.

In addition to the -prof option your system might be setup to enable you to compile and link with the -prof-details option instead. This enables additional detailed counts to be reported with the -P RTS option.

How to control your profiled program at runtime

It isn't enough to compile your program for profiling with -prof!

When you run your profiled program, you must tell the runtime system (RTS) what you want to profile (e.g., time and/or space), and how you wish the collected data to be reported. You also may wish to set the sampling interval used in time profiling.

Executive summary: ./a.out +RTS -p produces a time profile in a.out.prof; ./a.out +RTS -hC produces space-profiling info which can be mangled by hp2ps and viewed with ghostview (or equivalent).

Profiling runtime flags are passed to your program between the usual +RTS and -RTS options.

-p<sort> or -P<sort>:

The -p option produces a standard time profile report. It is written into the file <program>.prof.

The -P option produces a more detailed report containing the actual time and allocation data as well. (Not used much.)

The -P option also produces serial time-profiling information, in the file <program>.time. This can be converted into a (somewhat unsatisfactory) PostScript graph using hp2ps (see Section hp2ps).

???? -F2s needed for serial time profile??? ToDo

The <sort> indicates how the cost centres are to be sorted in the report. Valid <sort> options are:

T:
by time, largest first (the default);
A:
by bytes allocated, largest first;
C:
alphabetically by group, module and cost centre.

-i<secs>:

Set the profiling (sampling) interval to <secs> seconds (the default is 1 second).

-h<break-down>:

Produce a detailed space profile of the heap occupied by live closures. The profile is written to the file <program>.hp from which a PostScript graph can be produced using hp2ps (see Section hp2ps).

The heap space profile may be broken down by different criteria:

-hC:
cost centre which produced the closure (the default).
-hM:
cost centre module which produced the closure.
-hG:
cost centre group which produced the closure.
-hD:
closure description -- a string describing the closure.
-hY:
closure type -- a string describing the closure's type.

By default all live closures in the heap are profiled, but particular closures of interest can be selected (see below).

Heap (space) profiling uses hash tables. If these tables should fill the run will abort. The -z<tbl><size> option is used to increase the size of the relevant hash table (C, M, G, D or Y, defined as for <break-down> above). The actual size used is the next largest power of 2.

The heap profile can be restricted to particular closures of interest. The closures of interest can selected by the attached cost centre (module:label, module and group), closure category (description, type, and kind) and closure age using the following options:

-c\{<mod>:<lab>,<mod>:<lab>...\}:

Selects individual cost centre(s).

-m\{<mod>,<mod>...\}:

Selects all cost centres from the module(s) specified.

-g\{<grp>,<grp>...\}:

Selects all cost centres from the groups(s) specified.

-d\{<des>,<des>...\}:

Selects closures which have one of the specified descriptions.

-y\{<typ>,<typ>...\}:

Selects closures which have one of the specified type descriptions.

-k\{<knd>,<knd>...\}:

Selects closures which are of one of the specified closure kinds. Valid closure kinds are CON (constructor), FN (manifest function), PAP (partial application), BH (black hole) and THK (thunk).

The space occupied by a closure will be reported in the heap profile if the closure satisfies the following logical expression:

([-c] or [-m] or [-g]) and ([-d] or [-y] or [-k]) 















where a particular option is true if the closure (or its attached cost centre) is selected by the option (or the option is not specified).

What's in a profiling report?

When you run your profiled program with the -p RTS option , you get the following information about your "cost centres":

COST CENTRE:
The cost-centre's name.

MODULE:
The module associated with the cost-centre; important mostly if you have identically-named cost-centres in different modules.

scc:
How many times this cost-centre was entered; think of it as "I got to the _scc_ construct this many times..."

%time:
What part of the time was spent in this cost-centre (see also "ticks," below).

%alloc:
What part of the memory allocation was done in this cost-centre (see also "bytes," below).

inner:
How many times this cost-centre "passed control" to an inner cost-centre; for example, scc=4 plus subscc=8 means "This _scc_ was entered four times, but went out to other _scc_s eight times."

cafs:
How many CAFs this cost centre evaluated.

dicts:
How many dictionaries this cost centre evaluated.

In addition you can use the -P RTS option to get the following additional information:

ticks:
The raw number of time "ticks" which were attributed to this cost-centre; from this, we get the %time figure mentioned above.

bytes:
Number of bytes allocated in the heap while in this cost-centre; again, this is the raw number from which we get the %alloc figure mentioned above.

Finally if you built your program with -prof-details the -P RTS option will also produce the following information:

closures:
How many heap objects were allocated; these objects may be of varying size. If you divide the number of bytes (mentioned below) by this number of "closures", then you will get the average object size. (Not too interesting, but still...)

thunks:
How many times we entered (evaluated) a thunk -- an unevaluated object in the heap -- while we were in this cost-centre.

funcs:
How many times we entered (evaluated) a function while we we in this cost-centre. (In Haskell, functions are first-class values and may be passed as arguments, returned as results, evaluated, and generally manipulated just like data values)

PAPs:
How many times we entered (evaluated) a partial application (PAP), i.e., a function applied to fewer arguments than it needs. For example, Int addition applied to one argument would be a PAP. A PAP is really just a particular form for a function.

Producing graphical heap profiles

Utility programs which produce graphical profiles.

hp2ps--heap profile to PostScript

USAGE: hp2ps [flags] [<file>[.stat]]

The program hp2ps converts a heap profile as produced by the -h<break-down>

runtime option into a PostScript graph of the heap profile. By convention, the file to be processed by hp2ps has a .hp extension. The PostScript output is written to <file>.ps. If <file> is omitted entirely, then the program behaves as a filter.

hp2ps is distributed in ghc/utils/hp2ps. It was originally developed by Dave Wakeling as part of the HBC/LML heap profiler.

The flags are:

-d
In order to make graphs more readable, hp2ps sorts the shaded bands for each identifier. The default sort ordering is for the bands with the largest area to be stacked on top of the smaller ones. The -d option causes rougher bands (those representing series of values with the largest standard deviations) to be stacked on top of smoother ones.

-b
Normally, hp2ps puts the title of the graph in a small box at the top of the page. However, if the JOB string is too long to fit in a small box (more than 35 characters), then hp2ps will choose to use a big box instead. The -b option forces hp2ps to use a big box.

-e<float>[in|mm|pt]
Generate encapsulated PostScript suitable for inclusion in LaTeX documents. Usually, the PostScript graph is drawn in landscape mode in an area 9 inches wide by 6 inches high, and hp2ps arranges for this area to be approximately centred on a sheet of a4 paper. This format is convenient of studying the graph in detail, but it is unsuitable for inclusion in LaTeX documents. The -e option causes the graph to be drawn in portrait mode, with float specifying the width in inches, millimetres or points (the default). The resulting PostScript file conforms to the Encapsulated PostScript (EPS) convention, and it can be included in a LaTeX document using Rokicki's dvi-to-PostScript converter dvips.

-g
Create output suitable for the gs PostScript previewer (or similar). In this case the graph is printed in portrait mode without scaling. The output is unsuitable for a laser printer.

-l
Normally a profile is limited to 20 bands with additional identifiers being grouped into an OTHER band. The -l flag removes this 20 band and limit, producing as many bands as necessary. No key is produced as it won't fit!. It is useful for creation time profiles with many bands.

-m<int>
Normally a profile is limited to 20 bands with additional identifiers being grouped into an OTHER band. The -m flag specifies an alternative band limit (the maximum is 20).

-m0 requests the band limit to be removed. As many bands as necessary are produced. However no key is produced as it won't fit! It is useful for displaying creation time profiles with many bands.

-p
Use previous parameters. By default, the PostScript graph is automatically scaled both horizontally and vertically so that it fills the page. However, when preparing a series of graphs for use in a presentation, it is often useful to draw a new graph using the same scale, shading and ordering as a previous one. The -p flag causes the graph to be drawn using the parameters determined by a previous run of hp2ps on file. These are extracted from file.aux.

-s
Use a small box for the title.

-t<float>
Normally trace elements which sum to a total of less than 1% of the profile are removed from the profile. The -t option allows this percentage to be modified (maximum 5%).

-t0 requests no trace elements to be removed from the profile, ensuring that all the data will be displayed.

-?
Print out usage information.

stat2resid -- residency info from GC stats

USAGE: stat2resid [<file>[.stat] [<outfile>]]

The program stat2resid converts a detailed garbage collection statistics file produced by the -S runtime option into a PostScript heap residency graph. The garbage collection statistics file can be produced without compiling your program for profiling.

By convention, the file to be processed by stat2resid has a .stat extension. If the <outfile> is not specified the PostScript will be written to <file>.resid.ps. If <file> is omitted entirely, then the program behaves as a filter.

The plot can not be produced from the statistics file for a generational collector, though a suitable stats file can be produced using the -F2s runtime option when the program has been compiled for generational garbage collection (the default).

stat2resid is distributed in ghc/utils/stat2resid.

Glasgow extensions to Haskell

As with all known Haskell systems, GHC implements some extensions to the language. To use them, you'll need to give a -fglasgow-exts option.

Virtually all of the Glasgow extensions serve to give you access to the underlying facilities with which we implement Haskell. Thus, you can get at the Raw Iron, if you are willing to write some non-standard code at a more primitive level. You need not be "stuck" on performance because of the implementation costs of Haskell's "high-level" features -- you can always code "under" them. In an extreme case, you can write all your time-critical code in C, and then just glue it together with Haskell!

Executive summary of our extensions:

Unboxed types and primitive operations:
You can get right down to the raw machine types and operations; included in this are "primitive arrays" (direct access to Big Wads of Bytes). Please see Chapter glasgow-unboxed and following.

Calling out to C:
Just what it sounds like. We provide lots of rope that you can dangle around your neck. Please see Chapter glasgow-ccalls.

"Monadic I/O:"
This stuff will be coming to you For Real with Haskell 1.3, whenever that is. Please see Chapter io-1-3 (the "1.3 I/O" section).

"HBC-ish" extensions:
Extensions implemented because people said, "HBC does Y. Could you teach GHC to do the same?" Please see Chapter glasgow-hbc-exts for a quick list.

Before you get too carried away working at the lowest level (e.g., sloshing MutableByteArray#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 Part syslibs.

The definitive guide for many of the low-level facilities in GHC is the "state interface document" (distributed in ghc/docs/state-interface.dvi). We do not repeat its details here.

Unboxed types

These types correspond to the "raw machine" types you would use in C: Int# (long int), Double# (double), Addr# (void *), etc. The primitive operations (PrimOps) on these types are what you might expect; e.g., (+#) is addition on Int#s, and is the machine-addition that we all know and love -- usually one instruction.

A numerically-intensive program using unboxed types can go a lot faster than its "standard" counterpart -- we saw a threefold speedup on one example.

Please see the very first part of the "state interface document" (distributed in ghc/docs/state-interface.dvi) for the details of unboxed types and the operations on them.

Primitive state-transformer monad

This monad underlies our implementation of arrays, mutable and immutable, and our implementation of I/O, including "C calls".

You probably won't use the monad directly, but you might use all those other things!

The "state interface document" defines the state-related types in sections 1.4 and 1.5, and the monad itself in section 2.1.

Primitive arrays, mutable and otherwise

GHC knows about quite a few flavours of Large Swathes of Bytes.

First, GHC distinguishes between primitive arrays of (boxed) Haskell objects (type Array# obj) and primitive arrays of bytes (type ByteArray#).

Second, it distinguishes between...

Immutable:
Arrays that do not change (as with "standard" Haskell arrays); you can only read from them. Obviously, they do not need the care and attention of the state-transformer monad.

Mutable:
Arrays that may be changed or "mutated." All the operations on them live within the state-transformer monad and the updates happen in-place.

"Static" (in C land):
A C routine may pass an Addr# 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 "static" pointer.

"Stable" pointers:
If, for some reason, you wish to hand a Haskell pointer (i.e., not an unboxed value) to a C routine, you first make the pointer "stable," so that the garbage collector won't forget that it exists. That is, GHC provides a safe way to pass Haskell pointers to C.

Please see Section glasgow-stablePtrs for more details.

"Malloc" pointers:
A "malloc" pointer is a safe way to pass a C pointer 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 "please free this memory when you're done with it."

Please see Section glasgow-mallocPtrs for more details.

See sections 1.4 and 1.6 of the "state interface document" for the details of all these "primitive array" types and the operations on them.

Calling C directly from Haskell

SINCE VERSION 0.22: "Literal-literals", e.g., "NULL", can now be any `boxed-primitive' type -- they are not automatically taken to be _Addrs. This is cool, except you may sometimes have to put in a type signature to force the desired type.

SINCE VERSION 0.19: ccall and casm have been renamed to _ccall_ and _casm_ and veryDangerousCcall and veryDangerousCasm have been removed. It is no longer necessary (nor legal!) to unbox/rebox the arguments and results to _ccall_. GHC does the unboxing/reboxing for you.

GOOD ADVICE: Because this stuff is not Entirely Stable as far as names and things go, you would be well-advised to keep your C-callery corraled in a few modules, rather than sprinkled all over your code. It will then be quite easy to update later on.

WARNING AS OF 0.26: Yes, the _ccall_ stuff probably will change, to something better, of course! We are only at the musing-about-it stage, however.

_ccall_ and _casm_: an introduction

The simplest way to use a simple C function

double fooC( FILE *in, char c, int i, double d, unsigned int u )

is to provide a Haskell wrapper

fooH :: Char -> Int -> Double -> _Word -> PrimIO Double
fooH c i d w = _ccall_ fooC ``stdin'' c i d w

The function fooH will unbox all of its arguments, call the C function fooC and box the corresponding arguments.

So, if you want to do C-calling, you have to confront the underlying Glasgow I/O system. It's just your typical monad whatnot.

One of the annoyances about _ccall_s is when the C types don't quite match the Haskell compiler's ideas. For this, the _casm_ variant may be just the ticket (NB: no chance of such code going through a native-code generator):

oldGetEnv name
  = _casm_ ``%r = getenv((char *) %0);'' name `thenPrimIO` \ litstring@(A# str#) ->
    returnPrimIO (
        if (litstring == ``NULL'') then
            Failure (SearchError ("GetEnv:"++name))
        else
            Str (unpackCString# str#)
    )

The first literal-literal argument to a _casm_ is like a printf format: %r is replaced with the "result," %0--%n-1 are replaced with the 1st--nth arguments. As you can see above, it is an easy way to do simple C casting. Everything said about _ccall_ goes for _casm_ as well.

Using function headers

When generating C (using the -fvia-C directive), one can assist the C compiler in detecting type errors by using the -#include directive to provide .h files containing function headers.

For example,

typedef unsigned long *StgMallocPtr;
typedef long StgInt;

extern void          initialiseEFS PROTO( (StgInt size) );
extern StgInt        terminateEFS ();
extern StgMallocPtr  emptyEFS();
extern StgMallocPtr  updateEFS PROTO( (StgMallocPtr a, StgInt i, StgInt x) );
extern StgInt        lookupEFS PROTO( (StgMallocPtr a, StgInt i) );

You can find appropriate definitions for StgInt, StgMallocPtr, etc using gcc on your architecture by consulting ghc/includes/StgTypes.lh. The following table summarises the relationship between Haskell types and C types.

C type name                Haskell Type                
\hline

StgChar Char# StgInt Int# StgWord Word# StgAddr Addr# StgFloat Float# StgDouble Double# StgArray Array# StgByteArray ByteArray# StgArray MutableArray# StgByteArray MutableByteArray# StgStablePtr StablePtr# StgMallocPtr MallocPtr#

Note that this approach is only essential for returning floats (or if sizeof(int) != sizeof(int *) on your architecture) but is a Good Thing for anyone who cares about writing solid code. You're crazy not to do it.

Subverting automatic unboxing with "stable pointers"

The arguments of a _ccall_ are automatically unboxed before the call. There are two reasons why this is usually the Right Thing to do:

It is possible to subvert the unboxing process by creating a "stable pointer" to a value and passing the stable pointer instead. (To use stable pointers, you must import PreludeGlaMisc.) For example, to pass/return an integer lazily to C functions storeC and fetchC, one might write:

storeH :: Int -> PrimIO ()
storeH x = makeStablePtr x              `thenPrimIO` \ stable_x ->
           _ccall_ storeC stable_x

fetchH :: PrimIO Int
fetchH x = _ccall_ fetchC               `thenPrimIO` \ stable_x ->
           deRefStablePtr stable_x      `thenPrimIO` \ x ->
           freeStablePtr stable_x       `seqPrimIO`
           returnPrimIO x

The garbage collector will refrain from throwing a stable pointer away until you explicitly call one of the following from C or Haskell.

void freeStablePointer( StgStablePtr stablePtrToToss )
freeStablePtr :: _StablePtr a -> PrimIO ()

As with the use of free in C programs, GREAT CARE SHOULD BE EXERCISED to ensure these functions are called at the right time: too early and you get dangling references (and, if you're lucky, an error message from the runtime system); too late and you get space leaks.

Pointing outside the Haskell heap

There are two types that ghc programs can use to reference (heap-allocated) objects outside the Haskell world: _Addr and _MallocPtr. (You must import PreludeGlaMisc to use _MallocPtr.)

If you use _Addr, it is up to you to the programmer to arrange allocation and deallocation of the objects.

If you use _MallocPtr, ghc's garbage collector will call the user-supplied C function

void FreeMallocPtr( StgMallocPtr garbageMallocPtr )

when the Haskell world can no longer access the object. Since _MallocPtrs only get released when a garbage collection occurs, we provide ways of triggering a garbage collection from within C and from within Haskell.

void StgPerformGarbageCollection()
performGC :: PrimIO ()

Avoiding monads

The _ccall_ construct is part of the PrimIO monad because 9 out of 10 uses will be to call imperative functions with side effects such as printf. Use of the monad ensures that these operations happen in a predictable order in spite of laziness and compiler optimisations.

There are three situations where one might like to use unsafePerformPrimIO to avoid the monad:

C-calling "gotchas" checklist

And some advice, too.

"HBC-ish" extensions implemented by GHC

fromInt method in class Num:
It's there. Converts from an Int to the type.

toInt method in class Integral:
Converts from type type to an Int.

Overlapping instance declarations:

In instance <context> => Class (T x1 ... xn), the xis can be types, rather than just type variables.

Thus, you can have an instance instance Foo [Char], as well as the more general instance Foo [a]; the former will be used in preference to the latter, where applicable.

As Lennart says, "This is a dubious feature and should not be used carelessly."

See also: SPECIALIZE instance pragmas, in Chapter faster.

Signal-handling I/O request:

The Haskell-1.2 I/O request SigAction n act installs a signal handler for signal n :: Int. The number is the usual UNIX signal number. The action is of this type:

data SigAct
  = SAIgnore
  | SADefault
  | SACatch Dialogue

The corresponding continuation-style I/O function is the unsurprising:

sigAction :: Int -> SigAct -> FailCont -> SuccCont -> Dialogue

When a signal handler is installed with SACatch, receipt of the signal causes the current top-level computation to be abandoned, and the specified dialogue to be executed instead. The abandoned computation may leave some partially evaluated expressions in a non-resumable state. If you believe that your top-level computation and your signal handling dialogue may share subexpressions, you should execute your program with the -N RTS option, to prevent black-holing.

The -N option is not available with concurrent/parallel programs, so great care should be taken to avoid shared subexpressions between the top-level computation and any signal handlers when using threads.

System libraries

We intend to provide more and more ready-to-use Haskell code, so that every program doesn't have to invent everything from scratch.

At the moment, we supply a part of the HBC library, as well as the beginnings of one of our own ("GHC library").

If you provide a -syslib <name> option, then the interfaces for that library will come into scope (and may be imported), and the code will be added in at link time.

The GHC system library

We have started to put together a "GHC system library."

At the moment, the library is made of generally-useful bits of the compiler itself.

To use this library, just give a -syslib ghc

option to GHC, both for compiling and linking.

The Bag type

A bag is an unordered collection of elements which may contain duplicates. To use, import Bag.

emptyBag        :: Bag elt
unitBag         :: elt -> Bag elt

unionBags       :: Bag elt   -> Bag elt -> Bag elt
unionManyBags   :: [Bag elt] -> Bag elt
snocBag         :: Bag elt   -> elt     -> Bag elt

elemBag         :: Eq elt => elt -> Bag elt -> Bool
isEmptyBag      ::                  Bag elt -> Bool
filterBag       :: (elt -> Bool) -> Bag elt -> Bag elt
partitionBag    :: (elt -> Bool) -> Bag elt-> (Bag elt, Bag elt)
        -- returns the elements that do/don't satisfy the predicate

listToBag       :: [elt] -> Bag elt
bagToList       :: Bag elt -> [elt]

The BitSet type

Bit sets are a fast implementation of sets of integers ranging from 0 to one less than the number of bits in a machine word (typically 31). If any element exceeds the maximum value for a particular machine architecture, the results of these operations are undefined. You have been warned. ["If you put any safety checks in this code, I will have to kill you." --JSM]

mkBS        :: [Int]  -> BitSet
listBS      :: BitSet -> [Int]
emptyBS     :: BitSet 
singletonBS :: Int    -> BitSet

unionBS     :: BitSet -> BitSet -> BitSet
minusBS     :: BitSet -> BitSet -> BitSet
elementBS   :: Int    -> BitSet -> Bool
intersectBS :: BitSet -> BitSet -> BitSet

isEmptyBS   :: BitSet -> Bool

The FiniteMap type

What functional programmers call a finite map, everyone else calls a lookup table.

Out code is derived from that in this paper:

S Adams
"Efficient sets: a balancing act"
Journal of functional programming 3(4) Oct 1993, pages 553-562


Guess what? The implementation uses balanced trees.

--      BUILDING
emptyFM         :: FiniteMap key elt
singletonFM     :: key -> elt -> FiniteMap key elt
listToFM        :: Ord key => [(key,elt)] -> FiniteMap key elt
                        -- In the case of duplicates, the last is taken

--      ADDING AND DELETING
                   -- Throws away any previous binding
                   -- In the list case, the items are added starting with the
                   -- first one in the list
addToFM         :: Ord key => FiniteMap key elt -> key -> elt  -> FiniteMap key elt
addListToFM     :: Ord key => FiniteMap key elt -> [(key,elt)] -> FiniteMap key elt

                   -- Combines with previous binding
addToFM_C       :: Ord key => (elt -> elt -> elt)
                           -> FiniteMap key elt -> key -> elt  
                           -> FiniteMap key elt
addListToFM_C   :: Ord key => (elt -> elt -> elt)
                           -> FiniteMap key elt -> [(key,elt)] 
                           -> FiniteMap key elt

                   -- Deletion doesn't complain if you try to delete something
                   -- which isn't there
delFromFM       :: Ord key => FiniteMap key elt -> key   -> FiniteMap key elt
delListFromFM   :: Ord key => FiniteMap key elt -> [key] -> FiniteMap key elt

--      COMBINING
                   -- Bindings in right argument shadow those in the left
plusFM          :: Ord key => FiniteMap key elt -> FiniteMap key elt
                           -> FiniteMap key elt

                   -- Combines bindings for the same thing with the given function
plusFM_C        :: Ord key => (elt -> elt -> elt) 
                           -> FiniteMap key elt -> FiniteMap key elt -> FiniteMap key elt

minusFM         :: Ord key => FiniteMap key elt -> FiniteMap key elt -> FiniteMap key elt
                   -- (minusFM a1 a2) deletes from a1 any bindings which are bound in a2

intersectFM     :: Ord key => FiniteMap key elt -> FiniteMap key elt -> FiniteMap key elt 
intersectFM_C   :: Ord key => (elt -> elt -> elt)
                           -> FiniteMap key elt -> FiniteMap key elt -> FiniteMap key elt 

--      MAPPING, FOLDING, FILTERING
foldFM          :: (key -> elt -> a -> a) -> a -> FiniteMap key elt -> a
mapFM           :: (key -> elt1 -> elt2) -> FiniteMap key elt1 -> FiniteMap key elt2
filterFM        :: Ord key => (key -> elt -> Bool) 
                           -> FiniteMap key elt -> FiniteMap key elt

--      INTERROGATING
sizeFM          :: FiniteMap key elt -> Int
isEmptyFM       :: FiniteMap key elt -> Bool

elemFM          :: Ord key => key -> FiniteMap key elt -> Bool
lookupFM        :: Ord key => FiniteMap key elt -> key -> Maybe elt
lookupWithDefaultFM
                :: Ord key => FiniteMap key elt -> elt -> key -> elt
                -- lookupWithDefaultFM supplies a "default" elt
                -- to return for an unmapped key

--      LISTIFYING
fmToList        :: FiniteMap key elt -> [(key,elt)]
keysFM          :: FiniteMap key elt -> [key]
eltsFM          :: FiniteMap key elt -> [elt]

The ListSetOps type

Just a few set-sounding operations on lists. If you want sets, use the Set module.

unionLists          :: Eq a => [a] -> [a] -> [a]
intersectLists      :: Eq a => [a] -> [a] -> [a]
minusList           :: Eq a => [a] -> [a] -> [a]
disjointLists       :: Eq a => [a] -> [a] -> Bool
intersectingLists   :: Eq a => [a] -> [a] -> Bool

The Maybes type

Note: a Maybe type is nearly inevitable in Haskell 1.3. You should use this module with -fhaskell-1.3.

Two non-abstract types:

data Maybe    a       = Nothing       | Just a -- Prelude; re-exported
data MaybeErr val err = Succeeded val | Failed err

Some operations to do with Maybe (some commentary follows):

maybeToBool :: Maybe a -> Bool      -- Nothing => False; Just => True
catMaybes   :: [Maybe a] -> [a]
allMaybes   :: [Maybe a] -> Maybe [a]
firstJust   :: [Maybe a] -> Maybe a
findJust    :: (a -> Maybe b) -> [a] -> Maybe b

assocMaybe  :: Eq a => [(a,b)] -> a -> Maybe b
mkLookupFun :: (key -> key -> Bool) -- Equality predicate
            -> [(key,val)]          -- The assoc list
            -> (key -> Maybe val)   -- A lookup fun to use

    -- a monad thing
thenMaybe   :: Maybe a -> (a -> Maybe b) -> Maybe b
returnMaybe :: a -> Maybe a
failMaybe   :: Maybe a
mapMaybe    :: (a -> Maybe b) -> [a] -> Maybe [b]

catMaybes takes a list of Maybes and returns a list of the contents of all the Justs in it.

allMaybes collects a list of Justs into a single Just, returning Nothing if there are any Nothings.

firstJust takes a list of Maybes and returns the first Just if there is one, or Nothing otherwise.

assocMaybe looks up in an association list, returning Nothing if it fails.

Now, some operations to do with MaybeErr (comments follow):

    -- a monad thing (surprise, surprise)
thenMaB   :: MaybeErr a err -> (a -> MaybeErr b err) -> MaybeErr b err
returnMaB :: val -> MaybeErr val err
failMaB   :: err -> MaybeErr val err

listMaybeErrs :: [MaybeErr val err] -> MaybeErr [val] [err]
foldlMaybeErrs :: (acc -> input -> MaybeErr acc err)
               -> acc
               -> [input]
               -> MaybeErr acc [err]

listMaybeErrs takes a list of MaybeErrs and, if they all succeed, returns a Succeeded of a list of their values. If any fail, it returns a Failed of the list of all the errors in the list.

foldlMaybeErrs works along a list, carrying an accumulator; it applies the given function to the accumulator and the next list item, accumulating any errors that occur.

The _PackedString type

The type _PackedString is built-in, i.e., no special action (other than a -fglasgow-exts flag) is required to use it.

The documentation here describes the built-in functions.

You may also access this code as a system library and not use the -fglasgow-exts flag. Just do import PackedString, heave in your -syslib ghc, and drop off the leading underscores which you see here.

We still may change this interface (again).

The basic type and functions which are available are:

data _PackedString

_packString      :: [Char] -> _PackedString
_packStringST    :: [Char] -> _ST s _PackedString
_packCString     :: _Addr  -> _PackedString
_packCBytes      :: Int -> _Addr -> _PackedString
_packCBytesST    :: Int -> _Addr -> _ST s _PackedString
_packBytesForC   :: [Char] -> _ByteArray Int
_packBytesForCST :: [Char] -> _ST s (_ByteArray Int)
_byteArrayToPS   :: _ByteArray Int -> _PackedString
_psToByteArray   :: _PackedString -> _ByteArray Int

_unpackPS        :: _PackedString -> [Char]

We also provide a wad of list-manipulation-like functions:

_nilPS      :: _PackedString
_consPS     :: Char -> _PackedString -> _PackedString

_headPS     :: _PackedString -> Char
_tailPS     :: _PackedString -> _PackedString
_nullPS     :: _PackedString -> Bool
_appendPS   :: _PackedString -> _PackedString -> _PackedString
_lengthPS   :: _PackedString -> Int
_indexPS    :: _PackedString -> Int -> Char
            -- 0-origin indexing into the string
_mapPS      :: (Char -> Char) -> _PackedString -> _PackedString {-or String?-}
_filterPS   :: (Char -> Bool) -> _PackedString -> _PackedString {-or String?-}
_foldlPS    :: (a -> Char -> a) -> a -> _PackedString -> a
_foldrPS    :: (Char -> a -> a) -> a -> _PackedString -> a
_takePS     :: Int -> _PackedString -> _PackedString
_dropPS     :: Int -> _PackedString -> _PackedString
_splitAtPS  :: Int -> _PackedString -> (_PackedString, _PackedString)
_takeWhilePS:: (Char -> Bool) -> _PackedString -> _PackedString
_dropWhilePS:: (Char -> Bool) -> _PackedString -> _PackedString
_spanPS     :: (Char -> Bool) -> _PackedString -> (_PackedString, _PackedString)
_breakPS    :: (Char -> Bool) -> _PackedString -> (_PackedString, _PackedString)
_linesPS    :: _PackedString -> [_PackedString]
_wordsPS    :: _PackedString -> [_PackedString]
_reversePS  :: _PackedString -> _PackedString
_concatPS   :: [_PackedString] -> _PackedString

_substrPS   :: _PackedString -> Int -> Int -> _PackedString
            -- pluck out a piece of a _PS
            -- start and end chars you want; both 0-origin-specified

The Pretty type

This is the pretty-printer that we use in GHC.

type Pretty

ppShow          :: Int{-width-} -> Pretty -> [Char]

pp'SP           :: Pretty -- "comma space"
ppComma         :: Pretty -- ,
ppEquals        :: Pretty -- =
ppLbrack        :: Pretty -- [
ppLparen        :: Pretty -- (
ppNil           :: Pretty -- nothing
ppRparen        :: Pretty -- )
ppRbrack        :: Pretty -- ]
ppSP            :: Pretty -- space
ppSemi          :: Pretty -- ;

ppChar          :: Char -> Pretty
ppDouble        :: Double -> Pretty
ppFloat         :: Float -> Pretty
ppInt           :: Int -> Pretty
ppInteger       :: Integer -> Pretty
ppRational      :: Rational -> Pretty
ppStr           :: [Char] -> Pretty

ppAbove         :: Pretty -> Pretty -> Pretty
ppAboves        :: [Pretty] -> Pretty
ppBeside        :: Pretty -> Pretty -> Pretty
ppBesides       :: [Pretty] -> Pretty
ppCat           :: [Pretty] -> Pretty
ppHang          :: Pretty -> Int -> Pretty -> Pretty
ppInterleave    :: Pretty -> [Pretty] -> Pretty -- spacing between
ppIntersperse   :: Pretty -> [Pretty] -> Pretty -- no spacing between
ppNest          :: Int -> Pretty -> Pretty
ppSep           :: [Pretty] -> Pretty

The Set type

Our implementation of sets (key property: no duplicates) is just a variant of the FiniteMap module.

mkSet           :: Ord a => [a]  -> Set a
setToList       :: Set a -> [a]
emptySet        :: Set a
singletonSet    :: a -> Set a

union           :: Ord a => Set a -> Set a -> Set a
unionManySets   :: Ord a => [Set a] -> Set a
intersect       :: Ord a => Set a -> Set a -> Set a
minusSet        :: Ord a => Set a -> Set a -> Set a
mapSet          :: Ord a => (b -> a) -> Set b -> Set a

elementOf       :: Ord a => a -> Set a -> Bool
isEmptySet      :: Set a -> Bool

The Util type

Stuff that has been useful to use in writing the compiler. Don't be too surprised if this stuff moves/gets-renamed/etc.

-- general list processing
forall          :: (a -> Bool) -> [a] -> Bool
exists          :: (a -> Bool) -> [a] -> Bool
zipEqual        :: [a] -> [b] -> [(a,b)]
nOfThem         :: Int -> a -> [a]
lengthExceeds   :: [a] -> Int -> Bool
isSingleton     :: [a] -> Bool

-- association lists
assoc       :: Eq a => String -> [(a, b)] -> a -> b

-- duplicate handling
hasNoDups    :: Eq a => [a] -> Bool
equivClasses :: (a -> a -> _CMP_TAG) -> [a] -> [[a]]
runs         :: (a -> a -> Bool)     -> [a] -> [[a]]
removeDups   :: (a -> a -> _CMP_TAG) -> [a] -> ([a], [[a]])

-- sorting (don't complain of no choice...)
quicksort          :: (a -> a -> Bool)     -> [a] -> [a]
sortLt             :: (a -> a -> Bool)     -> [a] -> [a]
stableSortLt       :: (a -> a -> Bool)     -> [a] -> [a]
mergesort          :: (a -> a -> _CMP_TAG) -> [a] -> [a]
mergeSort          :: Ord a => [a] -> [a]
naturalMergeSort   :: Ord a => [a] -> [a]
mergeSortLe        :: Ord a => [a] -> [a]
naturalMergeSortLe :: Ord a => [a] -> [a]

-- transitive closures
transitiveClosure :: (a -> [a])         -- Successor function
                  -> (a -> a -> Bool)   -- Equality predicate
                  -> [a] 
                  -> [a]                -- The transitive closure

-- accumulating (Left, Right, Bi-directional)
mapAccumL :: (acc -> x -> (acc, y))
                        -- Function of elt of input list and
                        -- accumulator, returning new accumulator and
                        -- elt of result list
          -> acc        -- Initial accumulator
          -> [x]        -- Input list
          -> (acc, [y]) -- Final accumulator and result list

mapAccumR :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])

mapAccumB :: (accl -> accr -> x -> (accl, accr,y))
          -> accl -> accr -> [x]
          -> (accl, accr, [y])

-- comparisons
cmpString :: String -> String -> _CMP_TAG

-- this type is built-in
data _CMP_TAG = _LT | _EQ | _GT

-- pairs
applyToPair :: ((a -> c), (b -> d)) -> (a, b) -> (c, d)
applyToFst  :: (a -> c) -> (a, b) -> (c, b)
applyToSnd  :: (b -> d) -> (a, b) -> (a, d)
foldPair    :: (a->a->a, b->b->b) -> (a, b) -> [(a, b)] -> (a, b)
unzipWith   :: (a -> b -> c) -> [(a, b)] -> [c]

Interfaces to C libraries

The GHC system library (-syslib ghc) also provides interfaces to several useful C libraries, mostly from the GNU project.

The Readline interface

(Darren Moffat supplied the Readline interface.)

The Readline module is a straightforward interface to the GNU Readline library. As such, you will need to look at the GNU documentation (and have a libreadline.a file around somewhere...)

You'll need to link any Readlining program with -lreadline -ltermcap, besides the usual -syslib ghc (and -fhaskell-1.3).

The main function you'll use is:

readline :: String{-the prompt-} -> IO String

If you want to mess around with Full Readline G(l)ory, we also provide:

rlInitialize, addHistory,

rlBindKey, rlAddDefun, RlCallbackFunction(..),

rlGetLineBuffer, rlSetLineBuffer, rlGetPoint, rlSetPoint, rlGetEnd,
rlSetEnd, rlGetMark, rlSetMark, rlSetDone, rlPendingInput,

rlPrompt, rlTerminalName, rlSetReadlineName, rlGetReadlineName

(All those names are just Haskellised versions of what you will see in the GNU readline documentation.)

The Regexp and MatchPS interfaces

(Sigbjorn Finne supplied the regular-expressions interface.)

The Regex library provides quite direct interface to the GNU regular-expression library, for doing manipulation on _PackedStrings. You probably need to see the GNU documentation if you are operating at this level.

The datatypes and functions that Regex provides are:

data PatBuffer  # just a bunch of bytes (mutable)

data REmatch
 = REmatch (Array Int GroupBounds)  -- for $1, ... $n
           GroupBounds              -- for $` (everything before match)
           GroupBounds              -- for $& (entire matched string)
           GroupBounds              -- for $' (everything after)
           GroupBounds              -- for $+ (matched by last bracket)

-- GroupBounds hold the interval where a group
-- matched inside a string, e.g.
--
-- matching "reg(exp)" "a regexp" returns the pair (5,7) for the
-- (exp) group. (_PackedString indices start from 0)

type GroupBounds = (Int, Int)

re_compile_pattern
        :: _PackedString        -- pattern to compile
        -> Bool                 -- True <=> assume single-line mode
        -> Bool                 -- True <=> case-insensitive
        -> PrimIO PatBuffer

re_match :: PatBuffer           -- compiled regexp
         -> _PackedString       -- string to match
         -> Int                 -- start position
         -> Bool                -- True <=> record results in registers
         -> PrimIO (Maybe REmatch)

-- Matching on 2 strings is useful when you're dealing with multiple
-- buffers, which is something that could prove useful for
-- PackedStrings, as we don't want to stuff the contents of a file
-- into one massive heap chunk, but load (smaller chunks) on demand.

re_match2 :: PatBuffer          -- 2-string version
          -> _PackedString
          -> _PackedString
          -> Int
          -> Int
          -> Bool
          -> PrimIO (Maybe REmatch)

re_search :: PatBuffer          -- compiled regexp
          -> _PackedString      -- string to search
          -> Int                -- start index
          -> Int                -- stop index
          -> Bool               -- True <=> record results in registers
          -> PrimIO (Maybe REmatch)

re_search2 :: PatBuffer         -- Double buffer search
           -> _PackedString
           -> _PackedString
           -> Int               -- start index
           -> Int               -- range (?)
           -> Int               -- stop index
           -> Bool              -- True <=> results in registers
           -> PrimIO (Maybe REmatch)

The MatchPS module provides Perl-like "higher-level" facilities to operate on _PackedStrings. The regular expressions in question are in Perl syntax. The "flags" on various functions can include: i for case-insensitive, s for single-line mode, and g for global. (It's probably worth your time to peruse the source code...)

matchPS :: _PackedString    -- regexp
        -> _PackedString    -- string to match
        -> [Char]           -- flags
        -> Maybe REmatch    -- info about what matched and where

searchPS :: _PackedString   -- regexp
         -> _PackedString   -- string to match
         -> [Char]          -- flags
         -> Maybe REmatch

-- Perl-like match-and-substitute:
substPS :: _PackedString    -- regexp
        -> _PackedString    -- replacement
        -> [Char]           -- flags
        -> _PackedString    -- string
        -> _PackedString

-- same as substPS, but no prefix and suffix:
replacePS :: _PackedString  -- regexp
          -> _PackedString  -- replacement
          -> [Char]         -- flags
          -> _PackedString  -- string
          -> _PackedString

match2PS :: _PackedString   -- regexp
         -> _PackedString   -- string1 to match
         -> _PackedString   -- string2 to match
         -> [Char]          -- flags
         -> Maybe REmatch

search2PS :: _PackedString  -- regexp
          -> _PackedString  -- string to match
          -> _PackedString  -- string to match
          -> [Char]         -- flags
          -> Maybe REmatch

-- functions to pull the matched pieces out of an REmatch:

getMatchesNo    :: REmatch -> Int
getMatchedGroup :: REmatch -> Int -> _PackedString -> _PackedString
getWholeMatch   :: REmatch -> _PackedString -> _PackedString
getLastMatch    :: REmatch -> _PackedString -> _PackedString
getAfterMatch   :: REmatch -> _PackedString -> _PackedString

-- (reverse) brute-force string matching;
-- Perl equivalent is index/rindex:
findPS, rfindPS :: _PackedString -> _PackedString -> Maybe Int

-- Equivalent to Perl "chop" (off the last character, if any):
chopPS :: _PackedString -> _PackedString

-- matchPrefixPS: tries to match as much as possible of strA starting
-- from the beginning of strB (handy when matching fancy literals in
-- parsers):
matchPrefixPS :: _PackedString -> _PackedString -> Int

Network-interface toolkit -- Socket and SocketPrim

(Darren Moffat supplied the network-interface toolkit.)

Your best bet for documentation is to look at the code -- really! -- normally in ghc/lib/ghc/\{BSD,Socket,SocketPrim\}.lhs.

The BSD module provides functions to get at system-database info; pretty straightforward if you're into this sort of thing:

getHostName         :: IO String

getServiceByName    :: ServiceName -> IO ServiceEntry
getServicePortNumber:: ServiceName -> IO PortNumber
getServiceEntry     :: IO ServiceEntry
setServiceEntry     :: Bool -> IO ()
endServiceEntry     :: IO ()

getProtocolByName   :: ProtocolName -> IO ProtocolEntry
getProtocolByNumber :: ProtocolNumber -> IO ProtcolEntry
getProtocolNumber   :: ProtocolName -> ProtocolNumber
getProtocolEntry    :: IO ProtocolEntry
setProtocolEntry    :: Bool -> IO ()
endProtocolEntry    :: IO ()

getHostByName       :: HostName -> IO HostEntry
getHostByAddr       :: Family -> HostAddress -> IO HostEntry
getHostEntry        :: IO HostEntry
setHostEntry        :: Bool -> IO ()
endHostEntry        :: IO ()

The SocketPrim interface provides quite direct access to the socket facilities in a BSD Unix system, including all the complications. We hope you don't need to use it! See the source if needed...

The Socket interface is a "higher-level" interface to sockets, and it is what we recommend. Please tell us if the facilities it offers are inadequate to your task!

The interface is relatively modest:

connectTo       :: Hostname -> PortID -> IO Handle
listenOn        :: PortID -> IO Socket

accept          :: Socket -> IO (Handle, HostName)
sendTo          :: Hostname -> PortID -> String -> IO ()

recvFrom        :: Hostname -> PortID -> IO String
socketPort      :: Socket -> IO PortID

data PortID     -- PortID is a non-abstract type
  = Service String      -- Service Name eg "ftp"
  | PortNumber Int      -- User defined Port Number
  | UnixSocket String   -- Unix family socket in file system

type Hostname = String

Various examples of networking Haskell code are provided in ghc/misc/examples/, notably the net???/Main.hs programs.

The HBC system library

This documentation is stolen directly from the HBC distribution. The modules that GHC does not support (because they require HBC-specific extensions) are omitted.

Either:

A binary sum data type:

data Either a b = Left a | Right b

The constructor Left is typically used for errors; it can be renamed to Wrong on import.

Maybe:

A type for failure or success:

data Maybe a = Nothing | Just a
thenM :: Maybe a -> (a -> Maybe b) -> Maybe b
    -- apply a function that may fail

Option:

An alias for Maybe:

data Option a = None | Some a
thenO :: Option a -> (a -> Option b) -> Option b

ListUtil:

Various useful functions involving lists that are missing from the Prelude:

assoc :: (Eq c) => (a -> b) -> b -> [(c, a)] -> c -> b
        -- assoc f d l k looks for k in the association list l, if it
        -- is found f is applied to the value, otherwise d is returned.
concatMap :: (a -> [b]) -> [a] -> [b]
        -- flattening map (LML's concmap)
unfoldr :: (a -> (b, a)) -> (a -> Bool) -> a -> [b]
        -- unfoldr f p x repeatedly applies f to x until (p x) holds.
        -- (f x) should give a list element and a new x.
mapAccuml :: (a -> b -> (a, c)) -> a -> [b] -> (a, [c])
        -- mapAccuml f s l maps f over l, but also threads the state s
        -- through (LML's mapstate).
union :: (Eq a) => [a] -> [a] -> [a]
        -- union of two lists
intersection :: (Eq a) => [a] -> [a] -> [a]
        -- intersection of two lists
chopList :: ([a] -> (b, [a])) -> [a] -> [b]
        -- LMLs choplist
assocDef :: (Eq a) => [(a, b)] -> b -> a -> b
        -- LMLs assocdef
lookup :: (Eq a) => [(a, b)] -> a -> Option b
        -- lookup l k looks for the key k in the association list l
        -- and returns an optional value
tails :: [a] -> [[a]]
        -- return all the tails of a list
rept :: (Integral a) => a -> b -> [b]
        -- repeat a value a number of times
groupEq :: (a->a->Bool) -> [a] -> [[a]]
        -- group list elements according to an equality predicate
group :: (Eq a) => [a] -> [[a]]
        -- group according to} ==
readListLazily :: (Text a) => String -> [a]
        -- read a list in a lazy fashion

Pretty:

John Hughes's pretty printing library.

type Context = (Bool, Int, Int, Int)
type IText = Context -> [String]
text :: String -> IText                 -- just text
(~.) :: IText -> IText -> IText         -- horizontal composition
(^.) :: IText -> IText -> IText         -- vertical composition
separate :: [IText] -> IText            -- separate by spaces
nest :: Int -> IText -> IText           -- indent
pretty :: Int -> Int -> IText -> String -- format it

QSort:

A sort function using quicksort.

sortLe :: (a -> a -> Bool) -> [a] -> [a]
        -- sort le l  sorts l with le as less than predicate
sort :: (Ord a) => [a] -> [a]
        -- sort l  sorts l using the Ord class

Random:

Random numbers.

randomInts :: Int -> Int -> [Int]
        -- given two seeds gives a list of random Int
randomDoubles :: Int -> Int -> [Double]
        -- random Double with uniform distribution in (0,1)
normalRandomDoubles :: Int -> Int -> [Double]
        -- random Double with normal distribution, mean 0, variance 1

Trace:
Simple tracing. (Note: This comes with GHC anyway.)
trace :: String -> a -> a       -- trace x y  prints x and returns y

Miranda:

Functions found in the Miranda library. (Note: Miranda is a registered trade mark of Research Software Ltd.)

Word:

Bit manipulation. (GHC doesn't implement absolutely all of this. And don't count on Word being 32 bits on a Alpha...)

class Bits a where
    bitAnd :: a -> a -> a       -- bitwise and
    bitOr :: a -> a -> a        -- bitwise or
    bitXor :: a -> a -> a       -- bitwise xor
    bitCompl :: a -> a          -- bitwise negation
    bitRsh :: a -> Int -> a     -- bitwise right shift
    bitLsh :: a -> Int -> a     -- bitwise left shift
    bitSwap :: a -> a           -- swap word halves
    bit0 :: a                   -- word with least significant bit set
    bitSize :: a -> Int         -- number of bits in a word

data Byte                       -- 8  bit quantity
data Short                      -- 16 bit quantity
data Word                       -- 32 bit quantity

instance Bits Byte, Bits Short, Bits Word
instance Eq Byte, Eq Short, Eq Word
instance Ord Byte, Ord Short, Ord Word
instance Text Byte, Text Short, Text Word
instance Num Byte, Num Short, Num Word
wordToShorts :: Word -> [Short]   -- convert a Word to two Short
wordToBytes :: Word -> [Byte]     -- convert a Word to four Byte
bytesToString :: [Byte] -> String -- convert a list of Byte to a String (bit by bit)
wordToInt :: Word -> Int          -- convert a Word to Int
shortToInt :: Short -> Int        -- convert a Short to Int
byteToInt :: Byte -> Int          -- convert a Byte to Int

Time:

Manipulate time values (a Double with seconds since 1970).

--               year mon  day  hour min  sec  dec-sec  weekday
data Time = Time Int  Int  Int  Int  Int  Int  Double  Int
dblToTime :: Double -> Time     -- convert a Double to a Time
timeToDbl :: Time -> Double     -- convert a Time to a Double
timeToString :: Time -> String  -- convert a Time to a readable String

Hash:

Hashing functions.

class Hashable a where
    hash :: a -> Int                            -- hash a value, return an Int
-- instances for all Prelude types
hashToMax :: (Hashable a) => Int -> a -> Int    -- hash into interval [0..x-1]

NameSupply:

Functions to generate unique names (Int).

type Name = Int
initialNameSupply :: NameSupply
        -- The initial name supply (may be different every
        -- time the program is run.
splitNameSupply :: NameSupply -> (NameSupply,NameSupply)
        -- split the namesupply into two
getName :: NameSupply -> Name
        -- get the name associated with a name supply

Parse:

Higher order functions to build parsers. With a little care these combinators can be used to build efficient parsers with good error messages.

infixr 8 +.+ , ..+ , +.. 
infix  6 `act` , >>> , `into` , .> 
infixr 4 ||| , ||! , |!! 
data ParseResult a b 
type Parser a b = a -> Int -> ParseResult a b 
(|||) :: Parser a b -> Parser a b -> Parser a b
        -- Alternative
(||!) :: Parser a b -> Parser a b -> Parser a b
        -- Alternative, but with committed choice
(|!!) :: Parser a b -> Parser a b -> Parser a b
        -- Alternative, but with committed choice
(+.+) :: Parser a b -> Parser a c -> Parser a (b,c)
        -- Sequence
(..+) :: Parser a b -> Parser a c -> Parser a c
        -- Sequence, throw away first part
(+..) :: Parser a b -> Parser a c -> Parser a b
        -- Sequence, throw away second part
act   :: Parser a b -> (b->c) -> Parser a c
        -- Action
(>>>) :: Parser a (b,c) -> (b->c->d) -> Parser a d
        -- Action on two items
(.>) :: Parser a b -> c -> Parse a c
        -- Action ignoring value
into :: Parser a b -> (b -> Parser a c) -> Parser a c
        -- Use a produced value in a parser.
succeed b :: Parser a b
        -- Always succeeds without consuming a token
failP :: Parser a b
        -- Always fails.
many :: Parser a b -> Parser a [b]
        -- Kleene star
many1 :: Parser a b -> Parser a [b]
        -- Kleene plus
count :: Parser a b -> Int -> Parser a [b]
        -- Parse an exact number of items
sepBy1 :: Parser a b -> Parser a c -> Parser a [b]
        -- Non-empty sequence of items separated by something
sepBy :: Parser a b -> Parser a c -> Parser a [b]
        -- Sequence of items separated by something
lit :: (Eq a, Text a) => a -> Parser [a] a
        -- Recognise a literal token from a list of tokens
litp :: String -> (a->Bool) -> Parser [a] a
        -- Recognise a token with a predicate.
        -- The string is a description for error messages.
testp :: String -> (a -> Bool) -> (Parser b a) -> Parser b a
        -- Test a semantic value. 
token :: (a -> Either String (b, a)) -> Parser a b
        -- General token recogniser.
parse :: Parser a b -> a -> Either ([String], a) [(b, a)]
        -- Do a parse.  Return either error (possible tokens and rest
        -- of tokens) or all possible parses.
sParse :: (Text a) => (Parser [a] b) -> [a] -> Either String b
        -- Simple parse.  Return error message or result.

Native:

Functions to convert the primitive types Int, Float, and Double to their native representation as a list of bytes (Char). If such a list is read/written to a file it will have the same format as when, e.g., C read/writes the same kind of data.

type Bytes = [Char] -- A byte stream is just a list of characters

class Native a where 
    showBytes     :: a -> Bytes -> Bytes
        -- prepend the representation of an item the a byte stream
    listShowBytes :: [a] -> Bytes -> Bytes
        -- prepend the representation of a list of items to a stream
        -- (may be more efficient than repeating showBytes).
    readBytes     :: Bytes -> Maybe (a, Bytes)
        -- get an item from the stream and return the rest,
        -- or fail if the stream is to short.
    listReadBytes :: Int -> Bytes -> Maybe ([a], Bytes)
        -- read n items from a stream.

instance Native Int 
instance Native Float 
instance Native Double 
instance (Native a, Native b) => Native (a,b)
        -- juxtaposition of the two items
instance (Native a, Native b, Native c) => Native (a, b, c)
        -- juxtaposition of the three items
instance (Native a) => Native [a]
        -- an item count in an Int followed by the items

shortIntToBytes :: Int -> Bytes -> Bytes
        -- Convert an Int to what corresponds to a short in C.
bytesToShortInt :: Bytes -> Maybe (Int, Bytes)
        -- Get a short from a byte stream and convert to an Int.

showB :: (Native a) => a -> Bytes       -- Simple interface to showBytes.
readB :: (Native a) => Bytes -> a       -- Simple interface to readBytes.

Number:

Simple numbers that belong to all numeric classes and behave like a naive user would expect (except that printing is still ugly). (NB: GHC does not provide a magic way to use Numbers everywhere, but you should be able to do it with normal importing and defaulting.)

data Number                     -- The type itself.
instance ...                    -- All reasonable instances.
isInteger :: Number -> Bool     -- Test if a Number is an integer.

Concurrent and Parallel Haskell

Concurrent and Parallel Haskell are Glasgow extensions to Haskell which let you structure your program as a group of independent `threads'.

Concurrent and Parallel Haskell have very different purposes.

Concurrent Haskell is for applications which have an inherent structure of interacting, concurrent tasks (i.e. `threads'). Threads in such programs may be required. For example, if a concurrent thread has been spawned to handle a mouse click, it isn't optional -- the user wants something done!

A Concurrent Haskell program implies multiple `threads' running within a single Unix process on a single processor.

Simon Peyton Jones and Sigbjorn Finne have a paper available, "Concurrent Haskell: preliminary version." (draft available via ftp from ftp.dcs.gla.ac.uk/pub/glasgow-fp/drafts).

Parallel Haskell is about speed -- spawning threads onto multiple processors so that your program will run faster. The `threads' are always advisory -- if the runtime system thinks it can get the job done more quickly by sequential execution, then fine.

A Parallel Haskell program implies multiple processes running on multiple processors, under a PVM (Parallel Virtual Machine) framework.

Parallel Haskell was first released with GHC 0.26; it is more about "research fun" than about "speed." That will change. There is no paper about Parallel Haskell. That will change, too.

Some details about Concurrent and Parallel Haskell follow.

Concurrent and Parallel Haskell -- language features

Features specific to Concurrent Haskell

The Concurrent interface (recommended)

GHC provides a Concurrent module, a common interface to a collection of useful concurrency abstractions, including those mentioned in the "concurrent paper".

Just put import Concurrent into your modules, and away you go. NB: intended for use with the -fhaskell-1.3 flag.

To create a "required thread":

forkIO :: IO a -> IO a

The Concurrent interface also provides access to "I-Vars" and "M-Vars", which are two flavours of synchronising variables.

_IVars are write-once variables. They start out empty, and any threads that attempt to read them will block until they are filled. Once they are written, any blocked threads are freed, and additional reads are permitted. Attempting to write a value to a full _IVar results in a runtime error. Interface:

type IVar a = _IVar a -- more convenient name

newIVar     :: IO (_IVar a)
readIVar    :: _IVar a -> IO a
writeIVar   :: _IVar a -> a -> IO ()

_MVars are rendezvous points, mostly for concurrent threads. They begin empty, and any attempt to read an empty _MVar blocks. When an _MVar is written, a single blocked thread may be freed. Reading an _MVar toggles its state from full back to empty. Therefore, any value written to an _MVar may only be read once. Multiple reads and writes are allowed, but there must be at least one read between any two writes. Interface:

type MVar a  = _MVar a -- more convenient name

newEmptyMVar :: IO (_MVar a)
newMVar      :: a -> IO (_MVar a)
takeMVar     :: _MVar a -> IO a
putMVar      :: _MVar a -> a -> IO ()
readMVar     :: _MVar a -> IO a
swapMVar     :: _MVar a -> a -> IO a

A channel variable (CVar) is a one-element channel, as described in the paper:

data CVar a
newCVar :: IO (CVar a)
putCVar :: CVar a -> a -> IO ()
getCVar :: CVar a -> IO a

A Channel is an unbounded channel:

data Chan a 
newChan         :: IO (Chan a)
putChan         :: Chan a -> a -> IO ()
getChan         :: Chan a -> IO a
dupChan         :: Chan a -> IO (Chan a)
unGetChan       :: Chan a -> a -> IO ()
getChanContents :: Chan a -> IO [a]

General and quantity semaphores:

data QSem
newQSem     :: Int   -> IO QSem
waitQSem    :: QSem  -> IO ()
signalQSem  :: QSem  -> IO ()

data QSemN
newQSemN    :: Int   -> IO QSemN
signalQSemN :: QSemN -> Int -> IO ()
waitQSemN   :: QSemN -> Int -> IO ()

Merging streams -- binary and n-ary:

mergeIO  :: [a]   -> [a] -> IO [a]
nmergeIO :: [[a]] -> IO [a]

A Sample variable (SampleVar) is slightly different from a normal _MVar:

type SampleVar a = _MVar (Int, _MVar a)

emptySampleVar :: SampleVar a -> IO ()
newSampleVar   :: IO (SampleVar a)
readSample     :: SampleVar a -> IO a
writeSample    :: SampleVar a -> a -> IO ()

Finally, there are operations to delay a concurrent thread, and to make one wait:

threadDelay :: Int -> IO () -- delay rescheduling for N microseconds
threadWait  :: Int -> IO () -- wait for input on specified file descriptor

Features specific to Parallel Haskell

The Parallel interface (recommended)

GHC provides two functions for controlling parallel execution, through the Parallel interface:

interface Parallel where
infixr 0 `par`
infixr 1 `seq`

par :: a -> b -> b
seq :: a -> b -> b

The expression (x `par` y) sparks the evaluation of x (to weak head normal form) and returns y. Sparks are queued for execution in FIFO order, but are not executed immediately. At the next heap allocation, the currently executing thread will yield control to the scheduler, and the scheduler will start a new thread (until reaching the active thread limit) for each spark which has not already been evaluated to WHNF.

The expression (x `seq` y) evaluates x to weak head normal form and then returns y. The seq primitive can be used to force evaluation of an expression beyond WHNF, or to impose a desired execution sequence for the evaluation of an expression.

For example, consider the following parallel version of our old nemesis, nfib:

import Parallel

nfib :: Int -> Int
nfib n | n <= 1 = 1
       | otherwise = par n1 (seq n2 (n1 + n2 + 1))
                     where n1 = nfib (n-1) 
                           n2 = nfib (n-2)

For values of n greater than 1, we use par to spark a thread to evaluate nfib (n-1), and then we use seq to force the parent thread to evaluate nfib (n-2) before going on to add together these two subexpressions. In this divide-and-conquer approach, we only spark a new thread for one branch of the computation (leaving the parent to evaluate the other branch). Also, we must use seq to ensure that the parent will evaluate n2 before n1 in the expression (n1 + n2 + 1). It is not sufficient to reorder the expression as (n2 + n1 + 1), because the compiler may not generate code to evaluate the addends from left to right.

Underlying functions and primitives

The functions par and seq are really just renamings:

par a b = _par_ a b
seq a b = _seq_ a b

The functions _par_ and _seq_ are built into GHC, and unfold into uses of the par# and seq# primitives, respectively. If you'd like to see this with your very own eyes, just run GHC with the -ddump-simpl option. (Anything for a good time...)

You can use _par_ and _seq_ in Concurrent Haskell, though I'm not sure why you would want to.

Features common to Concurrent and Parallel Haskell

Actually, you can use the `par` and `seq` combinators (really for Parallel Haskell) in Concurrent Haskell as well. But doing things like "par to forkIO many required threads" counts as "jumping out the 9th-floor window, just to see what happens."

Scheduling policy for concurrent/parallel threads

Runnable threads are scheduled in round-robin fashion. Context switches are signalled by the generation of new sparks or by the expiry of a virtual timer (the timer interval is configurable with the -C[<num>] RTS option). However, a context switch doesn't really happen until the next heap allocation. If you want extremely short time slices, the -C RTS option can be used to force a context switch at each and every heap allocation.

When a context switch occurs, pending sparks which have not already been reduced to weak head normal form are turned into new threads. However, there is a limit to the number of active threads (runnable or blocked) which are allowed at any given time. This limit can be adjusted with the -t<num>

RTS option (the default is 32). Once the thread limit is reached, any remaining sparks are deferred until some of the currently active threads are completed.

How to use Concurrent and Parallel Haskell

[You won't get far unless your GHC system was configured/built with concurrency and/or parallelism enabled. (They require separate library modules.) The relevant section of the installation guide says how to do this.]

Using Concurrent Haskell

To compile a program as Concurrent Haskell, use the -concurrent option, both when compiling and linking. You will probably need the -fglasgow-exts option, too.

Three RTS options are provided for modifying the behaviour of the threaded runtime system. See the descriptions of -C[<us>], -q, and -t<num> in Section parallel-rts-opts.

Potential problems with Concurrent Haskell

The main thread in a Concurrent Haskell program is given its own private stack space, but all other threads are given stack space from the heap. Stack space for the main thread can be adjusted as usual with the -K RTS option, but if this private stack space is exhausted, the main thread will switch to stack segments in the heap, just like any other thread. Thus, problems which would normally result in stack overflow in "sequential Haskell" can be expected to result in heap overflow when using threads.

The concurrent runtime system uses black holes as synchronisation points for subexpressions which are shared among multiple threads. In "sequential Haskell", a black hole indicates a cyclic data dependency, which is a fatal error. However, in concurrent execution, a black hole may simply indicate that the desired expression is being evaluated by another thread. Therefore, when a thread encounters a black hole, it simply blocks and waits for the black hole to be updated. Cyclic data dependencies will result in deadlock, and the program will fail to terminate.

Because the concurrent runtime system uses black holes as synchronisation points, it is not possible to disable black-holing with the -N RTS option. Therefore, the use of signal handlers (including timeouts) with the concurrent runtime system can lead to problems if a thread attempts to enter a black hole that was created by an abandoned computation. The use of signal handlers in conjunction with threads is strongly discouraged.

Using Parallel Haskell

[You won't be able to execute parallel Haskell programs unless PVM3 (Parallel Virtual Machine, version 3) is installed at your site.]

To compile a Haskell program for parallel execution under PVM, use the -parallel option, both when compiling and linking. You will probably want to import Parallel into your Haskell modules.

To run your parallel program, once PVM is going, just invoke it "as normal". The main extra RTS option is -N<n>, to say how many PVM "processors" your program to run on. (For more details of all relevant RTS options, please see section parallel-rts-opts.)

In truth, running Parallel Haskell programs and getting information out of them (e.g., parallelism profiles) is a battle with the vagaries of PVM, detailed in the following sections.

Dummy's guide to using PVM

Before you can run a parallel program under PVM, you must set the required environment variables (PVM's idea, not ours); something like, probably in your .cshrc or equivalent:

setenv PVM_ROOT /wherever/you/put/it
setenv PVM_ARCH `$PVM_ROOT/lib/pvmgetarch`
setenv PVM_DPATH $PVM_ROOT/lib/pvmd

Creating and/or controlling your "parallel machine" is a purely-PVM business; nothing specific to Parallel Haskell.

You use the pvm command to start PVM on your machine. You can then do various things to control/monitor your "parallel machine;" the most useful being:

Control-D            exit pvm, leaving it running     
halt                 kill off this "parallel machine" \& exit  
add <host>     add <host> as a processor  
delete <host>  delete <host>              
reset                kill what's going, but leave PVM up       
conf                 list the current configuration            
ps                   report processes' status                  
pstat <pid>    status of a particular process            
The PVM documentation can tell you much, much more about pvm!

Parallelism profiles

With Parallel Haskell programs, we usually don't care about the results -- only with "how parallel" it was! We want pretty pictures.

Parallelism profiles (a la hbcpp) can be generated with the -q RTS option. The per-processor profiling info is dumped into files named <full-path><program>.gr. These are then munged into a PostScript picture, which you can then display. For example, to run your program a.out on 8 processors, then view the parallelism profile, do:

% ./a.out +RTS -N8 -q
% grs2gr *.???.gr > temp.gr     # combine the 8 .gr files into one
% gr2ps -O temp.gr              # cvt to .ps; output in temp.ps
% ghostview -seascape temp.ps   # look at it!

The scripts for processing the parallelism profiles are distributed in ghc/utils/parallel/.

Other useful info about running parallel programs

The "garbage-collection statistics" RTS options can be useful for seeing what parallel programs are doing. If you do either +RTS -Sstderr or +RTS -sstderr, then you'll get mutator, garbage-collection, etc., times on standard error. The standard error of all PE's other than the `main thread' appears in /tmp/pvml.nnn, courtesy of PVM.

Whether doing +RTS -Sstderr or not, a handy way to watch what's happening overall is: tail -f /tmp/pvml.nnn.

RTS options for Concurrent/Parallel Haskell

Besides the usual runtime system (RTS) options (part runtime-control), there are a few options particularly for concurrent/parallel execution.

-N<N>:

(PARALLEL ONLY) Use <N> PVM processors to run this program; the default is 2.

-C[<us>]:

Sets the context switch interval to <us> microseconds. A context switch will occur at the next heap allocation after the timer expires. With -C0 or -C, context switches will occur as often as possible (at every heap allocation). By default, context switches occur every 10 milliseconds. Note that many interval timers are only capable of 10 millisecond granularity, so the default setting may be the finest granularity possible, short of a context switch at every heap allocation.

-q[v]:

Produce a quasi-parallel profile of thread activity, in the file <program>.qp. In the style of hbcpp, this profile records the movement of threads between the green (runnable) and red (blocked) queues. If you specify the verbose suboption (-qv), the green queue is split into green (for the currently running thread only) and amber (for other runnable threads). We do not recommend that you use the verbose suboption if you are planning to use the hbcpp profiling tools or if you are context switching at every heap check (with -C).

-t<num>:

Limit the number of concurrent threads per processor to <num>. The default is 32. Each thread requires slightly over 1K words in the heap for thread state and stack objects. (For 32-bit machines, this translates to 4K bytes, and for 64-bit machines, 8K bytes.)

-d:

(PARALLEL ONLY) Turn on debugging. It pops up one xterm (or GDB, or something...) per PVM processor. We use the standard debugger script that comes with PVM3, but we sometimes meddle with the debugger2 script. We include ours in the GHC distribution, in ghc/utils/pvm/.

-e<num>:

(PARALLEL ONLY) Limit the number of pending sparks per processor to <num>. The default is 100. A larger number may be appropriate if your program generates large amounts of parallelism initially.

-Q<num>:

(PARALLEL ONLY) Set the size of packets transmitted between processors to <num>. The default is 1024 words. A larger number may be appropriate if your machine has a high communication cost relative to computation speed.

Potential problems with Parallel Haskell

The "Potential problems" for Concurrent Haskell also apply for Parallel Haskell. Please see Section concurrent-problems.

What to do when something goes wrong

If you still have a problem after consulting this section, then you may have found a bug -- please report it! See Chapter bug-reports for a list of things we'd like to know about your bug. If in doubt, send a report -- we love mail from irate users :-!

(Part vs-Haskell-defn, which describes Glasgow Haskell's shortcomings vs. the Haskell language definition, may also be of interest.)

When the compiler "does the wrong thing"

"Help! The compiler crashed (or `panic'd)!"
These events are always bugs in the GHC system -- please report them.

"The compiler ran out of heap (or stack) when compiling itself!"
It happens. We try to supply reasonable -H<n> flags for ghc/compiler/ and ghc/lib/, but GHC's memory consumption can vary by platform (e.g., on a 64-bit machine).

Just say make all EXTRA_HC_OPTS=-H<a reasonable number> and see how you get along.

"The compiler died with a pattern-matching error."
This is a bug just as surely as a "panic." Please report it.

"Some confusion about a value specialised to a type..." Huh???
(A deeply obscure and unfriendly error message.)

This message crops up when the typechecker sees a reference in an interface pragma to a specialisation of an overloaded value (function); for example, elem specialised for type [Char] (String). The problem is: it doesn't know that such a specialisation exists!

The cause of this problem is (please report any other cases...): The compiler has imported pragmatic info for the value in question from more than one interface, and the multiple interfaces did not agree exactly about the value's pragmatic info. Since the compiler doesn't know whom to believe, it believes none of them.

The cure is to re-compile the modules that re-export the offending value (after possibly re-compiling its defining module). Now the pragmatic info should be exactly the same in every case, and things should be fine.

"Can't see the data constructors for a ccall/casm" Huh?
GHC "unboxes" C-call arguments and "reboxes" C-call results for you. To do this, it {\\em has} to be able to see the types fully; abstract types won't do!

Thus, if you say data Foo = Foo Int# (a cool "boxed primitive" type), but then make it abstract (only data Foo appears in the interface), then GHC can't figure out what to do with Foo arguments/results to C-calls.

Solutions: either make the type unabstract, or compile with -O. With the latter, the constructor info will be passed along in the interface pragmas.

"This is a terrible error message."
If you think that GHC could have produced a better error message, please report it as a bug.

"What about these `trace' messages from GHC?"
Almost surely not a problem. About some specific cases...
Simplifier still going after N iterations:
Sad, but harmless. You can change the number with a -fmax-simplifier-iterations<N> option (no space); and you can see what actions took place in each iteration by turning on the -fshow-simplifier-progress option.

If the simplifier definitely seems to be "looping," please report it.

"What about this warning from the C compiler?"
For example: "...warning: `Foo' declared `static' but never defined." Unsightly, but not a problem.

Sensitivity to .hi interface files:
GHC is very sensitive about interface files. For example, if it picks up a non-standard Prelude.hi file, pretty terrible things will happen. If you turn on -fno-implicit-prelude , the compiler will almost surely die, unless you know what you are doing.

Furthermore, as sketched below, you may have big problems running programs compiled using unstable interfaces.

"I think GHC is producing incorrect code":
Unlikely :-) A useful be-more-paranoid option to give to GHC is -dcore-lint ; this causes a "lint" pass to check for errors (notably type errors) after each Core-to-Core transformation pass. We run with -dcore-lint on all the time; it costs about 5% in compile time. (Or maybe 25%; who knows?)

"Why did I get a link error?"
If the linker complains about not finding _<something>_fast, then your interface files haven't settled -- keep on compiling! (In particular, this error means that arity information, which you can see in any .hi file, has changed.)

"What's a `consistency error'?"
(These are reported just after linking your program.)

You tried to link incompatible object files, e.g., normal ones (registerised, Appel garbage-collector) with profiling ones (two-space collector). Or those compiled by a previous version of GHC with an incompatible newer version.

If you run nm -o *.o | egrep 't (cc|hsc)\.' (or, on unregisterised files: what *.o), you'll see all the consistency tags/strings in your object files. They must all be the same! (ToDo: tell you what they mean...)

"Is this line number right?"
On this score, GHC usually does pretty well, especially if you "allow" it to be off by one or two. In the case of an instance or class declaration, the line number may only point you to the declaration, not to a specific method.

Please report line-number errors that you find particularly unhelpful.

When your program "does the wrong thing"

(For advice about overly slow or memory-hungry Haskell programs, please see part sooner-faster-quicker).

"Help! My program crashed!"
(e.g., a `segmentation fault' or `core dumped')

If your program has no _ccall_s/_casm_s in it, then a crash is always a BUG in the GHC system, except in one case: If your program is made of several modules, each module must have been compiled with a stable group of interface (.hi) files.

For example, if an interface is lying about the type of an imported value then GHC may well generate duff code for the importing module. This applies to pragmas inside interfaces too! If the pragma is lying (e.g., about the "arity" of a value), then duff code may result. Furthermore, arities may change even if types do not.

In short, if you compile a module and its interface changes, then all the modules that import that interface must be re-compiled.

A useful option to alert you when interfaces change is -hi-diffs . It will run diff on the changed interface file, before and after, when applicable.

If you are using make, a useful tool to make sure that every module is up-to-date with respect to its imported interfaces is mkdependHS (which comes with GHC). Please see chapter mkdependHS.

If you are down to your last-compile-before-a-bug-report, we would recommend that you add a -dcore-lint option (for extra checking) to your compilation options.

So, before you report a bug because of a core dump, you should probably:

% rm *.o        # scrub your object files
% make my_prog  # re-make your program; use -hi-diffs to highlight changes
% ./my_prog ... # retry...

Of course, if you have _ccall_s/_casm_s in your program then all bets are off, because you can trash the heap, the stack, or whatever.

If you are interested in hard-core debugging of a crashing GHC-compiled program, please see chapter hard-core-debug.

"My program entered an `absent' argument."
This is definitely caused by a bug in GHC. Please report it.

"What's with this `arithmetic (or `floating') exception' "?
Int, Float, and Double arithmetic is unchecked. Overflows and underflows are silent. Divide-by-zero may cause an untrapped exception (please report it if it does). I suppose other arithmetic uncheckiness might cause an exception, too...

How to report a bug in the GHC system

Glasgow Haskell is a changing system so there are sure to be bugs in it. Please report them to glasgow-haskell-bugs@dcs.glasgow.ac.uk! (However, please check the earlier part of this section to be sure it's not a known not-really-a problem.)

The name of the bug-reporting game is: facts, facts, facts. Don't omit them because "Oh, they won't be interested..."

Hard-core debugging of GHC-compiled programs

If your program is crashing, you should almost surely file a bug report, as outlined in previous sections.

This section suggests ways to Make Further Progress Anyway.

The first thing to establish is: Is it a garbage-collection (GC) bug? Try your program with a very large heap and a -Sstderr RTS flag.

If it is a GC bug, you may be able to avoid it by using a particular heap size or by using a -F2s runtime flag. (But don't forget to report the bug!!!)

ToDo: more here?

Haskell 1.2 vs. Glasgow Haskell 0.26: language non-compliance

This section lists Glasgow Haskell infelicities in its implementation of Haskell 1.2. See also the "when things go wrong" section (part wrong) for information about crashes, space leaks, and other undesirable phenomena.

The limitations here are listed in Haskell-Report order (roughly).

Expressions and patterns

Some valid irrefutable patterns are rejected:
As syntax errors; just put parentheses around them.

Very long String constants:
May not go through. If you add a "string gap" every few thousand characters, then the strings can be as long as you like.

Bear in mind that string gaps and the -cpp

option don't mix. The C-preprocessor may munch the backslashes.

Very long literal lists:
These may tickle a "yacc stack overflow" error in the parser. (It depends on the Yacc used to build your parser.)

Declarations and bindings

Contexts on data declarations are ignored:
Not that they do much, anyway... This won't wreck your life. (We still [vaguely] plan to add them, however.)

Location of instance declarations is unchecked:
We don't check that instance declarations occur either in the module where the class is declared or the module where the data type is declared. This shouldn't hurt you.

For better or worse, we do check if you try to declare a Prelude instance (Prelude class, Prelude type; e.g., instance Num Bool) in one of your own modules. For some reason, people like to do this! (But it is not legal Haskell.)

Derived instances of Text for infix constructors:
All the carry-on about derived readsPrec and showsPrec for infix constructors -- we don't do it (yet). We treat them the same way as all other constructors.

Derived instances of Binary:
We don't. (We don't do anything Binaryish.)

Module system and interface files

Duplicates in a `renaming' list:
Are not reported.

Duplicates in an `import' declaration:
These are reported as errors, which some might argue they shouldn't be. We reckon it's a feature, not a bug.

Export of `renamed' class methods:
Willnae work. That is: you import a class, renaming one or more methods; then export that class -- the renaming of the methods will not propagate.

(Otherwise, `renaming' -- disgusting though it may be -- should work.)

Fixities/precedences following `renamed' entities that are exported:
No chance.

import Foo () vs import Foo:
GHC cannot tell the difference (!).

Given that the only module on which you might want to do the former is import Prelude (), there are probably much bigger gremlins that would jump out and bite you if the import did work. Besides which, you can achieve the same result with -fno-implicit-prelude.

Some selective import/export checking not done:
On selective import and export of type-constructors/classes in which the data-constructors/methods are named explicitly: it'll work; it's just that every conceivable paranoia check won't be done.

Some Prelude entities cannot be hidden:
For example, this doesn't work:
import Prelude hiding (readParen)

That's because there are a few should-be-hideable Prelude entities which need to appear by magic for derived instances. They are (&&), (.), lex, map, not, readParen, showParen, and showString. SIGH.

M.. exports vs multiply-imported entities:
If an entity foo is imported from several interfaces, as in...
import A1 (foo); import A2 (foo); import A3 (foo)

... and you then do a "dot dot" export of A1 (for example), it will be pure luck if foo gets exported. This is very sad.

Workaround: export foo explicitly.

M.. with Prelude interfaces:
Doing Prelude<something>.. in an export list; don't even think it.

Export of Prelude types/classes must be explicit:
If you want to export a data type, type synonym or class from a Prelude module (its name starts with `Prelude'), then it must be listed explicitly in the export list. If you say:

module PreludeMeGently ( PreludeMeGently.. , other_stuff ) where ..

then the classes/types in PreludeMeGently will not be exported; just add them to the export list. (This shortcoming is only likely to affect people writing their own Prelude modules.)

Can't export primitives types (e.g., Int#):
Don't even try...

Naming errors with -O but not without:
Documentation by example -- Consider a module with these imports:

... various imports ...
import Prettyterm       -- desired import

import Pretty           -- sadly-needed import

The import Pretty is required because it defines a type Pretty.Doc which is mentioned in import Prettyterm. (Extremely sad, but them's the rules.)

But without -O, GHC uses its -fuse-get-mentioned-vars hack (for speed), trying to avoid looking at parts of interfaces that have no relevance to this module. As it happens, the thing in Prettyterm that mentions Pretty.Doc is not used here, so this module will go through without import Pretty. Nice, but wrong.

Numbers, basic types, and built-in classes

Very large/small fractional constants:
(i.e., with a decimal point somewhere) GHC does not check that these are out of range (e.g., for a Float), and bad things will inevitably follow. To be corrected.

This problem does not exist for integral constants.

For very large/small fractional constants near the limits of your floating-point precision, things may go wrong. (It's better than it used to be.) Please report any such bugs.

Unchecked arithmetic:
Arguably not an infelicity, but... Bear in mind that operations on Int, Float, and Double numbers are unchecked for overflow, underflow, and other sad occurrences.

Use Integer, Rational, etc., numeric types if this stuff keeps you awake at night.

Multiply-defined array elements -- not checked:
This code fragment should elicit a fatal error, but it does not:
main = print (array (1,1) [ 1:=2, 1:=3 ])

Support for Binary whatnot:
We don't.

Dialogue I/O

Dialogue-style I/O -- still the default for GHC -- is on its way out (see the stuff about "monadic I/O for Haskell 1.3"), so we probably won't fix these shortcomings.

Support for Dialogue I/O:
We do not yet support all Requests, notably: ReadBinFile, WriteBinFile, AppendBinFile, StatusFile, ReadBinChan, AppendBinChan, StatusChan, SetEnv. Also, we do not support the optional I/O Requests.

AppendChan and ReadChan requests:
The former only works for stdout and stderr; the latter only for stdin.

Echo request:
We don't do anything at all.

In Prelude support

Arbitrary-sized tuples:
Plain old tuples of arbitrary size do work. Note that lots of overloading can give rise to large tuples "under the hood" of your program.

HOWEVER: standard instances for tuples (Eq, Ord, Ix, and Binary) are available only up to 5-tuples; except Binary, which we don't do at all.

These limitations are easily subvertible, so please ask if you get stuck on them.

Haskell 1.3 DRAFT vs. Glasgow Haskell 0.26

There is work afoot on "Haskell 1.3," a substantial revision of the Haskell 1.2 language.

Haskell 1.3 is NOT a standard; it is NOT even a DRAFT standard. As of June 1995, there exists a 1.3 PROPOSAL, which will CERTAINLY change. Therefore, the "1.3 things" we "support" may change ARBITRARILY much, and we won't even be mildly apologetic about breaking programs that use "1.3" facilities.

That said, there are two categories of "1.3" things that we commend to you.

To use our 1.3 code, you should compile and link using a -fhaskell-1.3 flag.

Duffer's guide for converting 1.2 I/O to 1.3 I/O

Here is our "crib sheet" for converting 1.2 I/O to 1.3. In most cases, it's really easy.

Non-I/O things from the 1.3-DRAFT proposal

Besides the I/O stuff, you also get these things when you use the -fhaskell-1.3 flag.

Once again: ANY of thing might CHANGE COMPLETELY before we have "1.3 for real."

data Either a b = Left a | Right b deriving (Text, Eq, Ord)

data Maybe a = Nothing | Just a deriving (Eq, Ord, Text)

thenMaybe :: Maybe a -> (a -> Maybe b) -> Maybe b
thenMaybe Nothing _ = Nothing
thenMaybe (Just x) f = f x

curry   :: ((a,b) -> c) -> a -> b -> c
curry f x y = f (x,y)

uncurry :: (a -> b -> c) -> (a,b) -> c
uncurry f (x,y) = f x y

Vs 1.3 monadic I/O

The most notable improvement in Haskell 1.3 is its I/O, with a shift to "monadic-style" I/O.

We still offer direct access to the so-called PrimIO monad, via the PreludeGlaST interface. This is NON-STANDARD, an extension. This interface is described in Section io-1-3-prim-interface.

The old PreludePrimIO interface is DEAD.

The even-older PreludeGlaIO interface is DEADER.

Known shortcomings in monadic I/O

Before you begin with "1.3-style" monadic I/O, you might as well know the known shortcomings of our implementation, as at 0.26.

The error type is called IOError13, rather than IOError

(which is still the 1.2 type). (Prelude types cannot be renamed, so...) You probably shouldn't be messing with IOError much, anyway.

Some of the 1.3 I/O code, notably the Extremely Cool LibPosix stuff, is relatively untested. Go for it, but be wary...

1.3-style monadic I/O

To use our 1.3 I/O, you should compile and link using a -fhaskell-1.3 flag.

You should consult the PROPOSED 1.3-I/O standard. GHC 0.26 implements the "December 1994" draft, which we distribute in ghc/docs/io-1.3/.

Alternatively, you could grab the "June 1995" draft, from pub/haskell/report/, on ftp.dcs.glasgow.ac.uk. The main December--June change that you need to know about is: many of the I/O functions have been removed from Prelude* interfaces (no import required) and put into Lib* interfaces (import required).

GHC 0.26 still provides the I/O functions via Prelude.hi (no import required). Ignore the "June draft" pleadings for import LibIO, and you'll be fine.

There is no guarantee that the final 1.3 proposal will look anything like the current DRAFT. It ain't a standard until the fat committee sings.

For interaction with our non-standard PrimIO, including _ccall_s. we also provide:

-- impedance matching stuff
ioToPrimIO      :: IO a -> PrimIO a

Access to the PrimIO monad

In what we have implemented, PrimIO is the handle-the-errors-yourself monad (NB: used for C-calls and such); whereas IO is the 1.3-ish we-handle-errors-for-you monad.

Should you may need to play with the PrimIO monad directly, you can import PreludeGlaST.

NB: You used to get this stuff from the PreludePrimIO interface, which is now deceased. As of 0.26, you get all things state-transforming from the PreludeGlaST interface.

The usual monadic stuff for PrimIO:

returnPrimIO    :: a -> PrimIO a
thenPrimIO      :: PrimIO a -> (a -> PrimIO b) -> PrimIO b
seqPrimIO       :: PrimIO a -> PrimIO b -> PrimIO b
fixPrimIO       :: (a -> PrimIO a) -> PrimIO a
foldrPrimIO     :: (a -> b -> PrimIO b) -> PrimIO b -> [a] -> PrimIO b
listPrimIO      :: [PrimIO a] -> PrimIO [a]
mapPrimIO       :: (a -> PrimIO b) -> [a] -> PrimIO [b]
mapAndUnzipPrimIO :: (a -> PrimIO (b,c)) -> [a] -> PrimIO ([b],[c])
forkPrimIO      :: PrimIO a -> PrimIO a

unsafePerformPrimIO     :: PrimIO a -> a
unsafeInterleavePrimIO  :: PrimIO a -> PrimIO a
  -- and they are not called "unsafe" for nothing!

And some other stuff:

data _FILE  -- corresponds to a "FILE *" in C
            -- in classes Eq, _CCallable, and _CReturnable

fclose  :: _FILE -> PrimIO Int
fdopen  :: Int -> String -> PrimIO _FILE
fflush  :: _FILE -> PrimIO Int
fopen   :: String -> String -> PrimIO _FILE
fread   :: Int -> Int -> _FILE -> PrimIO (Int, _ByteArray Int)
freopen :: String -> String -> _FILE -> PrimIO _FILE
fwrite  :: _ByteArray Int -> Int -> Int -> _FILE -> PrimIO Int

-- please AVOID using these (They will probably die)
appendChanPrimIO :: String -> String -> PrimIO ()
appendFilePrimIO :: String -> String -> PrimIO ()
getArgsPrimIO    :: PrimIO [String]
readChanPrimIO   :: String -> PrimIO String

Using your own mainPrimIO

Normally, the GHC runtime system begins things by called an internal function mainPrimIO :: PrimIO () which, in turn, fires up dialogueToIO :: Dialogue -> IO (), linking in your Main.main to provide the Dialogue.

(If you give a -fhaskell-1.3 flag, then a different mainPrimIO will be linked in -- that's why it is important to link with -fhaskell-1.3...)

To subvert the above process, you need only provide a mainPrimIO :: PrimIO () of your own (in a module named Main). Do not use a -fhaskell-1.3 flag!

Here's a little example, stolen from Alastair Reid:

module Main ( mainPrimIO ) where

import PreludeGlaST

mainPrimIO :: PrimIO ()
mainPrimIO = 
         sleep 5                                `seqPrimIO`
         _ccall_ printf "%d\n" (14::Int)

sleep :: Int -> PrimIO ()
sleep t = _ccall_ sleep t

Other Haskell utility programs

This section describes other program(s) which we distribute, that help with the Great Haskell Programming Task.

Makefile dependencies in Haskell: using mkdependHS

It is reasonably straightforward to set up a Makefile to use with GHC, assuming you name your source files the same as your modules. Thus:

HC      = ghc
HCFLAGS = -fhaskell-1.3 -cpp -hi-diffs $(EXTRA_HC_OPTS)

SRCS = Main.lhs Foo.lhs Bar.lhs
OBJS = Main.o   Foo.o   Bar.o

.SUFFIXES : .o .hi .lhs
.o.hi:
        @:
.lhs.o:
        $(RM) $@
        $(HC) -c $< $(HCFLAGS)

cool_pgm : $(OBJS)
        $(RM) $@
        $(HC) -o $@ $(HCFLAGS) $(OBJS)

Note the cheesy .o.hi rule: It records the dependency of the interface (.hi) file on the source. The rule says a .hi file can be made from a .o file by doing... nothing. Which is true.

(Sophisticated make variants may achieve some of the above more elegantly. What we've shown should work with any make.)

The only thing lacking in the above Makefile is interface-file dependencies. If Foo.lhs imports module Bar and the Bar interface changes, then Foo.lhs needs to be recompiled.

Putting dependencies of the form Foo.o : Bar.hi into your Makefile by hand is rather error-prone. Don't worry -- never fear, mkdependHS is here! (and is distributed as part of GHC) Add the following to your Makefile:

depend :
        mkdependHS -- $(HCFLAGS) -- $(SRCS)

Now, before you start compiling, and any time you change the imports in your program, do make depend before you do make cool_pgm. mkdependHS will append the needed dependencies to your Makefile.

A few caveats about this simple scheme: (a) You may need to compile some modules explicitly to create their interfaces in the first place (e.g., make Bar.o to create Bar.hi). (b) You may have to type make more than once for the dependencies to have full effect. However, a make run that does nothing does mean "everything's up-to-date." (c) This scheme will work with mutually-recursive modules but, again, it may take multiple iterations to "settle."

To see mkdependHS's command-line flags, give it a duff flag, e.g., mkdependHS -help.

Emacs `TAGS' for Haskell: hstags

`Tags' is a facility for indexing the definitions of programming-language things in a multi-file program, and then using that index to jump around among these definitions.

Rather than scratch your head, saying "Now where did we define `foo'?", you just do (in Emacs) M-. foo RET, and You're There! Some people go wild over this stuff...

GHC comes with a program hstags, which build Emacs-able TAGS files. The invocation syntax is:

hstags [GHC-options] file [files...]

The best thing is just to feed it your GHC command-line flags. A good Makefile entry might be:

tags:
        $(RM) TAGS
        hstags $(GHC_FLAGS) *.lhs

The only flags of its own are: -v to be verbose; -a to **APPEND** to the TAGS file, rather than write to it.

Shortcomings: (1) Instance declarations don't get into the TAGS file (but the definitions inside them do); as instances aren't named, this is probably just as well. (2) Data-constructor definitions don't get in. Go for the corresponding type constructor instead.

(Actually, GHC also comes with etags [for C], and perltags [for You Know What]. And -- I cannot tell a lie -- there is Denis Howe's fptags [for Haskell, etc.] in the ghc/CONTRIB section...)

"Yacc for Haskell": happy

Andy Gill and Simon Marlow have written a parser-generator for Haskell, called happy. Happy is to Haskell what Yacc is to C.

You can get happy by FTP from ftp.dcs.glasgow.ac.uk in pub/haskell/happy, the file happy-0.8.tar.gz.

Happy is at its shining best when compiled by GHC.

Pretty-printing Haskell: pphs

Andrew Preece has written pphs,

a utility to pretty-print Haskell code in LaTeX documents. Keywords in bolds, variables in italics -- that sort of thing. It is good at lining up program clauses and equals signs, things that are very tiresome to do by hand.

The code is distributed with GHC in ghc/CONTRIB/pphs.

Using "ticky-ticky" profiling (for implementors)

(ToDo: document properly.)

It is possible to compile Glasgow Haskell programs so that they will count lots and lots of interesting things, e.g., number of updates, number of data constructors entered, etc., etc. We call this "ticky-ticky" profiling,

because that's the sound a Sun4 makes when it is running up all those counters (slowly).

Ticky-ticky profiling is mainly intended for implementors; it is quite separate from the main "cost-centre" profiling system, intended for all users everywhere.

To be able to use ticky-ticky profiling, you will need to have built appropriate libraries and things when you made the system. See "Customising what libraries to build," in the installation guide.

To get your compiled program to spit out the ticky-ticky numbers, use a -r RTS option .

Tutorial material about this compilation system

This guide assumes quite a bit of knowledge about UNIX compilers and their conventional use. This section has a little extra information for those who are new at this racket.

The (batch) compilation system components

The Glorious Haskell Compilation System, as with most UNIX (batch) compilation systems, has several interacting parts:

What really happens when I "compile" a Haskell program?

You invoke the Glasgow Haskell compilation system through the driver program ghc. For example, if you had typed a literate "Hello, world!" program into hello.lhs, and you then invoked:

ghc hello.lhs

the following would happen:

You have considerable control over the compilation process. You feed command-line arguments (call them "options," for short) to the driver, ghc; the "types" of the input files (as encoded in their names' suffixes) also matter.

Here's hoping this is enough background so that you can read the rest of this guide!

Generated by The AQUA Team Department of Computing Science University of Glasgow Glasgow, Scotland G12 8QQ Email: glasgow-haskell-{bugs,users}-request@dcs.glasgow.ac.uk using lit2html