summaryrefslogtreecommitdiff
path: root/docs/users_guide/separate_compilation.xml
diff options
context:
space:
mode:
authorEdward Z. Yang <ezyang@cs.stanford.edu>2014-08-07 18:32:12 +0100
committerEdward Z. Yang <ezyang@cs.stanford.edu>2014-10-24 15:49:41 -0700
commitaa4799534225e3fc6bbde0d5e5eeab8868cc3111 (patch)
tree60d77acae2286263a1c75d87d93d333bce5b01c0 /docs/users_guide/separate_compilation.xml
parent5bb73d79a83bca57dc431421ca1e022f34b8dec9 (diff)
downloadhaskell-aa4799534225e3fc6bbde0d5e5eeab8868cc3111.tar.gz
Implementation of hsig (module signatures), per #9252
Summary: Module signatures, like hs-boot files, are Haskell modules which omit value definitions and contain only signatures. This patchset implements one particular aspect of module signature, namely compiling them against a concrete implementation. It works like this: when we compile an hsig file, we must be told (via the -sig-of flag) what module this signature is implementing. The signature is compiled into an interface file which reexports precisely the entities mentioned in the signature file. We also verify that the interface is compatible with the implementation. This feature is useful in a few situations: 1. Like explicit import lists, signatures can be used to reduce sensitivity to upstream changes. However, a signature can be defined once and then reused by many modules. 2. Signatures can be used to quickly check if a new upstream version is compatible, by typechecking just the signatures and not the actual modules. 3. A signature can be used to mediate separate modular development, where the signature is used as a placeholder for functionality which is loaded in later. (This is only half useful at the moment, since typechecking against signatures without implementations is not implemented in this patchset.) Unlike hs-boot files, hsig files impose no performance overhead. This patchset punts on the type class instances (and type families) problem: instances simply leak from the implementation to the signature. You can explicitly specify what instances you expect to have, and those will be checked, but you may get more instances than you asked for. Our eventual plan is to allow hiding instances, but to consider all transitively reachable instances when considering overlap and soundness. ToDo: signature merging: when a module is provided by multiple signatures for the same base implementation, we should not consider this ambiguous. ToDo: at the moment, signatures do not constitute use-sites, so if you write a signature for a deprecated function, you won't get a warning when you compile the signature. Future work: The ability to feed in shaping information so that we can take advantage of more type equalities than might be immediately evident. Signed-off-by: Edward Z. Yang <ezyang@cs.stanford.edu> Test Plan: validate and new tests Reviewers: simonpj, simonmar, hvr, austin Subscribers: simonmar, relrod, ezyang, carter, goldfire Differential Revision: https://phabricator.haskell.org/D130 GHC Trac Issues: #9252
Diffstat (limited to 'docs/users_guide/separate_compilation.xml')
-rw-r--r--docs/users_guide/separate_compilation.xml96
1 files changed, 96 insertions, 0 deletions
diff --git a/docs/users_guide/separate_compilation.xml b/docs/users_guide/separate_compilation.xml
index 5ef78804b5..43ab182729 100644
--- a/docs/users_guide/separate_compilation.xml
+++ b/docs/users_guide/separate_compilation.xml
@@ -883,6 +883,102 @@ methods entirely; but you must either omit them all or put them all in.
</para>
</sect2>
+ <sect2 id="module-signatures">
+ <title>Module signatures</title>
+ <para>GHC supports the specification of module signatures, which
+ both implementations and users can typecheck against separately.
+ This functionality should be considered experimental for now; some
+ details, especially for type classes and type families, may change.
+ This system was originally described in <ulink
+ url="http://plv.mpi-sws.org/backpack/">Backpack: Retrofitting Haskell with
+ Interfaces</ulink>. Signature files are somewhat similar to
+ <literal>hs-boot</literal> files, but have the <literal>hsig</literal>
+ extension and behave slightly differently.
+ </para>
+
+ <para>Suppose that I have modules <filename>String.hs</filename> and
+ <filename>A.hs</filename>, thus:</para>
+
+<programlisting>
+module Text where
+ data Text = Text String
+
+ empty :: Text
+ empty = Text ""
+
+ toString :: Text -> String
+ toString (Text s) = s
+
+module A where
+ import Text
+ z = toString empty
+</programlisting>
+
+ <para>Presently, module <literal>A</literal> depends explicitly on
+ a concrete implementation of <literal>Text</literal>. What if we wanted
+ to a signature <literal>Text</literal>, so we could vary the
+ implementation with other possibilities (e.g. packed UTF-8 encoded
+ bytestrings)? To do this, we can write a signature
+ <filename>TextSig.hsig</filename>, and modify <literal>A</literal>
+ to include the signature instead:
+ </para>
+
+<programlisting>
+module TextSig where
+ data Text
+ empty :: Text
+ toString :: Text -> String
+
+module A where
+ import TextSig
+ z = toString empty
+</programlisting>
+
+ <para>To compile these two files, we need to specify what module we
+ would like to use to implement the signature. This can be done by
+ compiling the implementation, and then using the <literal>-sig-of</literal>
+ flag to specify the implementation backing a signature:</para>
+
+<programlisting>
+ghc -c Text.hs
+ghc -c TextSig.hsig -sig-of main:Text
+ghc -c A.hs
+</programlisting>
+
+ <para>Signature files can also be compiled as part of
+ <literal>--make</literal>, in which case the syntax is extended
+ to support specifying implementations of multiple signatures
+ as <literal>FooSig is main:Foo, BarSig is main:Bar</literal>.
+ At the moment, you must specify the full module name (package key,
+ colon, and then module name), although in the future we may support
+ more user-friendly syntax.</para>
+
+ <para>To just type-check an interface file, no <literal>-sig-of</literal>
+ is necessary; instead, just pass the options
+ <literal>-fno-code -fwrite-interface</literal>. <literal>hsig</literal>
+ files will generate normal interface files which other files can
+ also use to type-check against. However, at the moment, we always
+ assume that an entity defined in a signature is a unique identifier
+ (even though we may happen to know it is type equal with another
+ identifier). In the future, we will support passing shaping information
+ to the compiler in order to let it know about these type
+ equalities.</para>
+
+ <para>Just like <literal>hs-boot</literal> files, when an
+ <literal>hsig</literal> file is compiled it is checked for type
+ consistency against the backing implementation; furthermore, it also
+ produces a pseudo-object file <literal>A.o</literal> which you should
+ not link with. Signature files are also written in a subset
+ of Haskell similar to essentially identical to that of
+ <literal>hs-boot</literal> files.</para>
+
+ <para>There is one important gotcha with the current implementation:
+ currently, instances from backing implementations will "leak" code that
+ uses signatures, and explicit instance declarations in signatures are
+ forbidden. This behavior will be subject to change.</para>
+
+ </sect2>
+
<sect2 id="using-make">
<title>Using <command>make</command></title>