Transparent Modules with Fully Syntactic Signatures

advertisement
Transparent Modules with Fully Syntactic Signatures
Zhong Shao
Dept. of Computer Science
Yale University
New Haven, CT 06520
shao@cs.yale.edu
Technical Report YALEU/DCS/TR-1181 (supersedes TR-1161)
June 24, 1999
Abstract
ML-style modules are valuable in the development and maintenance of large software systems, unfortunately, none of the existing
languages support them in a fully satisfactory manner. The official SML’97 Definition does not allow higher-order functors, so a
module that refers to externally defined functors cannot accurately
describe its import interface. MacQueen and Tofte [26] extended
SML’97 with fully transparent higher-order functors, but their system does not have a type-theoretic semantics thus fails to support
fully syntactic signatures. The systems of manifest types [19, 20]
and translucent sums [12] support fully syntactic signatures but
they may propagate fewer type equalities than fully transparent
functors. This paper presents a module calculus that supports both
fully transparent higher-order functors and fully syntactic signatures (and thus true separate compilation). We give a simple typetheoretic
semantics to our calculus and show how to compile it into
an -like -calculus extended with existential types.
1
Introduction
Modular programming is one of the most commonly used techniques in the development and maintenance of large software systems. Using modularization, we can decompose a large software
project into smaller pieces (modules) and then develop and understand each of them in isolation. The key ingredients in modularization are the explicit interfaces used to model inter-module dependencies. Good interfaces not only make separate compilation
type-safe but also allow us to think about large systems without
holding the whole system in our head at once. A powerful module
language must support equally expressive interface specifications
in order to achieve the optimal results.
1.1
more, different applications of the same functor can share a single
copy of the implementation (i.e., object code), even though each
application may produce modules with different interfaces.
Functors have proven to be valuable in the modeling and organization of extensible systems [1, 10, 6, 32]. The Fox project at
CMU [1] uses ML functors to represent the TCP/IP protocol layers;
through functor applications, different protocol layers can be mixed
and matched to generate new protocol stacks with applicationspecific requirements. Also, a standard C++ template library written using the ML functors would not require nasty cascading recompilations when the library is updated, simply because ML functors can be compiled separately before even being applied.
Unfortunately, any use of functors and nested modules also implies that the underlying module language must support higherorder functors (i.e., functors passed as arguments or returned as
results by other functors), because otherwise, there is no way to
accurately specify the import signature of a module that refers to
externally defined functors. For example, if we decompose the
following ML program into two smaller pieces, one for FOO and
another for BAR:
functor FOO (A : SIG) = ...
......
structure BAR = struct structure B = ...
structure C = FOO(B)
end
the fragment for BAR must treat FOO as its import argument. This
essentially turns BAR into a higher-order functor since it must take
another functor as its argument. Without higher-order functors, we
cannot fully specify the interfaces1 of arbitrary ML programs. The
lack of fully syntactic (i.e., explicit) signatures also violates the
fundamental principles of modularization and makes it impossible
to support Modula-2 style true separate compilation [19].
Why higher-order functors?
1.2
Standard ML [27, 28] provides a powerful module system. The
main innovation of the ML module language is its support of parameterized modules, also known as functors. Unlike Modula-3
generics [31] or C++ templates [37], ML functors can be typechecked and compiled independently at its definition site; further
This research was sponsored in part by the Defense Advanced Research Projects
Agency ITO under the title “Software Evolution using HOT Language Technology,”
DARPA Order No. D888, issued under Contract No. F30602-96-2-0232, and in part
by an NSF CAREER Award CCR-9501624, and NSF Grant CCR-9633390. The views
and conclusions contained in this document are those of the authors and should not be
interpreted as representing the official policies, either expressed or implied, of the
Defense Advanced Research Projects Agency or the U.S. Government.
Main challenges
Supporting higher-order functors with fully syntactic signatures
turns out to be a very hard problem. Standard ML (SML) [28]
only supports first-order functors. MacQueen and Tofte [26, 38] extended SML with fully transparent higher-order functors but their
scheme does not provide fully syntactic signatures. Independently,
Harper and Lillibridge [12] and Leroy [19] proposed to use translucent sums and manifest types to model type sharing; their scheme
1
We only need to write the signatures for first-order functors if we use a special
“compilation unit” construct with import and export statements, but reasoning such
construct would likely require similar formalism as reasoning higher-order modules.
EMC
KMC
FTC
AMC
Figure 1: Relationship among five different calculi
because abstract types must be made concrete during the translation. The translation of translucent sums
is even more problem
with singleton and depenatic: Crary et al [8] have to extend
dent kinds to capture the sharing information in the surface language. The translation based on our new interpretation rightly
turns opaque modules and abstract types into simple existential
types. Furthermore, it does not need to use singleton and dependent kinds. This is significant because typechecking singleton and
dependent kinds is notoriously difficult [8].
The main challenge is thus to design a module language that
satisfies all of the following properties:
It must have fully syntactic signatures: if we split a program
at an arbitrary point, the corresponding interface must be expressible using the underlying signature calculus.
It must have simple type-theoretical semantics: a clean semantics makes formal reasoning easier; it is also a prerequisite for a simple signature calculus.
In the rest of this paper, we first use a series of examples to
informally explain the main ideas. We then present our new Extended Module Calculus (EMC) which supports both fully transparent higher-order functors and fully syntactic signatures. We
demonstrate the expressiveness of EMC by translating a version of
the Abstract Module Calculus (AMC) and a version of the Transparent Module Calculus (TMC) into the EMC calculus. Finally, to
support type-directed compilation [18, 15, 35, 36], we show how
EMC can be
translated into a Kernel Module Calculus (KMC) and
then to an -like Target Calculus (FTC). The relationship among
these five calculi is depicted in Figure 1.
It should support fully transparent higher-order functors:
higher-order functors should be a natural extension of firstorder ones; simple ML functors can propagate type sharing
from the argument to the result; higher-order functors should
propagate sharing in the same way.
It should support opaque types and signatures: type abstraction is the standard method of hiding implementation details
from the clients of a module; the same mechanism should be
applicable to higher-order functors as well.
It should support efficient elaboration and implementation:
a module system will not be practical if it cannot be typechecked and compiled efficiently; compilation of module
programs should also be compatible with the standard typedirected compilation techniques [18, 15, 35, 36].
1.3
TMC
supports fully syntactic signatures but fails to propagate as much
sharing
as in the MacQueen-Tofte system. Leroy [20] proposed to
use applicative semantics to model full transparency, but his signature calculus is not fully syntactic since it only handles limited
forms of functor expressions; this limitation was lifted in Courant’s
recent proposal [7], but only at the expense of putting arbitrary
module implementation code into the interfaces, which in turn
compromises the very benefits of modularization and makes interface checking much harder.
2 Informal Development
2.1
Fully transparent higher-order functors
We first use a series of examples to show how the MacQueen-Tofte
system [26] supports fully transparent higher-order functors. We
start by defining a signature SIG and a functor signature FSIG:
Our contributions
signature SIG = sig type t val x : t end
funsig FSIG = fsig (X: SIG): SIG
This paper presents a higher-order module calculus that satisfies all
of the above properties. We show that fully transparent higherorder functors can also have simple type-theoretic semantics so
they can be added into ML-like languages while still supporting true separate compilation. Our key idea is to adapt and incorporate the phase-splitting interpretation of higher-order modules [14, 36] into a surface module calculus—the result is a new
method that propagates more sharing information (across functor
application) than the system based on translucent sums [12] and
manifest types [19]. More specifically, given a signature or a functor signature , we extract all the flexible components in into a
single higher-order “type-constructor” variable ; here, by flexible,
we mean those undefined type or module components inside . We
call such as the flexroot constructor of signature . We use to
denote the kind of and to denote the instantiation of whose
flexible components are redirected to the corresponding entries in
. An opaque view of signature can be modeled as an existential type . A transparent view of can be obtained by
substituting the flexroot of with the actual constructor information. Full transparency is then achieved by propagating the flexroot
information through functor application.
MacQueen and Tofte use strong sum to express the module type,
so signature SIG is equivalent to a dependent sum type "!#% ! and signature FSIG is same as the dependent product type
$&
'()* . We also define a structure S with signature SIG,
and two functors F1 and F2, both with signature FSIG:
structure S = struct type t=int val x=1 end
functor F1 (X: SIG)
struct type t=X.t
functor F2 (X: SIG)
struct type t=int
=
val x=X.x end
=
val x=1 end
Although SIG does not define the actual type for t, functor applications such as F1(S) will always re-elaborate the body of F1
with X bound to S, so the type identity of X.t (which is int) is
faithfully propagated into the result F1(S). Now suppose we define the following higher-order functor which takes a functor F as
argument and applies it to the previously defined structure S:
Our new phase-splitting interpretation also leads to a simpler
type theory for the system based on translucent sums and manifest
types. Recent work on phase-splitting transformation [14, 36, 8]
has shown that ML-like module
languages are better understood
by translating them into an -like polymorphic -calculus. These
translations, however, do not support opaque modules very well
functor APPS (F: FSIG) = F(S)
We can then apply APPS to functors F1 and F2:
2
The abstract approach relies on signature subsumption and
strengthening [12, 19] to propagate sharing information from the
functor argument to the result. But the subsumption rules are not
powerful enough to support fully transparent higher-order functors.
Nevertheless, the abstract approach does have fully syntactic signatures; and having a functor parameter returning an abstract result is
sometimes useful. Take the functor APPS as an example, sometimes we indeed want the parameter F to be a functor that always
generate new types at each application.
structure R =
struct structure R1 = APPS(F1)
structure R2 = APPS(F2)
val res = (R1.x = R2.x)
............
end
In the MacQueen-Tofte system, both APPS(F1) and APPS(F2)
will re-elaborate the body of APPS which in turn re-elaborates the
functor body in F1 and F2; it successfully infers that R1.x and
R2.x all have type int, so the equality test (R1.x = R2.x)
will typecheck.
2.3
MacQueen and Tofte [26] call functors such as APPS as fully
transparent modules since they faithfully propagate all sharing information in the actual argument (e.g., F1 and F2) into the result
(e.g., R1 and R2). Unfortunately, their scheme does not support
fully syntactic signatures. If we want to turn module R into a separate compilation unit, we have no way to completely specify its
import interface. More specifically, we cannot write a signature for
APPS so that all sharing information in the argument is propagated
into the result. The closest we get is to assign APPS with signature:
Transparent modules with syntactic signatures
We would like to extend the abstract approach to support fully
transparent higher-order functors. Our key idea is to adapt and
incorporate the phase-splitting interpretation of higher-order modules [14, 36] into a surface module calculus; the result is a new
method that propagates more sharing information (across functor
application) than the system based on translucent sums and manifest types. Given a signature or a functor signature , we extract
all the flexible components in into a single higher-order “typeconstructor” variable ; here, by flexible, we mean those undefined
type or module components inside . We call such as the flexroot
constructor of signature . We use to denote the kind of and
to denote the instantiation of with all of its flexible components referring to the corresponding entries in . An opaque view
of signature can be modeled as an existential type B
;
a transparent view of can be obtained by substituting all occurrences of in by an actual flexroot constructor. For example,
the previous signature declaration:
funsig BADSIG =
fsig (F: FSIG): sig type t=int val x : t end
But this would not work if R also contains the following code:
functor F3(X: SIG) =
struct type t=real val x=3.0 end
structure R3 = APPS(F3)
signature SIG = sig type t
val x : t end
Signature BADSIG clearly does not capture the sharing information propagated during the application of APPS(F3). The actual
implementation of the MacQueen-Tofte system [36] memoizes a
“skeleton” for each functor body to support re-elaboration, but this
is clearly too complex to be used in a surface signature calculus.
can be viewed as a template of form:
2.2
I#K9L
where kind is equal to Q t AR>S . We use #t TUWV to denote the
t component from a constructor record —this is to emphasize its
difference from the module access paths in ML (e.g., X.t).
8:<;DC7E*F"0HGJI#K9LM=N2
Translucent sums and manifest types
A more severe problem of the MacQueen-Tofte system is that it
lacks a clean type-theoretic semantics: its typechecker must use an
operational stamp generator to model abstract types; this makes it
impossible to express the typing property in the surface signature
calculus. In 1994, Harper and Lillibridge [12] and Leroy [19] proposed (independently) to use translucent sums and manifest types
to model ML modules; the resulting framework—which we call it
the abstract approach—has a clean type-theoretic equational theory on types; furthermore, both systems support fully syntactic signatures. Leroy [21] and Harper [16] have also shown that their systems are sufficiently expressive that it can type the entire module
language in the official SML’97 Definition [28].
sig type t = #t
Instantiating the flexroot of *
yields a signature of form:
2OFP?
val x : t end
?
with constructor Q t int S
sig type t = int val x : t end
Meanwhile, the following SML code:
structure X :> SIG =
struct type t=int val x=1 end
creates
an opaque view of SIG so module X has type I#K9L
XTYJZ \[OV , or expanded to:
Unfortunately, in the case of higher-order functors, the abstract
approach does not propagate as much sharing as one would normally expect in the MacQueen-Tofte system. For example, the
previous equality test (R1.x = R2.x) would not typecheck in
Harper and Leroy’s systems [12, 19]. In fact, the abstract approach
treats the signature SIG as an existential type
$&% +,*!- ! and
() . The
the signature FSIG as a dependent product
functor APPS is assigned with the following signature type:
] F@0HG I-K3L =N2
sig type t = #t
2OFP?
?
val x : t end .
In the rest of this paper, we follow the abstract approach to treat
signature
matching as opaque by default.
Given a module
%
%
% identifier
and a signature , we say that has signature if % has type
can be
^_
1`aXT9bZ \[OV . The abstract flexroot constructor in
retrieved using dot% notation on existentials [5]—such notation is
usually written as c-d_e , but in this paper we use a more concise
%
notation; we
to represent the
% will use the overlined identifier
flexroot of .
."/10324.657098:<;>= 8:<;@?A= 8:<;
Applying APPS to F1 or F2 always yields a new existential package *!- ! so R1.t and R2.t are two distinct abstract types.
It is informative to compare flexroot with the notion% of access
paths in the abstract approach [12, 19]. A type path ! in the
3
|Po_8:';pCpEqFir\0UG1} t I#K9L= .
system based on translucent sums and manifest types may denote
an
type (as in dot notation). Under the flexroot notation,
f
% abstract
! always refers to an actual type definition—the ! component
%
%
of module —which in turn is defined
% as type gJ!<T V ; in other
are now redirected to the
words, all the flexible components in
%
abstract flexroot constructor .
X
032 ] F\u{= 8:<;>j FPuwlm?A=N2U8:<;vj Fir'j lNlm?
X
} t I-K3L
I#K9Ly
I-K3L
where kind is equal to (the algorithm calculating such kind is given later in Section 3.2). The flexroot of
TFSIG has a different kind from that of NFSIG because functors
with signature TFSIG } propagate
more sharing information (e.g.,
t I-K3L
) than those with signature NFSIG.
constructor of kind Notice how functor application propagates
sharing
r
r into the return
result: the flexroot of the result is Z X[ where is the flexroot of
the functor itself and X is the flexroot of the actual argument.
Combining all the flexible components into a single flexroot constructor makes it easier to propagate sharing information
through functor application. For example, the earlier ML code:
We can now write the fully transparent version of APPS as:
functor F1(X: SIG) =
struct type t=X.t val x=X.x end
functor APPS (F: TFSIG) = F(S)
creates a functor with type:2
.
X
0h2 ] Fi= 8:<;kj F*lm?Y=N2
sig type t = X.t val x : t end
and we can assign it with the following interface type:
?
.
F
0h2 ] FirP0UG1} t I#K9L=H|Po_8:';>j FirYlm?Y=N2H8:<;>j j ~
F t
C
S.t 
lNlm?
or written as signature:
or if we write it in an extended signature calculus:
fsig (X: SIG): sig type t = X.t val x : t end
fsig (F: TFSIG): sig type t= #t(F[{t=S.t}])
val x: t
end
Here, the type path X.t in the result signature really refers to type
#t T X V . During functor application, we create a transparent view
of the actual argument following signature SIG; we instantiate the
flexroot X into an actual constructor and then propagate this information into the result signature.
With proper syntactic hacks, this signature can even be written as:
fsig (F: TFSIG): sig type t = #t(F(S))
val x : t
end
The idea gets more interesting in the higher-order case. Because all functors are abstract under the abstract approach, we first
need to find a way to introduce transparent higher-order functors.
SML’97 uses the “:” and “:>” notation to distinguish between
transparent and opaque signature matching; we borrow the same
notation and use it to specify the abstract and transparent functors.
In the following example,
as long as we assume that all module identifiers (e.g., F and S)
referred inside the constructor context #t TY€ V are always referring
to their constructor counterparts.
Getting back to the earlier example in Section 2.1 where we
apply APPS to functors F1 and F2, we see why both R1.t and
R2.t are now equivalent to int. To apply APPS to F1 (or F2),
we match F1 (or F2) against TFSIG and calculate the flexroot F
of the actual argument; F is equal to \M Q t g‚!#TUWVƒS for F1 or
\M Q t int S for F2; in both cases, the t component of the result
is g‚!#T F Z Q'!" int S<[4V which ends up as int.
funsig NFSIG = fsig (X: SIG):> SIG
funsig TFSIG = fsig (X: SIG): SIG
Signature NFSIG represents an abstract functor that always creates
fresh new types at each application. Signature TFSIG represents a
fully transparent functor that always propagates the sharing information from the actual argument (i.e., X) into the result.
The definition of NFSIG introduces a template of form:
n6o_8:';pCpEqFir\0UGJs\t I-K3L = .
s\t I-K3L
X
2.4
0h2 ] FPu= 8:<;vj FPuwlm?Y=N2 ] Fx= 8:';kj Fx-lm?
Our syntactic signature looks similar to Leroy’s applicative-functor
approach [20] where he can also assign APPS with a signature:
I#K9Lzy
where kind is just r QS . Notice NFSIG does not
propagate any sharing information ( ) into the result signature; instead, each functor application always returns an existential package. For example, the abstract version of functor APPS:
fsig (F: FSIG): sig type t=F(S).t
val x: t
end
This similarity, however, stays only at the surface; the underlying
interpretations of the two are completely different. Under the applicative approach, a functor with signature FSIG will always generate the same abstract type if applied to the same argument. Under our scheme, an abstract functor (with signature NFSIG) always
generates a new type at each application while a transparent functor (with signature TFSIG) does not. We can simulate applicative
functors by opaquely matching a functor against a transparent functor signature. For example,
functor APPS (F: NFSIG) = F(S)
is assigned with the following interface type:
.
F
Relationship with Leroy’s applicative functors
0h2 ] Fir<= n6oa8:<;>j FirYlm?A=N2 ] FPu{= 8:<;vj FPuwlm?
or written as signature:
fsig (F: NFSIG):> SIG
functor F3 :> TFSIG = F1
On the other hand, the definition of TFSIG introduces a template of form:
Functor F3 would have type:
2
] F r 0HG1} t I#K9LM= .
we omitted the kind annotation for u to simplify the presentation; we will do the
same in the rest of the paper if the kind is clear from the context.
4
X
032 ] F u = 8:';>j F u lm?Y=N2H8:<;>j F r j lNlm?
X
Module expression and declaration:
path
mexp
„
‰
) ) Š
mdec
…‡†@ˆƒ„M … r<‹
‹
„ˆ str Š <' Š*r Œ end
u
fct TU… † 3Vh‰ŽˆY„ TN„ V
TN„)V"ˆ let Š in ‰
… † ‘‰’ˆ#! † ‘“1ˆ<” † •
ˆ
ˆ
) Module signature and specification:
sig
spec
) –
) ˆ
r<‹
‹
<# –—Œ end
sig –
fsig TU…‡†{3V)˜ … † 3pˆ<! † ˆ#! † ‘“1ˆ<” † H“
ctxt formation
ctyp formation
cexp formation
spec formation
sig formation
mexp formation
mdec formation
œ™Ÿž¡ ™¢œ£“
™¢œ¤•(“
™¢œ¤–
™¢œ
™¢œ£‰¥q
™¢œ£Š¦q–
ctyp equivalence
spec subsumption
sig subsumption
™¢œ£“1§“ ™¢œ¤–©¨ª– ™¢œ7¨
Figure 3: Static semantics for AMC: a summary
Core language:
“
ctyp
cexp
•
) ) !Y†ˆY„M !"ˆ'<
” † ˆY„M ”—ˆ<'
T sig –
™
) ‹
A‹ µ
¯O±{²a³ £´ < #
–(«¬w„˜­®– «°
‹
‹
r ‹
#< –—Œ end VA¬ƒ„˜­¶T sig – < < – Œ end V
T fsig TU…i†3V)˜ VA¬ƒ„˜­¶T fsig TU…i†36V*X1 V
Elaboration context:
ctxt
r<‹
šJˆ'™›ƒ–
_¬w„M …‘­+ TU… † 3VA¬w„˜­·TU… † 3 V
Figure 2: Syntax of the abstract module calculus AMC
T4!A†¡‘“‡VA¬w„1­·T4!A†'‘“‡V
TU” † H“‡VA¬w„˜­·TU” † H“‡V
T4!A†9VA¬w„˜­·T4!A†¡¸„M !AV
Because F3 is abstracted over its flexroot information, applying F3
to equivalent constructors will still result in equivalent types (e.g.,
2 j~ C
lm?
#t F3 t int  ).
Figure 4: Signature strengthening in AMC
One problem of the applicative approach is that it solely relies
on access paths to propagate sharing. Because access paths are not
allowed to contain arbitrary module expressions (doing otherwise
may break abstraction), the applicative approach cannot give an
accurate signature to the following functor:
first define an abstract module calculus that reviews the main ideas
behind translucent sums and manifest types. We then present our
new EMC calculus and show how it propagates more sharing than
the abstract approach.
3.1
functor PAPP (F : FSIG) (X : SIG) =
let structure Y =
struct type t = X.t * X.t
val x = X.x * X.x
end
in F(Y)
We use the Abstract Module Calculus (AMC) [19] as a representative of the system based on translucent sums [12] and manifest
types [19, 21]. The syntax of AMC is given in Figure 2. The static
semantics for AMC is summarized in Figure 3. The complete typing rules are given in Figures 4 to 6 and in Appendix A.
Leroy [20] did propose to type PAPP by “lambda-lifting” module
Y out of PAPP, but this dramatically alters the program structure,
making the module language impractical to program with.
AMC is a typical ML-style module calculus containing constructs such as module expressions (mexp), module declarations
(mdec), module access paths (path), signatures (sig, specifications
(spec), core-language types (ctyp) and expressions (cexp). Following Leroy [21], we use …‡† , !A† , and ”{† to denote module, type, and
value identifiers, and … , ! , and ” for module, type, and value labels.
We assume that each declaration or specification in AMC simultaneously defines an internal name (e.g.,
r<‹ ¹ ) and
‹ an external label
(e.g., … , ! , ” r').‹ Given
a structure str Š << Š*Œ end or a signa‹
ture sig –
<< мΠend, declarations and specifications defined
later can refer to those defined earlier using the internal names.
However, to access the module components from outside, we must
use the access paths such as „M … , „M ” , and „M ! where „ is another
path and … , ” , and ! are external labels.
Our approach uses the flexroot constructor to propagate sharing. We can easily give PAPP an accurate signature:
fsig (F : TFSIG) (X : SIG) :
sig type t = #t (F({t= #t(X) * #t(X)}))
val x : t
end
Notice we use TFSIG rather than NFSIG to emphasize that F is a
transparent functor.
3
The abstract module calculus AMC
Formalization
Signatures are used to type module expressions. An AMC signature can be either a functor signature or a regular signature that
contains an ordered list of module, type, and value specifications. A
functor signature is written as fsig TU…i†{3V)˜ where denotes
the argument signature and the result signature. We borrow the
SML’97 notation “:” and “:>” for signature matching and use it to
specify the abstract and transparent functors. Because AMC only
In this section we present an Extended Module Calculus (EMC)
that supports both fully transparent higher-order functors and fully
syntactic signatures. EMC is an extension of Leroy and Harper’s
abstract module calculus [19, 21, 12] but with support for fully
transparent functors. To make the presentation easier to follow, we
5
™¾œ¿„ sig –
œ™Ÿž¡ »…i†3½¼™
™¢œ¤…i†a¬¡…i†
™Ÿœ
™ŸœÇ
‹
‹
#< –¦À … † 3 < # end
™¢œ¿„
™ ›ƒ…i†{3Ɯ¤‰¥ 
fct TU…i†3Vh‰Ž fsig TU…i†3V)˜ r
y
y
‹
† à „M ! … †MÃ
Á ÂQ'! a
º
™Ÿœ„M … ÁWT9 V
™¢œ£Š1–
™6›ƒ–Ìœ£‰¥*
™Ÿœ let Š in ‰¥*
u
fsig TU…i†3V)˜ ™¢œ¿„ q y
r u
u
™¢œ¿„ TN„ È
V qQ¡… †Mà „ q
S T9 V
™Ÿœ¤‰¥
™¢œ¾TU…‡†¡‘‰ÍV"\TU…i†{3V
Rules for reflexivity and transitivity are omitted:
u ‹
‹
‹ ×
u ‹
Œ r ÔՇÖ
% – '< – % r – r < < – ¶
¨¿–
™ ›ƒ–
6
œ sig end ¨ sig end
r ‹ %
r ‹%
end
end ¨ sig – ™¢œ sig –
%
r
r
u
™ŸœÆT4!A†'˜“iV"¨½!A†
“
ctyp
™
ctxt
0Ó
) <<ˆ fsig TU… † 3V3 ) <<ˆ¡g‚!#T9Ù(V
) <<ˆ'™6›Yv9
Module constructor and kind
Ù
mcon
u
™ œÇ ¿
Ÿ
¨ ™6›A… † 3 œÇ ¿
¨ r
u
r
u
™¢œ¾T fsig TU… † 3 V )˜ V@¨£T fsig TU… † 3 V )˜ V
™ œz¨¿ ¾
™¢œ¾TU… † 3VȨÂTU… † 3 V
sig
%
r<‹
‹
‹
r ‹
– % '< – × –
<< º
– Œ % Ô Õ‡Ö
™6›ƒ–ºØpœ sig end ¨ sig end
%
‹%
™Ÿœ sig –—Ø
end ¨ sig end
r
and ÎÂϪÒ
™¾œ¤•(“
™¾œ¾TU”{†¡•V"‡TU”{†H“iV
All in AMC (Figure 2) plus:
%
™¢œ¤–
0¡Ñ
™ŸœÇ ¨¿
™¾œ¿„ ™ŸœÇ ¨¿
™¢œ¾TN„)VÈq
™¢œ£“
™Ÿœ¾T4!Y†¡‘“iV"PT4!A†¡‘“‡V
Figure 5: Selected typing rules for AMC: ÎÂϽÐ
%
r
‹
„M …Ÿˆ@! † … † ¼Ä ±Å TH– << –¦À{VƒS
r
‹
A‹ µ
r
™6›w– ›#<<<›ƒ– ÀÉ
œ Š À q
£
– ÀËÊ £
´ '<
r ‹
r ‹
‹
‹
™Ÿœ str Š << Š Œ end sig –
' # РΠend
œ¤™Ÿž¡ str end sig end
™¢œ
r
mcfd
mknd
mkfd
™ œ“—§“ Ÿ
™¢œ¾T4! † ‘“‡V"¨ÂT4! † ‘“ V
Ü
Û
) ) ) ) ˆ
r u
…i†r'ˆ<‹ˆ¡\‹ >9
Ùڈ¡Ù Z Ù [
QÛ
#< ی‡SJˆ¡g‚…T9Ù(V
!q‘r<“—‹ ˆ<…b
‹ Ù
r y
u
QÜ
<' ÜJŒ‡S(ˆ'
!P9Rªˆ<…v9
Figure 7: Syntax of the extended module calculus EMC
™ œ£“1§“ ¢
™¾œ¾TU”{†H“iV@¨ÂTU”†H“ V
identifier …i† of signature isr strengthened
to have signature _¬…i† .
u
Functor application (e.g., „ TNu „ V ) can propagate the sharing information in the argument („ ) into the result signature—this is
achieved byu substituting the formal parameter …i† with the actual
argument „ (see Figure 5).
Figure 6: Signature subsumption in AMC
supports abstract functors, a functor signature in AMC always uses
:> to specify its result. Later in Section 3.2, we’ll extend AMC
with transparent functor signatures in the form of fsig TU…i†{3V3 .
Unfortunately, this strengthening procedure has no effect on its
functor components. In the higher-order case, functor application
in AMC does not propagate as much sharing as one would normally
expect in the MacQueen-Tofte system. In the following, we show
how to extend AMC to support fully transparent functors.
AMC allows two kinds of type specifications: flexible type
specification (! † ) and manifest type specification (! † “ ). Figure 6
lists the standard signature subsumption rules. Manifest types can
be made opaque when matched against flexible specifications. Subsumption on functor signatures is contra-variant on the argument
but covariant on the result.
3.2
Figure 5 lists the formation rules for the AMC module expressions and declarations. AMC supports the usual set of module constructs
r ‹
‹ such as module access path („ ), structure definition (str
Š << Š Œ end),
r u functor definition (fct TU… † *Vh‰ ), functor application („ TN„ V ), signature matching („½)Ÿ ), and the let expression. Most of the typing rules for AMC are straightforward:
signature matching in AMC is done opaquely; to type a let expression, the result signature must not contain any references to
locally defined module variables (i.e., is well formed in context
™ but not ™6›ƒ– ; see Figure 5).
The extended module calculus EMC
The extended module calculus EMC contains the same set of module expressions and declarations as those in AMC. However, EMC
uses a different method to propagate sharing information; this allows EMC to support fully transparent higher-order functors. EMC
also has a more expressive signature calculus so that all functors in
EMC have fully syntactic signatures.
The syntax of EMC is given in Figure 7. The static semantics
for EMC is summarized in Figure 8. The complete typing rules
are given in Figures 9 to 15 and in Appendix B. Our typing rules
can be directly turned into a type-checking algorithm because the
signature subsumption rules are only used at functor application
and opaque signature matching (the same is true for AMC).
Type sharing in AMC is propagated through signature strengthening and functor application. Signature strengthening, which is
defined in Figure 4, is a variation of dot notation [4]; a module
6
àaáâ"T sig –
Similar forms as those for AMC (Figure 3) plus:
<'ƒ–—Œ end V­+Q&àaáâ"TH–
à_áâ"T9V6­®
àaáMâ@T fsig TU…i†{3V)˜ V­®
™¾œÙ£
™¾œ¤Û¤Ü
™¾œÙݧÝÙ ™¾œ¤Û§Û Ü
œ
Þ¨ª
œÜ¨¿Ü mcon formation
mcfd formation
mcon equivalence
mcfd equivalence
mknd subsumption
mkfd subsumption
r
àaáMâ@T4! † V­
!9R
œ¤™Ÿž¡ ߅ † 37¼Í™
™¾œ …i†qà_áâ@T9V
‹
‹ƒµ
™¢œ¤Ûi«‚qÜ>« ³ ¤´ <<
r'‹
‹
r<‹
‹
™ŸœÇQ¡Û
'< یiSJ*QÜ
<# ÜJŒ‡S
œ™Ÿž¡ »>9
©¼Í™
™Ÿœ¤q
_¬Ùæê)ë Ô ëAì ±{²Aí ì Ô{ՇÖ
T sig –
+™ŸœÇÙ
r u
™ŸœÙ Z Ù [M
™Ÿœ¤“
™¢œ¾T4!q‘“‡V6‡T4!9RkV
š
à_áâ"TU” † H“iV­
š
r
±¯ _¬T9Ù£àaáâ"T96VAV
‹
A‹ µ
– « ¬*T9Ù¤
åV"­æ– « ´ <'
³ £
r
<#ƒ– Œ end VA¬T9Ù¤q
åV­ sig – < 'ƒ– Œ end
T fsig TU…i†{3V)˜ VA¬T9Ù¤q
åV­
™ ›A>9
ãœÇÙ£q
6
y
™ŸœÇ\v9
Ù£q
™ŸœÙ
QS
Figure 10: EMC kind calculation çèqé‡T9V
‹
‹
™ŸœÙ
ÍQ<< >
… 9
<< S
™ŸœÇg¸…T9Ù(V"
u
y
à_áâ@T4! † ‘“iV­
à_áâ@TU… † 3V­®…>9àaáâT9V
y
VW#<ƒà_áâ@TH–—ŒPV6S
à_áâ@T9V6­®
à_áâ@T9 6
V ­®
y
à_áâ@T fsig TU…i†{3V3 V­æ
Figure 8: Static semantics for EMC: a summary
r
r
fsig TU…i†{3V)˜ y
¥
+U¬T9ÙºZ …i†U[_q
4V­+ T fsig TU…i†3V3 AV ¬T9Ù¤q
åV­ fsig TU…‡†{3V)˜ q
¬*T9g¸…T9Ù(V@q
åV6­+
a
‹
‹
UT … † 3VA¬T9Ù¤*Q'< …>9
<' S{V­¶TU… † 3 V
™¢œÇÙ£q
™ŸœäTU…ÈÙ(V6\TU…v9
åV
‹
‹
T4!Y†9VA¬T9Ù¤*Q'< ! 9R <<NS{V­·T4!A†¡g‚!#T9Ù(VAV
Figure 9: EMC constructor formation
T4!Y†'‘“iVA¬*T9ÙÚq
åV­¶T4!Y†'‘“iV
TU”{†H“iVA¬*T9Ù¤
åV6­îTU”{†H“iV
Figure 11: Signature strengthening in EMC
The EMC signature calculus contains two new features that are
not present in AMC: one is the new functor signature fsig TU… † V¡ used to specify transparent higher-order functors; another
is a simple constructor calculus that captures the sharing information (using constructor Ù and kind ) and a new type expression
gJ!<T9Ù(V that selects the type field ! from constructor Ù .
specifically, given a signature (or a functor signature) , we extract
all the flexible components in into a single constructor variable
; we call such as the flexroot constructor of signature . We
use to denote the kind of and to denote the instantiation of
whose flexible components are redirected to the corresponding
entries in . An opaque view of signature can be modeled as
an existential type º-
. A transparent view of can be obtained by substituting the flexroot of with the actual constructor
information. Full transparency is then achieved by propagating the
flexroot information through functor application.
Transparent functors can propagate more sharing than abstract
‹
functors. For example, suppose is defined as sig ! † … † U! † end,
a functor with signature fsig TU…i†\#VaXD corresponds to an abstract functor whose application always produces a module with a
new abstract type component ! . On the other hand, a functor with
signature fsig TU…i†h6VPh corresponds to a fully transparent functor whose application always propagates the type information from
its argument into its result.
Both and can be calculated easily. Figure 10 shows how to
deduce à_áâ@T9V — the kind of the flexroot constructor of a module
with signature . Here, à_áâ@T9V­»
means that the flexible
constructor part of signature is of kind and à_áâ@TH–åVv­ïܸð
means that the flexible part in specification – is of kind field Ü ð
(which denotes either Ü or empty field š ). Notice in addition to
the flexible type specifications (!A† ), functor specifications are also
considered as the flexible components. A transparent functor with
TU…‡†*YV‡Y is treated as a higher-order constructor
signature fsig
y
of kind where and are the kinds for and . An
abstract functor with signature fsig TU…i†6PVÈP is treated as a
dummy constructor that returns an empty record kind.
The constructor
calculus itself (see Figure 7) is similar to those
used in the -like polymorphic -calculi. In this paper, we assume
conall types in the core language have kind R ; we use r ‹ to denote
‹
Œ
structor variables;r and
we
use
the
record
kind
and
¡
Q
Ü
<
<
Ü
S
y
u
function kind to type module constructors. A record
constructor consists of a sequence of core-language types (marked
by label ! ) and module constructors (marked by label … ). Given
a record constructor Ù , the selection form g¸…T9Ù(V is a module
constructor equivalent to the … field of Ù while g‚!<T9Ù(V is a corelanguage type expression equivalent to the ! field of Ù . Figure 9
gives the formation rules for the constructor calculus; other typing
rules summarized in Figure 8 are given in Appendix B.
Signature is calculated using a procedure similar to the idea
of signature strengthening, but signature strengthening in EMC is
very different from that in AMC: instead of relying on the access
path „ to propagate sharing, EMC uses the flexroot constructor to
The constructor calculus is designed to faithfully capture the
sharing information inside all EMC module constructs. More
7
ñ ò two of these rules—module identifier and functor application—are different from those for AMC (Figure 5):
Only
™ ›A… † 3¾œ‰Žq 6
fct TU… † 3Vh‰¥ fsig TU… † 3V)˜ ™Ÿœ
œ¤™Ÿž¡ str end sig end
™¢œ
™ŸœÇ
r
™¾œ¿„ sig –
œ™Ÿž¡ »…i†3½¼™
™¢œ¤… † a¬ … †
‹
‹
#< – À … † 3 < # end
r
™Ÿœ„
y
y
‹
† à „M ! … †MÃ
Á ÂQ'! a
º
™Ÿœ„M … ÁWT9 V
u
fsig TU…‡†36V*X1 Ÿ
™ œ„ *
y
r u
™¢œ¿„ NT „ V@Q …i† Ã
™Ÿœ¤‰¥
™¢œ¾TU…‡†¡‘‰ÍV"\TU…i†{3V
r
u
u
V3 V
™¢œ£“
‹
‹
™ŸœÆT4!A†'˜“iV ô Qq-< !9R << Sû­·T4!q‘“‡V
strengthen a signature. Given a signature and a constructor Ù
of kind àaáMâ@T9V , signature strengthening _¬Ù returns the result
of substituting the flexroot constructor in with Ù . We use the
auxiliary procedures given in Figure 11 to deduce a¬{Ù . Here,
_¬T9Ù·&
åV­ø means that instantiating by constructor Ù
of kind yields signature , and –‘¬*T9Ù¢P
åV>­·– means that
strengthening specification – by constructor Ù of kind yields
specification – . The additional kind parameter is used to identify
the flexible components in a signature.
For all other cases,
™Ÿœ¤–
ô Ž­æš
Figure 14: Narrowing instantiated signatures in EMC
a module … † of signature , we use the overlined identifier … † to
refer to the flexroot constructor hidden inside …i† . This is a form of
dot notation [5] where … † represents the abstract type defined by the
existential package …‡† . In AMC, signature strengthening is applied
to the access identifier (…i† ) itself and hidden type components are
represented using access paths („ ). EMC generalizes this idea so it
can propagates more sharing than AMC does.
Signature strengthening produces a special form of signature
whose type components are fully defined and whose functor components have abstract result signatures. This special form, which
we call it instantiated signature, can be accurately defined using
the following grammar:
X 0Ó
™¾œ ô ú­+Ù
‹
‹
™ŸœäTU…‡†{3V ô Q<< v
… 9
<' Sû­·TU…bÙ(V
Figure 13: Signature subsumption in EMC
–Íù
and ÎÝÏ¿Ò
œ¤
Þ¨¿à_áâ@T9y V
™›A… † 3䜝 ô ­+
y Ù ÙÚÝ\v9
Q …‡† à _S*T9Ù V
™¾œÙ£q
y
†
ô
fsig
™¢œÆT
TU… 3V)˜ V TH
V"­®Ù
r
u
r
u
™¢œ¾T fsig TU…i†{3 V3 V@¨ÂT fsig TU…i†{3 V)˜ V
u
ê)ë Ô{Õ ê Õ ë í ÔÕ í ê Ô íƒõ Ö ëAêXö Õ‡Ô íƒ÷P²ƒõ
r
u
r
u
™¢œ¾T fsig TU… † 3 V )˜ V@¨ÚT fsig TU… † 3 V3 V
ˆ
0¡Ñ
™¾œ¤•(“
™¾œ¾TU”{†¡•V"‡TU”{†H“iV
‹
A‹ µ
™¢œ¤– «‡ô ú­®Û « ð
³ £´ <<
r
r
™¢œ¾T sig – <#w–—Œ end V ô Ž­+QÛ ð # <ƒÛ Œ ð S
All subsumption rules in AMC (Figure 6) plus:
r
u
r
r
™ œ ¨¿
¢
™6›Y… † 3 Ç
œ ¨
r
u
™ŸœÆT fsig TU…i†{3 V3 VȨÂT fsig TU…i†{3
™¾œ¿„ ™ŸœÇ ¨¿
™¢œ¾TN„)VÈq
™¢œ£“
™Ÿœ¾T4!Y†¡‘“iV"PT4!A†¡‘“‡V
Figure 12: Selected typing rules for EMC: ΁ϪÐ
X ™Ÿœ ¿
¨ 󙟜 wô àaáâ"T96V­®Ù
y
‹
u
…i† à „ q
S T9 V
r
‹
A‹ µ
r
™6›w– ›#<<<›ƒ– ÀÉ
œ Š À q
£
– ÀËÊ £
´ '<
r ‹
r ‹
‹
‹
™Ÿœ str Š << Š Œ end sig –
' # РΠend
™¢œ£Š1–
™6›ƒ–Ìœ£‰¥*
™Ÿœ let Š in ‰¥*
ù
Ù
r
‹
„M …Ÿˆ@! † … † ¼Ä ±Å TH– << – À VƒS
Figure 13 gives the additional signature subsumption rules for
the EMC signatures. Subsumption on transparent functor signatures is also contra-variant on the argument and covariant on the
r re-u
sult. More interestingly, a transparent signature fsig
r TU… † Yu VPh
is a subtype of its abstract counterpart fsig TU…‡†qh VP)‘ ; this is
because we can always coerce a transparent functor into an abstract
one by blocking all ofr its sharing
information. Finally, an abstract
u
signature fsig TU…‡†Y u VP)‘ is a subtype of its transparent counterpart if the result is an instantiated signature; this corresponds
to the special case where the abstract version only hides a dummy
constructor so it should be equivalent to the transparent version.
‹
r ‹
sig –Íù << –ÍŒ ù end
fsig TU…i†¡3V)˜
… † 3ù&ˆ#! † ‘“1ˆ<” † H“
Notice under this special form, the argument of a functor signature
could still be an arbitrary EMC signature, but the result must always be abstract. The following lemma can be proved by structural
induction on the EMC signatures:
y
r More
u specifically,
u a kind is a dummyr'‹ kind‹ if it is Q{S , or
where is a dummy kind, or QÜ
<< ÜJŒ‡S where all
fields ÜJ† have dummy kinds. Given a context ™ and a constructor
Ù , we say Ù is a dummy constructor if ™©œ¥Ù¾i
and is a
dummy kind. A dummy constructor conveys no useful information
thus it can be safely eliminated. It is easy to show that if is an
instantiated signature then à_áâ@T9V is a dummy kind.
Lemma 3.1 Given an EMC context ™ , a signature , a kind ,
and a constructor Ù , if ¥
™ œ’ and ™úœúÙ¢\
and ϊ
+¨
à_áâ@T9V then a¬{Ù is an instantiated signature and ™Çœ¤_¬Ù .
Figure 12 gives the typing rules for the EMC module expressions and declarations. Intuitively, we say a module expression ‰
has signature if ‰ has type equal to (Aà_áâ"T9V-XT9_¬WV . Given
8
™¢œ ô ­+Ù¤q
™¢œ¾TU… † 3V ô TU… † 3 V­¶TU…ÈÙ(V6\TU…v9
åV
™¢œ£“1§“ ™ŸœäT4!Y†'‘“‡V ô T4!Y†#˜“ V"­
r
r
r
r
ô – ­®Û ð Ü ð
™Ÿœ£“1§“ ™ŸœÆTU”{†H“iV ô TU”†¡H“ 
V ­æšJš
™Ÿœ¾T sig end V ô T sig end V­,Q{S‚*Q{S
™ŸœäT4! † ‘“‡V ô ! † ­îT4!‘“iV‡T4!9RkV
™ŸœÇ–
š‚{š
u
u
œ¾T sig –
#<ƒ–—Œ end V ô T sig – <#ƒ–× end V"­+Q{ü"ý¡SJQ‡þÈýS
r
r
r ‹
r ‹
™Ÿœ¾T sig – '#ƒ–—Œ end V ô T sig – < 'A– × end V6­+Qۂð ü"ý'S‚*Q¡Üºð þÈý'S
™6›A–
r
r
r
< <w– Œ end V ô T sig – <<ƒ– × end V­+Ù¤
r
™¾œ¾T sig – Ø <<w– Œ end V ô T sig – #<ƒ– × end V­+Ù£q
™6›ƒ– Ø œ¾T sig –
™¢œŸQü"ýSJ*QiþÈý¡S
™ŸœÙ¤
r
u
r
r
u
r
r y
™¢œ ¨¿
™ ›A…i†{3 

œ ¨
ÙÝÝ\v9à_áâ@T9 V- QS
Žàaáâ"T9 V
r
u
r
u
™ŸœÆT fsig TU…i†3 6
V ž-ÿ1 V ô T fsig TU…i†{3 V)˜ V­+Ù¤q
kì õ#²ƒõ žwÿ—¹È•'¹H! • ±² X
r
r
™¢œ ¨¿
y
u
u
u
r
u
r
™6›Y…i†3 œ ô +
­ Ù ÙÂÝ\>9àaáâ"T9 -V Q …i† Ã
r
u
r
u
™ŸœÆT fsig TU…i†3 V"-ž ÿ1 V ô T fsig TU…i†{3 V3 V­ £
Ù q
u
u
r y
_S*T9Ù V
úàaáMâ@T9 V
kì õ#²ƒõ žwÿ—¹È•'¹H! • ±² X
QS
™¢œÙ¤
Figure 15: Narrowing instantiated signatures in EMC (alternative version)
This alternative signature narrowing procedure can also be used
to verify the signature subsumption relation defined in Figure 13.
To check if a functor signature is a subtype of another signature
, we first compare their corresponding argument signatures, then
compare their result signatures, and finally in the case that is
abstract and is transparent, we invoke the signature narrowing
procedure in Figure 15. If this algorithm does not get stuck, then is a sub-signature of .
Only two of the typing rules in Figure 12 are different from
those for AMC (in Figure 5): one for module identifier and another
for functor application. To access a module identifier …i† , we always strengthen
r u it with its flexroot constructor …i† . To type functor
application „ TN„ V , we first notice that the typing rules for access
paths (in Figure 12) satisfies the following property: if ™¢œ„q ,
then is an instantiated signature. This observation
r can be easily
established via Lemma 3.1.
So
we
can
assume
has signature
„
u
is an
;
furthermore,
fsig TU…‡†{3V)˜ and „ has signature
r u
instantiated signature. Typing „ TN„ V then involves checkingu if subsumes , extracting the actual flexroot information in „ (let’s
call it Ù ), and substituting all instances of …i† in with construcu
tor Ù and all instances of … † (not counting … † ) with access path „ .
Here, the substitution on …‡† is the key on why can propagate more
sharing and support fully transparent higher-order functors.
Lemma 3.3 Given an EMC context ™ , a signature , and an instantiated signature , if ™
œ
ô î­
Ù ‘
then
œ¤
Ž§Ýà_áâ@T9V and ™ŸœÙ
.
Lemma 3.4 Given an EMC context ™ , a signature , and an constructor Ù , if ™¢œÇÙ£qà_áâ@T9V then ™¢œÇ_¬Ù£¨¿ .
Constructoru Ù can be extracted from the actual argument signature of „ using the signature-narrowing procedure defined
in Figure 14. This procedure is initially invoked upon instantiated
signatures only. Given a context ™ , the deduction ™úœä ô ­
Ù extracts the type components from an instantiated signature and produces a constructor Ù of kind ; the specification counœã– ô Ë­øۂð extracts the type components in
terpart ™
– and produces either Û or empty field š . The side condition
™¶œ,Ù ensures that Ù only contains identifiers defined in
™ . We can prove the following lemma using structural induction on
the EMC signatures:
Lemma 3.5 Given an EMC context ™ , two signature and ,
and an instantiated signature , if ™Ýœ¿ ¨¿ and ™œ ô
p­®Ù£q
then ™Ÿœ ƒô D­+Ù£q
Lemma 3.6 Given an EMC context ™ , a signature , and an instantiated signature , then ™Žœä 6¨Ú is true if and only if
™ŸœÇ ô D­+Ù£q
succeeds.
Ù·k
,
Proof: For the “if” part: assuming ™ãœÌ _ô Æ­
we use structural induction on ; along the process, we create a
bridging signature S’=S / C and and also show ™¶œ, ¨Æ ;
this bridge and the fact ™Çœ¤M¨¿ (via Lemma 3.4) are used to
connect a transparent functor signature to its abstract counterpart.
For the “only if” part: we use structural induction on the size of the
instantiated signature and show that if ™BœB M¨¿ is true then
™œÚ ƒô D­+Ù£q
will not get stuck. The only nontrivial case
r
u
is when is an abstract functor signature fsigr TU…i†i¡
u V)7 while is a transparent signature fsig TU… † \ Vv‡ ; because
™Þœ© Ȩ¤ , there must
exist an instantiated bridging
signature
r
r
u
u
u
u
u
such that ™6›Y…i†*Y
œ¾ ¨Â and ™6›Y…iu†*Y
œ¾
u ¨Ý ;
u
u
u
because is instantiated, we have ™½œp ô u ­+Ù u u from
u
­ Ù

from
the induction hypothesis and ™ œî ô Lemma 3.5.
Lemma 3.2 Given an EMC context ™ , a signature , and an instantiated signature , let æà_áâ@T9V , if ™ãœ ¨©
and ™Ÿœ wô Ž­®Ù , then ™ŸœÇÙ¤
.
Figure 15 gives an alternative signature narrowing procedure.
This procedure is defined over arbitrary signatures, but it is initially
invoked upon a instantiated signature only. Given a context ™ , the
deduction ™^œz ô ­+Ù¤
extracts the type components from
an instantiated signature and produces a flexroot constructor Ù
of kind (for signature ); the specification counterpart ™^œ7– ô
–"­ïÛ ð _Ü ð extracts the type components in – and produces
either Û of kind Ü or empty field š . We use ü"ý and þÈý to denote a
sequence of constructor fields and kind fields. The side conditions
™¶œ·Ù 
and ™¶œ¶Qü"ýSD"Q‡þÈý¡S ensures that Ù and ü"ý
only contain identifiers defined in ™ . It is easy to show that two
signature narrowing procedures produce equivalent results.
Given an EMC context ™ , we say two signatures and are
equivalent, denoted as ™7œBp§Ý , if and only if both ™7œDz¨¿ and ™¥œŽ ¨Ú are true. The following propositions show why
the typing rules for EMC can hold together:
9
Lemma 3.7 Given an EMC context ™ , a signature , and u an instantiated
signature , assume ™Çœ¤ M¨¿ and
y ™Ç
‹ œ^„ y *
u à ٠…‡† à „ S ,
Q
i
…
†
and ™äœŸ ô àaáâ"T96V"­,Ù , and rlet Á¦£
u
r
then (1) givenu two type expressions
r “ and
u “ , if ™6›A…‡†{3
r œD“ and
u
™›A… † 3ݜ7“ and ™6›A… † 3ݜ7“ §“ then ™¿œ7ÁWTU“ V§ÁWTU“ V ;
r
u
(2) given two instantiated signatures and , if ™6›A…‡†6 œ
r
u
r
u
and ™6›A… † _»œ and ™›A… † _
œ §, then
r
u
™¢œÚÁWT9 V§ÁWT9 V .
which in turn is equivalent to:
] F@0HG
=N2
sig type t = #s
2mFP?
#s
2mFP?
val f: t end
?
where kind is just Q s _R>S . In other words, if we write each
signature as a template of \Ji
, the hidden type specifications will be present in the kind but not in the body signature .
Notice before this extension, is always equivalent to à_áâ@T9V ,
so all components in are always present in .
Theorem 3.8 (unique typing) Given an EMC context ™ , two signatures and , and a module expression ‰ , if ™ÇœÚ‰¥q and
™¢œ£‰¥q then ™Ÿœp§Ý .
4 Expressiveness
In this section, we show that both the translucent-sum-based calculus and the strong-sum-based calculus can be embedded into our
EMC calculus. We also compare EMC with the stamp-based semantics of the MacQueen-Tofte system [26, 36].
Proof: Expand this theorem to cover module declarations and core
language expressions; the generalized version of this theorem can
be proved by structural induction on the derivation tree.
3.3
Discussions and extensions
4.1
The EMC calculus given so far only allows abstract or fully transparent result signatures. We could extend the EMC signature calculus further to support partially transparent functors:
sig
We use the AMC calculus presented in Section 3.1 as a representative for the system based on translucent sums [12] and manifest
types [19]. Because AMC is a subset of EMC, the translation from
AMC to EMC (denoted as h€ ) is just an identity function, We can
show that this translation h€ maps all well typed AMC programs
into well-typed EMC programs.
‹
<'ˆ fsig TU… † 3VÈ pv T9 å
V
) Here, pv is a modifier that indicates the result signature is partially
transparent, and the kind is used to fine tune the amount of sharing being propagated through functor application; a well-formed
signature must have œÇàaáMâ@T9 VȨ
so that the kind annotation
actually make sense.
Theorem 4.1 Given an AMC context ™ , we have
More aggressively, we could instead extend EMC with an abstract module specification of form:
–
spec
) #<ˆ<…i†{)˜
This seems to be less adhoc than the pv keyword but it makes it
harder to reuse large signatures with small changes of transparency
notations.
EMC can also be extended to support other forms of module expressions in SML’97. For example, in SML’97, the let expression
(at the module level) allows its body type to refer to the new type
stamps generated in the let declarations. Also, SML’97 supports
transparent signature matching such as:
y
s, but the new type s is not
Here, type t is equivalent to s
exported. Both of these features involve exporting values and types
that make use of hidden abstract types. While it is doubtful that
such extension is really useful in practice, we can support it easily
by extending the EMC signature calculus with the following new
form of type specifications:
–
) if œ¥™úž¡ is a valid AMC deduction then œ4™Úž¡ valid in EMC; similarly,
if ™Ÿœ¤“ then 4™ œ4“ ;
if ™Ÿœ•J{“ then U
™ œ U• 4“ ;
™ 
œ H
;
if ™ŸœÇ then U
™ ª
œ 4
‰ º
U
;
if ™Ÿœ¤‰¥q then 4
™ ¿
œ 4
Š º
U
– ;
if ™Ÿœ¤Š1– then 4
™ ª
œ 4
“ (
§ O“ .
if ™Ÿœ¤“¦§“ then U
™ ¿
œ H
—
¨ H .
if ™ŸœÇz¨¿ then U
is
Proof: By structural induction on the derivation tree. The main difference between EMC and AMC is the way how module identifiers
and functor applications are typed. For the case of module identifiers, we use the following lemma (Lemma 4.2); for the case of
functor application, notice the result of any AMC functor signature
does not contain any reference to the flexroot constructor … † so the
typing rules for AMC and EMC have the same behavior.
structure A : sig type t val f : t end =
struct abstype s = ...
type t = s -> s
fun f (x : s) = x
end
spec
The abstract module calculus AMC
Lemma 4.2 Given an AMC context ™ , suppose is an AMC signature and … † -¼z™ , then U™ œH_¬… † § H ¬ … † is a
valid deduction in EMC.
Proof: Notice _¬…‡† refers to the strengthening operation for AMC
(as in Figure 4) while H ¬ … † refers to the strengthening operation
for EMC (as in Figure 11). To prove this lemma, we need to show
the following: given an EMC type path „M ! , let …i† be the root identifier in „ , and ۗTN„WV denotes the EMC constructor … † if „˜… † , and
g¸… THۗTN„ VAV if „˜7„ … , then the judgement ™Dœ¦„a !§ÂgJ!<THۗTN„WVAV
is valid in EMC.
'<ˆ#!A† hidden
We can then write down the interface for A as:
sig type s is hidden
type t = s -> s
val f : t
end
10
!
path
mexp
„
‰
) ) •
) ) ) ctyp
ctme
“
‰ ) ) ) ) ctce
• ) ctxt
™
) sig
ctsp
cexp
mtyp
'
.
ˆ
ˆ
ˆ
r
u
… ˆ" TN„WV6ˆ" TN„WV
‘
r ‹ u+
„‘ˆ#%$TH•V"ˆ#%&#r T('MV"u ˆ*)U…È‘‰
‰ r
u
\…>3 ‰’ˆY„ TN„ V@ˆ let
b
…
‘
‰ r in u ‰
$
r u
V (T 'MV6ˆ TYP ˆ¡@…v3 ˆ …>3 ",&-TN„WV6ˆ<<
" $ TN„WV6ˆ<<
r
u $
V TU“‡V6ˆ EQ TU“‡V"ˆ¡@…> r - u - $ ˆ …vr %.b u V TU“‡V6ˆ TYP ˆ¡@…v% . . ˆ …v% . .
" & TU‰ V"ˆ#<
…‘ˆ #%$TH• V@ˆ #&wTU“iV6ˆ¡\…v% .b ‰ r
u
r
u
‰ TU‰ V@ˆ let …È‘‰ in ‰ r
u
r ‹ u +
)U…È‘‰ ‰ ˆ " TU‰ V6ˆ " TU‰ V
" $ TU‰ V6ˆ<'
ctxt-to-ctxt translation
ctsp-to-ctyp translation
sig-to-sig translation
cexp-to-cexp translation
path-to-path translation
mexp-to-mexp translation
ctyp-to-ctyp translation
mtyp-to-sig translation
mtyp-to-sig translation
mtyp-to-kind translation
mtyp-to-kind translation
mtyp-to-mcon translation
ctme-to-mcon translation
“
™
Ãy •
„, Œ¦Ã
y „
4‰4'Œ Ã
‰
™¢œ£6
“ 5¶“ ™¢7
œ -85ï
™¢/
œ .y 5ï
9-:; Ã
y
<.= ;kÃ
™¢7
œ -85ïÙ
™¢œ£‰ *
-85ïÙ
U•'Œ
y
Figure 18: Translation from TMC to EMC: a summary
ctxt formation
mtyp formation
ctyp formation
ctme formation
ctce formation
œ¤™¾ž¡ ™Ÿœand ™Ÿœ/.
™Ÿœ“
™Ÿœ‰ ™ŸœÇ• “
cexp formation
mexp formation
sig formation
ctsp formation
™ŸœÇ•(“
™Ÿœ‰Ž
™ŸœŸ
™Ÿ/
œ '
ctyp equivalence
mtyp equivalence
mtyp subsumption
mtyp strengthening
r
u
™Ÿœ“ r §“
u
r
u
or ™¾œ/. §0.
™Ÿ
œ § 0
™Ÿ
œ - ¨1.
.@¬¡‰ 2
­ -
A module expression in TMC can either be an access path („ ), a
single-value-component module ( #%$*TH•{V ), a single-type-component
module
r#‹ u + ( # & TH•V ), a strong sum of two module components
r u ( )U…p
‰
‰
), a functor ( \…‚ƒ ‰ ), a functor application („ TN„ V ), or
a let expression.
To simplify the presentation, we restrict the TMC
applir functor
u
cation to work on simple access
only (i.e., „ TN„ V ). Arbitrary
r paths
u
functor applications (e.g., ‰ TU‰ V ) can just be A-normalized into
the restricted form using let expressions. We also do not support
type abbreviations in signatures. We insist that - be a subtype of
. if they have same number of components (see the subtyping rules
™¢
œ - 1
¨ . in Appendix C ). These restrictions do not affect the
main result because it is easy (but tedious) to extend TMC and the
TMC-to-EMC translation to support the additional features.
Figure 18 summarizes the translation from TMC to EMC; the
actual definition is given in Appendix D. Here, h€ Œ maps TMC
contexts, core types (in signatures), signatures, core expressions,
access paths, and module expressions into their EMC counterparts;
h€ ; maps TMC module types into EMC kinds. The translation
from TMC types to EMC types is based on the type formation rules,
so the judgement ™£œÝ6
“ 5î“ maps the TMC core type “ into an
œ ->5ï and ™Ç?
œ .5
EMC core type “ ; the judgements ™Ÿ/
map the TMC module types - or . into an EMC signature .
We also use judgements ™ª@
œ -85ïÙ and ™œ7‰ A
-85 Ù to
map TMC module types and expressions (embedded inside core
types) into EMC constructors. We can prove the following type
preservation theorem for the TMC-to-EMC translation:
Figure 17: Static semantics for TMC: a summary
The transparent module calculus TMC
We use the Transparent Module Calculus (TMC) as a representative
of the strong-sum-based approach. The syntax of TMC is given in
Figure 16; the static semantics is summarized in Figure 17; the
complete typing rules are given in Appendix C.
Theorem 4.3 Given a TMC context ™ , we have:
Following other strong-sum-based module systems [26, 28, 36],
we distinguish module signatures ( ) from module types ( - and
. ): module signatures are source-level specifications while module
types are semantic objects used for typechecking.
A module signature can either contain a single value specification (V T('MV ), a single type specification
r u (TYP), or a pair of two
other module
components
(
@
å
…
\
); it can also be a functor
$
r u
signature ( …‘ ). Only simple access paths (" & TN„iV ) are allowed in a specification.3 An . -shaped module type is like a module signature except that in its value specification V TU“‡V , core type “
can contain arbitrary module expressions (‰ ). - -shaped module
types are slightly different from . -shaped ones: they allow manifest types (or type abbreviations) of form EQ TU“iV but no flexible
type specification of form TYP. The module expression ‰ inside
the core type “ helps achieve the fully transparent propagation of
the sharing information in TMC.
3
3' Œ1Ã
y
H'Œ Ã
šûˆ'™6›A…>-ïˆ'™6›A…>%.
Figure 16: Syntax of the transparent module calculus TMC
4.2
y
yÃ
U™'Œ
The Standard ML signature calculus [28, 27] enforces a similar restriction.
11
if œÝ™Ýž¡ is a valid deduction in TMC, then œU™ Œ ž¡ is
valid in EMC; similarly,
if ™ŸœB' then U™<Œ£œ3''Œ ;
™ <ŒÚ
œ H
'Π;
if ™ŸœÇ then U
if ™Ÿœ•J{“ and ™Ÿœ£6
“ 5¶“ then U
™ Œ œU• Œ {“ ;
œ -85 then U
™ <ŒÚœ „'Œ˜q ;
if ™Ÿœ„
and ™¢7
if ™Ýœª‰¥A
- and ™ÝC
œ -85 then U
™ Œ D
œ 44
‰ Œ q ;
if ™Ÿœ¤E
“ 5 “ then U
™ 'ŒÂœ£“ ;
œ -25ï or ™¢/
œ .5 then U
™ <Œ£œ ;
if ™ŸF
r
u
if ™ŽG
and ™©
and ™¥
œ -H5ã r
œ .I5Ì
œ -Ë
¨ .
r J
u K
™ <ŒÚœ ô <.=;k­®Ù then U
™ <ŒÚœ ¨¿ ¬{Ù ;
and U
r
u
r
r
u
u
if ™pL
and
and
œ - r 0
§ ™7M
œ 5ïÙ
™7u M
œ u
r
r5 Ù ,
§ 9- ; and U
™ 'ŒÚœÙ §ÝÙ 9- ; .
then 9- ;kN
r
u
if r ™äœŸu ‰ -O5 Ù
and ™äP
œ -O5 Ù
then U
™ <Œœ
Ù §ÂÙ 9-: ; .
Proof: By structural induction on the derivation tree; along the
process,
we need to use the following two lemmas.
Q
r
Lemma y 4.4 Given a TMC context ™ , suppose ™äœ‰ R
r
ÁºÂQ¡… à ‰ S , then
if
if
if
if
r
Module expression and declaration:
r
u
r
u
u
™›A…vœFthen ™6›A…>œ£ÁWT%- V6§0- .
r
u
r
u
u
™›A…v œ .
7
then 6
™ ›Y…vœ£ÁWT9. V§:. .
r
r
™›A…v œ “ then ™6A› …>¤
œÚÁWTU“iV§“ .
r
u
r
u
then ™6›A…>™›A…v œ ‰ A¤
œ¤ÁWTU‰ VÈ- .
mtyp
Š
…i†ˆY„M r'…‘
‹ ˆ" v‹ TN„WV
„ˆQ'Š << Š*ŒiS(ˆ¡\…i†{- ‰Ž‹ ˆ<‰pTN„iV
T@>9
Í ‰úˆ<‰pZ Ùv[aˆ*)Uv9
¿Ù
‰Ýlet Š in ‰
… † ‘‰úˆ#! † ‘“˜ˆ<” † ‘•
ˆ
ˆ
) ) -
) U
mtfd
Ù
mcon
mcfd
mknd
mkfd
Comparison with the stamp-based semantics
+
) Û
) ) ) Ü
$
r ‹
‹
Q U
V
<' U Œ S(ˆ … † -Ý Wi>9
Í -*v9
… † - ˆ#! † ˜“1ˆ<” † H“
ˆ
ˆ
r'‹
‹
ˆ" t TN„WV"ˆQ¡Û r u << یiS(ˆ¡g¸…T9Ù(V
\v9
Ùڈ¡Ù Z Ù [
!q˜r “¦‹ ˆ<…b
r y
u
‹ Ù
QÜ
<# Ü Œ S(ˆ'
!P9Rªˆ<…v9
Core language:
“
ctyp
cexp
•
) ) ! † ˆY„M !"ˆ¡g‚!#T9Ù(V"ˆ<<
”†ˆY„a ”—ˆ<<
Elaboration context:
ctxt
functor G1(X: SIG) = X
functor G2(X: SIG) = struct abstype t = A
with val x = A
end
end
™
) ®š(ˆ'™›SUƈ'™6›Yv9
Figure 19: Syntax of the kernel module calculus KMC
as universal quantification
(W ), existential quantification ( ), de$
pendent product ( ), and transparent record ( Qq€ S ) to model higherorder modules. The syntax of KMC is given in Figure 19. The
static semantics for KMC is summarized in Figure 20. The complete typing rules are given in Figure 21 and in Appendix E. The
EMC-to-KMC translation is summarized in Figure 22 and its complete definition is given in Appendix F.
Both applications are legal under the stamp-based semantics: applying APPS to G1 results in a module whose t component is
equal to int while applying APPS to G2 creates a module whose
t component is a new abstract type. Under our scheme, the transparent version of APPS cannot be applied to G2; the abstract version works for both but it does not propagate sharing when applied
to G1. We believe this lack of expressiveness is not a problem in
practice.
Like other module calculi KMC supports a form of simple module that consists of an ordered list of type, module, and value
declarations—in KMC we use a record syntax ( Qq€ S ) rather than
str << end to represent such simple module. Following AMC
and EMC, we assume that each declaration in KMC simultaneously defines an internal name (e.g., ¹ ) and external
r ‹
‹ label (e.g.,
a
module
record
… , ! , ” ). r'Given
ß
‰
Ì
'
Q
Š
<
<
Š Œ S (or type
‹
‹
VQ U
<' UºŒiS , declarations (or specifications) defined later
can refer to those defined earlier using the internal names.
Implementation
A module system will not be practical if it cannot be type-checked
and compiled efficiently. Our EMC calculus can be checked efficiently following the typing rules given in Section 3.2; the only
nontrivial aspect of the elaboration is on how to efficiently test the
equivalence between two arbitrary EMC types; we plan to use the
realization-based approach used in the SML/NJ compiler [36] to
propagate type definitions.
The type structure of KMC resembles a typical predicative
polymorphic -calculus. The constructor calculus of KMC is almost identical to that of EMC. Module kind (mknd) characterizes module constructor (mcon) Ù ; module type (mtyp) - models module expressions (mexp) ‰ . An elaboration context ™ for
KMC contains bindings for core variables (” ), core type variables
(! ), module variables (… ), and module type variables ( ).
EMC is also compatible with the standard type-directed compilation techniques [18, 15, 35,36].
Most of these techniques
-like polymorphic lambda calare developed in the context of
culi [11, 33]. In this section, we define a Kernel Module Calculus
(KMC) and show how
to translate EMC into KMC and then translate KMC into an -like Target Calculus (FTC).
5.1
) ) Module type and constructor:
Compilers for the strong-sum-based calculus [26, 36] use stamps
to support type generativity and abstract types (TMC did not include these features). There are still higher-order module programs
that are supported by the stamp-based semantics but not by our
type-theoretic semantics. Take the higher-order functor APPS in
Section 2.1 as an example and consider applying it to the following
functors:
5
‰
mdec
Lemma 4.5 Given a TMC context ™ , a TMC module type - , an
EMC constructor Ù , and an EMC kind , if 4™6›A…(S-:'ŒŸœäÙ¢
is valid in EMC, then 4™'ŒªœÚÙ£
is valid in EMC as well.
4.3
„
path
mexp
, let
Opaque modules are modeled with existential types [30] and
dot notation [5, 4]. Given a module path „ of type ¸<
- , we
use " t TN„WV to denote „ ’s constructor component (which should have
kind ), and " v TN„WV to denote the module component (which should
have type Z " t TN„iVA¬\3[ - ). To construct an‹ opaque+ module, we use
the module expression of form )U>9
Ù ‰Ý where constructor Ù must be of kind , module ‰ must have type Z Ù&¬P([ - , and
the resulting module has type *v9
- .
The kernel module calculus KMC
Unlike EMC which is based on the ML syntax, the Kernel Module Calculus (KMC) uses only well-known typing constructs such
12
œ™Ÿž¡ »… † ™Ÿœ¤…i†A™¢œB"
™Ÿœ¿„QXU
¼Í™
™¾œ¿„>9
y
" t TN„WVƒS*T%-ÂV
v TN„WV@qQ¡ Ã
r
‹
<# U—À … † -
™¾œ7-
™6›ZU
y
y
‹
ÁºÂQ'! †Mà M
„ ! … †aÃ
™Ÿœ„a … ÁWT%-ÚV
<<NS
™ ›Y…i†{6
œ£‰¥A- $
™¢œ\…i†{- ‰¥ …i†{-Ý -
$
™Ÿœ£‰¥ …i†{-Ý - y
™¢œ£‰pTN„WV"*Q¡…i† Ã
™Ÿœ£‰¥A™¢œ¾TU… † ˜‰ÍV"‡TU… † -ÚV
™¢œ£“
™¢œ¾T4! † ‘
“‡V6‡T4! † ‘“iV
Figure 21: Selected typing rules for KMC: ÎÝϽÐ
œ ™Ÿž¡ ¤
™Ÿœ£“
™Ÿœ¤•(“
™ŸœÙ¤q
™Ÿœ¤Û¤qÜ
™Ÿ7
œ ™Ÿ/
œ U
™Ÿœ£‰¥
™Ÿœ£Š1*
U
ctyp equivalence
mcon equivalence
mcfd equivalence
mtyp equivalence
mtfd equivalence
™Ÿœ£“1§“ ™ŸœÙ§ÝÙ ™Ÿœ¤Û§ÝÛ qÜ
™Ÿ7
œ -ï0
§ - ™Ÿ/
œ U¢:
§ U—
ÙJS
y
™¢œÙ¤q
ÁºÂQ¡ à ÙJS
‹
™ŸœN)Uv9
¿Ù Ý
‰ -
‹
‹Aµ
r
'› <<<›SU À É
œ Š À U À Ê £´ <<
¤
r'‹
‹
'r ‹
‹
™ŸœŸQ¡Š < < *
Š Œ‡SJQXU
# ' UºŒ‡S
ctxt formation
ctyp formation
cexp formation
mcon formation
mcfd formation
mtyp formation
mtfd formation
mexp formation
mdec formation
™Ÿœ„„_SqT%- V
y
r
™¢œ£Š1*U
™6›SU‰¥A™¢œ let Š in ‰¥-
r
‹
„M …¢ˆ"! † … † ¼Ä ±Å T9U << U—ÀVƒS
™¾œ£‰¥VWi>9
Í ™¢œÙ¤
ÁºÚQ' Ã
™¢œ£‰DZ Ùv[MÁWT%-ÂV
™6›A>9
㜤‰Ž™¾œBT"v9
‰¥Y W‡v9
œ ™¢ž' ¤
™¾œÇQ{S‚Q{S
‹
0Y[
+
™Ÿœ¤‰¥{ÁWT%-ÂV
**v9
-
™Ÿœ•J{“
™ŸœÆTU” † ‘•{V"\TU” † H“‡V
0V\
and ÎÝÏ¿Ò
ctxt-to-ctxt translation
ctyp-to-ctyp translation
cexp-to-cexp translation
mcfd-to-mcfd translation
mcon-to-mcon translation
path-to-path translation
sig-to-mtyp translation
isig-to-mtyp translation
mexp-to-mexp translation
mexp coercion translation
U™^
4“ ^
U•^
UÛE ^
HÙ_ ^
y
yÃ
yÃ
“
™
Ãy •
Ãy Û
yà Ù
„,^ Ã
y „
H` Ã
y H^ Ã
™¾œ£‰Ž*a5¶‰ ™¾œ ô M<b
„ 5î‰
Figure 22: Translation from EMC to KMC: a summary
Figure 20: Static semantics for KMC: a summary
Proof: Expand this theorem to cover module declarations and core
language expressions; the generalized version of this theorem can
be proved by structural induction on the derivation tree.
KMC supports two forms of parameterized modules: one abstracted over module values (of type - ); another over module
constructors (of kind $ ). A module function \… † Y- ‰ has the
dependent product type …i†]-Ý - . Dependent product is necessary because we use dot notation to access opaque modules so the
return type of a function might refer to the actual argument. Dot notation [4] also requires that functions in KMC be applied to module
access paths only, as in ‰pTN„WV . This is not a problem because we
can always use let to introduce local declarations.
The translation from EMC to KMC is quite simple. Figure 22
summarizes the main translation rules; the actual definition is given
in Appendix F. Here, h€ ^ maps EMC contexts, core types, core
expressions, module constructors, module constructor fields, and
^ translates an EMC
access paths into their KMC counterparts; H
signature into a KMC module type - ; H
` translates an instantiated signature in EMC into a KMC module type - ; the judgement ™¤œÝ‰¥4
5¶‰ translates an EMC module expression ‰
of signature into a KMC expression ‰ . We also use the judge„ 5 ‰ to coerce a KMC path „ with type
ment ™©œ’ ô {
H
^ into a KMC expression ‰ with type H ^ , assuming and
are both instantiated signatures in EMC. We prove the following
type preservation theorem for the EMC-to-KMC translation:
Polymorphic modules in KMC are parameterized over module
constructors. A module expression T"Bq
Í ‰ has the quantified
type W‡v9
- . It can be applied to constructor Ù if Ù has kind ,
the result has type Z Ù&¬¡\3[ - .
Theorem 5.2 Given an EMC context ™ , we have
Typing module identifier and functor application in KMC (see
Figure 21) is much simpler than those in AMC and EMC. First,
there is no implicit “strengthening” when we access a module identifier. Second, KMC does not have any form of subtyping: to type
a functor application, we must make sure that the type of the actual
argument is exactly same as that of the functor’s formal argument.
if œŽ™úž¡ is a valid EMC deduction then œcU™ Œ
valid in KMC as well; similarly,
if ™Ÿœ¤“ then 4™ ^ œ4“ ^ ;
™ ^ œ U• ^ 4
“ ^;
if ™Ÿœ•J{“ then U
™ ^ œ U_
Ù ^ U
^ ;
if ™ŸœÇÙ¤
then U
if ™ŸœÛÜ then U
™ ^ œ 4E
Û ^ 4b
Ü ^ ;
Theorem 5.1 (unique typing) Given a KMC context ™ suppose ‰
is a KMC module expression, - and - are KMC module types,
if ™¾œ£‰¥
and ™Ÿœ£‰¥A- then ™Ÿœ-¶§0- .
-
13
if ™Ÿœ– ù then U ™
^
œ4– ù
^
if ™ŸœÇù then U ™^DœHù^ ;
;
ž¡ is
into concrete ones; this makes it hard to reason about type-directed
operations on values with abstract types. The translation given in
this paper rightly maps all opaque modules into abstract types, so
two different types in the source calculus would not be considered
as equivalent in the target calculus.
r y
u
r
r'‹
‹
Rˆ'
ˆQVe 9
r u <# eOŒÈ9
¦Œ‡S
Ù
<'r ˆ<‘r<ˆ¡‹ \v9‹ Ù£ˆ¡Ù Z Ù [
ˆ
Q e 3Ù
X
<<r emŒbr#3‹ ÙȌ\S(‹ ˆ¡gfehT9Ù(V@ˆ" t TN„WV
type X << emŒÈ -pŒiS
$g1T9Ù(V"ˆXQ e ˆ
…v -Ý - hˆ Wi>9
Í - ˆ¡>9
path „
X …‘ˆA„M eaˆ " vr TN„WV r<‹
‹
‰
X <'ˆY„‘ˆVQ e ‘‰
<# eOŒ6‘‰Œ‡S
exp
ˆ
\…> -Ý ‰úˆ<‹ ‰pTN„WV+ˆ T@>9
Í ‰Žˆ<‰prZ Ùv[
u
ˆ
)U>9
Ù
‰Ý ˆ let …˜‰
in ‰
ctxt
™
X šJˆ'™›A…v -ïˆ'™›Av9
Figure 23: Syntax of the -based target calculus FTC
d
kind
con
X X context formation
constructor formation
type formation
exp formation
constructor equivalence
type equivalence
6 Related Work
Module systems have been an active research area in the past
decade. The ML module system was first proposed by MacQueen [24] and later incorporated into Standard ML [27]. Harper
and Mitchell [13] show that the SML’90 module language can
be translated into a typed lambda calculus (XML) with dependent types. Together with Moggi, they later show that even in
the presence of dependent types, type-checking of XML is still decidable [14], thanks to the phase-distinction property of ML-style
modules. The SML’90 module language, however, contains several major problems; for example, type abbreviations are not allowed in signatures, opaque signature matching is not supported,
and modules are first-order only. These problems were heavily
researched [12, 19, 20, 23, 38, 26, 17] and mostly resolved in
SML’97 [28]. The main remaining issue is to design a higher-order
module calculus that satisfies all of the properties mentioned in the
beginning of this paper (see Section 1.2).
œ™Ÿž¡ ™¢œÙ¤X
™¢7
œ ™¢œ£‰¥
™¢œÙ§ÂÙ&_)q
™¢7
œ -ï0
§ - Figure 24: Static semantics for FTC: a summary
if
if
if
if
if
if
Supporting higher-order functors with fully syntactic signatures
turns out to be a very hard problem. In addition to the work discussed at the beginning of Section 1.2, Biswas [2] gives a semantics for the MacQueen-Tofte modules based on simple polymorphic types. His formulation differs from the phase-splitting semantics [14, 36] in that he does not treat functors as higher-order type
constructors. As a result, his scheme requires encoding certain type
components of kind R using higher-order types—this significantly
complicates the type-checking algorithm. Russo [34]’s recent work
is an extension of Biswas’s semantics to support opaque modules;
he uses the existentials to model type generativity, but his typechecking algorithm still relies on the use of higher-order matching
as in Biswas [2].
™¢œ then U™ ^ œ U` ;
™¢œ¿„* then U™ ^ œ „, ^ H ^ ;
™¢œ£‰¥qi5î‰ then U™ ^ œ£‰ U` ;
™¢œ£“1§“ then 4™ ^ œ4“ ^ §N4“ ^ ;
™¢œÙݧÚÙ q
then 4™^DœHÙ_^k§NHÙ ^vq
;
™¢œ¤Û§Û qÜ then U
™ ^D
œ UE
Û ^kN
§ UÛ ^&Ü ;
Proof: By structural induction on the derivation tree; along the
process, we need to use the following lemma.
Lemma 5.3 Given an EMC context ™ , suppose and are two
instantiated EMC signatures and „ is a KMC access path, if ™úœ
’¨Þ is valid in EMC, and U™^ޜfH^ is valid in
„ 5 ‰ coerces from „ into ‰ , then
KMC, and ™©œú ô 6
4
™ ^Dœ¤‰a
Hj ^ is valid in KMC.
5.2
The
Our kernel module calculus (KMC) is partly inspired by the
work on parameterized signatures of Mark Jones [17]. Both of our
approaches use higher-order type constructors to propagate sharing
information. However, our notion of signatures differ from his in
that we allow type components inside the module record. In fact,
our module record is a transparent sum and it can contain an ordered list of type, value, and module declarations; parameterized
signatures in Jones [17] only allow value components.
-like target calculus FTC
KMC can then be easily translated into an -like polymorphic calculus by simply dropping all the type components in the KMC
transparent records (after we inline all type definitions of course)
and by merging the module
constructor and the core type expres
sions. The result is an -based Target Calculus (FTC) as defined
in Figure
23. FTC is essentially the standard predicative variant of
the
calculus extended with dot notation (i.e.,$ " t TN„WV and " v TN„WV ),
existential types ( ), and dependent products ( ). Figure 24 and
Appendix G gives the typing rules for FTC. The translation from
KMC to FTC is omitted since it is rather trivial.
7 Conclusions
A long-standing open problem on ML-style module systems is to
design a calculus that supports both fully transparent higher-order
functors and fully syntactic signatures. In his Ph.D. thesis [23,
page 310] Mark Lillibridge made the following assessment on the
difficulty of this problem:
In principle it should be possible to build a system with
a rich enough type system so that both separate compilation and full transparency can be achieved at the same
time. Because separate compilation requires that all information needed for type checking the uses of a functor
be expressible in that functor’s interface, this goal will
require functor interfaces to (optionally) contain an idealized copy of the code for the functor whose behavior
The fact that all the
module languages given in this paper can
-based calculus is important because imbe compiled into an
mediately all important type-based compilation techniques [18, 35,
15, 29, 39] become applicable to these module languages as well.
In a previous paper [36], we presented a type-preserving translation
from the MacQueen-Tofte higher-order modules [25] into an
-based calculus, however, that algorithm turns all abstract types
14
they specify, I expect such a system to be highly complicated and hard to reason about.
[10] L. George. MLRISC: Customizable and reusable code generators.
Technical memorandum, Lucent Bell Laboratories, Murray Hill, NJ,
1997.
This paper shows that fully transparent higher-order functors can
also have simple type-theoretic semantics, so they can be added to
ML-like languages while still supporting true separate compilation.
Our solution only involves a conservative extension over the system
based on translucent sums and manifest types: modules that do
not use transparent higher order functors can still have the same
signature as before.
[11] J. Y. Girard. Interpretation Fonctionnelle et Elimination des Coupures
dans l’Arithmetique d’Ordre Superieur. PhD thesis, University of
Paris VII, 1972.
The new insight on full transparency also improves our understanding about other module constructs. Harper et al [14] and
Shao [36] have given a type-preserving translation
from ML-like
. Their phasemodule languages to polymorphic -calculus
splitting translations, however, do not handle opaque modules
well—abstract types must be made concrete during the translation.
Our new translation rightly turns opaque modules and abstract
types into simple existential types.
[13] R. Harper and J. C. Mitchell. On the type structure of Standard ML.
ACM Trans. on Programming Languages and Systems, 15(2):211–
252, April 1993.
[12] R. Harper and M. Lillibridge. A type-theoretic approach to higherorder modules with sharing. In Twenty-first Annual ACM Symp. on
Principles of Prog. Languages, pages 123–137, New York, Jan 1994.
ACM Press.
[14] R. Harper, J. C. Mitchell, and E. Moggi. Higher-order modules and
the phase distinction. In Seventeenth Annual ACM Symp. on Principles of Prog. Languages, pages 341–344, New York, Jan 1990. ACM
Press.
[15] R. Harper and G. Morrisett. Compiling polymorphism using intensional type analysis. In Twenty-second Annual ACM Symp. on Principles of Prog. Languages, pages 130–141, New York, Jan 1995. ACM
Press.
Higher-order functors and fully syntactic signatures allow us to
accurately express the linking process of ML module programs inside the module language itself. In the future we plan to use the
module calculus presented in this paper to formalize the configuration language used in the SML/NJ Compilation Manager [3]. We
also plan to extend our module calculus to support dynamic linking [22] and mutually recursive compilation units [9, 8].
[16] R. Harper and C. Stone. An interpretation of Standard ML in type
theory. Technical Report CMU–CS–97–147, School of Computer Science, Carnegie Mellon University, Pittsburgh, PA, June 1997.
[17] M. P. Jones. Using parameterized signatures to express modular structure. In Twenty-third Annual ACM Symp. on Principles of Prog. Languages, pages 68–78, New York, Jan 1996. ACM Press.
[18] X. Leroy. Unboxed objects and polymorphic typing. In Nineteenth
Annual ACM Symp. on Principles of Prog. Languages, pages 177–
188, New York, Jan 1992. ACM Press. Longer version available as
INRIA Tech Report.
Acknowledgement
I would like to thank Karl Crary, Robert Harper, Xavier Leroy,
David MacQueen, Claudio Russo, Valery Trifonov, and the ICFP
program committee for their comments and suggestions on an early
version of this paper.
[19] X. Leroy. Manifest types, modules, and separate compilation. In
Twenty-first Annual ACM Symp. on Principles of Prog. Languages,
pages 109–122, New York, Jan 1994. ACM Press.
[20] X. Leroy. Applicative functors and fully transparent higher-order
modules. In Twenty-second Annual ACM Symp. on Principles of Prog.
Languages, pages 142–153, New York, Jan 1995. ACM Press.
References
[1] E. Biagioni, R. Harper, P. Lee, and B. Milnes. Signatures for a network protocol stack: A systems application of Standard ML. In 1994
ACM Conference on Lisp and Functional Programming, pages 55–64,
New York, June 1994. ACM Press.
[21] X. Leroy. A syntactic theory of type generativity and sharing. Journal
of Functional Programming, 6(5):1–32, September 1996.
[22] S. Liang and G. Bracha. Dynamic class loading in the Java virtual
machine. In Proc. ACM SIGPLAN ’98 Conf. on Object-Oriented Programming Systems, Languages, and applications, pages 36–44, New
York, October 1998. ACM Press.
[2] S. K. Biswas. Higher-order functors with transparent signatures. In
Twenty-second Annual ACM Symp. on Principles of Prog. Languages,
pages 154–163, New York, Jan 1995. ACM Press.
[23] M. Lillibridge. Translucent Sums: A Foundation for Higher-Order
Module Systems. PhD thesis, School of Computer Science, Carnegie
Mellon University, Pittsburgh, PA, May 1997. Tech Report CMU-CS97-122.
[3] M. Blume. A compilation manager for SML/NJ. as part of SML/NJ
User’s Guide, 1995.
[4] L. Cardelli and X. Leroy. Abstract types and the dot notation. In Proc.
Programming Concepts and Methods, pages 479–504. North Holland,
1990.
[24] D. MacQueen. Modules for Standard ML. In 1984 ACM Conference
on Lisp and Functional Programming, pages 198–207, New York,
August 1984. ACM Press.
[5] L. Cardelli and D. MacQueen. Persistence and type abstraction. In
M. P. Atkinson, P. Buneman, and R. Morrison, editors, Data Types
and Persistence, pages 31–41. Springer-Verlag, 1988.
[25] D. MacQueen. Using dependent types to express modular structure.
In Proc. 13th Annual ACM SIGPLAN-SIGACT Symp. on Principles of
Programming Languages, pages 277–286. ACM Press, 1986.
[6] S. Corrico, B. Ewbank, T. Griffin, J. Meale, and H. Trickey. A tool
for developing safe and efficient database transactions. In 15th International Switching Symposium of the World Telecommunications
Congress, pages 173–177, April 1995.
[26] D. MacQueen and M. Tofte. A semantics for higher order functors.
In The 5th European Symposium on Programming, pages 409–423,
Berlin, April 1994. Spinger-Verlag.
[7] J. Courant. An applicative module calculus. In M. Bidoit and
M. Dauchet, editors, TAPSOFT’97: Theory and Practice of Software Development: LNCS Vol 1214, pages 622–636, New York, 1997.
Springer-Verlag.
[27] R. Milner, M. Tofte, and R. Harper. The Definition of Standard ML.
MIT Press, Cambridge, Massachusetts, 1990.
[28] R. Milner, M. Tofte, R. Harper, and D. MacQueen. The Definition of
Standard ML (Revised). MIT Press, Cambridge, Massachusetts, 1997.
[8] K. Crary, R. Harper, and S. Puri. What is a recursive module? In Proc.
SIGPLAN ’99 Symp. on Prog. Language Design and Implementation,
page (to appear). ACM Press, May 1999.
[29] Y. Minamide, G. Morrisett, and R. Harper. Typed closure conversion.
In Proc. 23rd Annual ACM SIGPLAN-SIGACT Symp. on Principles
of Programming Languages, pages 271–283, New York, 1996. ACM
Press.
[9] M. Flatt and M. Felleisen. Units: Cool modules for HOT languages.
In Proc. ACM SIGPLAN ’98 Conf. on Prog. Lang. Design and Implementation, pages 236–248. ACM Press, 1998.
15
A.4
[30] k J. Mitchell and G. Plotkin. Abstract types have existential type. In
Proc. 11th Annual ACM SIGPLAN-SIGACT Symp. on Principles of
Programming Languages, New York, 1984. ACM Press.
[31] G. Nelson, editor. Systems programming with Modula-3. Prentice
Hall, Englewood Cliffs, NJ, 1991.
[32] J. H. Reppy and E. R. Gansner. The eXene library manual. SML/NJ
documentations, March 1991.
[33] J. C. Reynolds. Towards a theory of type structure. In Proceedings,
Colloque sur la Programmation, Lecture Notes in Computer Science,
volume 19, pages 408–425. Springer-Verlag, Berlin, 1974.
[34] C. V. Russo. Types For Modules. PhD thesis, University of Edinburgh,
Edinburgh, UK, June 1998.
[35] Z. Shao. Flexible representation analysis. In Proc. 1997 ACM
SIGPLAN International Conference on Functional Programming
(ICFP’97), pages 85–98, New York, June 1997. ACM Press.
[36] Z. Shao. Typed cross-module compilation. In Proc. 1998 ACM
SIGPLAN International Conference on Functional Programming
(ICFP’98), pages 141–152. ACM Press, September 1998.
[37] B. Stroustrup, editor. The C++ Programming Languages, Third Edition. Addison Wesley, Reading, MA, 1998.
[38] M. Tofte. Principal signatures for high-order ML functors. In Nineteenth Annual ACM Symp. on Principles of Prog. Languages, pages
189–199, New York, Jan 1992. ACM Press.
[39] A. Tolmach. Tag-free garbage collection using explicit type parameters. In Proc. 1994 ACM Conf. on Lisp and Functional Programming,
pages 1–11, New York, June 1994. ACM Press.
A
™6›ƒ–
r
‹
‹Aµ
r
›'<<<›A– ÀÉ
œ – ÀËÊ £

´ <'
r ‹
‹
™¢œ sig –
< ' РΠend
(8)
A.5
(9)
spec formation: ™Ÿœ¤–
™Ÿœ
…i†>¼m
¬ lžYnTH™V
™Ÿœ… † 3
(10)
œ¤™Ÿž¡ »! † ¼o
¬ lžYnÍTH™MV
™ŸœÚ!A†
(11)
™Ÿœ“»!A†>¼m
¬ lžYnÍTH™V
™¢œÚ!A†'˜“
(12)
™Ÿœ£“
™Ÿœ£”{†H“
(13)
Static Semantics for AMC
A.6
œ£š½ž¡ (1)
™¢œ¤–
œ¤™›w–Ìž¡ (2)
ctyp formation: ™¾œ£“
™¢œ¿„*
‹
‹
‹ ‹
(ÍQ<< ! † ‘“ '< S ±{² Q'< ! † ' < S
™¢œ¿„M !
r ‹
‹
‹
‹
™ œ¿
¢
<< – À ‹'# – Œ end%
y „ sig
‹ –y
ÁºÚQ<!A† à % „M ! …irX† ‹ à ‹ „M …¾r ˆ@!Y† …i†¼Ä ±{Å T ƒV S
ÔÕ‡Ö – À ”{†H“
kì õ#²ƒõ
– <# – ÀÉ
œ¤™¢ž¡ °!A†¡‘“˜¼Í™
™¾œÚ!Y†M§“
(14)
r ‹
‹
‹
‹
™ œ
¢
<< – À ‹'< – Œ end%
y „ sig
‹ –y
ÁºÂQ'!Y† % à „M ! rN…i‹ † à ‹ „a …¢ˆ@!A† …‡†¼Ä ±Å T VƒS
r
Ô{Õ\Ö – À ¤T4!Y† ˜“iV
kì õ-²ƒõ
– '< – ÀÉ
™Ÿœ¿„M !Yi§ÁWTU“‡V
(15)
Static Semantics for EMC
This appendix gives the rest of the typing rules for the external
module calculus EMC. The formation rules for module constructors ( ™œ¤Ù£
), and module constructor fields ( ™œÚÛ¤qÜ ) are
given in Figure 9 in Section 3.2. The formation rules for module
expressions ( ™¥œ’‰+‡ ) and module declarations ( ™©œäŠÍ‡– )
are given in Figure 12 in Section 3.2. The subsumption rules for
signatures ( ™¥œŽ¨£ ) and specifications ( ™¥œä–,¨Ú– ) are
given in Figure 13 in Section 3.2.
(3)
(4)
cexp formation: ™Ÿœ•(“
œ™Ÿž¡ »”{†H“¼™
™Ÿœ¤” † “
ctyp equivalence: ™¾œ£“1§“ Rules for congruence, reflexivity, symmetry, and transitivity are
omitted.
ctxt formation: œ¤™¢ž¡ œ¤™¢ž¡ ø! † ¼ ™ ±² ! † ˜“‘¼Í™
™¢œ£!Y†
A.3
(7)
™ œ
¢
™6›A…‡†3Ɯ ™Ÿœ fsig TU…i†{3V)˜ B
A.2
œ¤™¢ž¡ sig end
™Ÿœ
This appendix gives the rest of the typing rules for the abstract
module calculus AMC. The formation rules for module expressions
( ™îœ+‰ï ) and module declarations ( ™îœ+Š½– ) are given
in Figure 5 in Section 3.1. The subsumption rules for signatures
( ™+œ Ú¨Ÿ ), and specifications ( ™ œÞ–î¨Ç– ) are given in
Figure 6 in Section 3.1.
A.1
sig formation: ™¢œ
B.1
(5)
(6)
™¾œ¿„a ”¦{ÁWTU“iV
16
ctxt formation: œ™Ÿž¡ œ£š½ž' (16)
™ŸœÇ–
œ¤™6›A–ãž¡ (17)
œ¤™Ÿž¡ ßz¼o
¬ lžYnÍTH™MV
œ¤™›ƒv9
ãž' (18)
a¬{Ùæê)ë Ô ëAì ±²Aí ì ÔՇÖ
component. To make this work, we need revise the EMC signaturestrengthening operation so that all references to … † are substituted
by equivalent constructors that have no such references. The new
routine is shown in Figure 25 where a¬{Ù is now implemented as
_¬T9Ù¢PàaáMâ@T9VAV-S› p with p denoting the identity substitution. The
auxiliary procedures _¬T9ِ'
åV-›YÁå­ means that instantiating
by constructor Ù of kind under substitution Á yields signature
, and –˜¬T9Ùzw
åV-›YÁ­ –U›YÁ* means that strengthening specification – by constructor Ù of kind under substitution Á yields
specification – and new substitution Á .
±{¯ _¬T9Ù£qà_áâ@T9VAV-›Sp
r
‹
Y‹ µ
Á Ø ¿Á»– « ¬T9ÙB9
åV-›YÁ «'É ­®– « ›AÁ « ³ ¤
´ <<
r
r
T sig – #<ƒ– Œ end VA¬T9ÙÍ9
åV-›AÁ¸­ sig – <#ƒ– Œ end
T fsig TU…i†36V*X1 VA¬T9ÙÍ9
åV-›AÁ¸­
fsig TU…i†36V*X1 y
Ý
Ž
¬*T9ÙºZ … † ['9
V-›YÁº­® T fsig TU… † 3V3 AV ¬T9ÙÍ9
åV-›AÁ¸­ fsig TU… † 3V)˜ y
a¬*T9g¸…T9Ù(V9
åV-›3Á—­®æÁ*W¿Á_qÍQ …i† à g¸…T9Ù(VƒS
‹
‹
TU…i†36VA¬*T9ÙBhQq#< …v9
<< S{V-›AÁº­îTU…‡†{3 V-›YÁ ‹
‹
T4!A†HVA¬*T9ÙBhQq'< P
! 9R << S{V-›AÁº­îT4!Y†'g‚!#T9Ù(VAV-›hÁ
T4!A†¡˜“iVA¬T9Ù9
åV-›YÁº­îT4!Y†¡˜ÁWTU“iVAV-›9Á
TU” † H“iVA¬*T9Ùå9
åV-›YÁº­îTU” † UÁWTU“iVAV-›3Á
B.5
™Ÿœ
™›A… † q
䜝 ™Ÿœ fsig TU… † 3 6V@q (26)
™ œ
Ÿ
™›A… † q䜝 ™Ÿœ fsig TU… † 3 6V@) (27)
spec formation: ™Ÿœ¤–
Figure 25: Signature strengthening in EMC (revised)
… † ¼m
¬ lžYnTH™V
™Ÿœ…‡†{3
(28)
(19)
œ¤™Ÿž¡ »!Y†>¼o
¬ lžYnÍTH™MV
™ŸœÚ! †
(29)
(30)
(20)
™Ÿœ“»! † ¼m
¬ lžYnÍTH™V
™¢œÚ!A†'˜“
™Ÿœ£“
™Ÿœ£”{†H“
(31)
™Ÿœ
B.2
ctyp formation: ™¾œ£“
œ¤™¢ž¡ ø!Y†¼™ ±² !A†'˜“‘¼Í™
™¢œ£! †
™¢œ¿„*
‹
‹
‹ ‹
(ÍQ<< ! † ‘“ '< S ±{² Q'< ! † ' < S
™¢œ¿„M !
™¢œÙ¤
‹
‹
ÍQq#< 
! 9R <<NS
™¢œg‚!#T9Ù(V
(21)
B.6
B.3
cexp formation: ™Ÿœ•(“
Rules for congruence, reflexivity, symmetry, and transitivity are
omitted.
œ™Ÿž¡ »”{†H“¼™
™Ÿœ¤” † “
r<‹
‹
‹
(22)
œ¤™¢ž¡ °!A†¡‘“˜¼Í™
™¾œÚ! † §“
‹
™¢œ¿
<< – À ‹'# —
РΠend%
y „ sig
‹ –y
ÁºÚQ<! †Mà % „M ! … rX†M‹ à ‹ „M …¾r ˆ@! † … † ¼Ä ±{Å T VƒS
ÔÕ‡Ö – À 
kì õ#²ƒõ
– <# – ÀÉ
”{†H“
™¾œ¿„a ”¦{ÁWTU“iV
B.4
r'‹
‹
‹
™ œ
¢
<< – À ‹'<
y „ sig
‹ –y
ÁºÂQ'! †Ã % „M ! … r †aà „a …¢ˆ@! † … †
‹ ‹
r
Ô{Õ\Ö
kì õ-²ƒõ
– '< – ÀÉ
™Ÿœ¿„M ! §ÁWTU“‡V
(23)
sig formation: ™¢œ
œ¤™Ÿž¡ ™ œ sig end
¢
r
r ±Å TH– <#wr – ÀÉ
™6›ƒ– ›<<<'›ƒ– À É
œ¤–
r<‹
™¢œ sig –
Wi…i†¼‘Ä
ctyp equivalence: ™¾œ£“1§“ r ‹
V …i†\ê)ë Õ ±{í¯m²ƒ‹ õ<õ ê Õ ‹Yµ – À
´ <<
À
Ê ¤
‹
<< –—Œ end
(32)
‹
–—Œ end%
¼Ä ±Å T ƒV S
– À ¿! † ˜“
‹
‹
™ŸœÙÚ§ÂQ<' !‘“ << S
™Ÿœg‚!#T9Ù(V§“
(24)
B.7
(33)
(34)
mcon equivalence: ™ŸœÇÙݧÝÙ q
Rules for congruence, reflexivity, symmetry, and transitivity are
omitted.
(25)
The side condition on – À in this rule is not absolutely necessary.
If we remove this requirement, we essentially allow free flexroot
references such as … † even when … † is a locally declared structure
y
Á—ÂQ' Ã
17
Ù S˙¢œÇÙ ™6›Yv9

œ Ù¤
™¢œ¾T9\>9
Ù(V#Z Ù [i§ÁWT9Ù(V"q
(35)
™ŸœÙ
™Ÿœ¾T9\v9
ÙºZ \[OV"§ÝÙ¤
y
‹
‹
‹
‹
™ŸœÇÙ§ÂQ'< …ÈÙ <<NSJQ'< …>9
<< S
™Ÿœg¸…T9Ù(V§ÝÙ r ‹
‹
ÂQÜ
ú
#< Ü Œ S
™ŸœŸ‹ Ù£‹A
µ
‹
™¢œ¤Û‡«û§¤T9e<gfe3T9Ù(VAV"qÜ>«
³ £´ '< ›ZeW… !-›
r ‹
‹
™¢œÇQÛ
<< Û Œ Sû§ÝÙ£q
C.3
(36)
(37)
ctme formation: ™Ÿœ¤‰a-
œ¤™¢ž' ߅v%.z¼Í™w.@¬¡…‘­8™Ÿœ…‘A-
(46)
œ™¢ž¡ ø…v-ï¼Í™
™Ÿœ…‘A-
(47)
™Ÿœ¤• {“
™¢œ/# $ TH• V@ V TU“iV
(48)
™Ÿœ£“
™¢œ/#&wTU“iV@ EQ TU“iV
(49)
r
u
™Ÿœ£‰ @…v- r
r
™¢œB" UT ‰mVÈ-
(50)
(38)
mcfd equivalence: ™¢œ¤ÛÚ§Û Ü
B.8
Rules for congruence, reflexivity, symmetry, and transitivity are
omitted.
mknd subsumption: œ¤
Þ¨ª
B.9
Rules for reflexivity and transitivity are omitted.
y
‹ ‹
‹ ‹Yµ
*Q´ '' ‰åS à Qq´ '#‹ œ¤Ü6sRt « u ¨ªÜ « £
´ #<
³
r<‹
‹
‹
r ‹
œ¢Q¡Ü
<' ܂Œ\S‚¨QÜ #'
r
S‹
‰
(39)
Ü × S
r
u
r
u
œ¤
¿
¨ œÇ
¨ ª
y
r y
u
r
u
ς
¨ ª
B.10
y
r
u
™¢œ£‰ *@…>- Á ÂQ¡… Ã
º
u
u
™ŸœB" UT ‰ V@
ÁWT%- V
™›ƒ…v% .䜤‰‘aA$
™ŸœŸ\…>%.k ‰ …v%.b r
u
r
r $
u
™Ÿœ‰ r v
… %. r ™¢œ£
y ‰ u
™Ÿœ7¨ .
x
Á¸ÂQ¡… à ‰ S
u
r
u
™Ÿœ£‰ TU‰ @
V ÁWT%- V
(41)
r
™¾œ£‰ *
-
C.2
C.4
u
r
u
u
™ œFŸ
™›ƒ…vœ£‰ *
u
r
u
let …b‘‰ in ‰ A-
(51)
(52)
œ£š½ž¡ (42)
™¢œ7…z¼o
¬ lžYnÍTH™MV
œ¤™6›A…>ž¡ (43)
™¢œ/.
…z¼o
¬ lžYnÍTH™MV
œ¤™6›A…>%.䞡 (44)
C.5
mtyp formation: ™ŸœF-
Rules for module types of form -
ctyp formation: ™¾œ£“
(45)
18
(53)
(54)
(55)
ctce formation: ™Ÿœ•¡_“
™¢œ£‰ V TU“iV
™¾œB"v$*TU‰ V@
“
ctxt formation: œ¤™¢ž¡ ™¾œ£‰ EQ TU“iV
™¢œB"v&wTU‰ V
r
™¢œ
Static Semantics for TMC
This appendix gives the complete typing rules for the transparent
module calculus TMC.
C.1
TU‰ VƒS
(40)
Rules for reflexivity and transitivity are omitted.
C
r
r
r
u
r
u
™¾œ£‰‘ *™ ›A…v
œ¤‰ +
r
u
‹r
u
™¾œP)U…È‘‰ ‰ q@…v- -
mkfd subsumption: œ¤Ü¨¿Ü œ ©¨

œ£…>9
¥¨¿…>9
"
(56)
and ™Ÿœ7.
:
™Ÿœ£“
™¾œ V TU“‡V
(57)
™Ÿœ£“
™Ÿœ EQ TU“iV
(58)
r
u
™ ›A…v
œ F
r
u
™Ÿœ@…>- -
(59)
™ ›A…v%.äœF
$
™¾œ
…v%.b -
y
r
u
™Ÿœ¿„*@…>- ÁºÂQ¡… Ã
u
u
™¾œB" TN„W"
V ÁWT%- V
(60)
Rules for module types of form . :
™Ÿœ¤“
™Ÿœ V TU“iV
™¢œ
C.6
r
u
™ ›A…v%.

œ7.
r u
™ŸœÇ@…v%. .
(63)
r
u
™ ›A…v%.

œ7.
$
r u
™¢œ
…v%. .
(64)
(75)
™Ÿœ£“
™¢œ/# & UT “iV@ EQ TU“iV
(76)
r
r
r
u
u
™¾œ£‰
*™ ›A…v
œ¤‰
wr ‹ u +
r
u
™¾œP)U…È‘‰
‰
q@…v- -
(77)
.7Ý
™›A…v%.Ɯ‰Ž$
™ŸœÇ\…v3 ‰’ …v%.b -
(78)
r $
r
u
u
™¢œ¿„ r v
… %. r ™¢œ¿y „ u ™¢œ7¨ .
1
Á ÂQ¡… à „ S
º
r u
u
™¢œ¿„ TN„ V@{ ÁWT%- V
cexp formation: ™Ÿœ•(“
r
(79)
(65)
™¾œ£‰
r
*-
r
™¢œ
ctsp formation: ™¾œ?'
C.10
(66)
u
r
u
u
™ œFŸ
™›ƒ…vœ£‰
*r
u
u
let …b‘‰
in ‰
A-
ctyp equivalence: ™Ÿœ¤“
r
§“
(80)
u
Rules for congruence, reflexivity, symmetry, and transitivity are
omitted.
sig formation: ™¢œ
™Ÿœ¤‰_ EQ TU“‡V
™ŸœB" & TU‰ V§“
Adding bindings such as “… ” to the context ™ is fine because
each signature is also a module type of form . .
C.11
™ œ/'
Ÿ
™Ÿœ V T('MV
(67)
™¢œ
(68)
TYP
r
§0-
u
and ™ÝœC.
r
§:.
u
C.12
™¾œ
(70)
mexp formation: ™Ÿœ£‰¥-
œ™Ÿž¡ »…>%.½¼™y."¬…˜­8™¢œ£…¼™
r
u
™Ÿœ¿„*@…>- r
r
™¢B
œ " TN„WV@-
mtyp subsumption: ™¢œ7-
¨x.
(69)
u
™›ƒ…v3
ς
$
r u
™¢œ
…v3 œ™Ÿž¡ »…>™¢œ£…-
r
mtyp equivalence: ™ÂœC-
(81)
Rules for congruence, reflexivity, symmetry, and transitivity are
omitted.
r
u
™ ›ƒ…v3

ς
r u
™¢œ@…v3 C.9
(74)
™Ÿœ¤•‚{“
™¢œ/#$*TH•VÈ V TU“iV
(62)
TYP
™¢œ„ EQ TU“iV
™Ÿœ/" & TN„iV
C.8
TN„WVƒS
(61)
™ œ¿„ V TU“‡V
¢
™¾œB" $ TN„WV@{“
C.7
r
"
EQ TU“‡V"¨
TYP
(82)
r
u
™¾œ£“ §“
r
u
™¢œ V TU“ b
V ¨ V TU“ V
(83)
r
r
™¾œ7¨1.
™¢œ@…vr
r
u
u
™6›A…>œ7¨ .
1
u
r u
¨¿@…v%. .
(84)
(71)
r
u
u
™6›Y…v%.
œ7¨ .
1
$
$
r
u
r u
™Ÿœ
…>%. ¨
… %. .
>
(72)
(73)
19
(85)
y
„ 'Œ Ã
D.5 path-to-path translation: ,
. ¬‰‘W­8mtyp strengthening: "
C.13
V TU“‡VA¬‰ ­
V TU“‡V
(86)
("
("
TYP ¬¡‰ ­
.
r
r
r
u
.
…>%.
u
y
(88)
„ 'Œ
<#$TH•V]
u
¬¡‰ UT …WV­8$
r u
r
u
. ¬‰ ­
…v%. -
H\…>3 ‰ r u
„ TN„ ]V 'Œ
r
u
in ‰ Œ
let …È‘‰
y
D.1 ctxt-to-ctxt translation: U ™ Œ¦Ã
The translation of a core type in TMC is based on its formation
rules. Given a well-formed core type “ in context ™ , it is translated
into EMC type “ if and only if the judgement ™ œ,“L5°“ is
valid.
™Ÿœ£‰ -25ïÙ
™Ÿœ7",&wTU‰ v
V 5 g typ T9Ù(V
D.8 mtyp-to-sig translation: ™ŸœF-25
™
Œ š
=
,
„ y
D.3 sig-to-sig translation: H Œ¦Ã
V T('MV]'Œ
TYP Œ
r u
H@…>3
' Œ
$
…>3
r
u
'Œ
=
=
=
=
y
Ã
r
u
-
r
u
u
™›A…vœ75
ï
r
sig fst € 3 u
snd €‚ 3 end
5
r
r
™¢œ/. 5 $
r
u
™Ÿœ
… %. >
5
r
u
u
™›A…v%.
œF5
r
u
V *
fsig T fst€ 3 @
D.9 mtyp-to-sig translation: ™Ÿœ7.5
sig ops † X3''Œ end
sig typ † end
r
sig fst € X H u 'Œ ;
snd €‚ XH Œ
end
r
u
fsig T fst € X H 'ŒPV@
H ' Œ
=
r
5
™ŸœÇ@…v-
Πtyp
D.4 cexp-to-cexp translation: U •'Œ Ã
TN„WV]'Œ
r
™¾œ7-
“
y
(" $
™¾œ£“65î“ EQ TU“iV,5 sig typ† ‘“ end
™Ÿœ
™¾œ7-85 U™6›A…>-0 Œ N
U
™ Œ › fst €3
™Ÿœ
TYP 5
r
r
5ï
™ŸœŸ@…>%.
•
r
.
u
r
r
™¢œ/. 5ï
$
r u
™Ÿœ
… %. .
>
,
„ 'Œi ops
20
™¾œ£“65î“\
V TU“‡V,5 sig ops † H“P end
™¾œ
™¢œ/.
™¾œ£“65î“ V TU“‡V,5 sig ops † H“ end
™¾œ
™¾œ/.5 U™6›A…>%. Œ N
U
™ Œ › fst €3
Œ
=
=
=
D.7 ctyp-to-ctyp translation: ™Ÿœ£“65¶“ Throughout the translation, we use fst and snd to denote
EMC module labels, ops for an EMC value label, and typ for
an EMC type label. A TMC module identifier … is translated to an
EMC identifier fst € where fst is an EMC module label and …
denotes the stamp.
j'<Œ
Œ
This appendix gives the complete translation algorithm from TMC
to EMC; the main translation is denoted by h€ 'Œ ; the auxiliary function that maps from - or . to EMC kind is denoted by 3€ ; ;
the translation from - or . to EMC signature is represented as
™ãz
œ -{5
and ™ |
œ ./5
; the translation from - or
‰ to EMC constructor Ù is represented as ™ c
œ -}5
Ù and
™ œï‰ ~
-5
Ù ; the translation from “ to EMC core type
“ 5î“ .
expression “ is represented by ™Ÿœ¤E
("v&wTN„WV]
<# & (T 'MV]'Œ
u+
‰
Œ
‰
„ 'Œ
str ops† NU• Œ end
str typ† N3''Œ end
r
str fst €J4‰ u Œ ›
4‰ <Œ
snd €‚ N
end
fct T fst €X H
Œ Vƒ4‰ Œ
r
u
„ 'Œ_
T „ 'Œ\V
r
u
let fst€J
O‰ Œ in O ‰ Œ
=
=
=
=
Œ
r ‹
])U…b‘‰
(89)
Translation from TMC to EMC
D.2 ctsp-to-ctyp translation:
fst €
,
„ 'Œ_ fst
,
„ Œ snd
D.6 mexp-to-mexp translation: 4 ‰ Œ—Ã
u
u
4šX
=
=
=
(87)
UT ‰ V6­8.
¬X" TU‰ V­8r u
r
u
@…v%. . ¬¡‰ ­®@…v- -
¬X"
$
D
EQ T<"v&wTU‰ VAV
O,
… Œ
NT „WV]'Œ
u
TN„WV] Œ
r
„
sig typ † end
5
r
u
u
™ ›Y…v%.
6
œ7. 5 r
sig fst € 3 u
snd €‚ 3 end
5
r
u
u
™ ›Y…v%.
6
œ7. 5 r
u
fsig T fst€3 @
V q
D.10
mtyp-to-kind translation:
V TU“iV] ;
EQ TU“iV];
r
u
U@…v- ;
$
…v% .b -0;
=
=
=
=
D.11
V TU“iV];
TYP ;
r u
H@…v%.
. ;
$
r u
…v%.
. ;
D.12
QS
Q typ R>S
r
Q fst 9y
<.=;
=
=
=
=
Ã
‹
;
y
™6›A…>%.䜤‰ A-25 Ù
ÁºÚQ fst € à _S
$
™Ÿœ\…v%.b ‰ …v%.b ->5 \vX<.=;¡ ÁWT9Ù(V
u
snd 9-
<.=;
y
Ã
r
u
r
r $
™¢œ¤‰ >
… %. 5
Ù
™¢œ£
y ‰
r
r
™Ÿ7
œ ¨ .
1
Á ÂQ¡… à ‰
º
u
r
r
u
™¢œ¤‰ TU‰ @
V {ÁWT%- v
V 5ïÙ Z Ù
S
r
™¾œ£‰ A
;
(.
;
S
E
r
r
u
™ŸœF5ïÙ
™6›A…>œ F
5
Ù
r
u
r-‹
u
™Ÿœ@…v- 5ïQ fst Ù
snd Ù S
™6›A…>%.
™¢œ
D.13
r
E.1
ctxt formation: œ™Ÿž¡ œ£š½ž' (90)
™Ÿœ7U
œ¤™6›SU ž¡ (91)
œ¤™Ÿž¡ ßz¼o
¬ lžYnÍTH™MV
œ¤™›ƒv9
ãž' (92)
u
y
Á ÂQ fst € à _S
º
r
u
\vX<. ;¡ ÁW9T Ù V
u
u
œ75ïÙ
$
r
u
…>%. 5
E.2
ctme-to-mcon translation: ™Ÿœ‰ -25ïÙ
ctyp formation: ™Ÿœ¤“
œ¤™¢ž¡ °!A†¡‘“˜¼Í™
™¢œ£!
All TMC module expressions (‰‘ ) embedded inside the core types
can be translated into EMC module constructors. The translation is
based on the formation rules for ‰‘ .
™¢œ¿„A-
-’ÍQq-<
œ¤™Ÿž¡ fst €
™ŸœÇÙ£q
… -ï¼Í™
v
™Ÿœ->5ïÙ
™Ÿœ¤…-25ïÙ
™ œ¤• {“
¢
™Ÿœ7#$*TH• V@ V UT “iV,5
™¾œ/#
&
‹
‹
!Y†'‘“ < < S
™¢œ„M !
œ¤™Ÿž¡ ߅>%.½¼™„."¬…‘­8™¾œ£…-25
E.3
‹
‹
ÍQ#' P

! %… '< S
™ŸœÇg‚!<T9Ù(V
œ¤™¾ž¡ ø”†H“‘¼™
™Ÿœ£” † “
r‹
‹
‹
‹
™ y œ„‹ qQVU y
¢
<< U À ‹'< UºŒiS
%
ÁºÂQ'! †Ã % „M ! … rX†a‹ à ‹ „a …¢r ˆ@! † … † ¼Ä ± Å T VƒS
ÔÕ‡Ö U À {” †H“
kì õ-²ƒõ
U << U ÀÉ
y
r
u
r
™¾œ£‰‘aq@…v- 5ïÙ
Á ÂQ¡… à " TU‰OVƒS
º
u
u
™ŸœB" TU‰ V@ÁWT%- V5 g snd T9Ù(V
™Ÿœ„M ”¦ÁWTU“‡V
™6›A…>u
-
5
(94)
(95)
cexp formation: ™Ÿœ¤•J“
r
u
™ œ£‰a*@…v- Ÿ
5ïÙ
r
r
™¢œB" TU‰ VÈ5ïg fst 9T Ù(V
r
(93)
Q{S
™ œ£“65¶“ ¢
TU“‡V" EQ TU“‡V,5 Q typ ‘“ S
r
r
r
™ œ£‰ A
¢
5ïÙ
r ‹ u +
™¢œP)U…b˜‰
‰
*@
…>-
u
Static Semantics for KMC
QS
r
Ù
u
r
u
u
™ œFŸ
™›ƒ…vœ£‰ *
5
ï
Ù
u
r
u
let …b‘‰ in ‰ A5
Ù
™¢œ£“65¶“ EQ TU“‡Vv5 Q typ ‘“\OS
™¢œ
5
This appendix gives the rest of the typing rules for the kernel module calculus KMC. The formation rules for module expressions
( ™’œŸ‰Þ- ) and module declarations ( ™äœŸŠ‘RU ) are given in
Figure 21 in Section 5.1.
- -shaped TMC module types can be translated into EMC module
constructors. The translation is based on the type formation rules
for - .
V TU“‡V,5
r
u
u
S
u
[
;
mtyp-to-mcon translation: ™ŸœF-25ïÙ
™¾œ
r
™¢œ
QS
Q typ q
R>S
r ‹
u
Q fst <. ; snd (.
y
r
u
<.
;
<-0;
mtyp-to-kind translation:
y
9-:;
r
u
u
u
œ ‰ A
¤
5ïÙ
r ‹
u
snd Ù S
Q fst Ù
21
(96)
(97)
E.4
mcon formation: ™ŸœÇÙ£q
œ¤™¾ž' »v9
©¼™
™Ÿœ£Íq
(98)
™¢œ¿„*>9
™¾B
œ " t TN„WV@
(99)
‹
‹Aµ
™ œ¤Ûi«‚qÜ>« ³ £´ <'
Ÿ
r'‹
‹
r'‹
‹
™ŸœŸQÛ
<< یiS‚qQÜ
<# ÜJŒ‡S
(100)
E.6
œ¤™¢ž¡ °! † ‘
“˜¼Í™
™¾œÚ! † §“
r‹
‹
‹
™ y œ„‹ qQVU y
¢
<< U À ‹'<
ÁºÂQ'! †Ã % „M ! … †aà „a …¢ˆ@! † … †
r‹ ‹
r
Ô{Õ\Ö
kì õ-²ƒõ
U '< U—ÀÉ
(114)
‹
UºŒiS
%
¼ Ä ±Å T VƒS
U—À(¿! † ‘
“
(101)
™Ÿœ¿„M ! §ÁWTU“‡V
™ ›A>9
œÙ£q
6
y
™¢œ\v9
Ù£q
(102)
‹
‹
™ŸœÙÚ§ÂQ<' !‘“ << S
™Ÿœg‚!#T9Ù(V§“
r
y
u
™¢œÙ r u
™ŸœÇÙ Z Ù [a
y
(104)
™¢œÙ¤q
™Ÿœ£…bÙÚ\TU…v9
åV
(105)
Á—ÂQ' Ã
(106)
r
{u ‹
‹
™6›ZU
ςQVU
< < ¸
U ŒiS
r ‹
‹
™¢œÇQVU
<< U ΠS
(107)
™›A…vœ- $
™Ÿœ
…i†-Ý -Ý
(108)
™ ›Av9
œ7
™¢œKW‡v9
-
(109)
™›Av9
œ7™¢œ*v9
-
(110)
E.10
™ œ¤“
Ÿ
™¢œ¤” † H“
y
(117)
(118)
‹
‹
‹
‹
™¢œÙ§ÂQq'< …bÙ #< S‚Qq#' …v9
<#NS
™¾œg‚…T9Ù(V§ÂÙ (119)
r'‹
‹
ŽÂQÜ
<< ÜJŒ‡S
™ŸœÙ¤q
‹ ‹Aµ
™¾œ¤Û « §T9†Mgf†\T9Ù(VAVqÜ «
³ £´ '<
r'‹
‹
™Ÿœ¢Q¡Û
<# ی‡Sû§ÂÙ£
(120)
mcfd equivalence: ™Ÿœ¤Û§ÝÛ qÜ
Rules for congruence, reflexivity, symmetry, and transitivity are
omitted.
E.11
mtyp equivalence: ™Ÿœ7-ï§0-Ý
Rules for congruence, reflexivity, symmetry, and transitivity are
omitted.
mtfd formation: ™¾œ/U
™Ÿœ¤“ß!Y†>¼o
¬ lžYnÍTH™MV
™¾œÚ! † ‘“
Ù S˙¢œÇÙ ™6›Yv9

œ Ù¤
™ œ¾T9\>9
Ù(V#Z Ù [i§ÁWT9Ù(V"q
¢
™¾œÙ¤
™Ÿœ¾T9\v9
ÙºZ P[4V6§Ýٝ
mtyp formation: ™ŸœF-
… † ¼m
¬ lžVnÍTH™V
™Ÿœ£…i†-
(116)
Rules for congruence, reflexivity, symmetry, and transitivity are
omitted.
™ œ¤“
Ÿ
™Ÿœ£!‘“˜\T4!P9RkV
™¾œ7-
(115)
mcon equivalence: ™ŸœÇÙݧÂÙ&aq
E.9
(103)
mcfield formation: ™¾œ¤Û¤Ü
œ¤™Ÿž¡ ™ŸœÇQS
E.7
Rules for congruence, reflexivity, symmetry, and transitivity are
omitted.
‹
‹
™ŸœŸÙ£
ÍQ<< >
… 9
<< S
™¢œg¸…T9Ù(V@
™ŸœŸÙ
E.5
ctyp equivalence: ™¢œ£“1§“\
E.8
™6›‡U
(111)
E.12
(112)
r
r
‹
‹Yµ
<› <#<›SU—À¡É
œ UºÀ(§0U À Ê ¤´ < <
7
r'‹
‹
‹
r ‹
™¢œÇQVU
<< UºŒiSû§ÂQXU— <# U—Œ S
(121)
mtfd equivalence: ™Ÿœ7UŸ§KU Rules for congruence, reflexivity, symmetry, and transitivity are
omitted.
(113)
22
F
9QÛ
Translation from EMC to KMC
This appendix gives a type-preserving translation algorithm from
EMC to KMC. To make the presentation easier, we first modify the
EMC syntax to distinguish different uses of module access paths:
path
mexp
‰
„
) ) ˆ
…i†"+ ˆw„M …
r<‹
)N„
ˆ str Š <<
fct TU… † 3Vh‰úˆY„
TN„X¿V@ˆ let Š
ˆ
‹
Š Œ u end
r *
TN„ V
in ‰
r'‹
‹
<< ÛMŒ‡S ^
Hg¸…T9Ù(V] ^
U\v9
_
Ù ^
r u
HÙ
Z Ù ‰[ ^
U_
Ù ^
…i<† ^
Here, we use )N„ to denote the places where a module path „ is
used as a stand-alone module expression. We then separate the
formation rules for module paths from regular module expressions:
H`
š
=
=
=
=
=
† H“^
U™›A…i†3 ^
U™6›ƒ>9
^
U™›A”
y
Ã
›Y!Y†¡14“ ^
† X 4
“ ^
U™ ^ ›A…‡†X
H
`
U™^›A>9
4”
†
^
„M ”
^
=
=
YTU…bÙ(V] ^
=
=
“
y
Ã
-
= >9àaáMâ"T9V-%Ha¬¡,
^
y
Ã
^
™¢œ¿„q
™¢P
œ )N„
•
y
Ã
Û
^
Ã
y
™¢œ ô à_áâ@T9V­+Ù
¶
NHa¬¡,
+
‹
45|)U>9àaáMâ"T9V1HÙ_ ^ „ ^ ^
y
y
‹
™›A…i†3Ɯ¤‰¥5¶‰‘ Á6QX" t TU…i†9V à " v TU…i†HV Ã
‰ :
T"v9à_áâ@T9V- \…i†{XH_¬ ^ ÁWTU‰ V
T4!14“ ^ V
TU…bˆ
H_
Ù ^ V
F.5 mcon-to-mcon translation: H Ù_
+
Note: according to Lemma 3.1, is an instantiated signature, so
à_áâ@T9V is always an empty kind Q{S and Ù is an empty constructor
QS . we always pack each structure expression this way so that we
can uniformly translate each structure identifier …i† in EMC into
" v TU… † V in KMC.
” †
,
„ ^ ”
^
`
In the following, we use Š&‰‘‰ to denote a KMC module expression “let …i†a‰ in ‰DTU…i†9V ” where …i† is a module identifier
that does not occur free in ‰ .
,
„ ^ !
g‚!#THÙ_ ^ V
F.4 mcfd-to-mcfd translation: U ÛE
YT4!‘“iV] ^
^
The translation from EMC mexp to KMC mexp is conducted along
the EMC typing rules. Given a context ™ , an EMC module expression ‰ is translated into a KMC expression ‰ if and only if
™Ÿœ¤‰¥qi
5¶‰ .
!A†
F.3 cexp-to-cexp translation: U •
and H -
F.8 mexp-to-mexp translation: ™¢œ¤‰¥45î‰
U™^›A”
=
=
=
…
‹
µ
‹
r ‹
r ‹
Š ^ = QvU– ù ^ << 4– Œ ù ^ S
sig – ù << – Œ ù • $
fsig TU…i†3V)˜ ^ = Wiv9à_áâ6T96V- …i†{Ua¬¡, ^ y
y
‹
Q " t TU…i†9V à " v TU…i†9V à …i3† SU X
YTU…i†{3 ù ]
V ^ = TU…i†X H ù ^ V
YT4!A†<‘“i]
V ^ = T4!A†<1
4
“ ^ V
4” † H
“ ^ = TU” † X O
“ ^#V
U™ ^
y
m!A<† ^
„ !]^
M
Hg‚!#T9Ù(V] ^
,
„ ^
™
F.2 ctyp-to-ctyp translation: 4 “^ Ã
" v TU…i†9V
Here the internal translation h € ^ is applied to instantiated signatures only:
The EMC-to-KMC translation is denoted as 3 € ^ . A special auxiliary function that translates EMC signature into KMC existential
module type - is denoted as h€ ` .
4šX ^
„
The translation from EMC signature to KMC module type is defined as:
™ œ„q
¢
+
™¢œN)N„ q
U™6›h!A†¡‘“ ^
=
=
Ã
y
As a result of this reorganization, we add the following rule to the
mexp formation:
^
4…i<† ^
„M …,^
y
^
F.7 sig-to-mtyp translation: H ` Ã
™¾œ¿„
™¾œ£‰¥
F.1 ctxt-to-ctxt translation: 4 ™
Ù
" t TU…i†9V
F.6 path-to-path translation: „ +
path formation
mexp formation
r ‹
‹
Q UÛ ^ <# U یA ^ S
g¸…THÙ_ ^ V
\v9
% HÙ_^
r
u
HÙ
^ %Z UÙ
^ [
=
=
=
=
=
=
™Ÿœ
…i†9S
5
‰ fct TU…i†{3Vh‰¥ fsig TU…i†{3V3 î
r
u
™¾œ¿„ fsig TU…i†{3V3 ™Ÿœ¿„ * ™Ÿœ ¨ u
™Ÿœ wô àaáâ"T96y V­®‹ Ù
y
† Ã
™Ÿœ ô T9_¬Ù(VÈ „ ^5¶‰
ÁºÚQ … †Ã Ù … a
r u
r
™¾œ¿„ TN„ V@ÁWT9 v
V 5‹ŠºT „ ^ Z9HÙ_ ^ [OVh‰
Ù
The case for … † cannot occur since all of their free references have
been replaced by a new constructor variable in KMC.
™Ÿœ
23
œ™¢ž¡ ‹
str end sig end 5|)U>hQSWÍQS QSMhQS
+
„_S
r
r
‹
‹Aµ
<› <<<›w–—ÀÉ r<œ£
‹ ŠÀ¸
‹ –—ÀŒ5¶Š À ›AŠ À ›ƒ– À Ê £´ <<
B sig –
<< мΠend
úà_áâ@T9V
‹
r ‹
sig Р<< РΠend
™ŸœÇ ƒô ú­+
Ù
+
‹ r ‹
‹
‰’/
)Uv9
1UÙ_^ Q'Šq << ŠqŒ SMXH_¬,^
r<‹
‹
r
™Ÿœ str Š #< Š*Œ end *i
5 let Šq <<YŠqŒ in ‰
™6›ƒ–
G
This appendix gives the complete typing rules for the
target calculus FTC.
™ŸœÇ ƒô àaáMâ"T9V"­®Ù
‰ TU‰ŽH_¬Ù_ ^ V
+
‹
™Ÿœ¾TN„)V@*a5|)U>9àaáâ"T96V1
H_
Ù ^ ‰ X H_¬
^
™ œ£Š¦q–F5¶Š ›<€)›'€
¢
™¾œ let Š in ‰Ž*a5
™ ›ƒ–Ìœ£‰¥*a5
6
let Š in ‰ ‰ ™¢œ£‰¥*a5¶‰ … † ‚ ê)ë Õ õ
–’¤TU… † ‚ 3a¬X" t TU…i†9VAV
™Ÿœ¾TU…i†¡˜‰ÍV"PTU…i†3V5 TU…i†'‘‰ V-›<TU… † ‚ 4" v TU…i†HVAV-›A–
™ œ£“
Ÿ
! † ‚ ê)ë Õ õ
™¢œ¾T4!A†¡‘“‡V6‡T4!Y†¡‘“iV5
– ¤T4! † ‚ ‘“‡V
Ž
T4!A†¡ˆ4“ ^ V-'› T4! † ‚ ˜!Y†HV-›ƒ–
(122)
™¾œ7…z¼I
¬ lžYnÍTH™MV
œÇ™›A…vž' (123)
œ¤™Ÿž¡ ßz¼o
¬ lžYnÍTH™MV
œ¤™›ƒv9
ãž' (124)
G.2 constructor formation: ™ŸœÇÙ¤
œ¤™¢ž¡ »v9
©¼™
™¢œ£Í
(125)
™¢œ„>9
Í ™Ÿ/
œ " t TN„iV"q
(126)
F.9 mexp translation with coercion: ™Ýœ¿ ô <„b5î‰ Given two instantiated EMC signatures and , suppose ™ œ
ª¨ , the coercion transformation ™äœ¢ ô ¡„5ï‰ turns
the KMC path „ with type U ^ into a KMC expression ‰ with
type H ^ . Note the deduction rules given below only work when
and are instantiated signatures.
%
To simplify the presentation, we use to represent an ordered
list of EMC specifications; this can either‹ % be an empty list (š ) or a
). Similarly, we use ŠR
specification followed by another list ( –
to represent an ordered list of KMC module fields.
™ŸœÇQVe
™Ÿœ ô <„M …b5¶‰
™ŸœÆTU…i†{3V ô TUi
… †{34VÈ-„b5 TU…i†¡‘‰V
T4! † ¸„a !AV
r
‹
‹Aµ
™¢œÙȆq
¦†,¹£´ < '
r ‹
r
r ‹
‹
‹
3Ù
<' e Œ 3Ù Œ S‚*XQ e 9
< ' e Π9
ΠS
(127)
‹
‹
™¾œÙ¤
+
-ÍQq<# e9
#< S
™Ÿœf
g ehT9Ù(VÈ
(128)
™ ›Av9
̜ŸÙ£

y
™ŸœÇ\v9
Ù¤
(129)
™ŸœÙ
™¢œÆTU” † H“iV ô UT ” † H“ VÈ#„b5 TU” † ¸„a ”V
%
%
#„b5¶ŠR
ô
™Ÿœ
%
%
™¢œ sig end ô sig end <„65 Q'ŠRS
r
y
u
q
™ŸœÇÙ r u
™¢œÙ Z Ù [_q
(130)
G.3 type formation: ™¢œ7-
™Ÿœ£š ô š‚#„b5¶š
%
%
r
r
r
r
ô – <„b5îŠ
ô
-„b5¶ŠR
™¢œ¤–
™ ›ƒ–
6
œ
r<‹ %
r
r ‹%
V@-„b5¶Š ŠR
™Ÿœ¾TH–
V ô TH– %
-based
œ£š½ž' ™Ÿœ¤•J“
” † ‚ )ê ë Õ õ
–úTU” † ‚ H“‡V
™¾œ¾TU” † •V"‡TU” † H“i,
V 5 TU” † 14•X^#V-›'TU” † ‚ ˜” † V-›ƒ–
™ŸœÆT4! † ˜“iV ô T4! † ‘“ V@<„b5
G.1 context formation: œ™Ÿž¡ ™¢œ¿„ ™ŸœŸ ¿
¨ ™ŸœÇ \ô T9_¬Ù(VÈ „, ^ 5¶‰
™Ÿœ
Static Semantics for FTC
%
ô
#„b5îŠR
™ ›ƒ–Ìœ
6
%
‹%
™Ÿœ¾TH–
V ô T O VÈ#„b5¶ŠR
r
r
r
r
r
r
 ¬ … †
™›A… † 3 r œ
r ô àaáMâ"T9 V6­®
r Ù
r
r
™6›A…i†3 
œ ô T9 ¬Ù Vȃ" v TU…i†9Vv5¶‰
r
r
r
¤T%ŠºTN„Z9HÙ ^ [OVh‰ V
‰
u
u
u
u
r
u
u
ô à_áâ@T9 V­+Ù
 ¬ … † ‚
™6›Au …‡†{3 ›Y… † ‚ 3
œŸ
u u
r
u
u
™6›A…i†3 ›A… † ‚ 3
œ ô T9 u ¬{Ù ‹ V@u *" v TU… † ‚ Vv5 + ‰
u
u
u
‰ /
)U‡'9àaáMâ@T9 y V1
H‹Ù ^ ‰ y X H ¬\3 ^
ÁºÂXQ " t TU… † V à " v TU… † V à … † S
r
r
r
u
‰’C
T@>9àaáMâ@T9 V- \…‡†{X H ^ ÁWT let … † ‚ ‰ in ‰ V
r
u
r
u
™Ÿœ fsig TU… † 3 V)˜ ô fsig TU… † 3 V)˜ <6
„ 5¶‰
24
™ŸœŸÙ£R
™Ÿœ7g1T9Ù(V
(131)
‹
‹Aµ
™ œ7-D†·¹£´ < '
¾
r
r ‹
‹
™¢œÇQVe '# e Œ - Œ S
(132)
™›A…vœ7- $
™Ÿœ
…>-Ý - (133)
™ ›A>9
œ76
™¢œKWi>9
-
(134)
™6›A>9
œ7™¢œ>9
-
(135)
G.4 exp formation: ™¢œ£‰¥A-
œ™Ÿž¡ »…>™¢œ£…-
¼™
‹
™Ÿœ„*Q'< e¡™Ÿœ„M eMA-
‹
(136)
#< S
(137)
y
™Ÿœ„>9
ÁºÂQ¡ Ã
™ŸœB" v NT „WV@ÁWT%-ÂV
r
™ŸœÇQXe
" t TN„WVƒS
‹
A‹ µ
™Ÿœ£‰ À - À Ê £´ < <
r ‹
r
r ‹
‹
‹
‘‰
#' e Œ ‘‰ Œ S‚
QVe < < e Π- ΠS
™6›A…> œ¤‰¥- $
™¢œ\…v- ‰Ž …v- $
™¢œ£‰¥ …v- - y
™Ÿœ£‰DTN„WV@*Q'… Ã
™ œ„Ÿ
„_S*T%-OV
r
A
™¾œ
r
(141)
(142)
™ŸœŸÙ£
ÙJSq%T -ÚV
y
™ŸœÇÙ£q
™Ÿœ¤‰¥*Q' à ÙJS*T%-ÂV
+
‹
™ŸP
œ )Uv9
Ù ‰Â**v9
™Ÿœ£‰
(139)
(140)
™›Av9
̜£‰¥A™Ÿœ/T@>9
Í ‰¥VWi>9
Í ™Ÿœ£‰¥VWi>9
Í y
™¢œ£‰pZ Ùv[M*Q¡ Ã
(138)
r
u
u
u
™ ›A…>6
œ¤‰
A
™¢œ7r
u
u
let …˜‰
in ‰
A
(143)
(144)
(145)
G.5 constructor equivalence: ™¾œÙݧÝÙ Rules for congruence, reflexivity, symmetry, and transitivity are
omitted.
y
Á¸£Q' Ã
Ù S ™¢œÙ ™›ƒv9
̜Ù
™ŸœÆT9\v9
Ù(V#Z Ù [W§¿ÁWT9Ù(V@
™ŸœÙ
™Ÿœ¾T9\v9
ÙºZ \[OV"§ÝÙ¤
y
(146)
(147)
‹
‹
‹
‹
™¢œÙÚ§ÂQ<< e#Ù& <<NSJQ'< ¡e 9
'< S
™¢œgfehT9Ù(V§ÝÙ q
(148)
r
r ‹
‹
ÂQXe 9
¥
<< e Π9
Œ S ‹ ‹Aµ
™ŸœÙȆ§Ýgfem†AT9Ù(VÈ
¦†
¹M£´ '<
r
r<‹
‹
™¢œÇVQ e Ù
#< eOŒ6ÙȌPSû§ÝÙ£q
(149)
G.6 type equivalence: ™Ÿœ7-ï§0-
Rules for congruence, reflexivity, symmetry, and transitivity are
omitted.
25
Download