<<

Inference

Michel Mauny Benoît Vaugon Unité d’Informatique et d’Ingénierie des Systèmes (U2IS) ENSTA-ParisTech France {michel.mauny,benoit.vaugon} ensta-paristech.fr

We present type inference algorithms for nullable types Now, the compilation of Some(expr) needs to generate a in ML-like programming languages. Starting with a sim- test, in order to use the special representation of Somen(None) ple system, presented as an algorithm, whose only inter- when expr evaluates to None, and pattern-matching against est is to introduce the formalism that we use, we replace Some/None also needs to be adjusted. unification by constraints and obtain a more in- teresting system. We state the usual properties for both systems. This is work in progress. This paper does not aim at opposing nullable types to op- tion types. Options, in the Hindley-Milner type discipline, offer not only type safety, but also precision by distinguish- 1 Nullable vs. option types ing Some(None) from None, but at the price of a memory al- location or a dynamic test for Some. On the other hand, nul- Imperative programming languages, such as C or Java deriva- lable types extend any classical type t into t?, to include NULL. tives, make abundant use of NULL either as a value for un- Such “nullable values” are easier to represent and compile known or invalid references, or as failure return values. Us- than options, but offer less precision since it makes no sense NULL if ing is rather practical, since the statement suffices for to extend further t?. Also, their static inference haven’t re- checking NULL-ity. Of course, the downside of having NULL as ceived much attention, so far. Indeed, although quite a few a possible value is that, without further support, it could acci- recent programming laguages statically check the safety of dentally be confused with a legal value, leading to execution NULL [3, 2, 11, 1], none of them really performs type infer- errors [7]. ence in the ML sense, but rather local inference, propagat- In languages using the ML type discipline, the ing mandatory type annotations of function parameters in- type α option = None | Some of α side the function bodies. injects regular values and the nullary data constructor None, into a single type that could be thought as a nullable type. 2 Nullable type inference The guarantees that options cannot be confused with regular values, and pattern-matching is used to check and extract regular values from options. In Haskell, the The purpose of this work is to study type inference of nul- “maybe” is heavily used for representing successes lable types, by adding them as a feature in a small functional and failures. The JaneStreet Core library [9] uses the option language. The language that we consider, given in figure 1, type to show possible failures in function types: it purposely is a classical mini-ML, extended with NULL test and creation. avoids exceptions, because their non-appearance in OCaml Section 3 starts with a naïve approach, where the types τ types hides the partiality of functions. In OCaml, None and Some are automatically inserted by the compiler for dealing c ::= () true f alse 0 1 2 ... + ... with optional arguments [5]. | | | | | | | | e ::= c x λx.e e e if e then e else e Using the option data type presents the disadvantage of | | | 1 2 | 1 2 3 let x = e in e allocating memory blocks for representing Some(_) values, | 1 2 NULL case e1 of NULL e2 x e3 which may refrain experienced programmers from heavily us- | |  k  ing options. Avoiding those memory allocations is not really difficult: if Some(v) is represented as v itself, that is, without Figure 1: The language allocating a block tagged as Some, we need a special represen- tation for None, distinct from the representation of v, for any v. Of course, when v is None itself, it then becomes impossi- (that are assigned to expressions e) are pairs (t, ν) of a usual ble to distinguish Some(None) from None. Therefore, None is type t and a “nullability” type information ν. A type (t, ?) cor- not the only special case that needs a special treatment: the responds to values that may be NULL, whereas (t, ∆) denotes whole range of Somen(None) values, for n 0 needs a spe- values that cannot be NULL. Nullability variables are written cial representation such that Somei(None) cannot≥ be confused δ. This system is mainly used to introduce the formalism that with Somej(None) when i , j. we use for writing our algorithms. For instance, unaligned addresses on 64- architectures, Section 4 shows a translation algorithm that encode nul- or a statically pre-allocated array of a sufficient size could do lable values with polymorphic variants. Typing the trans- the job1. lated programs with a unification-based mechanism suffers the same weakness as our naive type system. 1Although polymorphic recursion theoretically allows for unbounded depth of Somen(None) while this representation allows for representing only Section 5 presents a more sophisticated typing mechanism, a finite number of n, this limitation should never be met in practice. where unification is replaced by subtyping constraints.

Submitted to ML 2014 2

TCONST TINSTVAR TINST(α) Φ τ = T(c) B Φ0 Φ τ0 = τ B Φ0 let α0 fresh Φ, Γ x : σ[α α0] x : τ B Φ0 ` ` ⊕  ` Φ, Γ c : τ B Φ0 Φ, Γ x : τ0 x : τ B Φ0 Φ, Γ x : α.σ x : τ B Φ0 ` ⊕ ` ⊕ ∀ ` TINST(δ) let δ0 fresh Φ, Γ x : σ[δ δ0] x : τ B Φ0 ⊕  ` Φ, Γ x : δ.σ x : τ B Φ0 ⊕ ∀ ` TLAMBDA let α , δ , α , δ fresh Φ, Γ x :(α , δ ) e :(α , δ ) B Φ0 Φ0 τ = (α , δ ) (α , δ ) B Φ00 1 1 2 2 ⊕ 1 1 ` 2 2 ` 1 1 → 2 2 Φ, Γ λx.e : τ B Φ00 ` TAPP let α, δ fresh Φ, Γ e : ((α, δ) τ), ∆) B Φ0 Φ0, Γ e :(α, δ) B Φ00 ` 1 → ` 2 Φ, Γ e e : τ B Φ00 ` 1 2 TLET let α, δ fresh Φ, Γ e :(α, δ) B Φ0 Φ0, Γ x : gen(Φ0, Γ, (α, δ)) e : τ B Φ00 ` 1 ⊕ ` 2 Φ, Γ let x = e in e : τ B Φ00 ` 1 2 TIFTHENELSE TNULL Φ, Γ e :(bool, ∆) B Φ0 Φ0, Γ e : τ B Φ00 Φ00, Γ e : τ B Φ000 let α fresh Φ τ = (α, ?) B Φ0 ` 1 ` 2 ` 3 ` Φ, Γ if e then e else e : τ B Φ000 Φ, Γ NULL : τ B Φ0 ` 1 2 3 ` TCASE let δ fresh Φ, Γ e :(t, ?) B Φ0 Φ0, Γ e : τ B Φ00 Φ00, Γ x : δ.(t, δ) e : τ B Φ000 ` 1 ` 2 ⊕ ∀ ` 3 Φ, Γ case e1 of NULL e2 x e3 : τ B Φ000 `  k 

Figure 3: Typing rules

gen(Φ, Γ, τ) = gen0(Φ(Γ), Φ(τ)) τ ::= (t, ν) t ::= tb α τ1 τ2 µα.τ | | → | gen0(Γ, σ) = gen0(Γ, α.σ) when α FTV(σ) α < FTV(Γ) tb ::= unit bool int ν ::= ? δ ∆ ∀ ∈ ∧ | | | | gen0(Γ, σ) = gen0(Γ, δ.σ) when δ FTV(σ) δ < FTV(Γ) ∀ ∈ ∧ gen0(Γ, σ) = σ otherwise Figure 2: The types Figure 4: Generalisation

3 A simple type system or merge (EQMERGE) variable bindings in the Φ substitution. EQNEW , installs a binding in the substitution We first present a rather simple type system, where the types (α) α = t0 Φ[α (that is, in which free occurences of are replaced by carry a “nullability information” saying whether the value of t0] Φ α ) when there is no previous binding about in . Here, an expression may be NULL or not. t0 α Φ t0 is either t or t, depending on whether occurs or not in t. The judgements of our language’s type system are of the µα. α EQNEW(δ) does the same, in a simpler context, on nullability form Φ, Γ e :(t, ν) B Φ , where Φ and Φ are substitutions, Γ 0 0 variables. is a type environment` that maps program identifiers to type EQMERGE merges a new constraint t to a previous schemes (types with a prenex universal quantification of type (α) α = 0 t occuring in . Here, the resulting substitution is and nullability variables). Such a judgement should be read α = Φ Φ0 obtained by resolving the constraint t = t . EQMERGE(δ) does as: given Φ, under assumption Γ, the expression e has type τ 0 the same for nullability variables. with substitution Φ . 0 Correctness. The operational semantics needed for stating The rules should be read as the different cases of an al- the correction of the type system is also classical. NULL cannot gorithm that, given Φ, Γ, e, and τ, computes substitution Φ 0 handle operations such as being called as a function, tested which, when applied to τ and Γ, assign the type Φ (τ) to e. In 0 as a boolean, added as an integer, etc. The typing of values, other words, under assumptions Φ (Γ), e has type Φ (τ). 0 0 procuded by correct executions, is also slightly changed: the Because we have two kinds of variables, we have two in- type (t, ?) includes NULL as well as regular values. The cor- stanciation mechanisms, in distinct rules: TINST(α) for uni- rectness property can be stated as follows: versally quantified type variables, and TINST(δ) for universally If Φ, Γ e : τ B Φ0, then the evaluation of e in an exe- quantified nullability variables. ` Type equality constraints, introduced by typing rules, are cution environment compatible with Φ0(Γ) produces solved using a of rules displayed in figure 5. The only in- a value typable with Φ0(τ), if evaluation terminates. teresting resolution rules are the ones that introduce (EQNEW) Although this type system is simple and may seem practical, 3

EQSPLIT EQARROW EQBASE EQTRIVIAL(α) Φ t = t B Φ0 Φ0 ν = ν B Φ00 Φ τ = τ0 B Φ0 Φ0 τ = τ0 B Φ00 ` 1 2 ` 1 2 ` 1 1 ` 2 2 Φ (t , ν ) = (t , ν ) B Φ00 Φ tb = tb B Φ Φ τ τ = τ0 τ0 B Φ00 Φ α = α B Φ ` 1 1 2 2 ` ` 1 → 2 1 → 2 ` EQNEW(α) EQMERGE(α) EQTRIVIAL(δ) when t , α α = _ < Φ let t0 = clos(α, Φ(t)) when t , α Φ α = t0 t = t0 B Φ0 ∧ ⊕ ` Φ α = t B Φ[α t0] α = t0 Φ α = t0 α = t B Φ0 Φ δ = δ B Φ `  ⊕ ⊕ ` ` EQNEW(δ) EQMERGE(δ) when ν , δ δ = _ < Φ when ν , δ Φ δ = ν0 ν = ν0 B Φ0 clos( t) = t when FTV(t) ∧ ⊕ ` α, α < Φ δ = ν B Φ[δ ν] δ = ν Φ δ = ν0 δ = ν B Φ0 = µα.t otherwise `  ⊕ ⊕ `

Figure 5: Resolution rules

it imposes a certain style of programming where NULL val- As expected, the translation of the above example does not ues are as much isolated as possible from other parts of the pass OCaml typechecking: program. In a ML-like language, where NULL (or similar con- let (+) = ‘Some (fun x y -> struct such as None) are not as commonly used as in C or Java, match x, y with this might be acceptable. Still, one might want the following | ‘Some x, ‘Some y -> ‘Some (x+y)) example to be typable: let f = ‘Some (fun b k -> let f b k = let p = (match (+) with let p = k + 1 in | ‘Some f_0 -> f_0) k (‘Some 1) in if b then k else NULL in if match b with ‘Some b_0 -> b_0 ... then k else ‘None) in ... ^^^^^ This program cannot typecheck since the k parameter must at Error: this expression has type [> ‘None ] but an the same time have type (int,∆) in order to be sent to + and expression was expected of type [< ‘Some of int ]. (int,?) in order to have the same type as NULL. This is due to the fact that the type inference of OCaml poly- morphic variants use unification, even though it emulates 4 Encoding nullability as variants some form of subtyping with a rich type algebra [6]. We have extended the work of Garrigue in order to have a more flexible and powerful type system for polymorphic variants. Although this is still work in progress, we show NULL = ‘None J x K = x here how to apply this result to nullable types. J c K = ‘Some(c) J K if e1 then e2 else e3 J = if matchK e1 with ‘Some(b) b 5 A subtyping approach J K → then e2 else e3 λx.e = ‘SomeJ(λx.K e ) J K We saw in the example above that the propagation of in- J K J K case e1 of NULL e2 x e3 formation “backwards”, by unification in the typing environ- J  k  K = match e1 with ment, prevents typing some programs that could be perfectly J K ‘None e2 acceptable. | → J K ‘Some(x) (λx. e3 )(‘Some(x)) | → J K Replacing unification, which comes from type equality con- e1 e2 = (match e1 with ‘Some( f ) f ) e2 J K J K → J K straints, by inequality constraints, that is, by subtyping, re- Figure 9: Encoding of NULL as variants laxes the programming style imposed by using type unifica- tion. While this is clearly more permissive, the resolution of inequality constraints may still fail. On the one hand, some Typing nullability of our language can be easily performed unification constraints remain hidden as double inequalities by a typechecker for polymorphic variants such as those pro- (e.g. when trying to type 1 + "hello"). On the other hand, vided by OCaml. The trick is to encode NULL as ‘None, other some inequalites are clearly not satisfiable, such as those pro- values as ‘Some(_), and computations must assume that only duced when typing a conditional if NULL then ... else ..., definite functions, that is, with shape ‘Some(_), can be ap- where one fails to prove α? 6 bool, or an application NULL(...), plied without further tests. In the same vein, primitive oper- failing to prove α? 6 τ τ . Also, many primitive opera- 1 → 2 ations, such as +, accept only definite arguments. The trans- tions (like (+)) won’t accept nullable arguments. lation, given in figure 9, shows that the typability of nullable We start to change the type algebra of our language and values can trivially be reduced to the typing of polymorphic introduce the syntax “t?” for nullable types, figure 10. variants. Not a big deal, but improving the latter improves The new set of typing rules is given in figure 6. The essen- also the former. tial change that we bring to our initial system is in the TAPP 4

TCONST TINST n 6 > n n n Φ T(c) 6 τ B Φ0 let αk0 1 fresh Φ, αk 6 τ , αk > τ , αk τk≈i 1 [αk αk0 ]1 , τ[αk αk0 ]1 6 τ0 B Φ0 ` { } { { k,i } { k,i } ≈ { , }}  `  6 > n Φ, Γ c : τ B Φ0 Φ, Γ x : αk[6 τ ][> τ ][ τ≈ ] .τ x : τ0 B Φ0 ` ⊕ ∀{ { k,i } { k,i } ≈ { k,i } }1 ` TLAMBDA let α , α fresh Φ, Γ x : α e : α B Φ0 Φ0 α α 6 τ B Φ00 1 2 ⊕ 1 ` 2 ` 1 → 2 Φ, Γ λx.e : τ B Φ00 ` TAPP let α fresh Φ, Γ e : α τ B Φ0 Φ0, Γ e : α B Φ00 ` 1 → ` 2 Φ, Γ e e : τ B Φ00 ` 1 2 TLET let α fresh Φ, Γ e : α B Φ0 Φ0, Γ x : gen(Φ0, Γ, α) e : τ B Φ00 ` 1 ⊕ ` 2 Φ, Γ let x = e in e : τ B Φ00 ` 1 2 TIFTHENELSE TNULL Φ , Γ e : bool B Φ Φ , Γ e : τ B Φ Φ , Γ e : τ B Φ let α fresh Φ α? 6 τ B Φ0 0 ` 1 1 1 ` 2 2 2 ` 3 3 ` Φ, Γ if e then e else e : τ B Φ Φ, Γ NULL : τ B Φ0 ` 1 2 3 3 ` TCASE let α fresh Φ , Γ e : α? B Φ Φ , Γ e : τ B Φ Φ , Γ x : α e : τ B Φ 0 ` 1 1 1 ` 2 2 2 ⊕ 1 ` 3 3 Φ0, Γ case e1 of NULL e2 x e3 : τ B Φ3 `  k 

Figure 6: Subtyping rules

t ::= tb α τ1 τ2 τ ::= t t? when the set α FTV(Φ α) does not intersect the set of free | | → | type variables{ occurring}∪ in| Γ. Figure 10: Nullable types At instanciation time, a fresh instance of constraints is re- injected in Φ. Another important change in the new system concerns gen(Φ, Γ, τ) = α[Φ α] α gen_vars(Φ, Γ, τ) .τ the conditional, case selection (and, more generally pattern- ∀{ S| | ∈ } gen_vars(Φ, Γ, τ) = α gen_FTV(Φ,Γ,τ) deps∗(Φ, α ) matching constructs). Instead of unifying the types of all ∈ { } gen_FTV(Φ, Γ, τ) = branches, each of them is contrained to be “smaller” than α α FTV(τ) deps∗(Φ, α ) FTV(Γ) = the type of the construct itself. This forces all types of the deps A A { | ∈ ∧ when{ } ∩deps A ∅A } ∗(Φ, ) = (Φ, ) = branches to be compatible, but no more. See for instance deps∗(Φ, A) = deps∗(Φ, deps(Φ, A)) otherwise S rules TIFTHENELSE and TCASE on figure 6. This is precisely deps(Φ, A) = α A dep_alphas(Φ, α) ∈ S the reason why the example given at the end of section 3 is dep_alphas(Φ, α) = τ dep_tys(Φ,α) FTV(τ) dep_tys(Φ, α) = τ α∈6 τ Φ τ 6 α Φ α τ Φ accepted by the new system. { | ∈ ∨ ∈ ∨ ≈ ∈ } Figure 11: Generalization 6 Properties

We have a prototype implementation of this typing algorithm, rule, where the domain type of the function is constrained to and the proof of correctness of the extension of Garrigue’s be “larger” than the type of the argument in order to accept typing of polymorphic variants, in which this algorithm can it. Intuitively, a function accepting a possibly value as easily be translated. The proof is available online at https: argument, accepts also a provably non-null argument. //github.com/bvaugon/variants/. The inequality constraints, written τ1 > τ2, are integrated in the Φ component of the typing rules by the set of reso- lution rules given in figure 7. At resolution time, newly in- 7 Conclusion tegrated constraints are checked to be consistent with con- straints existing in Φ. In particular, resolution performs We have presented two type systems and a translation algo- the basic subtyping checks through rules LEQBASENULL and rithm aiming at inferring nullable types in ML-like languages. LEQARROWNULL, on figure 7(b). The first type system, rather naive and interesting by its sim- When a type variable α has to be “smaller” (resp. “greater”) plicity, is probably too restrictive to be usable by daily pro- than two types τ1 and τ2, the τi become constrained to be grammers. The translation technique using standard poly- “compatible” (see figure 8), that is to differ only in their (pos- morphic variants has the same weakness. However, exchang- sibly internal) “?” annotations. ing unification against subtyping provides us with a more ex- Generalization (figure 11) universally quantifies type vari- pressive type system. Soundness and termination properties ables α together with its associated constraints, written Φ , have been checked. |α 5

(a) Main comparison rules

GEQ EQ LEQNEW

Φ τ2 6 τ1 B Φ0 Φ τ1 6 τ2 B Φ0 Φ0 τ1 > τ2 B Φ00 when τ1 6 τ2 < ΦΦ, τ1 6 τ2 τ1 τ2 B Φ0 ` ` ` ` ≤ Φ τ > τ B Φ0 Φ τ = τ B Φ00 Φ τ 6 τ B Φ0 ` 1 2 ` 1 2 ` 1 2 LEQALREADYPROVED

Φ, τ 6 τ τ 6 τ B Φ, τ 6 τ 1 2 ` 1 2 1 2 (b) Standard comparison rules

LEQARROW LEQBASETY LEQBASENULL Φ τ0 6 τ B Φ0 Φ0 τ 6 τ0 B Φ00 ` 1 1 ` 2 2 Φ tb tb B Φ Φ τ τ τ0 τ0 B Φ00 Φ tb tb? B Φ ` ≤ ` 1 → 2 ≤ 1 → 2 ` ≤ LEQARROWNULL Φ τ0 6 τ B Φ0 Φ0 τ 6 τ0 B Φ00 ` 1 1 ` 2 2 Φ τ τ (τ0 τ0 )? B Φ00 ` 1 → 2 ≤ 1 → 2 (c) Type-variable comparison rule

LEQSAMEVAR

Φ α α B Φ ` ≤ LEQVARLEQTY when τ0 , α and τ τ0 < ΦΦ, α 6 τ, τ τ0 α τ0 B Φ0 Φ0 τ τ0 B Φ00 ≈ ≈ ` ≤ ` ' Φ, α 6 τ α τ0 B Φ00 ` ≤ GEQVARLEQTY when τ0 , α and τ0 6 τ < ΦΦ, α 6 τ, τ0 6 τ τ0 α B Φ0 Φ0 τ0 τ B Φ00 ` ≤ ` ≤ Φ, α 6 τ τ0 α B Φ00 ` ≤ LEQTYLEQVAR when τ0 , α and τ 6 τ0 < ΦΦ, τ 6 α, τ 6 τ0 α τ0 B Φ0 Φ0 τ τ0 B Φ00 ` ≤ ` ≤ Φ, τ 6 α α τ0 B Φ00 ` ≤ GEQTYLEQVAR when τ0 , α and τ τ0 < ΦΦ, τ 6 α, τ τ0 τ0 α B Φ0 Φ0 τ τ0 B Φ00 ≈ ≈ ` ≤ ` ' Φ, τ 6 α τ0 α B Φ00 ` ≤ LEQVARCPTTY when τ0 , α and τ τ0 < ΦΦ, α τ, τ τ0 α τ0 B Φ0 Φ0 τ τ0 B Φ00 ≈ ≈ ≈ ` ≤ ` ' Φ, α τ α τ0 B Φ00 ≈ ` ≤ GEQVARCPTTY when τ0 , α and τ τ0 < ΦΦ, α τ, τ τ0 τ0 α B Φ0 Φ0 τ τ0 B Φ00 ≈ ≈ ≈ ` ≤ ` ' Φ, α τ τ0 α B Φ00 ≈ ` ≤ LEQVAREND when τ0 , α when ( τ α 6 τ Φ τ τ0 Φ) when ( τ τ 6 α Φ τ 6 τ0 Φ) when ( τ α τ Φ τ τ0 Φ) ∀ | ∈ ⇒ ≈ ∈ ∀ | ∈ ⇒ ∈ ∀ | ≈ ∈ ⇒ ≈ ∈ Φ α τ0 B Φ ` ≤ GEQVAREND when τ0 , α when ( τ α 6 τ Φ τ0 6 τ Φ) when ( τ τ 6 α Φ τ τ0 Φ) when ( τ α τ Φ τ τ0 Φ) ∀ | ∈ ⇒ ∈ ∀ | ∈ ⇒ ≈ ∈ ∀ | ≈ ∈ ⇒ ≈ ∈ Φ τ0 α B Φ ` ≤

Figure 7: Comparison rules 6

(a) Main compatibility rules

CPTNEW CPTALREADYPROVED when τ1 τ2 < ΦΦ, τ1 τ2 τ1 τ2 B Φ0 ≈ ≈ ` ' Φ τ τ B Φ0 Φ, τ τ τ τ B Φ, τ τ ` 1 ≈ 2 1 ≈ 2 ` 1 ≈ 2 1 ≈ 2 (b) Standard compatibility rules

CPTARROW CPTBASETY CPTBASENULL Φ τ τ0 B Φ0 Φ0 τ τ0 B Φ00 ` 1 ≈ 1 ` 2 ≈ 2 Φ tb tb B Φ Φ τ τ τ0 τ0 B Φ00 Φ tb tb? B Φ ` ' ` 1 → 2 ' 1 → 2 ` ' CPTARROWNULL Φ τ τ0 B Φ0 Φ0 τ τ0 B Φ00 ` 1 ≈ 1 ` 2 ≈ 2 Φ τ τ (τ0 τ0 )? B Φ00 ` 1 → 2 ' 1 → 2 (c) Type-variable compatibility rules

CPTSAMEVAR

Φ α α B Φ ` ' CPTVARLEQTY when τ0 , α and τ τ0 < ΦΦ, α 6 τ, τ τ0 α τ0 B Φ0 Φ0 τ τ0 B Φ00 ≈ ≈ ` ' ` ' Φ, α 6 τ α τ0 B Φ00 ` ' CPTTYLEQVAR when τ0 , α and τ τ0 < ΦΦ, τ 6 α, τ τ0 α τ0 B Φ0 Φ0 τ τ0 B Φ00 ≈ ≈ ` ' ` ' Φ, τ 6 α α τ0 B Φ00 ` ' CPTVARCPTTY when τ0 , α and τ τ0 < ΦΦ, α τ, τ τ0 α τ0 B Φ0 Φ0 τ τ0 B Φ00 ≈ ≈ ≈ ` ' ` ' Φ, α τ α τ0 B Φ00 ≈ ` ' CPTVAREND when τ0 , α when ( τ α 6 τ Φ τ τ0 Φ) when ( τ τ 6 α Φ τ τ0 Φ) when ( τ α τ0 Φ τ τ0 Φ) ∀ | ∈ ⇒ ≈ ∈ ∀ | ∈ ⇒ ≈ ∈ ∀ | ≈ ∈ ⇒ ≈ ∈ Φ α τ0 B Φ ` '

Figure 8: Compatibility rules

References [8] Laurent Hubert, Thomas Jensen & David Pichardie (2008): Semantic Foundations and Inference of Non-null Annotations. [1] Apple (2014): Swift, a new for iOS and Available at http://hal.inria.fr/inria-00332356/en/. OS X. Available at https://developer.apple.com/swift. [9] JaneStreet: Package core. Available at https://ocaml. [2] Facebook (2014): HHVM/Hack/Nullable. Available at http: janestreet.com/ocaml-core/latest/doc/core. //docs.hhvm.com/manual/en/hack.nullable.php. [10] Xavier Leroy, Damien Doligez, Jacques Garrigue, Didier Rémy & Jérôme Vouillon (2008): The Objective Caml system (release [3] Facebook (2014): Programming productivity without breaking 4.01): Documentation and user’s manual. Institut National de things. Available at http://hacklang.org/. Recherche en Informatique et en Automatique. Available at [4] Jacques Garrigue (1998): Programming with polymorphic http://caml.inria.fr/pub/docs/manual-ocaml/. variants. Available at http://caml.inria.fr/pub/papers/ [11] Microsoft (2014): Nullable Types (C# Programming Guide). garrigue-polymorphic_variants-ml98.pdf. Available at http://msdn.microsoft.com/en-US/library/ [5] Jacques Garrigue (2001): Labeled and optional arguments 1t3y8s4s.aspx. for Objective Caml. Available at http://wwwfun.kurims. [12] Atsushi Ohori (1995): A Polymorphic Record Calculus and Its kyoto-u.ac.jp/~garrigue/papers/ppl2001.ps.gz. Compilation. ACM Transactions on Programming Languages [6] Jacques Garrigue (2002): Simple type inference for struc- and Systems 17(6), pp. 844–895. Available at http://www. tural polymorphism. In: The Ninth International Workshop riec.tohoku.ac.jp/~ohori/research/toplas95.pdf. on Foundations of Object-Oriented Languages. Available [13] Didier Rémy (1989): Typechecking Records and Variants in at http://www.math.nagoya-u.ac.jp/~garrigue/papers/ a Natural Extension of ML. In: POPL: 16th ACM SIGACT- structural-inf.pdf. Revised on 2002/12/11. SIGPLAN Symposium on Principles of Programming Lan- guages. Available at http://gallium.inria.fr/~remy/ftp/ [7] C. A. R. Hoare (2009): Null References: The Billion Dollar Mis- taoop1.pdf. take. In: Proceedings of QCon, Historically Bad Ideas, London, UK.