Principal Type Schemes for Gradual Programs With updates and corrections since publication (Latest: May 16, 2017)

Ronald Garcia ∗ Matteo Cimini † Software Practices Lab Indiana University Department of Computer Science [email protected] University of British Columbia [email protected]

Abstract to Siek and Taha (2006) has been used to integrate dynamic checks Gradual typing is a discipline for integrating dynamic checking into into a variety of type structures, including object-oriented (Siek a static . Since its introduction in functional languages, and Taha 2007), substructural (Wolff et al. 2011), and ownership it has been adapted to a variety of type systems, including object- types (Sergey and Clarke 2012). The key technical pillars of grad- oriented, security, and substructural. This work studies its applica- ual typing are the unknown type, ?, the consistency relation among tion to implicitly typed languages based on . Siek gradual types, and support for the entire spectrum between purely and Vachharajani designed a gradual type inference system and dynamic and purely static checking. A gradual type checker rejects algorithm that infers gradual types but still rejects ill-typed static type inconsistencies in programs, accepts statically safe code, and programs. However, the type system requires local reasoning about instruments code that could plausibly be safe with runtime checks. type substitutions, an imperative inference algorithm, and a subtle This paper applies the gradual typing approach to implicitly correctness statement. typed languages, like Standard ML, OCaml, and Haskell, where This paper introduces a new approach to gradual type inference, a type inference (a.k.a. type reconstruction) procedure is integral to type checking. This problem was investigated first by Siek and driven by the principle that gradual inference should only produce ?α static types. We present a static implicitly typed language, its grad- Vachharajani (2008), defining λ→ , a gradual type inference system and algorithm that infers gradual types, but rejects ill-typed static ual counterpart, and a type inference procedure. The gradual sys- 1 tem types the same programs as Siek and Vachharajani, but has a programs. This groundbreaking paper outlines principles that a modular structure amenable to extension. The language admits let- gradual implicitly typed language should satisfy, demonstrates how polymorphism, and its dynamics are defined by translation to the several plausible approaches fail, and ultimately produces a com- Polymorphic Blame Calculus (Ahmed et al. 2009, 2011). pelling type system and type inference algorithm. Though the re- The principal types produced by our initial type system mask sults satisfy the criteria for gradual typing, the type system requires the distinction between static parametric polymorphism and poly- special care in its handling of type variables, subtle statements morphism that can be attributed to gradual typing. To expose this and proofs of correctness, and a special-purpose imperative infer- difference, we distinguish static type parameters from gradual type ence algorithm. These complexities make it unclear how to adopt, parameters and reinterpret gradual type consistency accordingly. adapt, and extend this approach with modern features of implic- The resulting extension enables programs to be interpreted using itly typed languages, like let-polymorphism, row-polymorphism, either the polymorphic or monomorphic Blame Calculi. and first-class polymorphism. Furthermore, extending an existing implicitly typed language implementation with support for gradual typing would require a rewrite or substantial overhaul of the type 1. Introduction inferencer. Interest in integrating static and dynamic checking is increasing To support the extension of implicitly typed languages with among language researchers and industrial language designers. support for gradual typing, this paper introduces a new foundation (e.g. (Bierman et al. 2010; Gronski et al. 2006; Swamy et al. 2014; for gradual implicit typing. In particular, we make the following Tobin-Hochstadt and Felleisen 2008; Wrigstad et al. 2010)) Among contributions: the proposed foundations for such languages, gradual typing, due 1. We introduce a specification of static implicit typing that em- ∗ Partially funded by an NSERC discovery grant. phasizes the input-output modes of the type system. In particu- lar the types of subterms are viewed as opaque, and we rely on † Partially funded by NSF grant 1360694. partial functions to structure the system. This structure leads to a natural conception of gradual implicit typing that is easy to Permission to make digital or hard copies of all or part of this work for personal or reason about and extend. The key insight underlying the design classroom use is granted without fee provided that copies are not made or distributed is to only allow fully static types to be implicit: gradual types, for profit or commercial advantage and that copies bear this notice and the full citation in our approach, must originate in the program text. on the first page. Copyrights for components of this work owned by others than the author(s) must be honored. Abstracting with credit is permitted. To copy otherwise, or 2. Siek and Vachharajani’s type system is based explicitly on in- republish, to post on servers or to redistribute to lists, requires prior specific permission ferring gradual types and emphasizing type precision, a sub- and/or a fee. Request permissions from [email protected]. POPL ’15, January 15–17, 2015, Mumbai, India. Copyright is held by the owner/author(s). Publication rights licensed to ACM. 1 Rastogi et al. (2012) also combine gradual typing and type inference, ACM 978-1-4503-3300-9/15/01. . . $15.00. but focus on improving performance rather than detecting inconsistencies http://dx.doi.org/10.1145/2676726.2676992 (Sec. 13). stantially different conceptual foundation. Nonetheless, we x : T ∈ Γ (Tx) (Tn) (Tb) prove that the two foundations coincide: both type systems Γ ` x : T Γ ` n : Int Γ ` b : Bool accept exactly the same programs. Γ ` t1 : T1 Γ ` t2 : T2 dom(T1) = T2 3. We define a corresponding constraint typing judgment and con- (Tapp) Γ ` t t : cod(T ) straint solver. Central to its design is that we choose to limit the 1 2 1

type inference problem to deducing only static types. In addi- Γ ` t1 : T1 Γ ` t2 : T2 Γ ` t3 : T3 T1 = Bool tion to the standard equality constraints between static types, (Tif) Γ ` if t1 then t2 else t3 : equate(T2,T3) we require consistency constraints between gradual types; our solver naturally extends unification to support them. Γ ` t : T Γ ` t : T T = Int T = Int (T+) 1 1 2 2 1 2 4. To confirm the extensibility of the type system, we extend Γ ` t1 + t2 : Int it with support for let-polymorphism, using the standard ap- Γ, x : T1 ` t : T2 proach off the shelf. We give the language dynamics by trans- (Tλ) Γ ` (λx.t): T → T lating it to the Polymorphic Blame Calculus (Ahmed et al. 1 2

2009, 2011). The translation mirrors the analogous translation Γ, x : T1 ` t : T2 Γ ` t : TT = T1 of Hindley/Milner typing to System F, suggesting that recent (Tλ:) (T::) Γ ` (λx : T1.t): T1 → T2 Γ ` (t :: T1): T1 approaches to first-class polymorphism may also apply. 5. We observe that the principal types of the initial system mask dom : TYPE * TYPE cod : TYPE * TYPE the distinction between static parametric polymorphism and dom(T1 → T2) = T1 cod(T1 → T2) = T2 polymorphism due to gradual typing. To expose this difference, dom(T ) undefined otherwise cod(T ) undefined otherwise we distinguish static type parameters from gradual type param- eters and reinterpret gradual type consistency accordingly. The equate : TYPE × TYPE * TYPE resulting language can be interpreted using either a monomor- equate(T,T ) = T phic or polymorphic intermediate language. equate(T1,T2) undefined otherwise

2. Implicit Typing and Type Inference Figure 2. Static Language (ITSL): Type System This section briefly introduces the Implicitly Typed Static Lan- guage (ITSL). Its main purpose is to introduce the core type system The type system definition pays particular attention to the mode that we extend with gradual typing, as well as to briefly review the of the typing judgment, in the sense of logic programming (Debray principles of implicit typing. We highlight some particular details and Warren 1988). In particular, the type context and term are in- of our presentation that are important to the overall approach. terpreted as inputs to the typing judgment, while the term’s type is viewed as an output. The impact of this interpretation on the struc- ture of the definition is as follows, and can be seen in the (Tapp) A ∈ TPARAM,T ∈ TYPE, x ∈ VAR, b ∈ BOOL, rule. Though the structure of the terms t in the conclusions of rules n ∈ Z, t ∈ TERM, v ∈ VALUE Γ ∈ VAR * TYPE T ::= A | Int | Bool | T → T (types) are analyzed using pattern-matching-style syntax, the type position t ::= n | t + t | b | if t then t else t (terms) of each typing judgment in the premise is stated abstractly as some | x | λx.t | λx : T.t | t t | t :: T type T . For instance, the type rule for application usually has a v ::= n | b | x | λx.t | λx : T.t (syntactic values) premise Γ ` t1 : T11 → T12, but in contrast the (Tapp) rule only assumes that the result is a type T1. In lieu of pattern matching on a Figure 1. Static Language (ITSL): Syntax function type, the rules appeal to partial functions that are defined only for types with the proper shape. These partial functions name Fig. 1 presents the syntax for ITSL. By implicit typing we the result type of a term (e.g., cod(T1)) and assert properties that 2 mean that the language is statically typed, but programmers may must hold between interacting types (e.g., dom(T1) = T2). omit type annotations. In particular, this language provides function Our partial functions are partly responsible for imposing re- expressions λx.t that require no type annotation on their parameter, quirements on types. For instance, reference to dom(T1) in a rule in contrast to the annotated form λx : T.t, which it also supports. implies that T1 = T11 → T12 for some T11,T12, so this require- As a convenience, the language also provides type ascriptions t :: ment does not need to be explicitly stated in the rule. If dom(T1) is T , which could already be simulated as ((λx : T.x) t). undefined, then the (Tapp) rule does not apply. Using partial func- The implications of these language features become clearer in tions to abstract away type requirements is critical to our subse- the type system specification, presented in Fig. 2. The (Tλ:) rule quent development of gradual typing. uses the type annotation on a function parameter to type its body. A particularly interesting example of this phenomenon arises in The (Tλ) rule, on the other hand, types a function’s body with any the (Tif) rule. The requirement that T1 must be Bool is standard, parameter type that works. The broader impact of this is that a but the result type of the term is a partial function equate(T2,T3), function like λx : Int.x has only one legal type, Int → Int, but a that is defined only when the two types are equal, in which case it function like λx.x can be given many types, specifically any type of is the type itself. Typically, this rule is expressed by using pattern the form T → T . This flexibility reduces the annotation overhead matching on the results of typing t2 and t3 to force them into the for programmers while retaining static safety, and increases the same type, and then providing that type as the final result. Instead, expressiveness of the language if a polymorphic let construct is we keep the result types abstract and appeal to a partial function to added (see Sec. 10). “combine” them. In summary, we use predicates only to express relationships Presentation Style There are some notable differences between between types that do not imply some result type. For all cases the presentation in Fig. 2 and the typical textbook presentation (c.f. (Pierce 2002)). They do not affect the meaning of this type 2 In propositions that refer to partial functions, we interpret = as Kleene system definition, but they play an important structuring role that equality: both sides of the equation must either be defined and equal, or we exploit when we extend it to support gradual typing. undefined. where we need to determine a type in terms of subterm types, we The function Vars extends to terms and type contexts in the ex- defer to a partial function. pected way, and in the remainder of the paper we simply write Vars(o0, o1, . . . , on) for Vars(o0) ∪ Vars(o1) ... ∪ Vars(on), for 2.1 Type Polymorphism some n ≥ 0 and where oi can be a type, a term or a type context, As we mentioned earlier, a function like λx.x can be given the for 0 ≤ i ≤ n . types Int → Int, Bool → Bool, and any other type of the form Note that type variables and type parameters are distinct con- T → T . We would like to express this polymorphism somehow, but cepts. Type parameters actually are types, while type variables are our language does not support first-class polymorphism: each type merely placeholders, just as variables in algebra are not numbers. is concrete. For this purpose we endow the language with a set of However, all types count as type expressions too (i.e. TYPE ⊂ type parameters A TYPEEXP); the analogous status also holds for term expressions , which are uninterpreted types in the sense that 3 the type system gives them no special treatment. As a consequence and type expression contexts. We give all of these expression any situation where a type parameter A is used, any other particular forms meaning by substituting types for type variables. type could appear. Let us formalize this observation. X Definition 3. Let S ∈ XSUBST = TVAR → TYPE denote type A Definition 1. Let S ∈ ASUBST = TPARAM → TYPE denote variable substitutions, or X-substitutions. type parameter substitutions, or A . -substitutions Observe that these substitutions produce real types, terms, and Notation. If S is some sort of substitution function, then we use type contexts in accordance with the source language. Sb(T ), Sb(Γ), and Sb(t) to denote the compatible closure of substi- X X Definition 4. Let S1 and S2 be two type variable substitutions and tution over types, type contexts, and terms, respectively. X X let X ⊆ TVAR. We say that S2 agrees with S1 over X whenever X X The A-substitutions give meaning to type parameters. With this for all variables X ∈ X , it holds that S1(X) = S2(X). we can treat them as representatives for type polymorphism. In algebra, we use variables to write down equation expressions, Proposition 1. If Γ ` t : T then ScA(Γ) ` ScA(t): ScA(T ) for any which are problems that may have solutions. By analogy, we use A S ∈ ASUBST. our expressions to formalize the type inference problem and to characterize its solutions. Proof. Straightforward induction on derivations of Γ ` t : T . Definition 5 (Type Inference Problem). Given a type expression context ΓX and a term expression tX, the type inference problem for Prop. 1 shows us that a type with parameters can be made more ITSL asks if ScX(ΓX) ` ScX(tX): T for some X-substitution SX and specific arbitrarily. Regarding the dual consideration, we can ask type T . about the presence of a most general type for a program. Only the context and term are expressions here. Definition 2 (Principal Type). If Γ ` t : T , then we say that T A type inferencer, then, is a decision procedure for the type is a principal type of Γ and t if whenever Γ ` t : T0 holds, then inference problem. We do not present a type inference algorithm for A A A Sc (Γ) = Γ, Sc (t) = t, and T0 = Sc (T ) for some A-substitution this static language. However, such an algorithm can be extracted SA. directly from the gradual type inferencer we present below. The first two constraints on the substitution SA force any pa- rameters that explicitly appear in the term or context to be treated 3. Introduction to Gradual Typing as constants, truly uninterpreted types. The third constraint formal- izes the sense that T unambiguously represents all possible types Gradual typing is a type discipline, introduced by Siek and Taha, that can be assigned to the term-context pair. to extend an existing type system with seamless support for static Principal types succinctly summarize all possible types of a and dynamic checks. Such a language supports both extremes of program. This particular language has principal types for every checking, fully static and fully dynamic, as well as any point in typeable program. We establish this once and for all in the gradually between. The gradual type system uses available type information typed setting. to detect inconsistencies between types. Typing conditions that cannot be determined statically are checked at runtime using casts. 2.2 Type Inference To achieve these goals, gradual typing extends an existing type system with an unknown type ?. For example, the corresponding While this type system specification has great appeal, the question gradual types for the language from the last section are as follows: arises as to whether it can be effectively type checked. Indeed it can, and a broad array of literature has discussed approaches to doing U ∈ GTYPE U ::= ? | A | Int | Bool | U → U (gradual types) so. We desire even more flexibility than the language provides as- is. To do so, we generalize the problem beyond purely elided type Based on this definition, every static type is also a gradual type. ? annotations. Fig. 3 presents the type system for λ→, the simply typed gradual To check implicit types, we must deduce types that are not calculus (Siek and Taha 2006). The rules for variables and functions present in the program text. To represent this problem in a broader are standard, but the rules for function application are not. The context, we introduce notions of type variables and type expres- (App?) rule applies when the operator has the unknown type. Since sions: the result could plausibly be a function, the program type checks, X ∈ TVAR,T X ∈ TYPEEXP and the result type of the application is unknown in turn. T X ::= X | A | Int | Bool | T X → T X The (AppU) rule applies when the operator has some function A type variable is a placeholder for one or more possible types, type. Unlike static typing, the rule does not require that the operand directly analogous to variables in secondary school algebra. Then a have the same type as the domain of the operator, but simply that type expression T X is just a type where some of its substructure has two types be consistent, written U ∼ U. We define consistency as been filled with type variables. This idea extends to term expres- X X sions t ∈ TERMEXP and type expression contexts Γ ∈ VAR * 3 Some presentations of type inference use a single entity for both concepts. TYPEEXP. We write Vars(T X) for the set of type variables in T X. We distinguish them for clarity and to support our development in Sec. 12. x : U ∈ Γ Γ, x : U1 ` t : U2 A ∈ TPARAM,T ∈ TYPE,U ∈ GTYPE, x ∈ VAR, (Var) (Abs) Γ ` x : U Γ ` (λx : U1.t): U1 → U2 b ∈ BOOL, n ∈ Z, t ∈ TERM, v ∈ VALUE T ::= A | Int | Bool | T → T (static types) Γ ` t : U → U Γ ` t : U U ∼ U U ::= ? | A | Int | Bool | U → U (gradual types) (AppU) 1 11 12 2 1 11 1 Γ ` t1 t2 : U12 t ::= n | t + t | b | if t then t else t (terms) | x | λx.t | λx : U.t | t t | t :: U Γ ` t : ? Γ ` t : U v ::= n | b | x | λx.t | λx : U.t (syntactic values) (App?) 1 2 2 Γ ` t1 t2 : ? Figure 4. Gradual Language (ITGL): Syntax ? Figure 3. λ→: Simply Typed Gradual Calculus

x : U ∈ Γ (Ux) (Un) (Ub) follows. Γ ` x : U Γ ` n : Int Γ ` b : Bool Int ∼ Int Bool ∼ Bool A ∼ A ? ∼ U Γ ` t1 : U1 Γ ` t2 : U2 domg (U1) ∼ U2 (Uapp) U ∼ U U ∼ U 11 21 12 22 Γ ` t1 t2 : codf (U1) U ∼ ? U11 → U12 ∼ U21 → U22 Γ ` t : U Γ ` t : U Γ ` t : U U ∼ Bool The intuition behind this definition is that two consistent gradual (Uif) 1 1 2 2 3 3 1 types need only agree on their statically known parts. Consistency Γ ` if t1 then t2 else t3 : U2 u U3 is one of the key innovations of the gradual typing approach. Γ ` t : U Γ ` t : U U ∼ Int U ∼ Int (U+) 1 1 2 2 1 2 The type system must be a conservative extension of the un- Γ ` t + t : Int derlying type system. This means that programs without any dy- 1 2 namism must type according to the underlying static type system. Γ, x : T ` t : U (Uλ) 1 2 Since consistency reduces to equality in the absence of ?, it follows Γ ` (λx.t): T1 → U2 that the type system conservatively extends its pre-existing simply Γ, x : U ` t : U Γ ` t : UU ∼ U typed counterpart. A programmer, development environment, or (Uλ:) 1 2 (U::) 1 syntactically-sugared source language then introduces dynamism Γ ` (λx : U1.t): U1 → U2 Γ ` (t :: U1): U1 by ascribing ? to program subterms (see Sec. 6). In addition to consistency, gradual types impose a notion of type dom] : GTYPE * GTYPE codg : GTYPE * GTYPE precision v as a partial order , which indicates that one type is less dom](U → U ) = U codg(U1 → U2) = U2 unknown than another. 1 2 1 dom](?) = ? codg(?) = ? U v U U v U 11 21 12 22 dom](U) undefined otherwise codg(U) undefined otherwise U v ? U v U U11 → U12 v U21 → U22

This relation coincides with the “na¨ıve ” relation of u : GTYPE × GTYPE * GTYPE 4 (Wadler and Findler 2009). T u T = T To support gradual typing, programs are instrumented with ? u U = U u ? = U type-directed runtime checks that ensure that consistency checks (U → U ) u (U → U ) = (U u U ) → (U u U ) that cannot be fully resolved at type-checking time are dynami- 11 12 21 22 11 21 12 22 cally verified. U1 u U2 undefined otherwise In short, a gradual type system takes an optimistic approach to checking that two types are compatible, only statically rejecting Figure 5. Gradual Language (ITGL): Type System combinations that exhibit inconsistencies, and dynamically verify- ing any remaining checks. ? If we compare this type system to λ→, we notice that the former has one rule for function application, (Uapp), while the latter has 4. A Gradual Implicitly Typed Language two, (AppU) and (App?). In this case, the domg partial function This section presents our conception of gradual typing for an im- provides the necessary abstraction to combine the two rules into plicitly typed language. The ideas from the last two sections com- one. The domg function is defined with two cases: folding them bine to yield a design that differs from λ?α in its foundations, but → into the (Uapp) rule, along with codg would recover the two rules of is ultimately equivalent. ? λ→. Fig. 4 presents the syntax of the Implicitly Typed Gradual Lan- Consider the (Uif) rule. Most of the structure is as expected, but guage (ITGL). As with standard practice, the singular difference is its result type is U u U , the greatest lower bound (or meet) of lifting of static types T to gradual types U. Every static type anno- 2 3 U2 and U3 according to the precision relation. In fact, the meet is tation can now be replaced with a gradual type annotation. the gradual partial function that corresponds to equate. To see how, The type system, presented in Fig. 5 builds on the ITSL type consider the two gradual types ? → Int and Bool → ?. The only system from Sec. 2. Most of the rules have the same structure, hope for some U to be a well-defined result of combining them except their static types have been lifted to gradual types, and the is for U to be Bool → Int. Naturally, one can always coerce two predicates and partial functions on static types have been lifted inconsistent branches to type-check using type ascriptions. to consistent predicates and partial functions on gradual types. A straightforward example of this is the (U+) rule, which replaces Implicit types must be static types The (Uλ) rule embodies im- type equality with type consistency, and static types with gradual plicit typing in ITGL. The corresponding ITSL rule types the body types. of the function using some arbitrary type, and the gradual type sys- tem does the same. To understand why the arbitrary type is static 4 We avoid calling it “subtyping” because it does not characterize substi- rather than gradual, consider the program λx.x x. This program tutability. has no unknown type annotations, so it is in the language of the ITSL type system, which cannot type it. As such, the gradual type SG;ΓX ` tX : U X | X ⊥(X , Vars(tX)) system must reject it as well. If the gradual type system could ar- bitrarily type x as ?, however, then this function would type check, x : U X ∈ ΓX (Gx) (Gn) even though the programmer introduced no ? annotations. The key SG;ΓX ` x : U X | ∅ SG;ΓX ` n : Int | ∅ insight is that dynamicity is introduced only via program annota- (Gb) tions. The type system itself must never introduce ? of its own ac- G X cord. As we see next, this insight has broader implications. S ;Γ ` b : Bool | ∅ G X X G X X S ;Γ ` t1 : U1 | X1 S ;Γ ` t2 : U2 | X2 4.1 Gradual Inference of Static Types G X X S |= U ' U → X ⊥({ X } , X1, X2) (Gapp) 1 2 As with ITSL, we generalize type inference, taking into account the G X S ;Γ ` t1 t2 : X | { X } ∪ X1 ∪ X2 insight that our type system need only infer static types. To state the gradual type inference problem, we introduce corresponding type G X X X S ;Γ , x : U1 ` t : U2 | X expressions, term expressions, and type context expressions. For (Gλ:) SG;ΓX ` (λx : U X.t): U X → U X | X brevity, we present only the gradual type expressions. 1 1 2 SG |= U X ' U X U X ∈ GTYPEEXP U X ::= ? | X | A | Int | Bool | U X → U X SG |= Bool ' Bool SG |= Int ' Int Gradual type expressions U X now include ?, since we are in a gradually-typed language. However, we do not update the defini- SG |= A ' A SG |= U X ' ? SG |= ? ' U X tion of X-substitutions: type variables map to static types. This G X X G X X property generalizes the reasoning underlying the (Uλ) rule: we S |= U11 ' U21 S |= U12 ' U22 only allow gradual types to be explicitly introduced in a program as SG |= U X → U X ' U X → U X a means to ensure that the type system cannot introduce dynamism 11 12 21 22 without prompt and thereby compromise inconsistency checking. G G X G G X S |= Sc (X) v U2 S |= Sc (X) v U1 Definition 6 (Gradual Type Inference Problem). Given a gradual G X G X S |= X ' U2 S |= U1 ' X type expression context ΓX and a term expression tX, the gradual type inference problem asks if there is an X-substitution SX and SG |= U v U X gradual type U such that ScX(ΓX) ` ScX(tX): U. ScG(X) = U ?α In contrast, λ→ (Siek and Vachharajani 2008) infers gradual SG |= U v X SG |= Bool v Bool SG |= Int v Int types, albeit with restrictions. In the next section, we reconcile this difference. SG |= A v A SG |= U v ?

?α SG |= U X v U X SG |= U X v U X 5. λ→ types the same programs 11 21 12 22 SG |= U X → U X v U X → U X Siek and Vachharajani (2008) analyze the concept of gradual type 11 12 21 22 ?α inference and design a language λ→ that formalizes and substanti- ?α ?α Figure 6. λ→ : Type System ates their approach. The λ→ language and types correspond to our gradual type expressions, but the type theoretic foundations differ ?α substantially. In particular, λ→ is based on inferring gradual types, not just static types, but in a controlled manner. To formalize this, Notation. We write ⊥ Q X  to mean that the given variable we introduce a new notion of substitutions. i

G ? X G G X X straightforward embeddings into ITGL. 1. Suppose S = Sc ◦ S . Then S |= Sc (U1 ) v U2 implies X X X X S |= Sc(U1 ) v U2 . 6.1 A Dynamic Language G ? X G X X 2. Suppose S = Sc ◦ S . Then S |= U1 ' U2 implies X X X If we reconsider the ITSL static language, the syntax of its natural S |= U1 ' U2 . dynamic counterpart, which we call DL, simply amounts to eliding 3. Suppose SG = Sc? ◦ SX. Then SG;ΓX ` tX : U X implies type information: SX;ΓX ` tX : U X. e ∈ DYNAMIC e ::= n | e + e | b | if e then e else e (terms) Proof. By induction on derivations. | x | λx.e | e e

It’s immediately clear that DYNAMIC ⊂ TERM: every DL program Prop. 2 tells us that with regards to solving the type inference looks exactly like an ITSL program, but looks can be deceiving. In ?α X problem for λ→ , we need only look to X-substitutions S , just as particular, one consistent property of dynamic languages is that any for ITGL. Thus, we restrict consideration to X-substitutions for the program in the syntax of the language has semantics. In contrast, ?α λ→ type system, which allows us to connect the two type systems ITSL only gives meaning to programs that are well-typed. For more directly. instance, (λx.x x) is a fine DL program, but it is not a legal X X X X ITSL program because it is not well-typed. The field of linguistics Proposition 3 (Completeness). If S ;Γ ` t : U | X then has a term for this: two similar-looking expressions, sometimes in X X X ScX(Γ ) ` ScX(t ): U for some U such that ScX(U ) v U. different languages, that might be mistaken for having the same meaning, but do not, are called false friends (Crystal 2008). In natural languages they lead to misunderstandings between native Proof. By induction on SX;ΓX ` tX : U X | X . speakers of different languages: in programming languages, the phenomenon recurs. How do we reconcile these syntactic similarities but semantic ?α The intuition behind this proposition is that since λ→ imposes differences between ITSL and DL? The key lies in ITGL: we define only a consistency on the type of (Gapp), the result type can be an both languages by translation to ITGL. The translation for ITSL is arbitrary static type if the codomain of the operator is ?; in contrast, trivial because it embeds immediately. The translation for DL (Siek ITGL propagates the gradual domain of the operator verbatim. and Taha 2006), on the other hand, has substance:

Proposition 4 (Soundness). If ScX(ΓX) ` ScX(tX): U then given G[[·]] : DYNAMIC → TERM X X any finite X0 that contains Vars(t , Γ ), G[[n]] = n :: ? G[[b]] = b :: ? G[[x]] = x :: ? X X X X X S0;Γ ` t : U | X where ⊥(X0, X ) for some S0 that agrees G[[e1 + e2]] = (G[[e1]] + G[[e2]]) :: ? X X X with S except at X , and Sc0(U ) = U. G[[if e1 then e2 else e3]] = (if G[[e1]] then G[[e2]] else G[[e3]]) :: ? G[[λx.e]] = (λx : ?.G[[e]]) :: ? X X X X Proof. By induction on Sc(Γ ) ` Sc(t ): U. G[[e1 e2]] = (G[[e1]] G[[e2]]) :: ? Under this translation, G[[λx.x x]] = (λx : ?.(x::?)(x::?)::?)::?, We have designed an interesting gradual type system with sup- which is a well-typed ITGL program, as are all embeddings of DL port for implicit typing, and have established that it types the same programs. ?α programs as λ→ . In Section 7 we deduce a type inference process that corresponds naturally to our type system and conservatively Proposition 5 (Siek and Taha (2006)). Let X be the free variables extends the corresponding static procedure. of e and Γ = { x : ? | x ∈ X }. Then Γ ` G[[e]] : ?. As we desire, all terms in DYNAMIC are well-defined DL pro- 6 These theorems consider only the corresponding subset of ITGL. grams. 6.2 A Hybrid Language for Interlanguage Migration Armed with a translational semantics for DL and a (trivial) trans- ΓX ` tX : U X | C? | X ⊥(X , Vars(tX, ΓX)) lational semantics for ITSL, we can now combine them. The re- x : U X ∈ ΓX (Cx) (Cn) sult is a hybrid multi-language semantics, which we call HL, X X X that seamlessly supports migration between the DL and ITSL Γ ` x : U | ∅ | ∅ Γ ` n : Int | ∅ | ∅ languages (Matthews and Findler 2009; Tobin-Hochstadt and (Cb) Felleisen 2006; Wadler and Findler 2009): ΓX ` b : Bool | ∅ | ∅ d s e ∈ DYNAMIC e ∈ STATIC ΓX ` tX : U X | C? | X ΓX ` tX : U X | C? | X s s s s s s 1 1 1 1 2 2 2 2 ? ? ? e ::= n | e + e | b | if e then e else e (static) ⊥(X1, X2) C = C ∪ C X = X1 ∪ X2 s s s s s (C+) 1 2 | x | λx.e | λx : T.e | e e | e :: T X X X ? X X d Γ ` t1 + t2 : Int | C ∪ { U1 ∼˙ Int,U2 ∼˙ Int } | X | xe y ed ::= n | ed + ed | b | if ed then ed else ed (dynamic) X X X ? X X X ? Γ ` t1 : U1 | C1 | X1 Γ ` t2 : U2 | C2 | X2 d d d s X X X ? X X . X ? | x | λx.e | e e | pe q Γ ` t3 : U3 | C3 | X3 U2 u U3 = U4 | C4 | X4 The HL syntax combines ITSL and DL, allowing each to include ⊥(X1, X2, X3, X4) X = X1 ∪ X2 ∪ X3 ∪ X4 C? = C? ∪ C? ∪ C? ∪ C? the other. Its semantics is defined by combining the two translations (Cif) 1 2 3 4 X X X X X ? X to ITGL, yielding a coarse-grained gradual language where each Γ ` if t1 then t2 else t3 : U4 | C ∪ { U1 ∼˙ Bool } | X type is either precisely static or completely unknown. ΓX ` tX : U X | C? | X ΓX ` tX : U X | C? | X Taking the dynamic language as primary, HL clearly differenti- 1 1 1 1 2 2 2 2 X . X ? X X ? ates between the dynamic program (λx.x x), the hybrid program codf (U1 ) = U3 | C3 | X3 domg (U1 )∼ ˙ U2 | C4 | X4 ⊥(X , X , X , X ) X = X ∪ X ∪ X ∪ X pλx.xx xyq and the static non-program pλx.x xq. 1 2 3 4 1 2 3 4 C? = C? ∪ C? ∪ C? ∪ C? DL and HL have close ties to research on using types to im- (Capp) 1 2 3 4 X X X X ? prove the performance of dynamic languages (Cartwright and Fa- Γ ` t1 t2 : U3 | C | X gan 1991; Rastogi et al. 2012; Swamy et al. 2014). By analogy, ΓX, x : X ` tX : U X | C? | X ⊥(X , { X }) the goal in that approach is to transform a DL program into a cor- (Cλ) responding HL program by automatically inserting transitions to ΓX ` (λx.tX): X → U X | C? | X ∪ { X } the static language for as much code as possible while retaining well-typing and behaviour. This problem has been approached us- ΓX, x : U X ` tX : U X | C? | X (Cλ:) 1 2 ing type-based analyses that do infer unknown types. X X X X X ? Γ ` (λx : U1 .t ): U1 → U2 | C | X 7. Constraints and Constraint Generation ΓX ` tX : U X | C? | X (C::) X X X X ? X X We have specified an implicit type system, demonstrated its ex- Γ ` (t :: U1 ): U1 | C ∪ { U ∼˙ U1 } | X pressiveness, and formalized the type inference problem for it: now C ∈ CONSTRAINT we must solve the problem. To do so, we follow the approach of ? (Wand 1987a): generate constraints for typeability and solve them. C ∈ P(CONSTRAINT) . Guided by the definition of the ITGL type system and properties of C ::= U X ∼˙ U X | T X = T X our gradual partial functions and predicates, we define a constraint typing judgment, which indicates what constraints must hold for a particular type expression-and-context pair to be typeable. Figure 7. Constraint Typing Judgment 7.1 Constraint Typing Judgments We first introduce a set of constraints C that need to be solved X . X ? X during type inference (Fig. 7). There are two kinds of constraints: codf (U1 ) = U2 | C | X ⊥(X , Vars(U1 )) the standard equality constraints on static types, and new consis- tency constraints on gradual types. Ultimately we want to deter- . . codf (X) = X2 | { X = X1 → X2 } | { X1,X2 } mine whether a set of constraints can be instantiated affirmatively using some substitution. X X . X . codf (U1 → U2 ) = U2 | ∅ | ∅ codf (?) = ? | ∅ | ∅ Definition 8 (Constraint Satisfaction).

X X X X X X X 1. S |= U1 ∼˙ U2 if and only if Sc(U1 ) ∼ Sc(U1 ); Figure 8. Constraint Codomain Judgment X X . X X X X X 2. S |= T1 = T2 if and only if Sc(T1 ) = Sc(T2 ); 3. SX |= C? if and only if SX |= C for each C ∈ C?.

X X ? X X Constraint Typing Fig. 7 presents the constraint typing judgment domg (U1 )∼ ˙ U2 | C | X ⊥(X , Vars(U1 ,U2 )) ΓX ` tX : U X | C? | X . It means that the type expression context ΓX X X X . X and term expression t , can be given type expression U so long as domg (X)∼ ˙ U2 | { X = X1 → X2,X1 ∼˙ U2 } | { X1,X2 } the constraints C? can be satisfied, where X are any extra variables needed to express the constraints. Since it involves type variables, X X X X X domg (U → U )∼ ˙ U | { U ∼˙ U } | ∅ the constraint typing judgment denotes a problem. 11 12 2 11 2

Definition 9 (Constraint Typing Problem). Given a gradual type domg (?)∼ ˙ U X | { ? ∼˙ U X } | ∅ expression context ΓX and a term expression tX, the constraint typ- 2 2 ing problem asks if there is a SX such that ΓX ` tX : U X | C? | X Figure 9. Constraint Domain Consistency Judgment and SX |= C?. X X . X ? X X sarily hold for an arbitrary substitution that solves the type infer- U1 u U2 = U3 | C | X ⊥(X , Vars(U ,U )) 1 2 ence problem. The key is that given an arbitrary substitution SX . . that solves the type inference problem, it’s always possible to mas- Int u Int = Int | ∅ | ∅ Bool u Bool = Bool | ∅ | ∅ X sage it into a slightly different S0 that produces the same solution . X . X X but also satisfies the constraints. A u A = A | ∅ | ∅ U1 u ? = U1 | { U1 ∼˙ ? } | ∅

X . X X 8. Gradual Unification ? u U2 = U2 | { ? ∼˙ U2 } | ∅ In this section we present a procedure that generalizes unifica- X . X tion (Robinson 1965) to account for consistency constraints and X1 u U = X1 | { X1 ∼˙ U } | ∅ 2 2 relates constraints to solutions, where possible. Since each rule of X the judgment is invertible and simplifies the constraints, together U1 ∈/ TVAR . they induce a straightforward decision procedure (bottom-up proof U X u X = X | { U X ∼˙ X } | ∅ 1 2 2 1 2 search) for gradual constraints. X X . X ? X X . X ? U11 u U21 = U1 | C1 | X1 U12 u U22 = U2 | C2 | X2 Proposition 8 (Consistency Inversion). ? ? ? C = C1 ∪ C2 ⊥(X1, X2) X = X1 ∪ X2 X X X X . X X ? 1. If U1 ∼ U2 then U2 ∼ U1; (U11 → U12) u (U21 → U22) = U1 → U2 | C | X 2. If T1 ∼ T2 then T1 = T2; 3. if U → U ∼ U → U ; then U ∼ U and U ∼ U ; Figure 10. Constraint Meet Judgment 11 12 21 22 11 21 12 22 Proof. Straightforward. Auxiliary Constraint Typing Constraint typing appeals to three Fig. 11 presents the gradual unification judgment C? U SX, auxiliary constraint judgments, which reduce complex conditions which means that the X-substitution SX satisfies the constraints in to consistency constraints on gradual types and equality constraints C?. Recall that satisfaction was defined in Sec. 7.1. Throughout, on static types. They are presented in Figs. 8,9, and 10. we assume that C? ∪ { C } implies C/∈ C?. X . X ? The codf (U1 ) = U2 | C | X judgment means that the Most of the cases are straightforward. The most interesting case X X X X codomain of gradual type expression U1 is U2 so long as the con- is for X ∼˙ U1 → U2 . Since X represents a static type, we ? X X ? expand it to X1 → X2 and make each component consistent to straints C can be satisfied. The domg (U1 )∼ ˙ U2 | C | X judg- X its corresponding gradual type. Equality would not work in general ment means that the domain of gradual type expression U1 is con- X ? since the type on the right hand side is gradual. Furthermore, the sistent with U2 so long as the constraints C can be satisfied. Fi- X X . X ? added consistency checks ensure that any ?s contained within the nally the U1 u U2 = U3 | C | X judgment means that the meet of X X X underlying types are ignored. gradual type expressions U1 and U2 is U3 so long as the constraints C? can be satisfied. In each case, X names any extra type variables We let SA : TVAR → TPARAM denote an injective map from needed to express the constraints. The rules for these judgments are type variables to type parameters. This function is responsible for based on the properties of the corresponding gradual operations. transforming any unconstrained type variables into type parame- These constraint judgments are not defined for all inputs. For in- ters. stance, the constraint meet judgment is not defined for Int and Bool. Notation. Any result would be contrived, so rather than relating these type 1. The notation X fresh means that if the consequent of the rule expressions to an arbitrary variable and unsatisfiable constraint, the ? X ? judgment simply fails to hold. is C U S , then ⊥ (X , Vars(C )). 2. The notation [X 7→ T ] stands for Sid [X 7→ T ], the type 7.2 Correctness and Decidability of Constraint Typing substitution that is identity everywhere except for X, which it maps to T . We must prove for each constraint judgment that if a substitution can satisfy the given constraints, then that substitution, and the Proposition 9 (Unification Soundness). If C? U SX then program type that it produces, solves the type inference problem. SX |= C?. Proposition 6 (Constraint Soundness). ? X If ΓX ` tX : U X | C? | X and SX |= C? then Proof. By induction on the structure of C U S . ScX(ΓX) ` ScX(tX): ScX(U X). X ? Proposition 10 (Unification Completeness). If S1 |= C then X X X ? ? X X X A X Proof. By induction on Γ ` t : U | C | X with lemmas to ad- C U S2 for some S2 and furthermore S1 = Sc ◦ S2 for some dress auxiliary constraint judgments. SA. Proof. By induction on the breakdown of constraint sets C? by the Proposition 7 (Constraint Completeness). unification rules. This is dependent on the decomposition structure X X X X X X If Sc(Γ ) ` Sc(t ): U then for finite X0 s.t. Vars(Γ , t ) ⊆ X0, X X X ? being well-founded. Γ ` t : U | C | X where ⊥(X0, X ), and furthermore there is an SX that agrees with SX except at X , where SX |= C? and 0 0 Proposition 11 (Unification is Decidable). Backward proof search X X ? X ? Sc0(U ) = U. on C U S driven by C is decidable.

Proof. By induction on ScX(ΓX) ` ScX(tX): U. with lemmas to ad- Proof. Consider the relation on constraint sets determined by how dress auxiliary constraint judgments. each rule (read bottom-up) transforms them. Given soundness and completeness, it suffices to prove that this relation is well-founded. The constraint completeness proposition must account for the Unlike other unification relations, the search structure cannot be extra variables X used by constraint typing, which do not neces- lexicographically ordered on the number of type variables. Instead, U ∈ P(CONSTRAINT) × XSUBST 10. Let Polymorphism Implicitly typed functional programming languages usually sup- ∅ U SA port let-polymorphism, introduced by Milner (1978). Siek and Vachharajani (2008) left this as an open problem for gradual type C? U SX U X ∈ { Int, Bool } ∪ TVAR ∪ TPARAM inference. Here we demonstrate that supporting let polymorphism C? ∪ { U X ∼˙ U X } U SX follows the same approach as for a static implicitly typed lan- guage (Ohori 1989; Wright 1995; Wright and Felleisen 1994). C? U SX C? U SX To extend ITGL with let-polymorphism, we introduce two new C? ∪ { ? ∼˙ U X } U SX C? ∪ { U X ∼˙ ? } U SX rules: Γ ` v : U1 ? X X X X X C ∪ { U ∼˙ U ,U ∼˙ U } U S Γ ` [v/x]t : U2 11 21 12 22 (Uletp) ? X X X X X Γ ` let x = v in t : U C ∪ { U11 → U12 ∼˙ U21 → U22 } U S 2

? . X X t ∈/ VALUE C? ∪ { X ∼˙ U X } U SX C ∪ { X = U } U S 1 X Γ ` (λx.t2) t1 : U U X ∈/ TVAR U ∈ { Int, Bool } ∪ TVAR ∪ TPARAM (Ulet) Γ ` let x = t in t : U C? ∪ { U X ∼˙ X } U SX C? ∪ { X ∼˙ U X } U SX 1 2

X X If the bound expression is a syntactic value, then it is treated { X1,X2 } fresh X/∈ Vars(U1 → U2 ) ? . X X X polymorphically; otherwise, the value is given a monomorphic type C ∪ { X = X1 → X2,X1 ∼˙ U ,X2 ∼˙ U } U S 1 2 according to the standard let translation.7 These typing rules yield C? ∪ { X ∼˙ U X → U X } U SX 1 2 the corresponding constraint generation rules. ? X X C U S T ∈ { Int, Bool } ∪ TVAR ∪ TPARAM X X X ? Γ ` v : U | C | X1 ? X . X X 1 1 C ∪ { T = T } U S X X X X ? Γ ` [v /x]t : U | C | X2 ⊥(X1, X2) (Cletp) 2 2 . . X X X X ? ? ? X X X X X Γ ` let x = v in t : U | C ∪ C | X1 ∪ X2 C ∪ { T11 = T21,T12 = T22 } U S 2 1 2 . C? ∪ { T X → T X = T X → T X } U SX 11 12 21 22 tX ∈/ VALUE ΓX ` (λx.tX ) tX : U X | C? | X (Clet) 1 2 1 ? . X X X X X X ? C ∪ { X = T } U S Γ ` let x = t1 in t2 : U | C | X X ? X X T X ∈/ TVAR [X\7→ T ](C ) U S X/∈ Vars(T ) . The substitution-based presentation of let polymorphism is sim- C? ∪ { T X = X } U SX ? . X X X C ∪ { X = T } U Sc ◦ [X 7→ T ] ple and clear, but impractical for implementations, so we also present an equivalent presentation based on type schemes, represen- Figure 11. Unification tatives of type polymorphism in the language. In the next section, we use this type system to endow ITGL with dynamic semantics. The Schematic ITGL type system is modeled after (Milner we can represent the set of constraints as a directed graph of 1978). It has the same terms and types as the original, but the typing constraint paths and show that a metric on the graph decreases at judgment changes. The key difference is that the type context now every step. maps variables to type schemes ∀X.U X instead of types. σ ∈ TYPESCHEME ∀ 9. Principal Types Γ ∈ VAR * TYPESCHEME X We establish our notion of principal types using the standard no- σ ::= ∀X.U tion, adapted to account for the separation between type variables This allows us to type polymorphic let expressions, without resort- and type parameters. ing to substitution, by introducing polymorphic assumptions. We X X can represent a type U as a vacuous type scheme ∀∅.U. By con- Definition 10 (Solution Pre-order). Let (S1,U1) and (S2,U2) be solutions for the same gradual type inference problem. Then vention, all type schemes must be closed. The type system then requires a few changes (Fig. 12). (SX,U ) ≤ (SX,U ) if and only if SX = SA ◦ SX and U = 1 1 2 2 2 c 1 2 The (σλ:) and (σλ) rules now introduce type schemes into the A A Sc (U1) for some A-substitution S . context when typing function bodies. The (σx) rule magically in- stantiates a variable’s corresponding type scheme to some grad- Definition 11 (Principal Solution). (SX,U) is a principal solution for a gradual type inference problem if and only if it is least among ual type. In the substitution-based system, this variable would have all other solutions to the problem. It directly follows that U is a been replaced with a full syntactic value, which conveys its poly- principal type. morphism implicitly. As we’ll see, this corresponds directly to the translation from let-polymorphism to parametric polymorphism.

X X X ? Type schemes with no type variables naturally instantiate to their Proposition 12 (Principal Types). Suppose Γ ` t : U | C | X . σ X ? X ? X underlying type. The ( letp) rule exploits the polymorphism of Then S1 |= C for some S1, implies that C U S2, and type parameters, abstracting some that are unconstrained (i.e. do X X X X X (S2, Sc2(U )) is a principal solution for Γ and t . not appear in the type context) to form the type scheme that is used to type the body. This formulation corresponds directly to the substitution-based specification. Proof. Follows from Props. 7 and 10. Definition 12. Let ∀ : GTYPE → TYPESCHEME be ∀(U) = ∀∅.U; For notational convenience, we write ∀(Γ) ≡ ∀ ◦ Γ. This proposition establishes that our type inference procedure produces the best type possible, which implies that the type system 7 Here we assume a call-by-value semantics, but in general that is not indeed has a well-defined notion of “best” types. necessary. Γ∀, x : ∀∅.U `∀ t : U x : U ∈ Γ (σλ:) 1 2 (∀x) (∀n) ∀ ∀ Ω | Γ ` x : U Ω | Γ ` n : Int Γ ` λx : U1.t : U1 → U2

∀ ∀ X ∀ (∀b) Γ , x : ∀∅.T1 ` t : U2 x : ∀Xi.U ∈ Γ Ω | Γ ` b : Bool (σλ) (σx) ∀ ∀ ∀ ∀ X Γ ` λx.t : T1 → U2 Γ ` x :[Ti/Xi]U Ω | Γ ` t1 : U1 → U2 Ω | Γ ` t2 : U1 (∀app) ∀ ∀ Γ ` (λx.t2) t1 : U t1 ∈/ VALUE Ω | Γ ` t1 t2 : U2 (σlet) ∀ ∀ Γ ` let x = t1 in t2 : U Ω | Γ ` t1 : Bool Ω | Γ ` t2 : U Ω | Γ ` t3 : U (∀if) ∀ ∀ ∀ ∀ Γ ` v1 : U1 Γ , x : σ ` t2 : U2 Ω | Γ ` if t1 then t2 else t3 : U ∀ σ = ∀Xi.[Xi/Ai]U1 Ai ∈/ Γ (σletp) Ω | Γ ` t1 : Int Ω | Γ ` t2 : Int ∀ ∀ Γ ` let x = v1 in t2 : U2 (∀+) Ω | Γ ` t1 + t2 : Int

Figure 12. Schematic Typing: Key Rules Ω | Γ, x : U1 ` t : U2 (∀λ:) Ω | Γ ` (λx : U1.t): U1 → U2

Ω,X | Γ ` t : U Ω | Γ ` t : ∀X.U A ∈ TPARAM,U ∈ GTYPE,X ∈ TVAR, x ∈ VAR, (∀Λ) (∀[]) b ∈ BOOL, n ∈ Z, t ∈ TERM, v ∈ VALUE Ω | Γ ` ΛX.t : ∀X.U Ω | Γ ` t[U0]:[U0/X]U U ::= ? | X | A | Int | Bool | U → U | ∀X.U (types) t ::= n | t + t | b | if t then t else t (terms) Ω | Γ ` t1 : U1 Ω | Γ, x : U1 ` t2 : U2 | x | λx : U.t | t t | ΛX.t | t[U] (∀let) Ω | Γ ` let x = t1 in t2 : U2 | let x = t in t | hU ⇐Ui t v ::= n | b | x | λx : U.t | ΛX.v (syntactic values) Ω | Γ ` t : U1 U1 ∼ U2 (∀⇐) Ω | Γ ` hU2 ⇐U1i t : U2 Figure 13. Polymorphic Blame Calculus (PBC): Syntax Figure 14. Polymorphic Blame Calculus (PBC): Type System Proposition 13 (Schematic Substitution). X X ∀ If Γ ` v :[Ai/Xi]U for Ai ∈/ Γ and ∀(Γ), x : ∀Xi.U ` t : U Fig. 15 presents a type-directed translation from the Schematic then Γ ` [v/x]t : U typing judgment for ITGL to PBC. In practice, the type derivation Proof. By induction on the structure of t. is produced by type inference. Most of the rules are straightforward compositional translations. Type abstractions and applications are introduced where necessary. Several of the rules insert casts, as ∀ Proposition 14 (Schematic Abstraction). If ∀(Γ) ` [v/x]t : U1 needed, in positions where consistency is needed. The hhU ⇐ Uiit ∀ ∀ X and ∀(Γ) ` v : U2 for some U2 then ∀(Γ) ` v :[Ai/Xi]U and function inserts a cast when the type translation is nontrivial. ∀(Γ), x : ∀X .U X `∀ t : U for some U X, A ∈/ ∀(Γ), and X . i 1 i i Definition 13 (Context Translation). Proof. By induction on the structure of t. [[]]X ::=  [[x : ∀X.U X, Γ∀]]X ::= [[Γ∀]]X X X Proposition 15. Γ ` t : U if and only if ∀(Γ) `∀ t : U. [[X, Γ∀]] ::= X, [[Γ∀]] [[]]x ::=  Proof. Both directions are by induction on the structure of the [[x : ∀X.U X, Γ∀]]x ::= x : ∀X.U X, [[Γ∀]]x x x corresponding typing judgment. [[X, Γ∀]] ::= [[Γ∀]]

11. Dynamic Semantics Proposition 16 (Well-typed Translation). If Γ∀ `∀ t t0 : U then [[Γ∀]]X | [[Γ∀]]x ` t0 : U. Gradually typed languages are defined by type-directed translation ; to an intermediate language with runtime casts. We do not need to ∀ ∀ 0 develop a new intermediate cast calculus for ITGL: we can translate Proof. By induction on the derivation of Γ ` t t : U it to the Polymorphic Blame Calculus (PBC) (Ahmed et al. 2009, ; 2011) In principle ITGL’s semantics can also be defined using the Fig. 13 presents the syntax of PBC, adapted to our notation. substitutive approach, which essentially monomorphises programs The language extends the polymorphic lambda calculus (Girard at the expense of code explosion. Taking this approach, the image 1972; Reynolds 1974) with support for runtime casts. At run- of the translation is the Blame Calculus (Siek et al. 2009; Wadler time, the calculus also uses runtime sealing to encapsulate poly- and Findler 2009), which is the monomorphic fragment of the PBC. morphically typed values in an effort to enforce representation- independence, even in the face of casts (Matthews and Ahmed 2008). The language supports first-class polymorphism using type- 12. Static and Gradual Polymorphism abstracted terms ΛX.t and types, ∀X.U X, which resemble type This section revisits Siek and Vachharajani’s analysis of gradual schemes, but only abstract a single type variable, and can be open. type inference. Their intuitions about parametric polymorphism Fig. 14 presents the type system of the polymorphic blame led them to design an inference algorithm that does not always calculus. For the most part the type system is standard, but it also yield principal types. Our analysis of that variance uncovers a supports casts hU2 ⇐ U1i t. To type casted terms, the polymorphic distinction among type parameters. We extend our type system and blame calculus presents a more complex consistency relation, but inference procedure to expose this distinction, and thereby give in the absence of first-class polymorphism, it reduces to ∼. firmer foundation to this idea. X ∀ x : ∀Xi.U ∈ Γ B ∈ STPARAM,T ∈ TYPE,U ∈ GTYPE, (σx) ∀ ∀ X W ∈ CASTABLE,Y ∈ GCASTABLE Γ ` x x[Ti]:[Ti/Xi]U V ∈ STATICTYPE = TYPE \ CASTABLE ; (σn) (σb) Z ∈ GSTATICTYPE = GTYPE \ GCASTABLE Γ∀ `∀ n n : Int Γ∀ `∀ b b : Bool T ::= A | B | Int | Bool | T → T U ::= ? | A | B | Int | Bool | U → U ∀ ∀ ; 0 ∀ ∀ 0 ; Γ ` t1 t : U1 Γ ` t2 t : U2 domg (U1) ∼ U2 W ::= A | Int | Bool | W → W (σapp) 1 2 ∀ ;∀ ; Y ::= ? | A | Int | Bool | Y → Y Γ ` t1 t2 : codf (U1) 0 (hhdomg;(U1) → codf (U1)⇐U1iit1) 0 Figure 16. Gradual and Static Type Parameters: Syntax (hhdomg (U1)⇐U2iit2)

∀ ∀ 0 ∀ ∀ 0 Γ ` t1 t1 : U1 Γ ` t1 t2 : U2 ∀ ∀ 0 Γ ` t1 ;t : U3 U1 ∼ Bool U;= U2 u U3 (σif) 3 Other times, type parameters indicate that a value’s only constraint ∀ ∀ ; Γ ` if t1 then t2 else t3 is that it may be cast to and from ?, which may introduce casts. 0 if hhBool⇐U1iit1 ; We distinguish this latter circumstance as an instance of gradual then hhU ⇐U iit0 else hhU ⇐U iit0 : U 2 2 3 3 polymorphism, the exact circumstance that the Polymorphic Blame Calculus was designed to address. Γ∀ `∀ t t0 : U Γ∀ `∀ t t0 : U 1 1 1 1 2 2 To clearly delineate this type-level distinction, we extend our U ∼ Int U ∼ Int (σ+) 1 ; 2 ; languages with another class of type parameters: in addition to the ∀ ∀ 0 0 Γ ` t1 + t2 (hhInt⇐U1iit1) + (hhInt⇐U2iit2): Int gradual type parameters A, we introduce static type parameters B ; (Fig. 16). Γ∀, x : ∀∅.U `∀ t t0 : U (σλ:) 1 2 In ITSL, these type parameters would all be equivalent. How- ∀ ∀ 0 Γ ` λx : U1.t λx : U;1.t : U1 → U2 ever, when we transition to gradual typing, these types are distin- ; guished from their forebears. Γ∀, x : ∀∅.T `∀ t t0 : U (σλ) 1 2 The gradual types extend the static types as usual, thereby cre- ∀ ∀ 0 Γ ` λx.t λx : T1.t; : T1 → U2 ating the universe of types for this language. The type distinc-

∀ ∀ ; 0 tion, however, leads to several families of static and gradual types. Γ ` (λx.t2) t1 t : U t1 ∈/ VALUE (σlet) Castable types W are those static types that can be passed to the ∀ ∀ 0 Γ ` let x =;t1 in t2 t : U dynamic world. Their two salient properties are the absence of the ; unknown type ? and the static type parameter B, which may not Γ∀ `∀ v v0 : U Γ∀, x : σ `∀ t t0 : U 1 1 1 2 2 2 pass to the dynamic world. Indeed there is a gradual counterpart Y . ∀ σ = ∀;Xi.[Xi/Ai]U1 Ai;∈/ Γ (σletp) The static and gradual types that do not appear in these sets make ∀ ∀ Γ ` let x = v1 in t2 up the static types V and gradual static types Z. These latter two 0 0 let x = (ΛXi.[X;i/Ai]v1) in t2 : U2 refer to those types that represent pure parametric polymorphism. In this new model, the unknown type ? no longer represents all Γ∀ `∀ t t0 : UU ∼ U (σ::) 1 possible static types, but only the types in GCASTABLE. In partic- ∀ ∀ 0 Γ ` (t :: U;1) hhU1 ⇐Uiit : U1 ular, they do not include the static types: any type that contains a ; static type parameter. hhU ⇐Uiit = t The most immediate change that results from this interpretation is that not all types are consistent with ?. In particular, Z 6∼ ? for hhU2 ⇐U1iit = hU2 ⇐U1i t if U1 6= U2 any Z ∈ GSTATICTYPE. In fact, it hereditarily follows that any type containing a static type parameter B is not consistent with ?. Figure 15. Gradual Language: Schematic Translation The relevant changes to consistency are as follows.

B ∼ B ? ∼ Y Y ∼ ? To motivate their design, Siek and Vachharajani consider how best to answer the following type inference problem: Static type parameters are consistent to themselves, as is standard, but now ? is consistent to only the castable gradual types Y , not all λx : ?.(λy : X.y) x gradual types U. In ITSL, the consequence is that the language has more type X Clearly this program is typeable, but what type should get? variables, which to date has not been a problem in practice. For Our type inferencer makes it a type parameter, producing the type instance, the program λx.x may be given type A → A, using → A ? , but Siek and Vachharajani’s type inference algorithm the gradual type parameters, but our earlier program can at best → → A produces ? ?. Their reasoning is that the type ? implies be given the type B → B using static type parameters. parametric polymorphism, and with it the idea that the type can Furthermore, this extension changes the nature of our type poly- be changed arbitrarily without affecting the program’s behavior. morphism theorem: However, this simple program gets the value of y from a value of type ?, which, assuming a na¨ıve casting model, could trigger a cast Definition 14. error depending on which type is assigned to X.8 In their view, type A signatures with type parameters should indicate static parametric 1. Let S ∈ ASUBST = TPARAM → CASTABLE denote the polymorphism, and this type does not. gradual type parameter substitutions, or A-substitutions. B This observation suggests a distinction that we currently sup- 2. Let S ∈ BSUBST = STPARAM → TYPE denote the static press. Sometimes type parameters indicate parametric polymor- type parameter substitutions, or B-substitutions. P phism in the traditional sense: irrelevant to program execution. 3. Let S ∈ PSUBST = A B A B { S ∪ S | S ∈ ASUBST,S ∈ BSUBST } denote the type 8 Their system precedes PBC and its dynamics had no runtime sealing. parameter substitutions, or P -substitutions. These two substitutions distill the semantics of polymorphism. Our language from Sec. 11 corresponds to interpreting both Gradual type parameters A represent castable types W ; conversely, static and gradual type parameters using runtime sealing. A more static type parameters B represent all static types, including the refined language could use static parametric polymorphism for gradual type parameters A. In practice, we are interested in sub- static type parameters and reserve runtime sealing only for gradual stitutions SP = SA ∪ SB which simultaneously map gradual and type parameters. static type parameters to castable types and static types, respec- Viewed from this perspective, Siek and Vachharajani interpret tively. These P -substitutions capture our new notion of type poly- all gradual type parameters as ?, leaving only the static type pa- morphism. rameters. This language model can be translated to the (monomor- phic) Blame Calculus, erasing static type parameters in the stan- Proposition 17. dard way. Note, however, that this translation of Bs to ?s implies a 1. If Γ ` t : U then ScP (Γ) ` ScP (t): ScP (U) for any syntactic reinterpretation of our programs. In particular, since our P S ∈ PSUBST. type system does not infer gradual types, this reinterpretation cor- responds to a refinement process on programs that introduces new Proof. Straightforward induction on derivations Γ ` t : U. type annotations to a program that change some parameters to grad- ?α ual types. The λ→ language interprets these types without incident 12.1 Type Inference for Pure Parametric Polymorphism since gradual types were always inferrable, but at the cost of a com- Now that we have described an implicitly typed language with plex type system and inferencer. two tiers of parametric polymorphism, how do we infer these two types? Conveniently, doing so requires only a small extension to our type inference approach. Our type inferencer up to now has 13. Discussion simply discarded constraints that require a type to be consistent Construction of the type system and inference was systematic and with ?, since this was true of every type. Now we must consider driven by underlying principles of the static type system. The struc- them, because they make the difference between a static parametric ture of ITSL sheds light on the structure of the Simply Typed Grad- type and a gradual one. ual Calculus’ type system, in particular the origin of the two typing To account for the type distinction, we extend the unification rules for function application. relation to be a ternary relation The constraint typing judgment does not hold for every context– U ∈ P(GCASTABLEEXP) × P(CONSTRAINT) × XSUBST, term pair. This property falls out of our decision to reduce all grad- ? ? ual predicates and functions to consistency constraints on gradual where T | C U SX means that the constraints C plus (U X ∼˙ ?) types and equality constraints on static types. Alternatively, we for each U X ∈ T are unified by SX. We modify the previous unification relation as follows: could have produced constraints that directly correspond to those T ∪ { U X } | C? U SX operators. Doing so would force us to also support gradual type variables, at least to account for the meet operator when typing if T | C? ∪ { ? ∼˙ U X } U SX T | ∅ U ScB ◦ [Vars(T ) 7→ Ai] expressions. This design simplifies the constraint typing judgment,

X ? X at the expense of the unification judgment, which would have to T ∪ { U } | C U S process more constraints, and be mindful of the order in which they T | C? ∪ { U X ∼˙ ? } U SX are processed. Reducing constraints up-front imposes fewer exten- sions on the corresponding static unification judgment. [X\7→ T X](T ) | [X\7→ T X](C?) U SX X/∈ Vars(T X) The ITGL type system can be easily shown to conservatively . T | C? ∪ { X = T X } U ScX ◦ [X 7→ T X] extend the ITSL type system. In particular, the gradual operators all reduce to their static counterparts when applied to static types. In First, we no longer discard constraints that U X ∼ ? because we X contrast, Siek and Vachharajani (2008) requires explicit reasoning must now ensure that ScX(U ) ∈ GCASTABLE to secure the type to establish this property. distinction. Note that T ∈ GCASTABLEEXP imposes implicit Distinguishing type parameters from type variables was central side-conditions on each of the rules. Second, to satisfy an empty X to understanding the distinction between static polymorphism and constraint set, the corresponding substitution S must map all type gradual polymorphism, both of which are orthogonal to the type in- variables in T to gradual type parameters Ai. The remaining type ference problem. This distinction explains Siek and Vachharajani’s variables have no constraints, so they can safely be mapped to static observation about assigning the unknown type. Such types are not type parameters Bi. principal according to their type system, but they arise naturally With these few extensions, the corresponding notions of sound- from interpreting gradual type parameters in our system as ?. ness and completeness of unification, as well as principal types, The ease with which ITGL extends with let-polymorphism sug- hold. gests that the language may be amenable to other common features Proposition 18 (Principal Types). Suppose ΓX ` tX : U X | C? | X . of Hindley-Milner type systems, like row polymorphism (Wand X ? X ? X 1987b) and restricted first-class polymorphism (Peyton Jones et al. Then if S1 |= C for some S1, it follows that ∅ | C U S2, and 2007). We intend to explore some of these more advanced features (SX, ScX(U X)) is a principal solution for ΓX and tX. 2 2 in the future. Furthermore, we believe that the connection between This proposition establishes that our type inference procedure this system and its underlying static language suggests that it may produces the best type possible, and along the way proves that the be reasonable to extend an existing language implementation to type system has a well-defined notion of “best” types. support gradual type inference. Although ITGL can be safely translated to either the Blame 12.2 Dynamic Semantics Calculus (BC) or the Polymorphic Blame Calculus (PBC), we do This new type distinction suggests two more interpretations of not yet understand all the tradeoffs involved. The BC imposes ITGL. These interpretations differ with respect to whether or not less runtime overhead since it does not require runtime sealing, they enforce representation-independence at runtime, and con- but the PBC enforces representation-independence. Extending the versely with respect to the complexity of the necessary runtime language with first-class polymorphism, and implementing gradual support. type inference in a real language, may provide further insight. Related Work Aside from (Siek and Vachharajani 2008), the most D. Crystal. A dictionary of linguistics and phonetics. Blackwell, 2008. closely related work to ours is Rastogi et al. (2012). It presents an S. K. Debray and D. S. Warren. Automatic mode inference for logic approach to flow-based type inference for a variant of the Action- programs. Journal of Logic Programming, 5(3):207–229, Sept. 1988. Script language that combines static and dynamic checking. Al- J.-Y. Girard. Interprtation fonctionelle et limination des coupures de though both works involve graduality and inference, the two have l’arithmtique d’ordre suprieur. PhD thesis, Universit Paris VII, 1972. essential differences that make them complementary. J. Gronski, K. Knowles, A. Tomb, S. N. Freund, and C. Flanagan. Sage: First, the two approaches start with different kinds of languages. Hybrid checking for flexible specifications. In Proc. Scheme and Func- We begin with an implicitly typed functional language, for which tional Programming Workshop, pages 93–104, 2006. types are typically inferred using unification. Rastogi et al. start J. Matthews and A. Ahmed. Parametric polymorphism through run-time from a subtyping-based object-oriented language, for which unifi- sealing or, theorems for low, low prices! In Proc. European Conference cation is insufficient to infer types. on Programming Languages and Systems, ESOP’08/ETAPS’08, pages Second, the two approaches start from different conceptual 16–31, Berlin, Heidelberg, 2008. Springer-Verlag. foundations. Rastogi et al. begin with a gradually typed language in J. Matthews and R. B. Findler. Operational semantics for multi-language the style of (Siek and Taha 2006), where missing type annotations programs. ACM Transactions on Programming Languages and Systems, are syntactic sugar for ? annotations, and extend it with support for 31(3):12:1–12:44, Apr. 2009. type inference. To do so, they reinterpret missing type annotations R. Milner. A theory of type polymorphism in programming. Journal of as type variables and solve for gradual types using a flow-directed Computer and System Sciences, 17:348–375, Aug. 1978. algorithm. We begin with an implicitly typed language and extend A. Ohori. A simple semantics for ml polymorphism. In Proc. Interna- it with gradual typing. In doing so, we infer the same static types tional Conference on Functional Programming Languages and Com- as the underlying language. It is interesting to observe, however, puter Architecture, FPCA ’89, pages 281–292, New York, NY, USA, that Siek and Vachharajani (2008) start from similar foundations to 1989. ACM. . Rastogi et al., but arrive at a type system like ours. S. Peyton Jones, D. Vytiniotis, S. Weirich, and M. Shields. Practical type Third, the two approaches have distinct goals. Rastogi et al. are inference for arbitrary-rank types. Journal of Functional Programming, interested in reducing the performance overhead of gradual typ- 17(1):1–82, Jan. 2007. . ing by removing dynamic checks where possible without chang- B. C. Pierce. Types and programming languages. MIT Press, Cambridge, ing the runtime error behaviour of programs. We are interested in MA, USA, 2002. consistency-based reasoning about programs in terms of the under- A. Rastogi, A. Chaudhuri, and B. Hosmer. The ins and outs of gradual lying pre-existing type system. type inference. In Proc. Symposium on Principles of Programming Ultimately, the two approaches are complementary. In partic- Languages, pages 481–494, New York, NY, USA, 2012. ACM. . ular, we believe that techniques similar to Rastogi et al. could be J. C. Reynolds. Towards a theory of type structure. In Programming applied to ITGL to reduce runtime overhead. One open problem in Symposium, Proceedings Colloque Sur La Programmation, pages 408– this direction is the interaction between flow-based inference and 423, London, UK, UK, 1974. Springer-Verlag. runtime sealing. J. A. Robinson. A machine-oriented logic based on the resolution principle. J. ACM, 12(1):23–41, Jan. 1965. ISSN 0004-5411. . 14. Conclusion I. Sergey and D. Clarke. Gradual ownership types. In H. Seidl, editor, Proc. Dynamic checking is often characterized as the practice of check- European Symposium on Programming Languages and Systems, volume ing at runtime those expressions that lack type annotations. Static 7211 of ESOP ’12, pages 579–599, Tallinn, Estonia, 2012. Springer- checking, on the other hand, is associated with introducing type an- Verlag. notations to achieve more safety. This paper investigates the com- J. Siek and W. Taha. Gradual typing for objects. In E. Ernst, editor, bination of dynamic and static checking, and finds that the tables Proc. European Conference on Object-oriented Programming, number reverse in the foundations of gradual type inference: there can be 4609 in ECOOP ’07, pages 2–27, Berlin, Germany, July 2007. Springer- no dynamism without annotation. Verlag. J. Siek, R. Garcia, and W. Taha. Exploring the design space of higher- 15. Acknowledgments order casts. In Proc. European Symposium on Programming Languages, ESOP ’09, pages 17–31, Berlin, 2009. Springer-Verlag. The authors would like to thank Suzanna Crage, Jeremy Siek, Eric´ J. G. Siek and W. Taha. Gradual typing for functional languages. In Proc. Tanter, Sam Tobin-Hochstadt, Amal Ahmed, Bob Harper, and the Scheme and Functional Programming Workshop, pages 81–92, Sept. anonymous reviewers for comments and suggestions. 2006. We thank Khurram A. Jafery and Atsushi Igarashi for contribut- J. G. Siek and M. Vachharajani. Gradual typing with unification-based ing to updates and corrections after publication. inference. In Proc. 2008 Symposium on Dynamic Languages, DLS ’08, pages 7:1–7:12, New York, NY, USA, 2008. ACM. . References N. Swamy, C. Fournet, A. Rastogi, K. Bhargavan, J. Chen, P.-Y. Strub, and A. Ahmed, R. B. Findler, J. Matthews, and P. Wadler. Blame for all. In G. Bierman. Gradual typing embedded securely in JavaScript. In Proc. Proc. 1st Workshop on Script to Program Evolution, STOP ’09, pages 41st ACM SIGPLAN-SIGACT symposium on Principles of programming 1–13, New York, NY, USA, 2009. ACM. . languages (POPL 2014), pages 425–437, San Diego, CA, USA, Jan. 2014. ACM Press. A. Ahmed, R. B. Findler, J. G. Siek, and P. Wadler. Blame for all. In Proc. Symposium on Principles of Programming Languages, POPL ’11, pages S. Tobin-Hochstadt and M. Felleisen. Interlanguage migration: From scripts 201–214, New York, NY, USA, 2011. ACM. . to programs. In Companion to the 21st ACM SIGPLAN Symposium on Object-oriented Programming Systems, Languages, and Applications, G. Bierman, E. Meijer, and M. Torgersen. Adding dynamic types to # OOPSLA ’06, pages 964–974, New York, NY, USA, 2006. ACM. ISBN C . In T. D’Hondt, editor, Proc. 24th European Conference on Object- 1-59593-491-X. oriented Programming (ECOOP 2010), number 6183 in Lecture Notes in Computer Science, pages 76–100, Maribor, Slovenia, June 2010. S. Tobin-Hochstadt and M. Felleisen. The design and implementation of Springer-Verlag. Typed Scheme. In Proc. 35th ACM SIGPLAN-SIGACT Symposium on R. Cartwright and M. Fagan. Soft typing. In Proc. Conference on Program- Principles of Programming Languages (POPL 2008), pages 395–406, ming Language Design and Implementation, PLDI ’91, pages 278–292, San Francisco, CA, USA, Jan. 2008. ACM Press. New York, NY, USA, 1991. ACM. P. Wadler and R. B. Findler. Well-typed programs can’t be blamed. In Proc. 459–483, Lancaster, UK, July 2011. Springer-Verlag. European Symposium on Programming Languages, ESOP ’09, pages 1– A. K. Wright. Simple imperative polymorphism. Lisp Symb. Comput., 8(4): 16, Berlin, 2009. Springer-Verlag. 343–355, Dec. 1995. ISSN 0892-4635. . M. Wand. A simple algorithm and proof for type inference. Fundamenta A. K. Wright and M. Felleisen. A syntactic approach to type soundness. Infomaticae, 10:115–122, 1987a. Journal of Information and Computation, 115(1):38–94, Nov. 1994. M. Wand. Complete type inference for simple objects. In Proc. 2nd IEEE T. Wrigstad, F. Zappa Nardelli, S. Lebresne, J. Ostlund,¨ and J. Vitek. In- Symposium on Logic in Computer Science, pages 37–44, 1987b. tegrating typed and untyped code in a scripting language. In Proc. R. Wolff, R. Garcia, E.´ Tanter, and J. Aldrich. Gradual typestate. In 37th annual ACM SIGPLAN-SIGACT symposium on Principles of pro- M. Mezini, editor, Proc. European Conference on Object-oriented Pro- gramming languages (POPL 2010), pages 377–388, Madrid, Spain, Jan. gramming, volume 6813 of Lecture Notes in Computer Science, pages 2010. ACM Press.