Copyright | (c) 2000 - 2007 Wolfgang Lux 2015 Jan Tikovsky 2016 Finn Teegen |
---|---|
License | BSD-3-clause |
Maintainer | bjp@informatik.uni-kiel.de |
Stability | experimental |
Portability | portable |
Safe Haskell | None |
Language | Haskell2010 |
Interface files include declarations of all entities that are exported by the module, but defined in another module. Since these declarations can become inconsistent if client modules are not recompiled properly, the compiler checks that all imported declarations in an interface agree with their original definitions.
One may ask why we include imported declarations at all, if the compiler always has to compare those declarations with the original definitions. The main reason for this is that it helps to avoid unnecessary recompilations of client modules. As an example, consider the three modules:
module A where { data T = C } module B(T(..)) where { import A } module C where { import B; f = C }
where module B could be considered as a public interface of module A, which restricts access to type A.T and its constructor C. The client module C imports this type via the public interface B. If now module A is changed by adding a definition of a new global function
module A where { data T = C; f = C }
module B must be recompiled because A's interface is changed. On the other hand, module C need not be recompiled because the change in A does not affect B's interface. By including the declaration of type A.T in B's interface, the compiler can trivially check that B's interface remains unchanged and therefore the client module C is not recompiled.
Another reason for including imported declarations in interfaces is that the compiler in principle could avoid loading interfaces of modules that are imported only indirectly, which would save processing time and allow distributing binary packages of a library with a public interface module only. However, this has not been implemented yet.