460 likes | 581 Views
Higher-Order Modules and the Phase Distinction. Harper, Mitchell, Moggi Presented by Aleksey Kliger Fall Semester, 2002. Motivation. HM86 introduces dependent types for modeling modules Too powerful: type equality depends on value equality Not clear how to statically typecheck. HMM outline.
E N D
Higher-Order Modules and the Phase Distinction Harper, Mitchell, Moggi Presented by Aleksey Kliger Fall Semester, 2002
Motivation • HM86 introduces dependent types for modeling modules • Too powerful: type equality depends on value equality • Not clear how to statically typecheck
HMM outline • Introduce lML a simple calculus with the phase distinction property. No modules. • Extend to lMLstr , a simple structures-only calculus • Show that the full module calculus lMLmod is a definitional extension of lMLstr by a novel interpretation of dependent types • Focused on compile-time type checking, not concerned with abstraction,generativity,etc.
Phase distinction • “compile-time” vs “run-time” • Separate equality of types from equality of terms • For practical applications, want compile-time judgments to be decidable (reduces to want type equality to be decidable)
First cut: No modules • lML is similar to core-ML • Parameterized by a collection of equational axioms on terms • Comes equipped with a theorem that it can be typechecked at compile-time • Forms the definition for what it means to be checkable at compile-time
lML constuctor-level k2kind ::= 1 | T | k1£k2 | k1!k2 u2constr ::= v | ¤ | £ | ! | 1 | hu1, u2i| pi(u) | (lv:k.u) | u1u2 • Constructors-as-data • Essential for later development that we have product and function kinds
lML term-level s 2type ::= 1 | set(u) | s1£s2 | s1!s2 | (8v:k.s) e2term ::= x | ¤ | he1, e2i | pi(e) | (lx:s.e) | e1e2 | (Lv:k.e) | e[u] F2context ::= ; | F, u:k | F, x:s
F context FÀu : k Àstype FÀe : s FÀu1 = u2 : k FÀs1 = s2type FÀe1 = e2 : s lML judgments
Intersting lML term equality judgments Usual b and h rules for unit, product and sums We won’t need term equality, but we don’t know that yet
Compile-time type checking • A priori we do not know that lML is phase separable • Constructor equality may well depend on arbitrary axioms on terms • So to say that we have a phase distinction, we say formally that equality judgments are derivable in the absence of all term equality axioms
Theories • Parametrize lML by a theory T=(FT, AT) • FT is a well-formed context • ATis a collection of run-time axiomse1 = e2 : s (where ;Àei:s) • lML[T]`J iff J derivable in theory T
Contexts If F is a context • let Fc be F with all term variable declarations removed (compile-time context) • let Fr be F with all constructor variable declarations removed (run-time context) • lML[T]`ctJ iff J derivable using only rules in T; constructor- and type- equality rules and the formation rules (but not the “run-time” term equality rules) of lML
Compile-time type checking If T is a theory, then • lML[T]`Fcontextimplies lML[FT,;]`ctFccontext andlML[FT,;]`ctFrcontext • lML[T]` FÀ u:k implies lML[FT,;]`ctFcÀ u:k • lML[T]` FÀu1=u2:k implieslML[FT,;]`ctFcÀu1=u2:k
Compile-time typechecking (cont’d) • lML[T]` FÀs type implieslML[FT,;]`ctFcÀstype • lML[T]` FÀs1=s2 type implieslML[FT,;]`ctFcÀs1=s2type • lML[T]` FÀe: s implieslML[FT,;]`ctFc,FrÀ e:s • FÀe1=e2:s implies lML[FT,;]`ctFc,FrÀei:s
Compile-time type checking • Note that in the last implication, we only get to conclude lML[FT,;]`ctFc,FrÀei:s • Confirms our intuition that in general term equality is not available to us at compile-time • Compile-time type checking is decidable and independent of all equalities on terms
Modules • Extend lML to a calculus with modules • Based on the dependent type interpretation of sharing as in prior papers we’ve looked at • But non-standard interpretation of what it means to be a dependent product/sum
Structures only k2kind ::= L u2constr ::= L | sc s2type ::= L e2term ::= L | sr S2sig ::= [v:k, s] M2mod ::= [u, e] F2context ::= L | F, s:S
Structures only (cont’d) • Only have structure variable in contexts • New constructor and term rules • Projection rules for open-scope existentials
Structures only (cont’d) Four new judgment forms • FÀS sig • FÀM:S • FÀS1=S2 sig • FÀ M1=M2:S Defined in the expected way (for open-scope existentials)
Compile-time typechecking for structures calculus Show decidable by giving a translation into lML Split contexts F into F¤ by replacing structure variables s:[v:k,s] with sc:k, sr:[sc/v]s
Compile-time typechecking for structures calculus (cont’d) For any lML theory T, • lMLstr[T]`FÀ[v:k,s] sigiff lML[T]`F¤,v:kÀstype • lMLstr[T]`FÀ [u,e] mod iff lML[T]`F¤Àu:kand lML[T]`F¤Àe:[u/v]s • Similarly for equality judgments
Towards a full module calculus • So what about substructures and functors? • Turns out that they are definable in lMLstr • The remainder of the talk will show how
Intuition • Consider all modules and all operations on modules as being composed of two separate parts: the constructor part and the term part • Example from SML: Given functor F (sig type t val x:t end) : sig type t val x:t end = …we “know” that the result type t does notreally depend on the value x in the argument.
Example (cont’d) • So model F as a structure of a constructor function and a value function with signature: [f:T! T, 8sc:T.set(sc!fsc)]
The full module calculus k2kind ::= L u2constr ::= L | Fst(M) s2type ::= L e2term ::= L | Snd(M) S2sig ::= [v:k,s] | 1 | (Ss:S1.S2) | (Ps:S1.S2) M2mod ::= s | [u,e] | ¤ | hM1,M2i | pi(M) | (ls:S.M) | M1M2 F2context ::= L | s:S
Formation rules • Formation rules are standard for dependent types • Selfification rule for full modules • Necessary since modules may have multiple types
Selfification example structure X = struct type t = int val x : int = 3 end X : sig type t val x : int end X : sig type t val x : int end and
Equational rules (signatures) • Flatten higher-order module signatures to structures • of higher kind: • Pairs for substructures • Functions for functors
Substructures sig structure X : sig type t1 val x1 : t1 end type t2 val x2 : X.t1 * t2 end sig constr t : T £ T val x : p1 t £ (p1 t £p2 t) end ) • Pseudo-SML with a constr declaration for constructors of higher kind
Functors funsig (X: sig type t1 val x1 : t1) : sig type t2 val x2 : X.t1 * t2 end sig constr t : T ! T val x : 8 t1 : T . (t1! t1£ t t1) end )
Strategy for compile-time type checking • Show that lMLmod is a conservative definitional extension of lMLstr • In that the non-standard equational rules for modules are “explained” by a translation from lMLmod into lMLstr. • Neither do they let you prove anything new about structures • Type check by translating down to lMLstr, which we know to be decidable
Translating down • Let -b be the mapping that translates away the higher order modules • Recursively flatten all higher-order modules: Mb = [u,e] even if M is is a dependent sum or product
Translating down (cont’d) • Fst(M)b = u if Mb = [u,e] • Snd(M)b = e if Mb = [u,e] • sb = [sc, sr] • [v:k,s]b = [v:k, [v/v]sb] Where v is a variable that does not occur in lMLmod expressions
Translating down(signatures) • (Ss:S1.S2)b = [v:k1£k2, ([p1v/v]s1£[p1v, p2v / sc, v]s2)] if SbI = [v:ki, si] • (Ps:S1.S2)b = [v:k1!k2,8sc:k1.[sc/v]s1! [vsc/v]s2)] if SbI = [v:ki,si] Left to right direction of the signature equality judgment for lMLmod
Definitional extension • In the sense that If lMLmod`FÀ M:S then lMLmod`FÀ M = (Mb)e : S • Where -e embeds the lMLstr in the module language • Flattened modules are “the same as” higher-order modules
Conservative extension • In the sense that lMLstr`J iff lMLmod`Je • No new equalities possible because of higher-order modules
What does it mean to typecheck lMLmod at compile time? • Disallow b and h for term equivalence • Disallow b and h rules for dependent sums and products • Rules for simple structures [u,e] still allowed,e.g.:
lMLmod[T]`ct • Theorem: If T is a theory, then • if lMLmod[T]`FÀS1 = S2 sigthen lMLmod[FT,;]`ctFÀS1 = S2 sig • This is the clause we care about, since typechecking modules depends on signature equality • if lMLmod[T]`FÀe1=e2:s then lMLmod[FT,;]`ctFÀei:s • if lMLmod[T]`FÀM1=M2: Sthen lMLmod[FT,;]`ctFÀMi:Sand lMLmod[FT,;]`ctFÀ [Fst(M1),Snd(M1)] = [Fst(M2),Snd(M1)]:S • N.B. we don’t have equality of modules at compile time, only equality of their type components • (and other clauses)
Typechecking algorithm • Given by inference rules FÀs³FbÀsbtype FÀS³FbÀSbsig FÀM³FbÀMb : [:k,s] (and similarly for expressions and kinds) • More than just the -b interpretation: produces typing derivations. • For modules M produces the “most specific” (non-dependent) signature
Soundness • If TC[T]`FÀ M ³FbÀ [u,e]: [:k,s] then lMLmod`ctFÀ M: [:k,se] • Similarly for other formation judgments
Completeness • For modules, algorithm produces non-dependent signature: If lMLmod[T]`ctFÀ M:S then TC[T]`FÀ S ³FbÀ [v:k,s] sigFÀ M ³FbÀ [u,e]: [:k,s’]FbÀs’ = [u/v]s type For other compile time formation judgments, algorithm produces the correct type or kind
Conclusion • Phase distinction is essential for practical typechecking of higher-order modules • By interpreting modules as pairs of compile-time and runtime objects, can achieve phase distinction even for functors and substructures • Critically depend on a “rich enough” constructor calculus • Turns out that in such a calculus, higher order modules arise “for free” as a definitional extension