CONTENT="Modular DocBook HTML Stylesheet Version 1.64
This section describes how GHC supports separate compilation.
When GHC compiles a source file A.hs which contains a module A, say, it generates an object A.o, and a companion interface file A.hi. The interface file is merely there to help the compiler compile other modules in the same program. Interfaces are in a binary format, so don't try to look at one; however you can see the contents of an interface file by using GHC with the --show-iface option (see Section 4.9.4, below).
NOTE: In general, the name of a file containing module M should be named M.hs or M.lhs. The only exception to this rule is module Main, which can be placed in any file.
The interface file for A contains information needed by the compiler when it compiles any module B that imports A, whether directly or indirectly. When compiling B, GHC will read A.hi to find the details that it needs to know about things defined in A.
The interface file may contain all sorts of things that aren't explicitly exported from A by the programmer. For example, even though a data type is exported abstractly, A.hi will contain the full data type definition. For small function definitions, A.hi will contain the complete definition of the function. For bigger functions, A.hi will contain strictness information about the function. And so on. GHC puts much more information into .hi files when optimisation is turned on with the -O flag (see Section 4.11). Without -O it puts in just the minimum; with -O it lobs in a whole pile of stuff.
A.hi should really be thought of as a compiler-readable version of A.o. If you use a .hi file that wasn't generated by the same compilation run that generates the .o file the compiler may assume all sorts of incorrect things about A, resulting in core dumps and other unpleasant happenings.
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.
See also the section on packages (Section 4.10), which describes how to use installed libraries.
GHC supports a hierarchical module namespace as an extension to Haskell 98 (see Section 7.5.1).
A module name in general consists of a sequence of components separated by dots (‘.’). When looking for interface files for a hierarchical module, the compiler turns the dots into path separators, so for example a module A.B.C becomes A/B/C (or A\B\C under Windows). Then each component of the import directories list is tested in turn; so for example if the list contains directories D1 to Dn, then the compiler will look for the interface in D1/A/B/C.hi first, then D2/A/B/C.hi and so on.
Note that it's perfectly reasonable to have a module which is both a leaf and a branch of the tree. For example, if we have modules A.B and A.B.C, then A.B's interface file will be in A/B.hi and A.B.C's interface file will be in A/B/C.hi.
For GHCi and --make, the search strategy for source files is exactly the same, just replace the .hi suffix in the above description with .hs or .lhs.
In the olden days, GHC compared the newly-generated .hi file with the previous version; if they were identical, it left the old one alone and didn't change its modification date. In consequence, importers of a module with an unchanged output .hi file were not recompiled.
This doesn't work any more. Suppose module C imports module B, and B imports module A. So changes to A.hi should force a recompilation of C. And some changes to A (changing the definition of a function that appears in an inlining of a function exported by B, say) may conceivably not change B.hi one jot. So now…
GHC keeps a version number on each interface file, and on each type signature within the interface file. It also keeps in every interface file a list of the version numbers of everything it used when it last compiled the file. If the source file's modification date is earlier than the .o file's date (i.e. the source hasn't changed since the file was last compiled), and the reompilation checking is on, GHC will be clever. It compares the version numbers on the things it needs this time with the version numbers on the things it needed last time (gleaned from the interface file of the module being compiled); if they are all the same it stops compiling rather early in the process saying “Compilation IS NOT required”. What a beautiful sight!
Patrick Sansom had a workshop paper about how all this is done (though the details have changed quite a bit). Ask him if you want a copy.
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:
(Sophisticated make variants may achieve some of the above more elegantly. Notably, gmake's pattern rules let you write the more comprehensible:
What we've shown should work with any make.)
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.
Note the inter-module dependencies at the end of the Makefile, which take the form
They tell make that if any of Foo.o, Foo.hc or Foo.s have an earlier modification date than Baz.hi, then the out-of-date file must be brought up to date. To bring it up to date, make looks for a rule to do so; one of the preceding suffix rules does the job nicely.
Putting inter-dependencies of the form Foo.o : Bar.hi into your Makefile by hand is rather error-prone. Don't worry, GHC has support for automatically generating the required dependencies. Add the following to your Makefile:
Now, before you start compiling, and any time you change the imports in your program, do make depend before you do make cool_pgm. ghc -M will append the needed dependencies to your Makefile.
In general, if module A contains the line
By default, ghc -M generates all the dependencies, and then concatenates them onto the end of makefile (or Makefile if makefile doesn't exist) bracketed by the lines "# DO NOT DELETE: Beginning of Haskell dependencies" and "# DO NOT DELETE: End of Haskell dependencies". If these lines already exist in the makefile, then the old dependencies are deleted first.
Don't forget to use the same -package options on the ghc -M command line as you would when compiling; this enables the dependency generator to locate any imported modules that come from packages. The package modules won't be included in the dependencies generated, though (but see the ––include-prelude option below).
The dependency generation phase of GHC can take some additional options, which you may find useful. For historical reasons, each option passed to the dependency generator from the GHC command line must be preceded by -optdep. For example, to pass -f .depend to the dependency generator, you say
Currently, the compiler does not have proper support for dealing with mutually recursive modules:
When compiling either module A and B, the compiler will try (in vain) to look for the interface file of the other. So, to get mutually recursive modules off the ground, you need to hand write an interface file for A or B, so as to break the loop. These hand-written interface files are called hi-boot files, and are placed in a file called <module>.hi-boot. To import from an hi-boot file instead of the standard .hi file, use the following syntax in the importing module:
The hand-written interface need only contain the bare minimum of information needed to get the bootstrapping process started. For example, it doesn't need to contain declarations for everything that module A exports, only the things required by the module that imports A recursively.
For the example at hand, the boot interface file for A would look like the following:
The syntax is similar to a normal Haskell source file, but with some important differences:
Notice that we only put the declaration for the newtype TA in the hi-boot file, not the signature for f, since f isn't used by B.
If you want an hi-boot file to export a data type, but you don't want to give its constructors (because the constructors aren't used by the SOURCE-importing module), you can write simply:
(You must write all the type parameters, but leave out the '=' and everything that follows it.)
Haskell specifies that when compiling module M, any instance declaration in any module "below" M is visible. (Module A is "below" M if A is imported directly by M, or if A is below a module that M imports directly.) In principle, GHC must therefore read the interface files of every module below M, just in case they contain an instance declaration that matters to M. This would be a disaster in practice, so GHC tries to be clever.
In particular, if an instance declaration is in the same module as the definition of any type or class mentioned in the head of the instance declaration, then GHC has to visit that interface file anyway. Example:
The instance declaration is only relevant if the type T is in use, and if so, GHC will have visited A's interface file to find T's definition.
The only problem comes when a module contains an instance declaration and GHC has no other reason for visiting the module. Example:
GHC identifies orphan modules, and visits the interface file of every orphan module below the module being compiled. This is usually wasted work, but there is no avoiding it. You should therefore do your best to have as few orphan modules as possible.
You can identify an orphan module by looking in its interface file, M.hi, using the --show-iface. If there is a ``!'' on the first line, GHC considers it an orphan module.