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.
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.
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.
File names with "meaningful" suffixes (e.g., .lhs or .o) cause the "right thing" to happen to those files.
A "literate Haskell" module.
Files with other suffixes (or without suffixes) are passed straight to the linker.
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 \hlineliterate 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.
This is taken to mean: "Please compile quickly; I'm not over-bothered about compiled-code quality." So, for example: ghc -c Foo.hs
Means: "Generate good-quality code without taking too long about it." Thus, for example: ghc -c -O Main.lhs
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.
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.
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!
This option will make GHC "forget" any -Oish options it has seen so far. Sometimes useful; for example: make all EXTRA_HC_OPTS=-Onot.
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:
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.
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).
We have not played with -fsemi-tagging enough to recommend it. (For all we know, it doesn't even work in 0.26. Sigh.)
Some flags only make sense for particular target platforms.
Means to pass the like-named option to GCC. Required for Very Big modules, maybe. (Probably means you're in trouble...)
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.
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.
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...
Undefine macro <foo> in the usual way.
Specify a directory in which to look for #include files, in the usual UNIX/C way.
The ghc driver pre-defines several macros:
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.
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].)
Only defined when -concurrent is in use! This symbol is defined when pre-processing Haskell (input) and pre-processing C (GHC output).
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 \hlineliterate 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).
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 \hlineliterate 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)
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.
Where to find user-supplied libraries... Prepend the directory <dir> to the library directories path.
Tell the linker to avoid shared libraries.
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.
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.
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.
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.
Reports a one-line useful collection of time- and space- statistics for a module's compilation.
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.
Tell the compiler it has an HBC-style RTS; i.e., it was compiled with HBC. Not used in Real Life.
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.
From time to time, we provide GHC options for "experimenting." Easy come, easy go. In version 0.26, the "experimental" options are:
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...
(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.
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 \hlineIf you use the ambiguous -pgmcOle, it will take it to mean "use program le for optimised C compiling."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
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
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
Do generate an interface file. This would normally be used in conjunction with -noC, which turns off interface generation; thus: -noC -hi.
This debugging option shows the exact prefix-form Haskell that is fed into the Haskell compiler proper.
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 \hlineliterate 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
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
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.
Dump out the assembly-language stuff, before the "mangler" gets it.
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...
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.
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 \hlineliterate 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:
Set the heap size to <size> bytes [default: 4M].
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...
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).
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.
Minimum % <n> of heap which must be available for allocation. The default is 3%.
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.
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.
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%.
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!
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..."
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.
An RTS debugging flag; varying quantities of output depending on which bits are set in <num>.
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:
What's printed out before the message from error.
The heap-overflow message.
The stack-overflow message.
The message printed if malloc fails.
The message printed if a pattern-match fails (the failures that were not handled by the Haskell programmer).
What's printed out before a trace message.
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
GHC is surprisingly zippy for normal compilations without -O!
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.
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).
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.
to derive only the showsPrec method. Quicker, smaller code.
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.
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).
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"...
At version 0.26, -O2 is nearly indistinguishable from -O.
So, when we want very fast code, we use: -O -fvia-C -O2-for-C.
The automatic specialisation of overloaded functions should take care of overloaded local and/or unexported functions.
(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.
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...
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.
% 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.
(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) -> ... }}
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!)
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.
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.
GHC can be quite a bit more aggressive with pieces of code if it knows they are not exported.
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, ...
Chapter glasgow-ccalls says a little about how to use C calls.
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.
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.
GHC will automatically add _scc_ constructs for all top-level, exported functions.
All top-level functions, exported or not, will be automatically _scc_'d.
Ignore any _scc_ constructs, so a module which already has _scc_s can be compiled for profiling with the annotations ignored.
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.
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:
Set the profiling (sampling) interval to <secs> seconds (the default is 1 second).
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:
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:
Selects individual cost centre(s).
Selects all cost centres from the module(s) specified.
Selects all cost centres from the groups(s) specified.
Selects closures which have one of the specified descriptions.
Selects closures which have one of the specified type descriptions.
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).
([-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).
When you run your profiled program with the -p RTS option , you get the following information about your "cost centres":
In addition you can use the -P RTS option to get the following additional information:
Finally if you built your program with -prof-details the -P RTS option will also produce the following information:
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:
-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.
-t0 requests no trace elements to be removed from the profile, ensuring that all the data will be displayed.
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.
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:
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.
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...
Please see Section glasgow-stablePtrs for more details.
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.
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.
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 \hlineNote 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.StgChar Char# StgInt Int# StgWord Word# StgAddr Addr# StgFloat Float# StgDouble Double# StgArray Array# StgByteArray ByteArray# StgArray MutableArray# StgByteArray MutableByteArray# StgStablePtr StablePtr# StgMallocPtr MallocPtr#
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 ()
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:
atan2d :: Double -> Double -> Double atan2d y x = unsafePerformPrimIO (_ccall_ atan2d y x) sincosd :: Double -> (Double, Double) sincosd x = unsafePerformPrimIO ( newDoubleArray (0, 1) `thenPrimIO` \ da -> _casm_ ``sincosd( %0, &((double *)%1[0]), &((double *)%1[1]) );'' x da `seqPrimIO` readDoubleArray da 0 `thenPrimIO` \ s -> readDoubleArray da 1 `thenPrimIO` \ c -> returnPrimIO (s, c) )
For example, an imperative implementation of a purely functional lookup-table might be accessed using the following functions.
empty :: EFS x update :: EFS x -> Int -> x -> EFS x lookup :: EFS a -> Int -> a empty = unsafePerformPrimIO (_ccall_ emptyEFS) update a i x = unsafePerformPrimIO ( makeStablePtr x `thenPrimIO` \ stable_x -> _ccall_ updateEFS a i stable_x ) lookup a i = unsafePerformPrimIO ( _ccall_ lookupEFS a i `thenPrimIO` \ stable_x -> deRefStablePtr stable_x )
You will almost always want to use _MallocPtrs with this.
trace :: String -> a -> a trace string expr = unsafePerformPrimIO ( appendChan# ``stderr'' "Trace On:\n" `seqPrimIO` appendChan# ``stderr'' string `seqPrimIO` appendChan# ``stderr'' "\nTrace Off.\n" `seqPrimIO` returnPrimIO expr )
(This kind of use is not highly recommended -- it is only really useful in debugging code.)
And some advice, too.
primIOToIO :: PrimIO a -> IO a
to promote a _ccall_ to the IO monad.
You don't have to, but you should.
Also, use the -#include "prototypes.h" flag (hack) to inform the C compiler of the fully-prototyped types of all the C functions you call. (Section glasgow-foreign-headers says more about this...)
This scheme is the only way that you will get any typechecking of your _ccall_s. (It shouldn't be that way, but...)
If you do use floats, check and re-check that the right thing is happening. Perhaps compile with -keep-hc-file-too and look at the intermediate C (.hc file).
The type checker must be able to figure out just which of the C-callable/returnable types is being used. If it can't, you have to add type signatures. For example,
f x = _ccall_ foo x
is not good enough, because the compiler can't work out what type x is, nor what type the _ccall_ returns. You have to write, say:
f :: Int -> PrimIO Double f x = _ccall_ foo x
This table summarises the standard instances of these classes.
C type name Haskell Type \hlineThe brave and careful programmer can add their own instances of these classes for the following types:StgChar Char# StgInt Int# StgWord Word# StgAddr Addr# StgFloat Float# StgDouble Double# StgArray Array# StgByteArray ByteArray# StgArray MutableArray# StgByteArray MutableByteArray# StgStablePtr StablePtr# StgMallocPtr MallocPtr# Type CCallable CReturnable Which is probably... \hline
Char Yes Yes unsigned char Int Yes Yes long int _Word Yes Yes unsigned long int _Addr Yes Yes char * Float Yes Yes float Double Yes Yes double () No Yes void [Char] Yes No char * (null-terminated) Array Yes No unsigned long * _ByteArray Yes No unsigned long * _MutableArray Yes No unsigned long * _MutableByteArray Yes No unsigned long * _State Yes Yes nothing! _StablePtr Yes Yes unsigned long * _MallocPtr Yes Yes see later
A boxed primitive type is any data type with a single unary constructor with a single primitive argument. For example, the following are all boxed primitive types:
Int Double data XDisplay = XDisplay Addr# data EFS a = EFS# MallocPtr#
instance _CCallable (EFS a) instance _CReturnable (EFS a)
data MyVoid = MyVoid instance _CReturnable MyVoid
Also, the now-builtin type _PackedString is neither _CCallable nor _CReturnable. (But there are functions in the PackedString interface to let you get at the necessary bits...)
"HBC-ish" extensions implemented by GHC
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.
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.
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.
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.
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]
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
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]
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
Note: a Maybe type is nearly inevitable in Haskell 1.3. You should use this module with -fhaskell-1.3.
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 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
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
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
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]
The GHC system library (-syslib ghc) also provides interfaces to several useful C libraries, mostly from the GNU project.
(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.
This documentation is stolen directly from the HBC distribution. The modules that GHC does not support (because they require HBC-specific extensions) are omitted.
data Either a b = Left a | Right b
The constructor Left is typically used for errors; it can be renamed to Wrong on import.
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
data Option a = None | Some a thenO :: Option a -> (a -> Option b) -> Option b
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
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
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
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 :: String -> a -> a -- trace x y prints x and returns y
Functions found in the Miranda library. (Note: Miranda is a registered trade mark of Research Software Ltd.)
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
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
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]
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
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.
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.
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.]
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.
[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.
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 processThe PVM documentation can tell you much, much more about pvm!
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.
(PARALLEL ONLY) Use <N> PVM processors to run this program; the default is 2.
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.
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).
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.)
(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/.
(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.
(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"
Just say make all EXTRA_HC_OPTS=-H<a reasonable number> and see how you get along.
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.
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.
If the simplifier definitely seems to be "looping," please report it.
Furthermore, as sketched below, you may have big problems running programs compiled using unstable interfaces.
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...)
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).
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.
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!!!)
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).
Bear in mind that string gaps and the -cpp
option don't mix. The C-preprocessor may munch the backslashes.
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.)
Module system and interface files
(Otherwise, `renaming' -- disgusting though it may be -- should work.)
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.
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.
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.
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.)
... 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
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.
Use Integer, Rational, etc., numeric types if this stuff keeps you awake at night.
main = print (array (1,1) [ 1:=2, 1:=3 ])
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.
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.
The basic I/O functions are "unlikely" to change and so are reasonably safe to adopt. (But see WARNING above...)
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
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...
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
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
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...)
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.
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:
unlit that extracts Haskell code from a literate script; used if you believe in that sort of thing.
hscpp, only needed by people requiring conditional compilation, probably for large systems. The "Haskellised" part just means that #line directives in the output have been converted into proper Haskell \{-# LINE ... -\} pragmas.
You must give an explicit -cpp option for the C pre-processor to be invoked.
which -- in normal use -- takes its input from the C pre-processor and produces assembly-language output (sometimes: ANSI C output).
compiles hsc's C output into assembly language for a particular target architecture. (It doesn't have to be an ANSI C compiler, but that's preferred; to go fastest, you need GNU C, version 2.x.)
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