Document not found! Please try again

Rank 2 Intersection Types for Local Definitions ... - ACM Digital Library

0 downloads 0 Views 595KB Size Report
A first example of recursive definition that is not ML-typable is the expression. (for a more interesting .... In this section we introduce the syntax of our rank 2 intersection types, together with other basic ...... Example 7.11. (Use of rule (IFI)).
Rank 2 Intersection Types for Local Definitions and Conditional Expressions FERRUCCIO DAMIANI Universita` di Torino

We propose a rank 2 intersection type system with new typing rules for local definitions (let-expressions and letrec-expressions) and conditional expressions (if-expressions and matchexpressions). This is a further step towards the use of intersection types in “real” programming languages. The technique for typing local definitions relies entirely on the principal typing property (i.e. it does not depend on particulars of rank 2 intersection), so it can be applied to any system with principal typings. The technique for typing conditional expressions, which is based on the idea of introducing metrics on types to “limit the use” of the intersection type constructor in the types assigned to the branches of the conditionals, is instead tailored to rank 2 intersection. However, the underlying idea might also be useful for other type systems. Categories and Subject Descriptors: D.3.2 [Programming Languages]: Language classifications—applicative (functional) languages; D.3.3 [Programming Languages]: Language Constructs and Features—polymorphism; F.3.3 [Logics and Meanings of Programs]: Studies of Program Constructs—functional constructs, type structure General Terms: Algorithms, Theory, Languages Additional Key Words and Phrases: Type inference, principal typings, polymorphic recursion

1. INTRODUCTION The Damas/Milner type system [Damas and Milner 1982] is the core of the type systems of modern functional programming languages, like ML [Milner et al. 1997] and Haskell. The fact that this type system is somewhat inflexible1 has motivated the search for more expressive, but still decidable, type systems (see, 1 In

particular it does not allow assigning different types to different occurrences of a formal parameter in the body of a function.

Partially supported by IST-2001-33477 DART and MURST Cofin’01 NAPOLI projects. The funding bodies are not responsible for any use that might be made of the results presented here. Author’s address: Dipartimento di Informatica, Universita` di Torino, Corso Svizzera 185, 10149 Torino, Italy; email: [email protected]. Permission to make digital or hard copies of part or all of this work for personal or classroom use is granted without fee provided that copies are not made or distributed for profit or direct commercial advantage and that copies show this notice on the first page or initial screen of a display along with the full citation. Copyrights for components of this work owned by others than ACM must be honored. Abstracting with credit is permitted. To copy otherwise, to republish, to post on servers, to redistribute to lists, or to use any component of this work in other works requires prior specific permission and/or a fee. Permissions may be requested from Publications Dept., ACM, Inc., 1515 Broadway, New York, NY 10036 USA, fax: +1 (212) 869-0481, or [email protected]. ° C 2003 ACM 0164-0925/03/0700-0401 $5.00 ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003, Pages 401–451.

402



Ferruccio Damiani

for instance, Leivant [1983]; Mycroft [1984]; van Bakel [1993]; Kfoury and Wells [1994]; Damiani and Giannini [1994]; Coppo and Giannini [1995]; Yokouchi [1995]; Jim [1996]; Kfoury and Wells [1999]; Jim [2000]; van Bakel et al. [2000]). Intersection type systems [Coppo and Dezani-Ciancaglini 1980; Coppo 1980; Coppo et al. 1981; Barendregt et al. 1983] are particularly interesting since they generally have the principal pair property (a.k.a. principal typing property),2 whose advantages with respect to the principal type property 3 of the ML type system have been described by Jim [1996] (ML’s lack of principal pairs was already pointed out by Damas [1984] in his PhD thesis). In particular, the system of rank 2 intersection types [Leivant 1983; van Bakel 1993; Yokouchi 1995; Jim 1996] is able to type all ML programs, has the principal pair property, decidable type inference, and complexity of type inference which is of the same order as in ML. In this paper we propose a rank 2 intersection type system with new typing rules for (possibly mutually recursive) local definitions and conditional expressions. This is a further step towards the use of intersection types in “real” programming languages. In order to simplify the exposition, the new typing rules are first introduced though three orthogonal extensions (for local definitions, recursive definitions, and conditional expressions) of a rank 2 intersection type system for a λ-calculus with constants, and then combined into a single system. For the reader unfamiliar with (rank 2) intersection types, we give an early explanation of what a rank 2 intersection type is. Intersection types are obtained from simple types (see, for instance, Hindley [1997]) by adding the intersection type constructor ∧. An expression has type u1 ∧ u2 (u1 intersection u2 ) if it has both type u1 and type u2 . For example, the identity function λx.x has both type int → int and bool → bool, so it has type (int → int) ∧ (bool → bool). Rank 2 intersection types are types that may contain intersections only to the left of a single arrow. So, for instance, ((int → int) ∧ (bool → bool)) → int → int is a rank 2 intersection type,4 while (((int → int) ∧ (bool → bool)) → int) → int is not a rank 2 intersection type. 1.1 Rank 2 Intersection for Local Definitions The Curry/Hindley type system [Hindley 1997] assigns the same type to all the uses of an identifier. To overcome this limitation the ML type system [Damas and Milner 1982] considers the following rule to type local definitions: → U ` e0 : u0 U, x : ∀− α .u0 ` e : u (LETML) U ` let x = e0 in e : u → where − α are the free type variables of u that do not occur free in U . 0

2A

type system has the principal pair property if, whenever a term e is typable, there exist a type environment A and a type v representing all possible typings of e. 3 A type system has the principal type property if, whenever a term e is typable in a type environment A, there exists a type v representing all possible types of e in A. 4 As usual, the arrow type constructor is right associative, so ((int → int) ∧ (bool → bool)) → int → int means ((int → int) ∧ (bool → bool)) → (int → int). ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

Rank 2 Intersection Types for Local Definitions and Conditional Expressions



403

→ The formula ∀− α .u0 is a type scheme: it represents all types u00 that can be → α = obtained from u0 by substituting all the occurrences of the type variables − 0 α1 · · · αm (m ≥ 0) with types u1 · · · um (in this case we say that u0 is an instance → of ∀− α .u0 ). The rule (LETML) allows assigning a different instance of the type → scheme ∀− α .u0 to each occurrence of the let-bound identifier x in e. Systems with rank 2 intersection types can type all the ML typable expressions by handling let-expressions “let x = e0 in e” as syntactic sugar for “(λ x.e)e0 ”. However this strategy has a drawback: it forces assigning simple types to the uses of the locally defined identifier x in e. For instance, the expression5 let g = λ f .λ x. f ( f x) in g (λ y.λ z. y) 3 () true

(1)

(which safely computes 3) cannot be typed, since to type (1) it is necessary to assign the rank 2 type ((int → (bool → int)) ∧ ((bool → int) → (unit → bool → int))) → int → (unit → bool → int) to the use of the let-bound identifier g in the body of the let. In this paper we present a technique that allows assigning rank 2 intersection types to the uses of locally defined identifiers, by exploiting the fact that their definition is indeed available. As we will see (in Section 5.1), the “straightforward” extension of rule (LETML) to rank 2 intersection, that is typing let-expressions let x = e0 in e by associating to the identifier x a rank 2 → α .v0 , where v0 is a rank 2 type and type scheme for e0 (which is a formula ∀− − → α are some of the type variables of v0 ) is not a good solution. In fact, when e0 contains free identifiers, it may happen that replacing a subexpression (λ x.e)e0 with let x = e0 in e does not preserve typability. To avoid this problem we propose → α .hA0 , v0 i, to associate to x a rank 2 pair scheme for e0 (which is a formula ∀− − → where A0 is a type environment, v0 is a rank 2 type, and α are all the type variables of A0 and v0 ). It is worth mentioning that this technique relies entirely on the principal pair property (i.e. it does not depend on particulars of rank 2 intersection), so it can be applied to any system with principal pairs. 1.2 Rank 2 Intersection for Recursive Definitions The typing rule for recursive definitions of the ML type system [Damas and Milner 1982] (FIXML)

U ` λx.e : u → u U ` rec {x = e} : u

allows assigning to a recursive definition rec {x = e} any simple type u that can be assigned to e by associating type u to all the occurrences of x in e. 5 This

example was introduced by Coppo [1980] to illustrate the limitations of the ML type system. ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

404



Ferruccio Damiani

A first example of recursive definition that is not ML-typable is the expression (for a more interesting example we refer to Section 6): rec {x = xx},

(2)

where the application xx can not be typed by assuming a simple type for x. To overcome this limitation Meertens [1983]6 and, independently, Mycroft [1984] proposed the rule for polymorphic recursion: (FIX)

→ → U, x : ∀− α .u ` e : ∀− α .u U ` rec {x = e} : u

Rule (FIX) allows, for instance, assigning type α to the expression (2). However type inference in presence of rule (FIX) is undecidable [Kfoury et al. 1993; Henglein 1993]. Mycroft [1984] presented a semi-algorithm for polymorphic recursion and suggested the following (decidable) restriction of rule (FIX)7 : (FIX0 )

U ` λx1 . · · · λxm .e0 : u1 → · · · → um → u U ` rec {x = e} : u

where (a) e0 is obtained from e by renaming all the free occurrences of x with fresh names x1 , . . . , xm , → (b) − α are the type variables of u that are not free in U , and → α .u. (c) for all j ∈ {1, . . . , m}, u j is an instance of ∀− To see how this rule works observe that typing the expression rec {x = e} with rule (FIX0 ) is the same as typing the expression rec {x = (λx1 . · · · λxm .e0 ) |x ·{z · · x}} m

with rule (FIX). Rule (FIX0 ) is of intermediate power between (FIXML) and (FIX). For instance, rule (FIX0 ) allows assigning type α to the expression (2), but does not allow typing the expression (λ f .rec {x = f (xx)})(λ y. y), that, by using (FIX), can be typed with type α. Rule (FIX0 ) can be further restricted by replacing the requirement (b) with → (b1) − α are the type variables of u that are not free in U, x1 : u1 , . . . , xn : un . The resulting rule, (FIX1), is of intermediate power between (FIXML) and (FIX0 ). For instance it does not allow to typing the expression (2), but it allows assigning 6 The language considered by Meertens [1983], B, has no higher-order function or nested definitions. 7 A semi-algorithm and a check to arrive at a (terminating) type inference algorithm for the language

B was first given by Meertens [1983]. ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

Rank 2 Intersection Types for Local Definitions and Conditional Expressions



405

type α → int → int to the expression8 rec {x = λ y.λz.if (z < 3) then 1 else (x 0 (z − 1) + x false (z − 2))},

(3)

that can not be typed by using (FIXML). By relying on the principal typing property of the system of rank 2 intersection types Jim [1996] proposed a new typing rule for recursive definitions. Jim’s rule can be understood as the extension to rank 2 intersection of rule (FIX1). As we will see (in Section 6.1) the extended rule is more elegant since the use of intersection avoids the renaming of the occurrences of x in e. The typing rule for recursive definitions considered in this paper is a slight improvement of the rule suggested by Jim [1996]. 1.3 Rank 2 Intersection for Conditional Expressions The ML type system handles an if-expression “if e0 then e1 else e2 ” like the application “ifc e0 e1 e2 ”, where ifc is a constant of type scheme ∀α.bool → α → α → α. If we apply this strategy to a system with rank 2 intersection types we are forced to assign simple types to the if-expression and to its branches, e1 and e2 , and so the additional type information provided by intersection is lost. In this paper we propose a technique for assigning rank 2 intersection types to conditional expressions. As we will see (in Section 7.2), allowing one to assign to an if-expression if e0 then e1 else e2 any rank 2 type v that can be assigned to both e1 and e2 destroys the principal pair (and type) property of the rank 2 intersection type system. To preserve the principal pair property, we introduce two metrics on types to “limit the use” of the intersection type constructor in the type v (assigned to the branches e1 and e2 of the if-expression) by “looking at the use” of the arrow type constructor in the principal pairs of e1 and e2 . Although the typing rules presented in the paper are tailored to rank 2 intersection types, the idea of introducing metrics on types to limit the use of intersection in the types assigned to the branches of the conditionals expressions might also be useful for other type systems. 1.4 Organization of the Paper Section 2 of this paper introduces a small programming language, which can be considered the kernel of functional programming languages like ML and Haskell (the evaluation mechanism, call-by-name or call-by-value, is not relevant for the purpose of typechecking). Section 3 introduces the syntax of our rank 2 intersection types, together with other basic definitions. Section 4 presents a rank 2 intersection type system, `∧2 , for the “λ-core” of the language, which does not include local definitions, recursive definitions, and conditional 8 This expression represents a function that, when applied to an arbitrary value e and to an integer n, ignores the argument e and returns:

— 1, if n < 1. — The n-th number of Fibonacci, otherwise. ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

406



Ferruccio Damiani

expressions. Sections 5, 6, and 7 describe three orthogonal extensions of `∧2 : `Loc ∧2 , with a typing rule for local definitions, `Rec ∧2 , with a typing rule for mutually recursive definitions, and `Con ∧2 , with typing rules for conditional expressions (including definitions by pattern matching). , which combines the three extenSection 8 presents the type system `Loc,Rec,Con ∧2 sions. Section 9 describes a sound and complete type inference algorithm for . Related work is discussed in Section 10. Proofs of the main theorems `Loc,Rec,Con ∧2 can be found in the appendix. An extended abstract describing a preliminary version of the system presented in this paper appeared as Damiani [2000]. A prototype implementation of the type inference algorithm for `Loc,Rec,Con ∧2 has been developed as a part of the Master thesis of Leporati [2000] (an online demonstration is available at the url http://lambda.di.unito.it/rank2/). The prototype is written in O’Caml [O’CAML ] and the language accepted is a small subset of O’Caml itself. 2. A SMALL ML-LIKE LANGUAGE We consider two classes of constants: constructors for denoting base values (integer, booleans) and building data structures, and base functions for denoting operations on base values and for decomposing data structures. The base functions include some arithmetic and logical operators, and the functions for decomposing pairs (fst and snd). The constructors include the unique element of type unit, the booleans, the integer numbers, and the constructors for tuples and lists. Let bf range over base functions (all unary) and csn range over n-ary constructors. The syntax of constants (ranged over by c) is as follows c bf cs0 cs2 csn

::= ::= ::= ::= ::=

bf | cs0 | cs2 | cs3 | · · · not | and | or | + | − | ∗ | / | = | < | fst | snd () | true | false | · · · | −1 | 0 | 1 | · · · | nil tuple2 | cons tuplen (n ≥ 3)

Sometimes we will use pair as short for tuple 2 . Expressions (ranged over by e) and patterns (ranged over by p) have the following syntax e ::= x | c | λ x.e | e1 e2 | let x = e0 in e | reci {x1 = e1 , . . . , xn = en } | if e0 then e1 else e2 | match e0 with {p1 ⇒ e1 [] · · · []pn ⇒ en } p ::= x | cs0 | cs2 p1 p2 | cs3 p1 p2 p3 | · · · where x, x1 , . . . , xn range over identifiers. The construct rec allows mutually recursive expression definitions, and the construct match allows definitions by pattern matching. ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

Rank 2 Intersection Types for Local Definitions and Conditional Expressions



407

The finite set of the free identifiers of an expression e is denoted by FV(e). Remark 2.1. (About rec-expressions). A rec-expression reci {x1 = e1 , . . . , xn = en } (where 1 ≤ i ≤ n) denotes the i-th expression defined by the mutually recursive definition {x1 = e1 , . . . , xn = en }. We consider this kind of expression, instead of the more usual letrec-expression letrec {x1 = e1 , . . . , xn = en } in e, for convenience in presenting the type system: considering rec-expressions instead of letrec-expressions allows the separation of the issue of typing mutually recursive definitions from the issue of typing local definitions. This is not restrictive since, for the purpose of typechecking, the expression letrec {x1 = e1 , . . . , xn = en } in e is equivalent to the expression let x1 = e01 in · · · let xn = e0n in e where, for i ∈ {1, . . . , n}, ei0 = reci {x1 = e1 , . . . , xn = en }. A shortcut typing rule for letrec-expression, which avoids the introduction of the n auxiliary expressions ei0 , will be described in Remark 8.2 at the end of Section 8. 3. TYPES, SCHEMES, ENVIRONMENTS, AND ∀-CLOSURE In this section we introduce the syntax of our rank 2 intersection types, together with other basic definitions that will be used in the rest of the paper. 3.1 Types and Schemes We will be defining several classes of types. For sake of readibility we will omit parens ‘(’ and ‘)’ from the grammars describing these types, but parens are of course needed and used throughout the paper.9 The set of simple types (T0 ), ranged over by u, is defined by the grammar: u ::= α | u1 → u2 | d 0 | u1 d 1 | u1 u2 d 2 | · · · We have type variables (ranged over by α), arrow types, and a selection of parametric datatypes (ranged over by d n , where n ≥ 0 is the number of parameters). The 0-parameter datatypes (also called ground types) are: unit (the singleton type), bool (the set of booleans), and int (the set of integers). The other types are list types and n-ary product types (n ≥ 2). d 0 ::= unit | bool | int d 1 ::= list d n ::= ×n

(n ≥ 2)

For sake of readibility, we will often write u1 × · · · × un instead of u1 · · · un ×n . The constructor → is right associative, for example, u1 → u2 → u3 means u1 → (u2 → u3 ), and the constructors d n (n ≥ 1) bind more tightly than →, for example, u1 → u2 list means u1 → (u2 list). The set of rank 1 intersection types (T1 ), ranged over by ui, the set of rank 2 intersection types (T2 ), ranged over by v, and the set of rank 2 intersection 9 Indeed,

we already adopted this convention when we presented the syntax of the programming language (in Section 2). ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.



408

Ferruccio Damiani

schemes (T∀2 ), ranged over by vs, are defined as follows ui ::= u1 ∧ · · · ∧ un v ::= u | ui → v → vs ::= ∀− α .v

(rank 1 types, i.e. intersections of simple types) (rank 2 types) (rank 2 schemes) → where u ranges over the set of simple types T , n ≥ 1, and − α is a finite (possibly 0

empty) sequence of type variables α1 · · · αm (m ≥ 0). Note that T0 = T1 ∩ T2 . Let ² denote the empty sequence, ∀².v is a legal expression, syntactically different from v, so that T2 ∩ T∀2 = ∅. The constructor ∧ binds more tightly than →, for example, u1 ∧ u2 → u3 means (u1 ∧ u2 ) → u3 . Free and bound type variables are defined as usual. For every type t ∈ T1 ∪ T2 ∪ T∀2 let FTV(t) denote the set of free type variables of t. For every scheme → → ∀− α .v it is assumed that {− α } ⊆ FTV(v). Moreover, schemes are considered equal modulo renaming of bound type variables. We say that a scheme vs is closed if FTV(vs) = ∅. To simplify the presentation we adopt the following syntactic convention: we consider ∧ to be associative, commutative, and idempotent. Modulo this convention any type in T1 can be considered as a set of types in T0 . We assume a countable set Tv of type variables. A substitution s is a function from type variables to simple types which is the identity on all but a finite number of type variables. The domain and the set of free type variables occurring in the range of a substitution s are the sets of type variables: Dom(s) = {α | s(α) 6= α} and FTVR(s) = ∪α∈Dom(s) FTV(s(α)). The composition of two substitutions s1 and s2 is the substitution, denoted by s1 ◦ s2 , such that s1 ◦ s2 (α) = s1 (s2 (α)), for all type variables α. We say that s is more general than s0 , written s ≤ s0 , if there is a substitution s00 such that s0 = s00 ◦s. A substitution is idempotent if s = s◦s (i.e. if Dom(s)∩FTVR(s) = ∅). The application of a substitution s to a type t, denoted by s(t), is defined as usual. Note that, since substitutions replace free variables by simple types, we have that T0 , T1 , T2 , and T∀2 are closed under substitution. The following definitions are fairly standard. Note that we keep a clear distinction between subtyping and instantiation relations, and we do not introduce a subtyping relation between rank 2 schemes. Definition 3.1. (Subtyping relations ≤1 and ≤2 ). The subtyping relations ≤1 (⊆ T1 × T1 ) and ≤2 (⊆ T2 × T2 ) are defined by the rules in Figure 1.10 Note that the relations ≤1 and ≤2 are reflexive and transitive. Definition 3.2. (Instantiation relations ≤∀2,0 and ≤∀2,1 ). The instantiation relations ≤∀2,0 (⊆ T∀2 × T0 ) and ≤∀2,1 (⊆ T∀2 × T1 ) are defined as follows. For → every scheme ∀− α .v ∈ T∀2 and for every type → α .v ≤∀2,0 u to mean that u = s(v), for some substitution s; 0. u ∈ T0 , let ∀− → → α .v ≤ u ∧ · · · ∧ u to mean that ∀− α .v ≤ u, 1. u ∧ · · · ∧ u ∈ T , let ∀− 1

n

1

for every i ∈ {1, . . . , n}.

∀2,1

1

n

∀2,0

i

rule (Ref), the condition that u is not an arrow type (i.e., not a type of the shape u0 → u00 ) is included for technical convenience only, to get a syntax directed system.

10 In

ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

Rank 2 Intersection Types for Local Definitions and Conditional Expressions



409

Fig. 1. Subtyping relations ≤1 and ≤2 .

Example 3.3. For vs = ∀α1 α2 α3 .((α1 → α3 ) ∧ (α2 → α3 )) → α3 , we have (remember that ∧ is idempotent): — vs ≤∀2,0 (int → int) → int (by using the substitution s1 = [α1 , α2 , α3 := int]), and — vs ≤∀2,1 ((int → int) → int) ∧ ((bool → bool) → bool) (by s1 as above, and s2 = [α1 , α2 , α3 := bool]). As stated by the following Lemmas, subtyping and instantiation are closed by substitution. LEMMA 3.4. 1. ui ≤1 ui 0 implies s(ui) ≤1 s(ui 0 ). 2. v ≤2 v0 implies s(v) ≤2 s(v0 ). LEMMA 3.5. 0. vs ≤∀2,0 u implies s(vs) ≤∀2,0 s(u). 1. vs ≤∀2,1 ui implies s(vs) ≤∀2,1 s(ui). Remark 3.6. (Comparison with the relations ≤1 , ≤2 , and ≤∀2,1 of Jim [1996]). The relations ≤1 , ≤2 , and ≤∀2,1 are the same as Jim [1996]. However, we have defined the relation ≤∀2,1 in terms of the relation ≤∀2,0 (see Definition 3.2), while Jim [1996] defines ≤∀2,1 in terms of a more complex relation ≤∀2 (⊆ T∀2 × T∀2 ). 3.2 Environments An environment T is a set {x1 : t1 , . . . , xn : tn } of type or scheme assumptions for identifiers such that every identifier xi (1 ≤ i ≤ n) can occur at most once in T . The expression Dom(T ) denotes the domain of T , which is the set {x1 , . . . , xn }. We write T1 , T2 for the environment T1 ∪T2 where it is assumed that Dom(T1 )∩Dom(T2 ) = ∅, and T, x : t as short for T, {x : t}. T | X for the restriction of T to the set of identifiers X , which is the environment {x : t | x ∈ X }. The application of a substitution s to an environment T , denoted by s(T ), is defined as usual. Definition 3.7.

(Rank 0, rank 1, and closed rank 2 environments).

0. A rank 0 environment U is an environment {x1 : u1 , . . . , xn : un } of simple type assumptions for identifiers. 1. A rank 1 environment A is an environment {x1 : ui1 , . . . , xn : uin } of rank 1 type assumptions for identifiers. ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

410



Ferruccio Damiani

2. A closed rank 2 environment D is an environment {x1 : vs1 , . . . , xn : vsn } of closed rank 2 schemes assumptions for identifiers. Given two rank 1 environments A1 and A2 we write A1 + A2 to denote the rank 1 environment {x : ui1 ∧ ui2 | x : ui1 ∈ A1 and x : ui2 ∈ A2 }∪ {x : ui1 ∈ A1 | x 6∈ Dom(A2 )} ∪ {x : ui2 ∈ A2 | x 6∈ Dom(A1 )}, and write A1 ≤1 A2 to mean that —Dom(A1 ) = Dom(A2 ),11 and —for every assumption x : ui2 ∈ A2 there is an assumption x : ui1 ∈ A1 such that ui1 ≤1 ui2 . 3.3 ∀-Closure Given a type v ∈ T2 and a set of type variables W , we write Gen(W, v) for the → → ∀-closure of v in W , i.e. for the scheme ∀− α .v where {− α } = FTV(v) − W . For every rank 1 environment A, let Gen(A, v) be a short for Gen(FTV(A), v). The following lemma will be useful for proving soundness and completeness (Theorem 9.13 of Section 9.3). of the inference algorithm for system `Loc,Rec,Con ∧2 LEMMA 3.8. Then

→ → Let Gen(A, v) = ∀− α .v and {− α } ∩ (Dom(s) ∪ FTVR(s)) = ∅.

s(Gen(A, v)) ≤∀2,1 s(ui) implies Gen(s(A), s(v)) ≤∀2,1 s(ui). 4. SYSTEM `∧2 : RANK 2 INTERSECTION TYPES FOR THE “λ-CORE” OF THE LANGUAGE In this section we introduce the `∧2 type system for the “λ-core” of the language—we do not consider local definitions, recursive definitions, and conditional expressions. We first present the type inference rules (Section 4.1), then we discuss the role played by the two type environments occurring in the judgments of the system (Section 4.2) and state the principal pair property of the system (Section 4.3). In Sections 5, 6, and 7, we will extend `∧2 with new typing rules for local definitions, recursive definitions, and conditional expressions. 4.1 The Type Inference Rules of `∧2 The type inference system `∧2 has judgements of the form D; A `∧2 e : v, requirement Dom(A1 ) = Dom(A2 ) in the definition of A1 ≤1 A2 is “unusual” (going counter to the definitions in other papers). The “usual” definition drops this requirement, thus allowing Dom(A1 ) ⊇ Dom(A2 ). We have added such a requirement since it will simplify the presentation of the type inference system `∧2 (in Section 4).

11 The

ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

Rank 2 Intersection Types for Local Definitions and Conditional Expressions



411

Fig. 2. Types for base functions.

Fig. 3. Types for constructors.

where — v is the rank 2 type inferred for e, — D is a closed rank 2 environment specifying types for the globally defined identifiers12 (note that, by definition of closed rank 2 environment, FTV(D) = ∅), and — A is a rank 1 environment containing the type assumptions for the free identifiers of e which are not in Dom(D). In any valid judgment, we have: —Dom(D) ∩ Dom(A) = ∅, —Dom(A) = FV(e) − Dom(D), and —FV(e) = Dom(D|FV(e) ) ∪ Dom(A). System `∧2 is meant to be used to infer pairs (and not just types).13 We call undefined the identifiers in Dom(A), since their definition is not available when typechecking the expression e.14 We say that e is typable in `∧2 with respect to the environment D if there exist a typing D; A `∧2 e : v, for some A and v. Since we distinguish between global(ly defined) and undefined identifiers, we have two different rules for identifiers (see Figure 4). The rule for typing constants uses the function Typeof (tabulated in Figures 2 and 3), which specifies a closed type scheme for each constant. 12 E.g.

for the identifiers defined in the libraries available to the programmer. way to emphasize this aspect is to use typing judgments of the shape D `∧2 e : hA, vi. However, to make the comparison with other type systems easier, we adopt the more usual notation D; A `∧2 e : v. 14 The possibility of dealing with undefined identifiers allows the support of incremental type inference [Aditya and Nikhil 1991] and smartest recompilation [Shao and Appel 1993] as outlined in Section 4 of Jim [1996]. 13 A

ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

412



Ferruccio Damiani

Fig. 4. Type assignment rules for the “λ-core” of the language (system `∧2 ).

We have two rules for typing an abstraction λ x.e, corresponding to the two cases x ∈ FV(e) and x 6∈ FV(e). Note that rule (ABS) renames the occurrences of the bound identifier x before typing e (the condition “x 0 is fresh” is equivalent to “x 0 does not occur in D and FV(e)”). This renaming is done to prevent “nameclashes” with the identifiers in the environment D (this will be further explained in Section 4.2.3).15 The rule for typing function application, (APP), allows using different typing for each expected type of the argument. The only non-structural rule is (SUB), which allows strengthening the type assumptions in the rank 1 environment and weakening the rank 2 type inferred for the expression (for instance, without rule (SUB) it would not be possible to assign type (α1 ∧ α2 ) → α1 to the identity function λ x.x). 4.2 About Environments and Renaming in Rule (ABS) The two environments in the typing judgements of system `∧2 and the renaming in rule (ABS) will play an essential role in the design the new typing rules for local definitions (see Section 5), recursive definitions (see Section 6), and conditional expressions (see Section 7). In this section we try to clarify their role in system `∧2 . 4.2.1 The Environment A is “Relevant”. A notable feature of system `∧2 is a “relevant” treatment of the type environment A: for any typing D; A `∧2 e : v, —Dom(A) ⊆ FV(e), and —the type environment A has been “built-up” from the type environments of the typings of the subexpression of e. 4.2.2 The Environment D is for “Defined” Identifiers. The environment D stores the closed rank 2 scheme assumptions for the globally defined identifiers. 15 Remember

that, in any valid judgement D; A `∧2 e : v, we have Dom(D) ∩ Dom(A) = ∅.

ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

Rank 2 Intersection Types for Local Definitions and Conditional Expressions



413

4.2.3 The Renaming in Rule (ABS) is Done for “Preserving Typability under Alpha Conversion”. The renaming in rule (ABS) prevents “name clashes” with the identifiers occurring in environment D. It allows, for instance, typing the expression k(λk.fst k), with respect to the environment D = {k : ∀α1 α2 .α1 → α2 → α1 }. In fact we have: D; ∅ `∧2 fst : (β1 × β2 ) → β1 , by axiom (CONST), with s = [α1 := β1 , α2 := β2 ], D; {k 0 : β1 × β2 } `∧2 k 0 : β1 × β2 , by axiom (IDundefined ), D; {k 0 : β1 × β2 } `∧2 fst k 0 : β1 , from hypotheses (1) and (2), by rule (APP), D; ∅ `∧2 λk.fst k : (β1 × β2 ) → β1 , from hypothesis (3), by rule (ABS), (note that renaming the λ-bound identifier k into the fresh identifier k 0 prevents a “name-clash” with the global identifier k), (5) D; ∅ `∧2 k : ((β1 × β2 ) → β1 ) → γ → (β1 × β2 ) → β1 , by axiom (IDglobal ), with s = [α1 := (β1 × β2 ) → β1 , α2 := γ ], and (6) D; ∅ `∧2 k(λk.fst k) : γ → (β1 × β2 ) → β1 , from hypotheses (5) and (4), by rule (APP).

(1) (2) (3) (4)

Without the renaming performed by rule (ABS) in point (4), it would be not possible to type the expression k(λk.fst k), with respect to the environment D (that contains an assumption for the identifier k). be the system obtained from `∧2 by replacing rule (ABS) with the Let `Naive ∧2 following rule (ABSNAIVE)

D; A, x : ui ` e : v x ∈ FV(e) D; A ` λ x.e : ui → v

is not able to type the expression k(λk.fst k), with respect to the System `Naive ∧2 environment D, while it is able to type the expression k(λh.fst h), which is equal, modulo alpha conversion (i.e., renaming of bound identifiers). So, in system , typability is not preserved under alpha conversion, while it is preserved `Naive ∧2 in system `∧2 (that uses rule (ABS)). 4.3 Principal Pairs for `∧2 The type derivations of system `∧2 are closed by substitution (remember that FTV(D) = ∅). LEMMA 4.1. (Substitutivity property for `∧2 ). If D; A `∧2 e : v, then D; s(A) `∧2 e : s(v), for every substitution s. PROOF. By induction on the structure of derivations, using Lemma 3.4 for rule (SUB). The following definition of principal pair takes into account the presence of the environment D. Definition 4.2.

(Pairs, instantiation, and principal pairs for `∧2 ).

(1) A pair hA, vi is a pair for e with respect to D if D; A `∧2 e : v. (2) A pair hA0 , v0 i is an instance of a pair hA, vi if there is a substitution s such that Dom(s) = FTV(A) ∪ FTV(v), s(v) ≤2 v0 and A0 ≤1 s(A). ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

414



Ferruccio Damiani

(3) A pair for e with respect to D is principal if any pair for e with respect to D is an instance of it. If hA, vi is a principal pair for e with respect to D we say that D; A `∧2 e : v is a principal typing for e with respect to D. The type system `∧2 has the principal pair property. THEOREM 4.3. (Principal pair property for `∧2 ). If e is typable in `∧2 with respect to D, then it has a principal pair with respect to D. The proof of the Theorem 4.3 is similar to the proof of Theorem 8.4 of Section 8 , which is an extension of `∧2 ). (the principal pair property for system `Loc,Rec,Con ∧2 5. SYSTEM `Loc ∧2 : RANK 2 INTERSECTION FOR LOCAL DEFINITIONS In this section we extend the system `∧2 to deal with let-expressions. We first motivate and introduce the notion of pair scheme (Section 5.1). Then we present the new type system (Section 5.2). 5.1 From type schemes to pair schemes The simplest way to extend system `∧2 to deal with local definitions is to treat let-expressions let x = e0 in e as syntactic sugar for the application (λ x.e)e0 . This corresponds to introducing the following rule: (LETSUGAR)

D; A ` (λ x.e)e0 : v D; A ` let x = e0 in e : v

Rule (LETSUGAR) allows typing all the let-expressions that can be typed by the ML type system, but it does not allow assigning rank 2 types to the uses of x in e. To overcome this limitation, Jim [1996] suggests typing let-expressions let x = e0 in e by: —inferring a rank 2 type scheme vs0 for the expression e0 , and —associating a different rank 2 type, instance of vs0 , to each use of x in e. The following rule implements this strategy by storing in the environment D the assumptions of the rank 2 type schemes for the let-bound identifiers (note that now the environment D can contain free type variables).16 D; A0 ` e0 : v0 D, x 0 : Gen(FTV(D) ∪ FTV(A0 ), v0 ); A1 ` e[x:=x 0 ] : v D; A ` let x = e0 in e : v ½ A1 , if x ∈ FV(e) where x 0 is fresh and A = A0 + A1 , otherwise (LETTS)

The system `Ts ∧2 which uses this rule to type let-expressions allows, for instance, assigning type int to the expression (1) of Section 1. However it has an rule (LETTS), the condition “x 0 is fresh” is equivalent to “x 0 does not occur in D, FV(e0 ), and FV(e)”. The renaming of the bound identifier x is done just for preserving typability under alpha conversion (see the explanation for rule (ABS), in Section 4.2.3).

16 In

ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

Rank 2 Intersection Types for Local Definitions and Conditional Expressions



415

unpleasant feature: for some e0 and e such that FV(e0 ) 6= ∅, replacing (λ x.e)e0 with let x = e0 in e may not preserve typability, as the following example shows. Example 5.1. (Weakness of rule (LETTS)). System `Ts ∧2 is not able to type the expression x 0 x 0 with respect to the environment {x 0 : ∀².α}, so it is not able to type the expressions λ y.(let x = y in xx). Instead, as shown below, `∧2 (and so also `Ts ∧2 ) allows assigning type ((α1 → α2 ) ∧ α1 ) → α2 to the expression λ y.((λ x.xx) y). So λ y.(let x = y in xx) can be typed by using the rule (LETSUGAR) introduced at the beginning of the section. (1) ∅; {x 0 : α1 → α2 } `∧2 x 0 : α1 → α2 , by rule (IDundefined ), (2) ∅; {x 0 : α1 } `∧2 x 0 : α1 , by rule (IDundefined ), (3) ∅; {x 0 : (α1 → α2 ) ∧ α1 } `∧2 x 0 x 0 : α2 , from hypotheses (1) and (2), by rule (APP), (4) ∅; ∅ `∧2 λ x.xx : ((α1 → α2 ) ∧ α1 ) → α2 , from hypothesis (3), by rule (ABS), (5) ∅; { y 0 : α1 → α2 } `∧2 y 0 : α1 → α2 , by rule (IDundefined ), (6) ∅; { y 0 : α1 } `∧2 y 0 : α1 , by rule (IDundefined ), (7) ∅; { y 0 : (α1 → α2 ) ∧ α1 } `∧2 (λ x.xx) y 0 : α2 , from hypotheses (4), (5), and (6), by rule (APP), (8) ∅; ∅ `∧2 λ y.(λ x.xx) y : ((α1 → α2 ) ∧ α1 ) → α2 , from hypothesis (7), by rule (ABS). This unpleasant feature of system `Ts ∧2 is due to the fact that rule (LETTS) associates to the let-bound identifier x a type scheme which, in general, can not express the principal typing of the expression e0 . To overcome this limitation we introduce the notion of pair scheme. → Definition 5.2. (Pair schemes). A pair scheme ps is a formula ∀− α .hA, vi − → where A is a rank 1 environment, v is a rank 2 type, and α = FTV(A) ∪FTV(v). 5.2 The Type Inference Rules of `Loc ∧2 We propose typing let-expressions let x = e0 in e by: → —inferring a pair scheme ∀− α .hA0 , v0 i for the expression e0 , and → —associating a different rank 2 typing, instance of ∀− α .hA0 , v0 i, to each use of the local(ly defined) identifier x in e. The rules in Figure 5 implement this strategy: rule (LETPS) stores in the environment D the pair scheme assumptions for the let-bound identifier17 and rule (IDlocal ) associates a new rank 2 typing to each use of the let-bound identifier. System `Loc ∧2 extends `∧2 with the rules (IDlocal ) and (LETPS) of Figure 5. The Loc Loc new system extends `Ts ∧2 and is such that D; A `∧2 (λ x.e)e0 : v implies D; A `∧2 let x = e0 in e : v, for all expressions e0 and e. For instance, it allows assigning rule (LETPS), the condition “x 0 is fresh” is equivalent to “x 0 does not occur in D, FV(e0 ), and FV(e)”. Again, the renaming of the bound identifier x is done just for preserving typability under alpha conversion. 17 In

ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

416



Ferruccio Damiani

Fig. 5. Typing rules for local definitions (system `Loc ∧2 ).

type ((α1 → α2 ) ∧ α1 ) → α2 to the expression λ y.(let x = y in xx) of Example 5.1. In fact we have: 0 (1) ∅; { y 0 : α} `Loc ∧2 y : α, by rule (IDundefined ), 0 (2) {x 0 : ∀α.h{ y 0 : α}, αi}; { y 0 : α1 → α2 } `Loc ∧2 x : α1 → α2 , by rule (IDlocal ), with s = [α := α1 → α2 ], 0 (3) {x 0 : ∀α.h{ y 0 : α}, αi}; { y 0 : α1 } `Loc ∧2 x : α1 , by rule (IDlocal ), with s = [α := α1 ], 0 0 (4) {x 0 : ∀α.h{ y 0 : α}, αi}; { y 0 : (α1 → α2 ) ∧ α1 } `Loc ∧2 x x : α2 , from hypotheses (2) and (3), by rule (APP), 0 (5) ∅; { y 0 : (α1 → α2 ) ∧ α1 } `Loc ∧2 (let x = y in xx) : α2 , from hypotheses (1) and (4), by rule (LETPS), (6) ∅; ∅ `Loc ∧2 λ y.(let x = y in xx) : ((α1 → α2 ) ∧ α1 ) → α2 , from hypothesis (5), by rule (ABS).

We write Domglobal (D) for {x | x : vs ∈ D and vs is a closed rank 2 type scheme} and Domlocal (D) for {x | x : ps ∈ D and ps is a pair scheme}. The expression FVR(D) denotes the set of identifiers occurring in the range of D, which is the set ∪x:∀−→α .hA,vi∈Dom(D) Dom(A). In any valid judgement D; A `Loc ∧2 e : v, we have: — {Domglobal (D), Domlocal (D)} is a partition of Dom(D), —Dom(D) ∩ Dom(A) = ∅ and Dom(D) ∩ FVR(D) = ∅, —Dom(A) = (FV(e) − Dom(D)) ∪ FVR(D|FV(e) ), and —FV(e) = Dom(D|FV(e) ) ∪ Dom(A|FV(e) ). Rules (IDlocal ) and (LETPS) destroy the property Dom(A) ⊆ FV(e) of `∧2 . In fact, in system `Loc ∧2 , Dom(A) may contain identifiers that occur in FVR(D|FV(e) ) and do not occur in FV(e). Note, however, that we still have that system `Loc ∧2 does a “relevant” treatment of the type environment A (see Section 4.2.1), since Dom(A) ⊆ FV(e) ∪ FVR(D|FV(e) ). The system `Loc ∧2 has the substitutivity property and the principal pair property. Principal pairs with respect to an environment D are defined as for `∧2 ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

Rank 2 Intersection Types for Local Definitions and Conditional Expressions



417

(see Definition 4.2), just remember that, now, the environment D can contain pair schemes. For an example of application of rule (LETPS) where the principal typing of the let-bound identifier contains an intersection, consider the expression let twice = λ f .λ x. f ( f x) in let tolist = λ y.cons y nil in twice tolist that cannot be typed by the ML type system. The type system `Loc ∧2 can assign the following principal pair schemes to the let-bound identifiers of the expression: twice : ∀ α β γ . h∅, ((α → β) ∧ (β → γ )) → α → γ i tolist : ∀ δ . h∅, δ → δ listi and the principal pair h∅, ϑ → ϑ list listi to the expression twice tolist. The expression18 let selfApply2 = λ z.(z z) z in let apply = λ f .λ x. f x in let reverseApply = λ y.λ g . g y in let id = λ w.w in pair (selfApply2 apply not true) (selfApply2 reverseApply id false not) safely computes pair false true. However, it cannot be typed by the ML type system. System `Loc ∧2 instead allows typing it by assigning the following principal pair schemes to the let-bound indentifiers of the expression: selfApply2 apply reverseApply id

: : : :

∀ α β γ . h∅, ((α → β → γ ) ∧ α ∧ β) → γ i ∀ α β . h∅, (α → β) → α → βi ∀ α β . h∅, α → (α → β) → βi ∀ α . h∅, α → αi

Remark 5.3. (About the renaming in rules (ABS) and (LETPS)). The renaming in rules (ABS) and (LETPS) prevents “name-clashes” with the identifiers occurring in (the domain and in the range of) the environment D, thus preserving typability under alpha conversion. In Section 4.2.3 we have illustrated this point through an example with system `∧2 . We now present another example, illustrating how things become more “subtle” with system `Loc ∧2 , where the environment D can contain pair schemes. be the system obtained from `Loc Let `LocNaive ∧2 ∧2 by replacing rule (ABS) with the rule (ABSNAIVE) presented at the end of Section 4.2.3. Take the expression e1 = (λx.let y = x + 1 in λz.pair y (not z)) 4 true. 18 This

example, suggested by Joe Wells, is essentially a rearrangement of a program that Pawel Urzyczyn [1997] proved to be not typable in Fω . Indeed, Urzyczyn proved the untypability of the expression (λx.z(x(λ f u. f u))(x(λvg . g v)))(λ y. y y y), that cannot be typed in our system, but can be typed by using intersection at rank 3 (so it can be typed by the algorithm given in Kfoury and Wells [1999]). ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

418



Ferruccio Damiani

We have ∅; ∅ `LocNaive e1 : int × bool (indeed the expression e1 is ML-typable), ∧2 while the expression e2 = (λx.let y = x + 1 in λx.pair y (not x)) 4 true . Consider, (which is equal, modulo alpha conversion) cannot be typed by `LocNaive ∧2 in fact, the following fragment of derivation: x + 1 : int, from axioms (IDundefined ) and (CONST), by rule (1) ∅; {x : int} `LocNaive ∧2 (APP), y 0 : int, by axiom (IDlocal ), (2) { y 0 : ∀².h{x : int}, inti}; {x : int} `LocNaive ∧2 pair y 0 : bool → (int × bool), from (3) { y 0 : ∀².h{x : int}, inti}; {x : int} `LocNaive ∧2 axiom (CONST) and hypothesis (2), by rule (APP), not x : bool, from axioms (CONST) (4) { y 0 : ∀².h{x : int}, inti}; {x : bool} `LocNaive ∧2 and (IDundefined ), by rule (APP), pair y 0 (not x) : int × bool, from (5) { y 0 : ∀².h{x : int}, inti}; {x : int ∧ bool} `LocNaive ∧2 hypothesis (3) and (4), by rule (APP), λx.pair y 0 (not x) : (int ∧ bool) → (int × bool), (6) { y 0 : ∀².h{x : int}, inti}; ∅ `LocNaive ∧2 from hypothesis (5), by rule (ABSNAIVE). there is no way to assign to λx.pair y 0 (not x) the type By using system `LocNaive ∧2 bool → (int × bool), and so there is no way to type e2 . The problem that occurred in the example above is that, in the rank 1 environment {x : int ∧ bool} inferred for the expression pair y 0 (not x) in step (5), there has been a “name-clash” between the assumption x : int for the identifier x occurring in the definition of the let-bound identifier y (which is bound by the leftmost λ in e2 ) and the assumption x : bool for the identifier x occurring in the expression pair y 0 (not x) (which is bound by the rightmost λ in e2 ). The system `Loc ∧2 (in which typability is preserved under alpha conversion) prevents “name-clashes” in typing the expression e2 . In fact we have: 0 (1) ∅; {x 0 : int} `Loc ∧2 x + 1 : int, from axioms (IDundefined ) and (CONST), by rule (APP), 0 (2) { y 0 : ∀².h{x 0 : int}, inti}; {x 0 : int} `Loc ∧2 y : int, by axiom (IDlocal ), 0 (3) { y 0 : ∀².h{x 0 : int}, inti}; {x 0 : int} `Loc ∧2 pair y : bool → (int × bool), from axiom (CONST) and hypothesis (2), by rule (APP), 00 (4) { y 0 : ∀².h{x 0 : int}, inti}; {x 00 : bool} `Loc ∧2 not x : bool, by rules (CONST), (IDundefined ), and (APP), 0 00 (5) { y 0 : ∀².h{x 0 : int}, inti}; {x 0 : int, x 00 : bool} `Loc ∧2 pair y (not x ) : int × bool, from hypotheses (3) and (4), by rule (APP), 0 (6) { y 0 : ∀².h{x 0 : int}, inti}; {x 0 : int} `Loc ∧2 λx.pair y (not x) : bool → (int × bool), from hypothesis (5), by rule (ABS), 0 (7) ∅; {x 0 : int} `Loc ∧2 let y = x + 1 in λx.pair y (not x) : bool → (int × bool), from hypotheses (1) and (6), by rule (LETPS), and (8) ∅; ∅ `Loc ∧2 λx.let y = x + 1 in λx.pair y (not x) : int → bool → (int × bool), from hypotheses (7), by rule (ABS), ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

Rank 2 Intersection Types for Local Definitions and Conditional Expressions



419

(9) ∅; ∅ `Loc ∧2 (λx.let y = x + 1 in λx.pair y (not x)) 4 : bool → (int × bool), from hypotheses (8) and axiom (CONST), by rule (APP), (10) ∅; ∅ `Loc ∧2 e2 : int × bool, from hypotheses (9) and axiom (CONST), by rule (APP). 6. SYSTEM `Rec ∧2 : RANK 2 INTERSECTION FOR MUTUALLY RECURSIVE DEFINITIONS In this section we extend `∧2 to deal with rec-expressions. We first present the typing rule for recursive definition of Jim [1996] (Section 6.1). Then we present the new type system (Section 6.2). 6.1 Jim’s Rule for Recursive Definitions The rule for typing recursive definitions proposed by Jim [1996] is (modulo change of notation19 ): D; A ` λx.e : ui → v Gen((A, x : ui), v) ≤∀2,1 ui (REC) D; A ` rec {x = e} : v This rule can be understood as the straightforward extension to rank 2 intersection of the rule (FIX1) presented in Section 1.2. A first example of recursive definition that can be typed by (REC) (or (FIX1)) and cannot be typed by (FIXML) is the expression (3) of Section 1.2. Another example (taken from Jim [1996]) is the recursive definition: rec {x = (λ y.λz.z)(xx)}, that by using (REC) (or (FIX1)) can be typed with principal type α → α, but cannot be typed by (FIXML). Note that, when x 6∈ FV(e), rule (REC) requires that the rank 2 type v assigned to e must be such that Gen((A, x : ui), v) ≤∀2,1 ui, for some ui ∈ T0 (see rule (ABSVAC) of Figure 4). So, for instance, the term rec {x = λ f .λ y. f ( f y)} can be typed with principal type ((α → β) ∧ (β → γ )) → α → γ ,20 while the term rec {x = λ y. y y} cannot be typed.21 This anomaly has been pointed out in Jim [1995] where a solution to the problem is described: modify rule (REC) not to require Gen((A, x : ui), v) ≤∀2,1 ui when x 6∈ FV(e). 6.2 The Type Inference Rules of `Rec ∧2 22 System `Rec This extension ∧2 extends `∧2 with the rule (REC2) of Figure 6. preserves the substitutivity property and the principal pair property. 19 We

still give to the rule the original name used in Jim [1996], but we adapt the rule to fit in the type assignment system `∧2 . 20 Since ∀αβγ .((α → β) ∧ (β → γ )) → α → γ ≤ ∀2,1 (δ → δ) → δ → δ. 21 Since λ y. y y has no rank 0 types. 22 In rule (REC2), the condition “x 0 , . . . , x 0 are fresh” is equivalent to “x 0 , . . . , x 0 are distinct and do n n 1 1 not occur in D, FV(e1 ), . . . , FV(en )”. Again, the renaming of the bound identifiers x1 , . . . , xn is done just for preserving typability under alpha conversion. ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

420



Ferruccio Damiani

Fig. 6. Typing rule for recursive definitions (system `Rec ∧2 ).

By observing that the rank 1 environment A is “relevant” (as it is pointed out in Section 4.2.1) we can note that rule (REC2) applies “for free” to mutually recursive definitions Jim’s extension of rule (REC) described at the end of Section 6.1. The constraint Gen(A1 + · · · + An , v j ) ≤∀2,1 ui j is enforced only for those j such that x j ∈ ∪i∈{1,...,n} FV(ei ).23 Remark 6.1. (Comparison with Mycroft’s (FIX0 ) rule). There are many interesting examples of polymorphic recursion that can be typed by rule (FIX0 ) and cannot be typed by rule (REC2). Consider for instance the following O’Caml program24 type ’a tree

= EMPTY | NODE of ’a * (’a tree) tree ;;

let rec collect t = match t with EMPTY -> [] | NODE(n,t1) -> n::flatmap collect (collect t1);; where ’a tree is a polymorphic tree type and flatmap is the standard list manipulation function of principal type (’a -> ’b list) -> ’a list -> ’b list. The function collect, which collects all the labels in an ’a tree and returns them in an ’a list, is not typable by (REC2) but can be typed (with principal type ’a tree -> ’a list) by rule (FIX0 ). As pointed out by Jim [1996], rule (REC2) can be easily generalized along the lines of rule (FIX0 ): just replace the condition (∀ j ∈ { j 1 , . . . , j m }) Gen(A1 + · · · + An , v j ) ≤∀2,1 ui j by (∀ j ∈ { j 1 , . . . , j m }) Gen( A, v j ) ≤∀2,1 ui j . 23 The

rule for mutually recursive definitions proposed in Jim [1996, 1995] enforces the constraint Gen(A1 + · · · + An , v j ) ≤∀2,1 ui j for all j ∈ {1, . . . , n}. So rule (REC2) is a slight generalization of that rule. 24 This example is taken from Jim [1996], it originally comes from the ML mailing list, and has arisen in practice. Here we use O’Caml syntax since this is the syntax accepted by our prototype implementation of the type inference algorithm (see Section 1.4). ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

Rank 2 Intersection Types for Local Definitions and Conditional Expressions



421

Fig. 7. Type assignment rules for patterns.

The resulting system still has principal typing and decidable type inference. For simplicity, we do not consider this extension.25 7. SYSTEM `Con ∧2 : RANK 2 INTERSECTION FOR CONDITIONAL EXPRESSIONS In this section we extend system `∧2 to deal with if-expressions and matchexpressions. We first introduce the typing rules for patterns (Section 7.1) and the notions of →-index and ∧-index of a type (Section 7.2). Then we present the new type system (Section 7.3). 7.1 System B: Types for Patterns The type inference system B (see Figure 7) has judgements of the form U Bp : u, where — u is the rank 0 type inferred for the pattern p, and —U is a rank 0 environment containing type assumption for all and only the free identifiers occurring in the pattern (i.e., Dom(U ) = FV(p)). The type derivations of system B are closed by substitution and the system has the principal pair property. This follows straightforwardly from the well-known substitutivity property and principal pair property of the Curry/Hindley type system (see, for instance, Chapter 3 of Hindley [1997]). LEMMA 7.1. (Substitutivity property for B). If U Bp : u, then s(U ) B p : s(u), for every substitution s. Definition 7.2.

(Pairs, instantiation, and principal pairs for B).

(1) A pair hU, ui is a pair for p if U B p : u. (2) A pair hU 0 , u0 i is an instance of a pair hU, ui if there is a substitution s such that Dom(s) = FTV(U ) ∪ FTV(u), s(u) = u0 and U 0 = s(U ). (3) A pair for p is principal if any pair for p is an instance of it. 25 The

corresponding inference algorithm requires a termination check and a iteration to compute the fixpoint, along the line of the inference algorithm for the system with (FIX0 ) described by Mycroft [1984]. ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

422



Ferruccio Damiani

LEMMA 7.3. (Principal pair property for B). If p is typable in B, then it has a principal pair. 7.2 Introducing ∧-Indexes and →-Indexes The simplest way to extend system `∧2 to deal with conditional expressions is to treat them as in ML. This amounts to introducing the following typing rules (note that rule (MATCHSIMPLE) uses the system B to type patterns)26 (IFSIMPLE)

D; A ` e : bool D; A1 ` e1 : u D; A2 ` e2 : u D; A + A1 + A2 ` if e then e1 else e2 : u

D; A0 ` e0 : u0 (∀i ∈ {1, . . . , n}) Ui B pi0 : u0 D; Ai , { y : u0 ∈ Ui | y ∈ FV(ei0 )} ` ei0 : u (MATCHSIMPLE) D; A0 + A1 + · · · + An ` matche0 with {p1 ⇒ e1 , . . ., pn ⇒ en } : u where (∀i ∈ {1, . . . , n}) {xi,1 , . . . , xi,mi } = FV(pi ), 0 0 , . . . , xi,m are fresh xi,1 i 0 0 0 pi = pi [xi,1 := xi,1 ] · · · [xi,mi := xi,m ], and i 0 0 0 ei = ei [xi,1 := xi,1 ] · · · [xi,mi := xi,mi ] that assign to a conditional expression the unique rank 0 type inferred for its branches. Rule (IFSIMPLE) does not allow assigning rank 2 types to the branches of ifexpressions. So it does not allow typing expressions that have a “true rank 2 type” (i.e., a type in T2 − T0 ) and no rank 0 type, as illustrated by the following example. Example 7.4. 1 true). We have

Take the expressions e1 = λ f . f (pair 1 2) and e2 = λ g . g (pair

—∅; ∅ `∧2 e1 : u1 , where u1 = ((int × int) → α) → α, and — ∅; ∅ `∧2 e2 : u2 , where u2 = ((int × bool) → α) → α. Let v = (((int × int) → α) ∧ ((int × bool) → α)) → α. Since both u1 ≤2 v and u2 ≤2 v (v is, indeed, the least upper bound of u1 and u2 with respect to ≤2 ), we have ∅; ∅ `∧2 e1 : v and ∅; ∅ `∧2 e2 : v. However, the expression e = λ z.if z then e1 else e2 cannot be typed by system `∧2 extended with rule (IFSIMPLE). We may consider replacing rule (IFSIMPLE) by the following rule (IFSTRONG)

D; A ` e0 : bool D; A1 ` e1 : v D; A2 ` e2 : v D; A + A1 + A2 ` if e0 then e1 else e2 : v

which allows assigning a rank 2 type to the branches of an if-expression. By using rule (IFSTRONG) we can assign the type bool → v to the expression rule (MATCHSIMPLE), the condition “xi,1 , . . . , xi,mi (1 ≤ i ≤ n) are fresh” is equivalent to “x1,1 , . . . , x1,m1 , . . . , xn,1 , . . . , xn,mn are distinct and do not occur in D, FV(e0 ), FV(p1 ), . . . , FV(pn ), FV(e1 ), . . . , FV(en )”. Again, the renaming of the bound identifiers xi,1 , . . . , xi,mi (1 ≤ i ≤ n) is done just for preserving typability under alpha conversion. 26 In

ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

Rank 2 Intersection Types for Local Definitions and Conditional Expressions



423

e = λ z.if z then e1 else e2 introduced at the end of Example 7.4. However the Strong resulting system, `∧2 , has neither the principal pair property nor the principal type property, as the following example shows. Example 7.5. (Rule (IFSTRONG) destroys the principal pair property of `∧2 ). Let e0 = λ z.λ x1 .λ x2 .if z then x1 else x2 . We have if z 0 then x10 else x20 : α, and — ∅; {z 0 : bool, x10 : α, x20 : α} `∧2 Strong 0 — ∅; ∅ `∧2 e : bool → α → α → α. Strong

We also have if z 0 then x10 else x20 : v, and —∅; {z 0 : bool, x10 : u1 , x20 : u2 } `∧2 Strong 0 — ∅; ∅ `∧2 e : bool → u1 → u2 → v, Strong

where u1 , u2 , and v are as in Example 7.4. Strong 0 Strong 0 The fact that both ∅; ∅ `∧2 e : bool → α → α → α and ∅; ∅ `∧2 e : Strong bool → u1 → u2 → v shows that in `∧2 there is no principal type for e0 : the “natural candidate” is u = bool → α → α → α, but there exists no substitution s such that s(u) ≤2 bool → u1 → u2 → v. This problem is due to the fact that, by definition, substitutions map type variables into simple types (see Section 3.1). In order to restore the principal pair property we will restrict rule (IFSTRONG) by adding some condition, involving the principal pairs of e1 and e2 with respect to D, that must be satisfied by the rank 2 type v. As a first attempt, we restrict rule (IFSTRONG) with the condition: (C1)

v = s(v0 ), v10 ≤2 v0 , and v20 ≤2 v0 , where hAi0 , vi0 i is a principal pair for ei with respect to D (1 ≤ i ≤ 2).

Consider the types u1 , u2 , and v introduced in Example 7.4. The resulting rule, (IFC1), —allows assigning type bool → v to the expression e of Example 7.4, —allows assigning type bool → α → α → α to the expression e0 of Example 7.5, and —prevents assigning the type bool → u1 → u2 → v to e0 . In fact, we have that (modulo renaming of type variables) the principal pairs for xi0 are of the shape h{xi0 : βi }, βi i (1 ≤ i ≤ 2) and, for any type v0 , if β1 ≤2 v0 and β2 ≤2 v0 , then β1 = β2 = v0 = β, for some type variable β. So, since there is no substitution s such that v = s(β), the type v does not satisfy the condition (C1). However, rule (IFC1) has a serious drawback: it does not allow typing all the expressions that can be typed by using rule (IFSIMPLE), as shown by the following example. Example 7.6. (Rule (IFC1) does not extend rule (IFSIMPLE)). System `∧2 extended with rule (IFSIMPLE) allows assigning type u0 = bool → (α → α) → α → α to the expression e0 = λ z.λ x.if z then x else λ y. y. Instead, e0 cannot be typed ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

424



Ferruccio Damiani

Fig. 8. The functions Ind∧ (v) and Ind→ (v).

by system `∧2 extended with rule (IFC1). In fact (modulo renaming of type variables), the principal pairs for x 0 are of the shape h{x 0 : β}, βi, the principal pairs for λ y. y are of the shape h∅, (γ1 ∧ · · · ∧ γn ) → γ1 i (n ≥ 1), and there is no type v0 such that β ≤2 v0 and (γ1 ∧ · · · ∧ γn ) → γ1 ≤2 v0 . So the condition (C1) cannot be satisfied.27 Our second attempt avoids any explicit reference to the notion of substitution. It is based on the idea of restricting rule (IFSTRONG) by “limiting the use” of the intersection type constructor in the type v by “looking at the use” of the arrow type constructor in the principal pairs of e1 and e2 . To do this we introduce two metrics on types: the ∧-index and the →-index of a type. Definition 7.7. (∧-index and →-index of a type). For every type v ∈ T2 the ∧-index of v, Ind∧ (v), and the →-index of v, Ind→ (v), are the natural numbers defined in Figure 8 (note that Ind∧ (v) ≤ Ind→ (v)).28 The fundamental properties of the metrics Ind∧ and Ind→ are expressed by the following propositions. PROPOSITION 7.8. (1) If Ind∧ (v) = p and Ind→ (v) = q (q ≥ p ≥ 0), then v is of the form v = ui1 → · · · → ui p → u1 → · · · → uq− p → u for some ui1 , . . . , ui p ∈ T1 and u1 , . . . , uq− p , u ∈ T0 , with ui p 6∈ T0 and u not an arrow type. (2) For every substitution s, Ind∧ (v) ≥ Ind∧ (s(v)) and Ind→ (v) ≤ Ind→ (s(v)).29 (3) If v ≤2 v0 then Ind∧ (v) ≤ Ind∧ (v0 ) and Ind→ (v) = Ind→ (v0 ). PROOF. (1) By induction on the definition of Ind→ and Ind∧ (Definition 7.7). (2) By structural induction of v, using the fact that any substitution s maps type variables to rank 0 types. (3) By induction on the definition of ≤2 (Definition 3.1). may consider weakening the condition (C1) by applying the substitution s directly on v10 and v20 and just requiring v to be an upper bound of s(v10 ) and s(v20 ). However, some restriction on the substitution s must be specified, since the condition

27 We

(C0) v = v0 , where s(vi0 ) ≤2 v0 and hAi0 , vi0 i is a principal typing for ei with respect to D (1 ≤ i ≤ 2) is satisfied by any type v that can be assigned to both e1 and e2 (see Definition 4.2), i.e., it does not restrict rule (IFSTRONG). 28 Remember that ∧ is idempotent, so, for any u ∈ T , the type u ∧ u is considered to be an element 0 of T0 . 29 Remember that a substitution s may transform a type ui ∈ T − T into a type s(ui) ∈ T (take, 1 0 0 for instance, ui = β ∧ γ and s = [β := α, γ := α]). ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

Rank 2 Intersection Types for Local Definitions and Conditional Expressions



425

PROPOSITION 7.9. For every expression e and environment D, if hA, vi is a principal pair for e with respect to D, then Ind→ (v) = Min{Ind→ (v0 ) | D; A0 ` e : v0 }. PROOF. By Definition 4.2, observing that (by Proposition 7.8.(2)) Ind→ (v) ≤ Ind→ (s(v)), for every substitution s, and that (by Proposition 7.8.(3)) v ≤2 v0 implies Ind→ (v) = Ind→ (v0 ). We can now formulate the condition: (C2)

Ind∧ (v) ≤ Min{Ind→ (v10 ), Ind→ (v20 )}, where hAi0 , vi0 i is a principal pair for ei with respect to D (1 ≤ i ≤ 2).

that produces a rule, (IFC2), which retains the principal pair property, is of intermediate power between rule (IFSIMPLE) and (IFSTRONG), and “successfully handles” the expressions considered in the above examples: it allows assigning type bool → v to the expression e of Example 7.4, it allows assigning type bool → α → α → α to the expression e0 of Example 7.5, and it prevents assigning to e0 the type bool → u1 → u2 → v. Indeed, we can do even better, as “suggested” by the following example. Example 7.10.

(A limitation of rule (IFC2)). The expression e00 = λ z.(λ x.if z then x else e2 ) e1 ,

where e1 = λ f . f (pair 1 2) and e2 = λ g . g (pair 1 true) are the expressions introduced in Example 7.4, is not typable by rule (IFC2). In fact, the type v = (((int × int) → α) ∧ ((int × bool) → α)) → α considered in Example 7.4 is such that Ind∧ (v) = 1 6≤ 0 = Min{0, 1} = Min{Ind→ (β), Ind→ (((int × bool) → α) → α)} (where h{x 0 : β}, βi is a principal pair for x 0 and h∅, ((int × bool) → α) → αi is a principal pair for e2 ). So, condition (IFC2) cannot be satisfied. In order to be able to assign type bool → v to the expression e00 of Example 7.10, we weaken the condition (C2) into the following condition: (C3)

Ind∧ (v) ≤ Max{Ind→ (v10 ), Ind→ (v20 )}, where hAi0 , vi0 i is a principal pair for ei with respect to D (1 ≤ i ≤ 2).

that produces a rule which extends rule (IFC2) while retaining the principal pair property. Note that the condition (C3) can be rephrased to avoid any explicit reference to principal pairs. In fact, in a system with the principal pair property, we have that (by Proposition 7.9) the condition (C3) is equivalent to the condition (Cif )

Ind∧ (v) ≤ Max{Min{Ind→ (v1 ) | D; A01 ` e1 : v1 }, Min{Ind→ (v2 ) | D; A02 ` e2 : v2 }},

that does not mention principal pairs. ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

426



Ferruccio Damiani

Fig. 9. Typing rules for conditional expressions (system `Con ∧2 ).

7.3 The Type Inference Rules of `Con ∧2 30 System `Con This ex∧2 extends `∧2 with rules (IFI) and (MATCHI) of Figure 9. tension preserves the substitutivity property and the principal pair property. Rule (IFI) is the restriction of rule (IFSTRONG) of Section 7.2 with the condition (Cif ) presented at the end of Section 7.2. Rule (MATCHI) applies the same idea to match-expressions.

Example 7.11. (Use of rule (IFI)). By using rule (IFI) instead of (IFSIMPLE), it is possible to assign type bool → v to the expression e = λ z.if z then e1 else e2 of Example 7.4. In fact, since the type v = ((int × int) → α ∧ (int × bool) → α) → α is such that Ind∧ (v) = 1 ≤ 1 = Max{1, 1} = Max{Min{Ind→ (v1 ) | ∅; A01 ` e1 : v1 } Min{Ind→ (v2 ) | ∅; A02 ` e2 : v2 }}, condition (Cif ) is satisfied. So, by rule (IFI), we can derive ∅; {z 0 : bool} `Con ∧2 if z 0 then e1 else e2 : v and then, by rule (ABS), we can obtain ∅; ∅ `Con ∧2 e : bool → v, which is, indeed, a principal typing of e. Also the expression e00 = λ z.(λ x.if z then x else e2 ) e1 (where e1 = λ f . f (pair 1 2) and e2 = λ g . g (pair 1 true)) of Example 7.10, is typable by `Con ∧2 . In fact, we have Ind∧ (v) = 1 ≤ 1 = Max{0, 1} = Max{Min{Ind→ (v1 ) | ∅; A01 ` x 0 : v1 }, Min{Ind→ (v2 ) | ∅; A02 ` e2 : v2 }}. rule (MATCHI), as in rule (MATCHSIMPLE), the renaming of the bound identifiers xi,1 , . . . , xi,mi (1 ≤ i ≤ n) is done just for preserving typability under alpha conversion. 30 In

ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

Rank 2 Intersection Types for Local Definitions and Conditional Expressions



427

0 0 So, by rule (IFI), ∅; {z 0 : bool, x 0 : ((int × int) → α) → α} `Con ∧2 if z then x else e2 : v and, by rules (ABS), (APP), and (ABS), we get 00 ∅; ∅ `Con ∧2 e : bool → v,

which is a principal typing of e00 . Instead, it is not possible to assign type bool → u1 → u2 → v to the expression e0 = λ z.λ x1 .λ x2 .if z then x1 else x2 of Example 7.5. In fact, since Ind∧ (v) = 1 6≤ 0 = Max{0, 0} = Max{Min{Ind→ (v1 ) | ∅; A01 ` x10 : v1 }, Min{Ind→ (v2 ) | ∅; A02 ` x20 : v2 }}, rule (IFI) cannot be used to assign type v to if z 0 then x10 else x20 . For an example of application of rule (MATCHI), consider the expression ( λ l .match l with nil ⇒ λ f . λ x. f ( f x) [] cons h r ⇒ λ w. λ z.r ) nil (λ y.cons y nil) 5. It safely computes cons (cons 5 nil) nil, however, it cannot be typed by the ML type system. Instead, the `Con ∧2 type system can assign the two principal pairs h∅, ((α → β) ∧ (β → γ )) → α → γ i h{r 0 : ϕ list}, δ → ϑ → ϕ listi to the first and to the second branch of the match-expression (respectively), principal pair h{l 0 : ϕ list}, ((α → β) ∧ (β → ϕ list)) → α → ϕ listi to the match-expression, principal pair h∅, ϕ list → ((α → β) ∧ (β → ϕ list)) → α → ϕ listi to the function (λ l . · · · ), and principal pair h∅, int list listi to the whole expression. Rec, Con : PUTTING THE THREE EXTENSIONS TOGETHER 8. SYSTEM `Loc, ∧2

In this section we present a type system, that combines the three extensions of `∧2 presented in Sections 5, 6, and 7. We first show that, because of a “subtle” interaction between the rules for typing local definitions and the rules for typing Con conditional expressions, the combination of `Loc ∧2 and `∧2 does not have the principal pair property. Then we present the new type system (Section 8.2) and its principal pair property (Section 8.3). 8.1 A Subtle Problem Extending `∧2 with both the rules in Figure 5 and the rules in Figure 9 does not preserve the principal pair property, as the following example illustrates. ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

428



Ferruccio Damiani

Example 8.1. (The interaction between (LETPS) and (IFI) destroys the principal pair property). Consider the expression e000 = λ z.λ y.λ x2 .let x1 = y in if z then x1 else x2 In the system `∧2 extended with the rules in Figures 5 and 9 we have: —{x10 : ∀α.h{ y 0 : α}, αi}; {z 0 : bool, y 0 : α 0 , x20 : α 0 } ` if z 0 then x10 else x20 : α 0 , — ∅; {z 0 : bool, y 0 : α 0 , x20 : α 0 } ` let x1 = y 0 in if z 0 then x1 else x20 : α 0 , and —∅; ∅ ` e000 : bool → α 0 → α 0 → α 0 . We also have — {x10 : ∀βγ .h{ y 0 : β → γ }, β → γ i}; {z 0 : bool, y 0 : β 0 → γ 0 , x20 : δ → γ 0 } ` if z 0 then x10 else x20 : β 0 ∧ δ → γ 0 , —∅; {z 0 : bool, y 0 : β 0 → γ 0 , x20 : δ → γ 0 } ` let x1 = y 0 in if z 0 then x1 else x20 : β 0 ∧ δ → γ 0 , and —∅; ∅ ` e000 : bool → (β 0 → γ 0 ) → (δ → γ 0 ) → β 0 ∧ δ → γ 0 . The fact both ∅; ∅ ` e000 : bool → α 0 → α 0 → α 0 and ∅; ∅ ` e000 : bool → (β 0 → γ 0 ) → (δ → γ 0 ) → β 0 ∧ δ → γ 0 shows (by the same argument used at the end of Example 7.5) that the system `∧2 extended with the rules in Figures 5 and 9 does not have the principal pair property. This problem is due to the fact that, since the condition in rule (IFI) considers the →-indexes of rank 2 types that can be assigned to the branches with respect to the given environment D (see Figure 9), the minimum →-index associated to the then-branch (the let-bound identifier x1 ) is computed on a subset of the types of the expression y associated to x1 .31 Rec, Con 8.2 The Type Inference Rules of `Loc, ∧2 Con The principal pair property for the combination of `Loc ∧2 and `∧2 can be restored by forcing one to assume types of minimum →-index for let-bound identifiers. This is exactly what rule (LETPSI) in Figure 10 does: it is the restriction of rule (LETPS) in Figure 5 requiring that, when typing a let-expression let x = e0 in e, → the pair scheme ∀− α .hA0 , v0 i assumed for the locally defined identifier x must satisfy the condition

(Clet )

Ind→ (v0 ) = Min{Ind→ (v00 ) | D; A00 ` e0 : v00 }.

For instance, by using rule (LETPSI) instead of (LETPS), it is not possible to assign type bool → (β 0 → γ 0 ) → (δ → γ 0 ) → β 0 ∧ δ → γ 0 to the term e000 of Example 8.1. is the extension of `∧2 with the typing rules in Figure 10, System `Loc,Rec,Con ∧2 where rule (MATCHI) uses the type inference system for patterns B (see Figure 7). Since rules (REC2), (IFI), and (MATCHI) are exactly the corresponding rules of Loc,Rec,Con Con extends both `Rec ∧2 (in Figure 6) and of `∧2 (in Figure 9), the system `∧2 Rec Con `∧2 and `∧2 . Moreover, in spite of the fact that rule (LETPSI) in Figure 10 is a 31 The

subset represented by the pair scheme assumed for x1 in the given environment D.

ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

Rank 2 Intersection Types for Local Definitions and Conditional Expressions



429

Fig. 10. Typing rules for local definitions, recursive definitions, and conditional expressions (system `Loc,Rec,Con ). ∧2

restriction of rule (LETPS) in Figure 5,32 we have that `Loc,Rec,Con also extends ∧2 . This follows from the fact that, by Proposition 7.9, any principal typing `Loc ∧2 Loc,Rec,Con D; A0 `∧2 e0 : v0 satisfies the condition (Clet ). Remark 8.2. (A shortcut typing rule for letrec-expression). As explained in Remark 2.1 at the end of Section 2, rec-expressions, reci {x1 = e1 , . . . , xn = en } (where 1 ≤ i ≤ n), have been considered instead of the more usual letrecexpressions, letrec {x1 = e1 , . . . , xn = en } in e, since they allow separating the 32 Rule

(IDlocal ), instead, is exactly the rule in Figure 5. ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

430



Ferruccio Damiani

Fig. 11. Shortcut typing rule for letrec-expressions (system `Loc,Rec,Con ). ∧2

issue of typing mutually recursive definitions from the issue of typing local definitions. Even though, for the purpose of typechecking, the expression letrec {x1 = e1 , . . . , xn = en } in e is equivalent to the expression let x1 = e01 in · · · let xn = e0n in e where ei0 = reci {x1 = e1 , . . . , xn = en } (i ∈ {1, . . . , n}), it is better, for the design of practical inference algorithm, to introduce a shortcut typing rule for letrecexpressions, which avoids the introduction of the n auxiliary rec-expressions ei0 and does not require typing each expression ei n times. The rule (LETRECPSI) in Figure 11 is a suitable shortcut typing rule for letrec.33 However, to keep the proofs simpler, we have expression in system `Loc,Rec,Con ∧2 not considered rule (LETRECPSI) in the type inference algorithm presented in Section 9. Rec, Con 8.3 Principal Pairs for `Loc, ∧2

The system `Loc,Rec,Con has the substitutivity property. ∧2 ). If D; A `Loc,Rec,Con e : v, LEMMA 8.3. (Substitutivity property for `Loc,Rec,Con ∧2 ∧2 e : s(v), for every substitution s. then D; s(A) `Loc,Rec,Con ∧2 PROOF By induction on the structure of derivations, using Proposition 7.8.(2) to deal with rule (IFI), and Lemma 7.1 and Proposition 7.8.(2) to deal with rule (MATCHI). 33 In rule (LETRECPSI), the minimum of the set of tuples of indexes is taken with respect to pointwise

ordering. The condition “x10 , . . . , xn0 are fresh” is equivalent to “x10 , . . . , xn0 are distinct and do not occur in D, FV(e1 ), . . . , FV(en ), and FV(e) ”. Again, the renaming of the bound identifiers x1 , . . . , xn is done just for preserving typability under alpha conversion. ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

Rank 2 Intersection Types for Local Definitions and Conditional Expressions



431

Principal pairs for `Loc,Rec,Con are defined as for `∧2 (see Definition 4.2). The ∧2 following result holds. THEOREM 8.4. (Principal Loc,Rec,Con with respect to D, ` ∧2

pair property for `Loc,Rec,Con ). If e is typable in ∧2 then it has a principal pair with respect to D.

PROOF. The result follows from Theorem 9.13 (soundness and completeness ) of Section 9. of the inference algorithm for `Loc,Rec,Con ∧2 Rec, Con 9. A SOUND AND COMPLETE INFERENCE ALGORITHM FOR `Loc, ∧2

In this section we present an algorithm that, for any expression e and environment D, with respect to D, and —reports a failure, if e can not be typed by `Loc,Rec,Con ∧2 —computes a principal pair for e with respect to D, otherwise. Until now, to simplify the presentation, we have considered ∧ to be associative, commutative, and idempotent. In this section we do not rely on this syntactic convention. 9.1 An Extension of Jim’s Subtype Satisfaction Algorithm Following Jim [1996, 1995] we say that a ≤∀2,1 -satisfaction problem is a formula → ∃− α .P , where → —− α is a (possibly empty) sequence of type variables occurring free in P , and — P is a set in which every element is —an equality between T0 types, or —an inequality between a T2 type and a T1 type, or —an inequality between a T∀2 type and a T1 type. → A substitution s is a solution to ∃− α .P if there exists a substitution s0 such that → α, —s(α) = s0 (α) for all α 6∈ − 0 0 — s (vs) ≤∀2,1 s (ui) for every inequality (vs ≤ ui) ∈ P , and — s0 (u1 ) = s0 (u2 ) for every equality (u1 = u2 ) ∈ P . Definition 9.1.

(Most general solutions of a ≤∀2,1 -satisfaction problem).

(1) A substitution s is a most general solution (mgs) of a ≤∀2,1 -satisfaction prob→ lem ∃− α .P if it satisfies the following conditions:34 → — s is a solution of ∃− α .P , → α .P , —s ≤ s0 , for all solutions s0 of ∃− —s is idempotent, and → —Dom(s) ⊆ FTV(∃− α .P ). → (2) We write MGS(∃− α .P ) for the (possibly empty) set of the most general → solutions of ∃− α .P . 34 The last two conditions are included for technical convenience only. Indeed they can be eliminated:

a ≤∀2,1 -satisfaction problem has a solution that satisfies the first two conditions if and only if it has a solution that satisfies all four conditions. ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

432



Ferruccio Damiani

Fig. 12. The partial function Lub≤2 : T2 × T2 → T2 .

THEOREM 9.2. If a ≤∀2,1 -satisfaction problem is solvable, then there is a most general solution for it. In particular, there is an algorithm that decides, for any ≤∀2,1 -satisfaction problem, whether it is solvable, and, if so, returns a most general solution. PROOF.

See Appendix A.1.

9.2 A Lub Satisfaction Algorithm Definition 9.3. (Least upper bound with respect to ≤2 ). Given two rank 2 types v1 , v2 ∈ T2 the least upper bound (lub) with respect to ≤2 of v1 and v2 is a rank 2 type v such that (1) v1 ≤2 v, v2 ≤2 v, and (2) for every v0 ∈ T2 if v1 ≤2 v0 and v2 ≤2 v0 then v ≤2 v0 . It straightforward to check that, for every v1 , v2 ∈ T2 , if the lub with respect to ≤2 exists then it is unique (modulo ∼ =2 ).35 Moreover, the lub operator, which is a partial function : T2 × T2 → T2 , is idempotent, commutative, and associative (modulo ∼ =2 ). As illustrated by the following lemmas the lub operator admits an inductive characterization and commutes with substitution. LEMMA 9.4. (Inductive characterization the lub with respect to ≤2 ). Let Lub≤2 : T2 ×T2 → T2 be the partial function defined by the clauses in Figure 12. For every v1 , v2 ∈ T2 , (1) if Lub≤2 (v1 , v2 ) is defined, then it is the lub with respect to ≤2 of v1 and v2 , and (2) if Lub≤2 (v1 , v2 ) is not defined, then no upper bound with respect to ≤2 of v1 and v2 exists. PROOF.

By induction on the definition of Lub≤2 (see Figure 12).

Observe that Lemma 9.4 assures that, for all v1 , v2 ∈ T2 , if there exists v ∈ T2 such that v1 ≤2 v and v1 ≤2 v, then Lub≤2 (v1 , v2 ) is defined. LEMMA 9.5. (Lub≤2 commutes with substitution). If v = Lub≤2 (v1 , v2 ), then s(v) ∼ =2 Lub≤2 (s(v1 ), s(v2 )). PROOF.

By induction on the definition of Lub≤2 (see Figure 12).

relation ∼ =2 v2 means that both =2 (⊆ T2 × T2 ) is the equivalence induced by ≤2 , i.e., v1 ∼ v1 ≤2 v2 and v2 ≤2 v1 .

35 The

ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

Rank 2 Intersection Types for Local Definitions and Conditional Expressions



433

For every v1 , . . . , vn ∈ T2 (n ≥ 1) define ( if n = 1 v1 , n Lub≤2 (v1 , . . . , vn ) = n−1 Lub≤2 (Lub≤2 (v1 , . . . , vn−1 ), vn ), if n > 1 A Lub≤2 -satisfaction problem is a pair h j, Qi where — Q is a finite non-empty set of rank 2 types, and — j ∈ {0, . . . , Max{Ind→ (v) | v ∈ Q}}. A substitution s is (s(v1 ), . . . , s(vn ))) ≤ j . Definition 9.6.

a

solution

to

h j, {v1 , . . . , vn }i

if

Ind∧ (Lubn≤2

(Most general solutions of a Lub≤2 -satisfaction problem).

(1) A substitution s is a most general solution (mgs) of a Lub≤2 -satisfaction problem h j, Qi if it satisfies the following conditions36 : — s is a solution of h j, Qi, — s ≤ s0 , for all solutions s0 of h j, Qi, — s is idempotent, and — Dom(s) ⊆ FTV(Q). (2) We write MGS(h j, Qi) for the (possibly empty) set of the most general solutions of h j, Qi. THEOREM 9.7. If a Lub≤2 -satisfaction problem is solvable, then there is a most general solution for it. In particular, there is an algorithm that decides, for any Lub≤2 -satisfaction problem, whether it is solvable, and, if so, returns a most general solution. PROOF.

See Appendix A.2.

Rec, Con 9.3 An Inference Algorithm for `Loc, ∧2

In the following definitions we will write “the pair hA, vi is fresh” as short for “the type variables in the pair hA, vi are fresh”. Moreover, for a rigorous → treatment of new type variables, we assume that, whenever “s ∈ MGS(∃− α .P )” (or “s ∈ MGS(h j, Qi)”) occurs in a mathematical context, s is chosen so that it does not interfere with “current” type variables, that is, we assume that → FTVR(s) ∩ W = ∅, where W ] FTV(∃− α .P ) (W ] FTV(Q)) is the set of the type variables present in the context.37 9.3.1 Inference Algorithm for B. The inference algorithm is presented by defining the function PAT that, for every pattern p, provides an inductive characterization of the set of principal pairs for p. Definition 9.8. (The function PAT). For every pattern p, the set PAT(p) is defined by structural induction on p. 36 As

for Definition 9.1, the last two conditions are included for technical convenience only. Indeed they can be eliminated: a Lub≤2 -satisfaction problem has a solution that satisfies the first two conditions if and only if it has a solution that satisfies all four conditions. 37 The operator ] denotes disjoint union. ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

434



Ferruccio Damiani

— If p = x, then h{x : α}, αi ∈ PAT(x). → α .u1 → · · · → un → u, the substitution — If p = csn p1 · · · pn , Typeof(csn ) = ∀− − → s is a fresh renaming of α , for all i ∈ {1, . . . , n} the pairs hUi , ui0 i ∈ PAT(pi ) are fresh, for all j, l ∈ {1, . . . , n} j 6= l implies Dom(U j ) ∩ Dom(Ul ) = ∅, and s0 ∈ MGS(∃².{u01 = s(u1 ), . . . , u0n = s(un )}, then hs0 (U1 ∪ · · · ∪ Un ), s0 (s(u))i ∈ PAT(csn p1 · · · pn ). For every pattern p, the set PAT(p) is an equivalence class of pairs modulo renaming of the type variables in a pair. LEMMA 9.9.

For every pattern p, if hU, ui ∈ PAT(p), then

(1) Dom(U ) = FV(p), and (2) hU 0 , u0 i ∈ PAT(p) if an only if there is a bijection s : Tv → Tv such that s(U ) = U 0 and s(u) = u0 . PROOF.

By induction on Definition 9.8.

Indeed Definition 9.8 specifies an inference algorithm: to perform type inference on a pattern p simply follow the definition of PAT(p), choosing fresh type variables and using the ≤2 -satisfaction algorithm as necessary. LEMMA 9.10.

(Soundness and completeness of PAT for B). For every pattern

p: (Soundness). If hU, ui ∈ PAT(p), then U Bp : u. (Completeness). If U 0 Bp : u0 , then there are a pair hU, ui ∈ PAT(p) and a substitution s such that: s(U ) = U 0 and s(u) = u0 . PROOF. By structural induction on p (note that system B is syntax directed). 9.3.2 An Inference Algorithm for `Loc,Rec,Con . The inference algorithm is ∧2 presented by defining the function PP which, for every expression e and environment D, returns a set of pairs PP(D, e) such that with respect to D, and — if PP(D, e) = ∅, then e can not be typed by `Loc,Rec,Con ∧2 —every element of PP(D, e) is a principal pair for e with respect to D.38 Definition 9.11. (The function PP). For every expression e and environment D, the set PP(D, e) is defined by structural induction on e. — If e = x, then → → — If x : ∀− α .hA, vi ∈ D and the substitution s is a fresh renaming of − α , then hs(A), s(v)i ∈ PP(D, x). → → — If x : ∀− α .v ∈ D and the substitution s is a fresh renaming of − α , then h∅, s(v)i ∈ PP(D, x). — If x 6∈ Dom(D) and α is a type variable, then h{x : α}, αi ∈ PP(D, x). 38 The

set PP(D, e) does not contain all the principal pairs for e with respect to D. For instance, h∅, (α1 ∧α2 ) → α1 i is a principal pair for λ x.x with respect to ∅, but h∅, (α1 ∧α2 ) → α1 i 6∈ PP(∅, λ x.x).

ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

Rank 2 Intersection Types for Local Definitions and Conditional Expressions



435

→ → — If e = c, Typeof(c) = ∀− α .v, and the substitution s is a fresh renaming of − α, then h∅, s(v)i ∈ PP(D, c). — If e = λ x.e0 , x 0 is fresh and hA, vi ∈ PP(D, e0 [x := x 0 ]), then — If x 6∈ FV(e0 ) and α is a fresh type variable, then hA, α → vi ∈ PP(D, λ x.e0 ) — If x ∈ FV(e0 ) and A = A0 , x 0 : ui, then hA0 , ui → vi ∈ PP(D, λ x.e0 ) — If e = e0 e1 and hA0 , v0 i ∈ PP(D, e0 ), then — If v0 = α (a type variable), α1 and α2 are fresh type variables, hA1 , v1 i ∈ PP(D, e1 ) is fresh, and s ∈ MGS(∃².{v1 ≤ α1 , α = α1 → α2 }, then hs(A0 + A1 ), s(α2 )i ∈ PP(D, e0 e1 ) — If v0 = u1 ∧ · · · ∧ un → v, for all i ∈ {1, . . . , n} the pairs hAi , vi i ∈ PP(D, e1 ) are fresh, and s ∈ MGS(∃².{vi ≤ ui | i ∈ {1, . . . , n}}), then hs(A0 + A1 + · · · + An ), s(v)i ∈ PP(D, e0 e1 ) → α = FTV(A0 )∪FTV(v0 ), x 0 is fresh, — If e = let x = e0 in e1 , hA0 , v0 i ∈ PP(D, e0 ), − − → 0 and hA1 , v1 i ∈ PP((D, x : ∀ α .hA0 , v0 i), e1 [x := x 0 ]) is fresh, then — If x ∈ FV(e1 ), then hA1 , v1 i ∈ PP(D, let x = e0 in e1 ) — If x 6∈ FV(e1 ), then hA0 + A1 , v1 i ∈ PP(D, let x = e0 in e1 ) — If e = reci0 {x1 = e1 , . . . , xn = en }, x10 , . . . , xn0 are fresh, for all i ∈ {1, . . . , n} the pairs hAi , vi i ∈ PP(D, ei [x1 := x10 ] · · · [xn := xn0 ]) are fresh, {x 0j1 , . . . , x 0jm } = {x10 , . . . , xn0 } ∩ Dom(A1 + · · · + An ), A1 + · · · + An = A, x 0j1 : ui j1 , . . . , x 0jm : ui jm , and s ∈ MGS(∃².{Gen(A1 + · · · + An , v j ) ≤ ui j | j ∈ { j 1 , . . . , j m }}), then hs(A), s(vi0 )i ∈ PP(D, reci0 {x1 = e1 , . . . , xn = en }) — If e = if e0 then e1 else e2 , hA0 , v0 i ∈ PP(D, e0 ), s0 ∈ MGS(∃².{v0 ≤ bool}), hA1 , v1 i ∈ PP(D, e1 ) and hA2 , v2 i ∈ PP(D, e2 ) are fresh, j = Max(Ind→ (v1 ), Ind→ (v2 )), and s ∈ MGS(h j, {v1 , v2 }i), then hs0 (A0 ) + s(A1 ) + s(A2 ), Lub≤2 (s(v1 ), s(v2 ))i ∈ PP(D, if e0 then e1 else e2 ) — If e = match e0 with {p1 ⇒ e1 , . . . , pn ⇒ en }, hA0 , v0 i ∈ PP(D, e0 ), for all l ∈ {1, . . . , n} — {xl ,1 , . . . , xl ,ml } = FV(pl ), — xl0 ,1 , . . . , xl0 ,ml are fresh, — pl0 = pl [xl ,1 := xl0 ,1 ] · · · [xl ,ml := xl0 ,ml ], —el0 = el [xl ,1 := xl0 ,1 ] · · · [xl ,ml := xl0 ,ml ], —hUl , ul i ∈ PAT(pl0 ) are fresh, —hAl , vl i ∈ PP(D, el0 ) are fresh, — { yl ,1 , . . . , yl ,hl } = Dom(Ul ) ∩ Dom(Al ),39 39 Observe

that { yl ,1 , . . . , yl ,hl } ⊆ {xl0 ,1 , . . . , xl0 ,ml }, since Dom(Ul ) = FV(pl0 ). ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

436



Ferruccio Damiani

—Ul = Ul0 , { yl ,1 : ul ,1 , . . . , yl ,hl : ul ,hl }, — Al = Al0 , { yl ,1 : uil ,1 , . . . , yl ,hl : uil ,hl }, α is a fresh type variable, [ s ∈ MGS(∃α.{v0 ≤ α} ∪ ( {ul ≤ α, uil ,1 ≤ ul ,1 , . . . , uil ,hl ≤ ul ,hl )}), and 1≤l ≤n

j = Max(Ind→ (s(v1 )), . . . , Ind→ (s(vn ))), and s0 ∈ MGS(h j, {s(v1 ), . . . , s(vn )}i), then ­ 0 ® s (s(A0 + A01 + · · · + A0n )), Lubn≤2 (s0 (s(v1 )), . . . , s0 (s(vn ))) ∈ PP(D, match e0 with {p1 ⇒ e1 , . . . , pn ⇒ en }) For every expression e and environment D, the set PP(D, e) is an equivalence class of pairs modulo renaming of the type variables in a pair. LEMMA 9.12. then

For every expression e and environment D, if hA, vi ∈ PP(D, e),

(1) Dom(A) = (FV(e) − Dom(D)) ∪ FVR(D|FV(e) ), and (2) hA0 , v0 i ∈ PP(D, e) if and only if there is a bijection s : Tv → Tv such that s(A) = A0 and s(v) = v0 . PROOF.

By induction on Definition 9.11.

Indeed Definition 9.11 specifies an inference algorithm: to perform type inference on an expression e with respect to the environment D simply follow the definition of PP(D, e), choosing fresh type variables and using the ≤2 -satisfaction, Lub≤2 -satisfaction, and PAT algorithms as necessary. ). For evTHEOREM 9.13. (Soundness and completeness of PP for `Loc,Rec,Con ∧2 ery expression e and environment D: (Soundness).

If hA, vi ∈ PP(D, e), then D; A `Loc,Rec,Con e : v. ∧2

e : v0 , then there are a pair hA, vi ∈ (Completeness). If D; A0 `Loc,Rec,Con ∧2 PP(D, e) and a substitution s such that A0 ≤1 s(A) and s(v) ≤2 v0 . PROOF.

See Appendix A.3.

10. RELATED WORK AND CONCLUSION The literature related to the present work has been partially quoted through the paper. We add here a brief survey on inference algorithms for systems involving intersection types. The system of intersection types [Coppo and Dezani-Ciancaglini 1980; Coppo 1980; Coppo et al. 1981; Barendregt et al. 1983] is undecidable. A first approach for designing a (semi-)algorithm for finding a principal pair is that of splitting the problem in two parts: first find a normal form for the term being typed (this problem is undecidable) and then build a principal pair for the normal form (this problem is decidable). To show that the approach is sound it is necessary to prove that both the normal form and the original term have the same typings. This approach has been followed, for instance, by Coppo et al. [1980], Ronchi della Rocca and Venneri [1984], and van Bakel [1993]. ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

Rank 2 Intersection Types for Local Definitions and Conditional Expressions



437

The first unification-based approach to intersection type inference was proposed by Ronchi della Rocca [1988] where, in particular, a decidable restriction which bounds the height of types is presented. More recently, Kfoury and Wells [1999] presented a simpler unification-based approach using a novel form of unification, called β-unification. In spite of the fact that System F [Girard 1972; Reynolds 1974] and its finite rank restrictions above 3 have neither principal typings nor decidable type inference [Wells 1994; Kfoury and Wells 1994], combining intersection types and universal quantification results in a system with principal typings [Margaria and Zacchi 1995]. Moreover, decidable restrictions of the combined system have been developed (e.g. [Damiani and Giannini 1994; Coppo and Giannini 1995; Jim 2000]). Due to the expressive power of the corresponding type systems, the inference algorithms mentioned above are inherently quite expensive. More efficient inference algorithms can be developed by considering the rank 2 restriction of intersection types [Leivant 1983; van Bakel 1993; Yokouchi 1995; Jim 1996]. Following this line of research, in the present paper we have proposed a sound and complete principal pair inference algorithm for a rank 2 intersection type system with new typing rules for assigning rank 2 types to: (1) local definitions, by using the principal pair property of the system to associate a different instance of the principal typing to each occurrence of the locally defined identifier; (2) mutually recursive definitions, by allowing a restricted form of polymorphic recursion (as explained in Section 6, this rule is a slight improvement of a rule proposed by Jim [1996, 1995]); (3) conditional expressions, by restricting the use of intersection in the types assigned to the branches in order to preserve the principal pair property. Both the techniques for local definitions and recursive definitions do not depend on the particulars of rank 2 intersection typing, but apply to any system with principal pairs. The technique for conditional expressions, instead, is tailored to rank 2 intersection types. However, the strategy of introducing metrics on types to limit the use of the intersection type constructor in the types assigned to the branches of the conditionals expressions might also be useful for other type systems. APPENDIX A.1 An Extension of Jim’s Subtype Satisfaction Algorithm (Theorem 9.2) We say that two ≤∀2,1 -satisfaction problems are equivalent if they have the same solutions. A unification problem is a ≤∀2,1 -satisfaction problem that involves only equalities.40 40 A

unification problem can be solved by Robinsons’s algorithm (see, for instance, Chapter 3 of Hindley [1997]), which can decide whether it is solvable, and, if so, return a most general solution. ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

438



Ferruccio Damiani

The following lemma implies Theorem 9.2. LEMMA A.1. Every ≤∀2,1 -satisfaction problem is equivalent to a unification problem. In particular, there is an algorithm that, given a ≤∀2,1 -satisfaction problem, either proves that it cannot be satisfied or transforms it into an equivalent unification problem. PROOF. Following Jim [1996, 1995], we prove the lemma by providing the transformation algorithm. We first introduce a set of transformation rules of the form → t ≤ ui ⇒ ∃− α .P (where t ∈ T2 ∪ T∀2 ). Each rule transforms an inequality in a ≤∀2,1 -satisfaction problem. The transformation rules are in Figure 13. Note that, for each transformation rule → t ≤ ui ⇒ ∃− α .P , we have that → FTV(t) ∪ FTV(ui) = FTV(∃− α .P ). (4) → In particular, the type variables − α are either fresh type variables introduced by the transformation rule (i.e., they do not appear in the left-hand side) or are the bound variables of t (when t ∈ T∀2 ). The transformation algorithm is specified as a rewrite relation on problems, =⇒, defined by the rule: → vs ≤ ui ⇒ ∃− α .P (=⇒) − → → → 0 ∃ β .(P ] {vs ≤ ui}) =⇒ ∃− β ]− α .(P 0 ∪ P ) where the operator “]” denotes disjoint union (this implies that the variables − → α must be fresh). To see that the rewriting relation =⇒ describes an algorithm which proves the lemma, observe that: (1) every rewriting step (corresponding to the application of one of the rules in Figure 13) transforms a ≤∀2,1 -satisfaction problem into another ≤∀2,1 satisfaction problem, (2) every rewriting step preserves the set of solutions (note that the condition (4) above is necessary to ensure this preservation), (3) every inequality matches the left-hand side of at most one rule, and (4) repeated application of these rules must terminate.41 This is proved by defining a metric | · | on problems for which each rewriting step is strictly decreasing. The size of inequalities will be defined by structural induction. By point (3), it is sufficient to consider the cases given by the left-hand sides of the rules in Figure 13. For the base case we set |u0 ≤ u| = 1. Every other case is simply defined so that the size of the left-hand side of a rule is greater than the sum of the of the inequalities appearing on the corresponding right-hand side. For example, define —|(ui → v) ≤ α| = |α1 ≤ ui| + |v ≤ α2 | + 1, —|(ui → v) ≤ (u1 → u2 )| = |u1 ≤ ui| + |v ≤ u2 | + 1, 41 In the original termination proof given in Jim [1996, 1995] there is an error. Here we are following

the termination proof given in Jim [2000]. ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

Rank 2 Intersection Types for Local Definitions and Conditional Expressions



439

Fig. 13. Transformation rules for ≤∀2,1 -satisfaction.

— |t ≤ (u1 ∧ · · · ∧ un )| = |t ≤ u1 | + · · · + |t ≤ un | + 1, and → — |(∀− α .v) ≤ u| = |v ≤ u| + 1. The function |·| is defined by structural induction (since types on right-hand sides either appear as syntactic subtypes on left-hand sides, or are type variables) and, by construction, gives a decreasing metric on problems. Normal forms are either unification problems (i.e. do not contain inequalities) or contain at least an inequality of the form ui → v ≤ u0 where u0 is a simple type which is neither a type variable nor an arrow type (such an inequality is clearly not satisfiable). Remark A.2. (Comparison with Jim’s subtype satisfaction algorithm). Lemma A.1 and Theorem 9.2 are a slight extension of results presented by Jim [1996, 1995]. The main differences are in the transformation rules. The transformation rules in Figure 13 either produce a unification problem or a satisfaction problem which is clearly not satisfiable. The transformation rules in Jim [1996, 1995], instead, always produce a unification problem. This difference is due to the richer set of types handled by our rules42 : if we restrict ourselves to the set of types considered in Jim [1996, 1995] the rules in Figure 13 always produce a unification problem. A.2 A Lub Satisfaction Algorithm (Theorem 9.7) We say that a Lub≤2 -satisfaction problem and a ≤∀2,1 -satisfaction problem are equivalent if they have the same solutions. A Lub≤2 -satisfaction problem h j, {v1 , . . . , vn }i is binary if n = 2. The following lemma implies Theorem 9.7 restricted to binary Lub≤2 -satisfaction problems. LEMMA A.3. Every binary Lub≤2 -satisfaction problem is equivalent to a ≤∀2,1 -satisfaction problem. In particular, there is an algorithm that, given a Lub≤2 -satisfaction problem transforms it into an equivalent ≤∀2,1 -problem. 42 The rules in Jim [1996, 1995] consider only type variables, arrow types, and top-level conjunctions.

We also consider parametric datatypes. ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

440



Ferruccio Damiani

Fig. 14. Transformation algorithm for binary Lub≤2 -satisfaction.

PROOF. We prove the lemma by providing the transformation algorithm. The transformation algorithm is specified as a recursive function TA defined by the clauses in Figure 14. To show that the recursive function TA describes an algorithm that proves the lemma, for every binary Lub≤2 -satisfaction problem h j, {v1 , v2 }i we will prove that: (1) TA( j, v1 , v2 ) is terminating and returns a ≤∀2,1 -satisfaction problem, (2) FTV(TA( j, v1 , v2 )) ⊆ FTV({v1 , v2 }), and (3) the transformation preserves the set of solutions (i.e. h j, {v1 , v2 }i and TA( j, v1 , v2 ) are equivalent). Points (1) and (2) are straightforward, so we consider only point (3). The proof is by induction on j ∈ {0, . . . , Max{Ind→ (v1 ), Ind→ (v2 )}}. j = 0. From the definition of TA (see Figure 14) we have TA(0, v1 , v2 ) = ∃α.P , where α is fresh and P = {v1 ≤ α, v2 ≤ α}. — If s is a solution of h0, {v1 , v2 }i then Ind∧ (Lub≤2 (s(v1 ), s(v2 ))) = 0, which implies s(v1 ) = s(v2 ) ∈ T0 . So s is a solution of ∃α.P . — If s is a solution of ∃α.P then s(v1 ) = s(v2 ) ∈ T0 , which implies Ind∧ (Lub≤2 (s(v1 ), s(v2 ))) = 0. So s is a solution of h0, {v1 , v2 }i. j > 0. By definition of Lub≤2 -satisfaction problem we have j ≤ Max{Ind→ (v1 ), Ind→ (v2 )}}, so at least one of v1 and v2 is an arrow type. —If they are both arrow types, say v1 = ui1 → v10 and v1 = ui2 → v20 , then TA( j, ui1 → v10 , ui2 → v20 ) = TA( j − 1, v10 , v20 ). By definition of Lub≤2 we have that, for every substitution s, Lub≤2 (s(v1 ), s(v2 )) = s(ui1 ) ∧ s(ui2 ) → Lub≤2 (s(v10 ), s(v20 )). So h j, {v1 , v2 }i and h j − 1, {v10 , v20 }i are equivalent, and the result follows by induction. — If v1 is a type variable α and v2 = ui → v, for some v = ui1 → · · · → uim → u (m ≥ 0) with u ∈ T0 such that u is not an arrow type and α 6∈ FTV(u) (the → β .({α = α1 → symmetric case is similar), then TA( j, α, ui → v) = ∃α1 α2 ] −

ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

Rank 2 Intersection Types for Local Definitions and Conditional Expressions



441

Fig. 15. Transformation algorithm for n-ary Lub≤2 -satisfaction.

→ α2 } ∪ P ), where α1 , α2 are fresh type variables, and ∃− β .P = TA( j − 1, [α := → β .({α = α1 → α2 ]v, α2 ). We now prove that h j, {α, ui → v}i and ∃α1 α2 ] − α1 → α2 } ∪ P ) are equivalent. —By definition of Lub≤2 we have that every solution s of h j, {α, ui → v}i is such that s(α) = u1 → u2 and Ind∧ (Lub≤2 (s(α), s(ui → v))) ≤ j . So s = s0 ◦[α := α1 → α2 ] for some fresh type variables α1 , α2 and substitution s0 such that s0 (γ ) = s(γ ) for every γ 6∈ {α1 , α2 } and s0 is a solution of h j − 1, {[α := α1 → α2 ]v, α2 }i. By induction s0 is a → solution to ∃− β .P = TA( j − 1, [α := α1 → α2 ]v, α2 ), so s is a solution to − → ∃α1 α2 ] β .({α = α1 → α2 } ∪ P ). → β .({α = α1 → α2 } ∪ P ), then s = s0 ◦[α := — If s is a solution to ∃α1 α2 ] − α1 → α2 ], for some substitution s0 such that s0 (γ ) = s(γ ) for every γ 6∈ → β .P = TA( j − 1, [α := α1 → α2 ]v, α2 ). {α1 , α2 } and s0 is a solution of ∃− 0 By induction s is a solution to h j − 1, {[α := α1 → α2 ]v, α2 }i, so s is a solution to h j, {α, ui → v}i. —Otherwise h j, {v1 , v2 }i has no solutions and is, therefore, equivalent to ∃².{int = bool}. The following lemma generalizes LemmaA.3 to n-ary Lub≤2 -satisfaction problems, and so implies Theorem 9.7. LEMMA A.4. Every Lub≤2 -satisfaction problem is equivalent to a ≤∀2,1 satisfaction problem. In particular, there is an algorithm that, given a Lub≤2 satisfaction problem transforms it into an equivalent ≤∀2,1 -problem. PROOF. We prove the lemma by providing the transformation algorithm. The transformation algorithm is specified as a recursive function TAn defined by the clauses in Figure 15, that generalizes the function TA in Figure 14 to an arbitrary number of arguments. To show that the recursive function TAn describes an algorithm that proves the lemma, for every n-ary (n ≥ 1) Lub≤2 -satisfaction problem h j, {v1 , . . . , vn }i

ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

442



Ferruccio Damiani

we will prove that, if j ≤ Ind→ (v1 ) then43 (1) TAn ( j, v1 , . . . , vn ) is terminating and returns a ≤∀2,1 -satisfaction problem, (2) FTV(TAn ( j, v1 , . . . , vn )) ⊆ FTV({v1 , . . . , vn }), and (3) the transformation preserves the set of solutions (i.e. h j, {v1 , . . . , vn }i and TAn ( j, v1 , . . . , vn ) are equivalent). Points (1) and (2) are straightforward, so we consider only point (3). The proof is by induction on n. n = 1. Every substitution s is a solution to h j, {v1 }i. Therefore, h j, {v1 }i and ∃².∅ are equivalent. n > 1. By induction h j, {v1 , . . . , vn−1 }i and TAn−1 ( j, v1 , . . . , vn−1 ) are equivalent. Therefore, if TAn−1 ( j, v1 , . . . , vn−1 ) has no solutions, then h j, {v1 , . . . , vn }i and ∃².{int = bool} are equivalent (they both have no solutions). Assume that → → α .P has solutions. For all s ∈ MGS(∃− α .P ) we TAn−1 ( j, v1 , . . . , vn−1 ) = ∃− have that, by Lemma A.3, n−1 h j, Lubn−1 ≤2 (s(v1 ), . . . , s(vn−1 )), s(vn )i and TA( j, Lub≤2 (s(v1 ), . . . , s(vn−1 )), n−1 → β .P 0 s(vn )) are equivalent. Let TA( j, Lub≤2 (s(v1 ), . . . , s(vn−1 )), s(vn )) = ∃− − → − → − → and γ = FTVR(s) − ( α ] β ). We now prove that h j, {v1 , . . . , vn }i and → → → ∃− α ]− β ]− γ .(P ∪ P 0 ) are equivalent. 0 — If s is a solution to h j, {v1 , . . . , vn }i then it is a solution of → h j, {v1 , . . . , vn−1 }i. So there is s ∈ MGS(∃− α .P ) such that s ≤ s0 and FTV(vn ) ∩ FTVR(s) = ∅. Since s is idempotent, s0 is a solution to − → 0 0 TA( j, Lubn−1 ≤2 (s(v1 ), . . . , s(vn−1 )), s(vn )) = ∃ β .P . Therefore, s is also a so− → − → − → 0 lution to ∃ α ] β ] γ .(P ∪ P ). → → → α ]− β ]− γ .(P ∪ P 0 ), then s0 is a solution to both — If s0 is a solution to ∃− n−1 h j, {v1 , . . . , vn−1 }i and h j, {Lub≤2 (s(v1 ), . . . , s(vn−1 )), s(vn )}i, for some s ∈ → MGS(∃− α .P ) such that FTV(vn ) ∩ FTVR(s) = ∅. Therefore, since s ≤ s0 and s is idempotent, Ind∧ (Lubn≤2 (s0 (v1 ), . . . , s0 (vn ))) ≤ j . s0 is a solution to h j, {v1 , . . . , vn }i. A.3 Soundness and Completeness of the Inference Algorithm Rec, Con (Theorem 9.13) for `Loc, ∧2 Loc,Rec,Con Let `sd obtained by removing ∧2 be the syntax directed restriction of `∧2 rule (SUB) and by replacing the rules (IFI) and (MATCHI) by the following rules:

D; A ` e0 : bool D; A1 ` e1 : v1 D; A2 ` e2 : v2 v = Lub≤2 (v1 , v2 ) Ind∧ (v) ≤ Max{ Min{Ind→ (v10 ) | D; A01 ` e1 : v10 }, Min{Ind→ (v20 ) | D; A02 ` e2 : v20 } } (IFISD) D; A + A1 + A2 ` if e0 then e1 else e2 : v 43 By definition of Lub -satisfaction problem we have 0 ≤ j ≤ Max{Ind→ (v ), . . . , Ind→ (v )}. The ≤2 n 1 condition j ≤ Ind→ (v1 ) is necessary to ensure that, for every k ∈ {1, . . . , n}, h j, {v1 , . . . , vk }i is a Lub≤2 -satisfaction problem (i.e. 0 ≤ j ≤ Max{Ind→ (v1 ), . . . , Ind→ (vk )}).

ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

Rank 2 Intersection Types for Local Definitions and Conditional Expressions



443

D; A0 ` e0 : u0 (∀i ∈ {1, . . . , n}) Ui Bpi0 : u0 D; Ai , { y : u ∈ Ui | y ∈ FV(ei0 )} ` ei0 : vi n v = Lub≤2 (v1 , . . . , vn ) Ind∧ (v) ≤ Max(∪1≤i≤n Min{ Ind→ (vi0 ) | D; A00 ` e0 : u00 , Ui0 Bpi0 : u00 , and D; Ai0 , { y : u ∈ Ui0 | y ∈ FV(ei0 )} ` ei0 : vi0 }) (MATCHISD) D; A0 + A1 + · · · + An ` matche0 with {p1 ⇒ e1 , . . ., pn ⇒ en } : v where (∀i ∈ {1, . . . , n}) {xi,1 , . . . , xi,mi } = FV(pi ), 0 0 xi,1 , . . . , xi,m are fresh i 0 0 0 pi = pi [xi,1 := xi,1 ] · · · [xi,mi := xi,m ], and i 0 0 0 ei = ei [xi,1 := xi,1 ] · · · [xi,mi := xi,mi ] Loc,Rec,Con , as shown by the followIndeed, system `sd ∧2 is as powerful as system `∧2 ing lemma. Loc,Rec,Con LEMMA A.5. (System `sd ). For every ex∧2 is as powerful as system `∧2 Loc,Rec,Con 0 pression e and environment D, if D; A `∧2 e : v, then D; A0 `sd ∧2 e : v for 0 0 0 0 some A and v such that A ≤1 A and v ≤2 v.

PROOF.

Let D1 ≤2 D2 mean that

—Dom(D1 ) = Dom(D2 ), → —for every assumption x : ∀− β .hA2 , v2 i ∈ D2 there is an assumption x : − → → → ∀ α .hA1 , v1 i ∈ D1 such that A2 ≤1 A1 , v1 ≤2 v2 , and − α ⊆− β ,44 and → − → α .v1 ∈ D1 —for every assumption x : ∀ β .v2 ∈ D2 there is an assumption x : ∀− − → − → such that v1 ≤2 v2 and α ⊆ β . The result can be proved by showing that (the proof is by structural induction on `Loc,Rec,Con derivations), for every expression e, environment D, and environ∧2 0 ment D 0 , such that D 0 ≤2 D, if D; A `Loc,Rec,Con e : v, then D 0 ; A0 `sd ∧2 ∧2 e : v for 0 0 0 0 some A and v such that A ≤1 A and v ≤2 v. By Lemma A.5, we have that Theorem 9.13 (Soundness and completeness of ) is implied by the following result. PP for `Loc,Rec,Con ∧2 LEMMA A.6. (Soundness and completeness of PP for `sd ∧2 ). For every expression e and environment D: (Soundness).

If hA, vi ∈ PP(D, e), then D; A `sd ∧2 e : v.

0 (Completeness). If D; A0 `sd ∧2 e : v , then there are a pair hA, vi ∈ PP(D, e) and 0 a substitution s such that A = s(A) and s(v) = v0 .

PROOF.

Both soundness and completeness by structural induction on e.

44 Observe

that — v1 ≤2 v2 implies FTV(v1 ) ⊆ FTV(v2 ), and — A2 ≤1 A1 implies FTV(A2 ) ⊇ FTV(A1 ). ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

444



Ferruccio Damiani

e = x. (Soundness). We have to consider three cases. → — If x : ∀− α .hA0 , v0 i ∈ D, then hs(A0 ), s(v0 )i ∈ PP(D, x), for some fresh → renaming s of − α . We have D; s(A0 ) `sd ∧2 x : s(v0 ) by rule (IDlocal ). − → — If x : ∀ α .v ∈ D, use rule (IDglobal ). — If x 6∈ Dom(D), use rule (IDundefined ). (Completeness). Again, we have to consider three cases. → — If x : ∀− α .hA0 , v0 i ∈ D, then the last (and only) rule applied must be (IDlocal ). → — If x : ∀− α .v ∈ D, the last (and only) rule applied must be (IDglobal ). — If x 6∈ Dom(D), the last (and only) rule applied must be (IDundefined ). In all the three cases the proof is immediate. e = c. (Soundness). Use rule (CONST). (Completeness). Immediate, since the last (and only) rule applied must be (CONST). e = λx.e0 . (Soundness). We have to consider two cases. — If x ∈ FV(e0 ), then hA, x 0 : ui, v0 i ∈ PP(D, e0 [x := x 0 ]) and hA, ui → v0 i ∈ 0 PP(D, λ x.e0 ). By induction, D; A, x 0 : ui `sd ∧2 e0 [x := x ] : v0 , and by rule (ABS) we get: D; A `sd ∧2 λx.e0 : ui → v0 . — If x 6∈ FV(e0 ), then hA, v0 i ∈ PP(D, e0 ) and hA, α → v0 i ∈ PP(D, λ x.e0 ) for some fresh type variable α. By induction, D; A `sd ∧2 e0 : v0 , and by rule (ABSVAC) we get: D; A `sd ∧2 λx.e0 : α → v0 . (Completeness). Again, we have to consider two cases. — If x ∈ FV(e0 ), then the last rule applied must be (ABS). We have v0 = 0 0 ui 0 → v00 and D; A0 , x 0 : ui 0 `sd ∧2 e0 [x := x ] : v0 . By induction there exist a 0 0 fresh pair h(A, x : ui), v0 i ∈ PP(D, e0 [x := x ]) and a substitution s such that A0 , x 0 : ui 0 = s(A, x 0 : ui) and s(v0 ) = v00 . So hA, ui → v0 i ∈ PP(D, λ x.e0 ) and s are the desired pair and substitution. — If x 6∈ FV(e0 ), then the last rule applied must be (ABSVAC). We have 0 v0 = u → v00 and D; A0 `sd ∧2 e0 : v0 . By induction there exist a fresh pair hA, v0 i ∈ PP(D, e0 ) and a substitution s such that A0 = s(A) and s(v0 ) = v00 . So hA, α → v0 i ∈ PP(D, λ x.e0 ), where α is a fresh type variable, and [α := u] ◦ s are the desired pair and substitution. ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

Rank 2 Intersection Types for Local Definitions and Conditional Expressions



445

e = e0 e1 . (Soundness). We have hA0 , v0 i ∈ PP(D, e0 ) and, by induction, D; A0 `sd ∧2 e0 : v0 . — If v0 is a type variable α, then we must have a fresh pair hA1 , v1 i ∈ PP(D, e1 ), A = s(A0 + A1 ) and v = s(α2 ), where s ∈ MGS(∃².{v1 ≤ α1 , α = α1 → α2 } for fresh type variables α1 and α2 . By induction, D; A1 `sd ∧2 e1 : v1 . By substitutivity D; s(A0 ) `sd ∧2 e0 : s(α), and D; s(A1 ) `sd ∧2 e1 : s(v1 ). Then, by rule (APP), we have: D; s(A0 + A1 ) `sd ∧2 e0 e1 : s(α2 ).

— If v0 = u1 ∧ · · · ∧ un → v0 , then we must have fresh pairs hAi , vi i ∈ PP(D, e1 ) (for all i ∈ {1, . . . , n}), s ∈ MGS(∃².{vi ≤ ui | i ∈ {1, . . . , n}}, A = s(A0 + A1 + · · · + An ), and v = s(v0 ). By induction and substitutivity 0 D; s(A0 ) `sd ∧2 e0 : s(u1 ∧ · · · ∧ un → v ), and sd D; s(A1 ) `∧2 ei : s(vi ) (for all i ∈ {1, . . . , n}). Then, by rule (APP), we have: 0 D; s(A0 + A1 + · · · + An ) `sd ∧2 e0 e1 : s(v ).

(Completeness). The last rule applied must be (APP). We have D; A00 `sd ∧2 0 0 0 e0 : u01 ∧ · · · ∧ u0n → v0 , D; Ai0 `sd ∧2 e1 : ui (∀i ∈ {1, . . . , n}), and A = A0 + A01 + · · · + A0n . By induction both PP(D, e0 ) and PP(D, e1 ) are not empty and, by Lemma 9.12.(2), it is enough to consider the following two cases on the structure of the pairs hA0 , v0 i ∈ PP(D, e0 ). — v0 = α (a type variable). By induction there exists a substitution s0 such that A00 = s0 (A0 ) and s0 (α) = u01 ∧ · · · ∧ u0n → v0 . By definition of substitution, s0 (α) ∈ T0 , so we have that n = 1 and v0 = u for some u ∈ T0 . By induction and Lemma 9.12.(2) there is a fresh pair hA1 , v1 i ∈ PP(D, e1 ) and a substitution s1 such that A01 = s1 (A1 ) and s1 (v1 ) = u01 . Let P = {v1 ≤ α1 , α = α1 → α2 }, where α1 , α2 are fresh. The substitution s0 = s0 ◦s1 ◦{α1 := u01 , α2 := u} is a solution of the satisfaction problem ∃².P and is such that A0 = s0 (A0 ) + s1 (A1 ) = s0 (A0 + A1 ), and s0 (α2 ) = u = v0 . So there is s ∈ MGS(∃².P ) such that hs(A0 + A1 ), s(α2 )i ∈ PP(D, e0 e1 ) 0

and s ≤ s . —v0 = u1 ∧ · · · ∧ um → v. By induction there exists a substitution s0 such that A00 = s0 (A0 ) and s0 (v) = u01 ∧ · · · ∧ u0m → v0 . ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

446



Ferruccio Damiani

By induction and Lemma 9.12.(2), for all j ∈ {1, . . . , m}, there are fresh pairs hA j , v j i ∈ PP(D, e1 ) and substitutions s j such that A0j = s j (A j ) and s j (v j ) = u0j . Let P = {v j ≤ u j | j ∈ {1, . . . , m}}. The substitution s0 = s0 ◦s1 ◦ · · · ◦sm is a solution of the satisfaction problem ∃².P and is such that A0 = s0 (A0 ) + s1 (A1 ) + · · · + sm (Am ) = s0 (A0 + A1 + · · · + Am ), and s0 (v) = v0 . So there is s ∈ MGS(∃².P ) such that hs(A0 + A1 + · · · + Am ), s(v)i ∈ PP(D, e0 e1 ) 0 and s ≤ s . e = let x = e0 in e1 . (Soundness). We have fresh pairs hA0 , v0 i ∈ PP(D, e0 ) and hA1 , vi ∈ → → α .hA0 , v0 i), e1 [x := x 0 ]), where − α = FTV(A0 ) ∪ FTV(v0 ). By PP((D, x 0 : ∀− − → sd 0 0 induction, D; A0 `∧2 e0 : v0 and D, x : ∀ α .hA0 , v0 i; A1 `sd ∧2 e1 [x := x ] : v1 . — If x ∈ FV(e1 ), then A = A1 . So by rule (LETPSI) we have:45 D; A `sd ∧2 let x = e0 in e1 : v. — If x 6∈ FV(e1 ), then A = A1 + A0 . So by rule (LETPSI) we have: D; A `sd ∧2 let x = e0 in e1 : v. (Completeness). The last rule applied must be (LETPSI). We have D; A00 `sd ∧2 − → 0 0 00 0 e0 : v00 , Ind→ (v00 ) = Min{Ind→ (v000 ) | D; A000 `sd ∧2 e0 : v0 }, D, x : ∀ α .hA0 , v0 i; 0 0 A01 `sd ∧2 e1 [x := x ] : v , and ( A01 , if x ∈ FV(e1 ) 0 A = 0 0 A1 + A0 , otherwise Let x ∈ FV(e1 ) (the other case is similar). By induction there are fresh pairs → hA0 , v0 i ∈ PP(D, e0 ), hA1 , v1 i ∈ PP((D, x 0 : ∀− α .hA00 , v00 i), e1 [x := x 0 ]), and substitutions s0 , s1 , such that: 0. A00 = s0 (A0 ) and s0 (v0 ) = v00 , 1. A01 = s1 (A1 ) and s1 (v1 ) = v0 . → α .hA0 , v0 i), e1 [x := By point (0), there are a fresh pair hA2 , vi ∈ PP((D, x 0 : ∀− 0 x ]) and a substitution s2 such that: 2. A01 = s2 (A2 ) and s2 (v) = v0 . So hA2 , vi ∈ PP(D, let x = e0 in e1 ) and s2 are the desired pair and substitution. e = reci0 {x1 = e1 , . . . , xn = en } (i0 ∈ {1, . . . , n}). (Soundness). We have fresh pairs hAi , vi i ∈ PP(D, ei [x1 := x10 ] · · · [xn := xn0 ]) (for all i ∈ {1, . . . , n}), and s ∈ MGS(∃².{Gen(A1 + · · · + An , v j ) ≤ ui j | j ∈ { j 1 , . . . , j m }}), with {x 0j1 , . . . , x 0jm } = {x10 , . . . , xn0 } ∩ (Dom(A1 + · · · + An )) and 45 The

rule can be applied, since: 0 Ind→ (v0 ) = Min{Ind→ (v00 ) | D; A00 `sd ∧2 e0 : v0 }

(by induction and Proposition 7.9). ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

Rank 2 Intersection Types for Local Definitions and Conditional Expressions



447

A1 + · · · + An = A, x 0j1 : ui j1 , . . . , x 0jm : ui jm . By induction and substitutivity 0 0 D; s(Ai ) `sd ∧2 ei [x1 := x1 ] · · · [xn := xn ] : s(vi ) (for all i ∈ {1, . . . , n}). By Definition 9.1, for all j ∈ { j 1 , . . . , j m }, s(Gen(A1 + · · · + An , v j )) ≤∀2,1 s(ui j ) and, by Lemma 3.8, Gen(s(A1 + · · · + An ), s(v j )) ≤∀2,1 s(ui j ). Then, by rule (REC2), we have: D; s(A) `sd ∧2 reci0 {x1 = e1 , . . . , xn = en } : s(vi0 ). (Completeness). The last rule applied must be (REC2). We have D; Ai0 `sd ∧2 ei [x1 := x10 ] · · · [xn := xn0 ] : vi0 (for all i ∈ {1, . . . , n}), Gen(A01 + · · · + A0n , v0j ) ≤∀2,1 ui 0j (for all j ∈ { j 1 , . . . , j m }), with {x 0j1 , . . . , x 0jm } = {x10 , . . . , xn0 } ∩ Dom(A01 + · · · + A0n ) and A01 + · · · + A0n = A0 , x 0j1 : ui 0j1 , . . . , x 0jm : ui 0jm . By induction, for all i ∈ {1, . . . , n}, there are fresh pairs hAi , vi i ∈ PP(D, ei [x1 := x10 ] · · · [xn := xn0 ]) and substitutions si such that Ai0 = si (Ai ) and si (vi ) = vi0 . Let A1 +· · ·+ An = A, x 0j1 : ui j1 , . . . , x 0jm : ui jm and P = {Gen(A1 +· · ·+ An , v j ) ≤ ui j | j ∈ { j 1 , . . . , j m }}. The substitution s0 = s1 ◦ · · · ◦sn is such that A0 = s0 (A) and s0 (vi0 ) = vi00 and is a solution of the satisfaction problem ∃².P . So there is s ∈ MGS(∃².P ) such that hs(A), s(vi0 )i ∈ PP(D, reci0 {x1 = e1 , . . . , xn = en }) 0

and s ≤ s . e = if e0 then e1 else e2 . (Soundness). We have fresh pairs hA0 , v0 i ∈ PP(D, e0 ), hA1 , v1 i ∈ PP(D, e1 ), hA2 , v2 i ∈ PP(D, e2 ), and substitutions s0 ∈ MGS(∃².{v0 ≤ bool}), s ∈ MGS(h j, {v1 , v2 }i), where j = Max(Ind→ (v1 ), Ind→ (v2 )). By induction and substitutivity D; s0 (A0 ) `sd ∧2 e0 : s0 (v0 ), and sd D; s(Ai ) `∧2 ei : s(vi ) (for all i ∈ {1, 2}). Then by rule (IFISD) we have46 D; s0 (A0 ) + s(A1 ) + s(A2 ) `sd ∧2 if e0 then e1 else e2 : Lub≤2 (s(v1 ), s(v2 )). (Completeness). The last rule applied must be (IFISD). We have D; A00 `sd ∧2 e0 : 0 0 0 0 0 0 0 sd sd 0 0 bool, D; A1 `∧2 e1 : v1 , D; A2 `∧2 e2 : v2 , A = A0 + A1 + A2 , v = Lub≤2 (v10 , v20 ), and 00 Ind∧ (v0 ) ≤ Max{ Min{Ind→ (v100 ) | D; A001 `sd ∧2 e1 : v1 }, → 00 00 sd Min{Ind (v2 ) | D; A2 `∧2 e2 : v200 } } 46 The

rule can be applied, since Ind∧ (Lub≤2 (s(v1 ), s(v2 ))) ≤ j

(since s ∈ MGS(h j, {v1 , v2 }i)), and j = Max(Ind→ (v1 ), Ind→ (v2 )) → 0 0 0 sd = Max{ Min{Ind→ (v10 ) | D; A01 `sd ∧2 e1 : v1 }, Min{Ind (v2 ) | D; A2 `∧2 e2 : v2 } } (by induction and Proposition 7.9). ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.



448

Ferruccio Damiani

By induction there are fresh pairs hA0 , v0 i ∈ PP(D, e0 ), hA1 , v1 i ∈ PP(D, e1 ), hA2 , v2 i ∈ PP(D, e2 ), and substitutions s0 , s1 , s2 , such that: 0. A00 = s0 (A0 ) and s0 (v0 ) = bool, 1. A01 = s1 (A1 ) and s1 (v1 ) = v10 , 2. A02 = s2 (A2 ) and s2 (v2 ) = v20 . Let P = {v0 ≤ bool}. The substitution s00 = s0 ◦s1 ◦s2 —is such that A00 + A01 + A02 = s00 (A0 + A1 + A2 )), and Lub≤2 (s00 (v1 ), s00 (v2 )) = v0 , —is a solution of the ≤∀2,1 -satisfaction problem ∃².P , and —is a solution to the Lub≤2 -satisfaction problem h j, {v1 , v2 }i, where j = Max(Ind→ (v1 ), Ind→ (v2 )).47 So there are — s3 ∈ MGS(∃².P ), and — s ∈ MGS(h j, {v1 , v2 }i), such that hs3 (A0 ) + s(A1 ) + s(A2 ), Lub≤2 (s(v1 ), s(v2 ))i ∈ PP(D, if e0 then e1 else e2 ), s = s03 ◦s3 and s00 = s000 ◦s, for some substitutions s03 , s000 such that Dom(s03 ) ∩ Dom(s000 ) = ∅, FTVR(s03 )∩Dom(s000 ) = ∅, Dom(s000 )∩FTV(s03 (s3 (A0 ))) = ∅, and Dom(s03 )∩(FTV(s(A1 ))∪FTV(s(A2 ))∪FTV(s(v1 ))∪s(FTV(v2 ))) = ∅. Therefore, s0 = s000 ◦s03 is such that 00

A00 + A01 + A02 = s0 (s3 (A0 ) + s(A1 ) + s(A2 )), and s0 (Lub≤2 (s(v1 ), s(v2 ))) = v0 . e = match e0 with {p1 ⇒ e1 , . . . , pn ⇒ en }. (Soundness). We have fresh pairs hA0 , v0 i ∈ PP(D, e0 ), hUl , ul i ∈ PAT(pl0 ) and hAl , vl i ∈ PP(D, el0 ) (for all l ∈ {1, . . . , n}), and substitutions S s ∈ MGS(∃α.{ v0 ≤ α} ∪ ( 1≤l ≤n {ul ≤ α, uil ,1 ≤ ul ,1 , . . . , uil ,hl ≤ ul ,hl })), s0 ∈ MGS(h j, {s(v1 ), . . . , s(vn )}i), with { yl ,1 , . . . , yl ,hl } = Dom(Ul ) ∩ Dom(Al ), Ul = Ul0 , { yl ,1 : ul ,1 , . . . , yl ,hl : ul ,hl }, Al = Al0 , { yl ,1 : uil ,1 , . . . , yl ,hl : uil ,hl }, α fresh type variable, and j = Max(Ind→ (s(v1 )), . . . , Ind→ (s(vn ))). By induction and substitutivity 0 D; s0 (s(A0 )) `sd ∧2 e0 : s (s(v0 )), 0 0 0 0 0 s (s(Ul ))Bpl : s (s(ul )) and D; s0 (s(Al )) `sd ∧2 el : s (s(vl )) (for all l ∈ {1, . . . , n}). Then by rule (MATCHISD) we have48 D; s0 (s(A0 + A01 + · · · + A0n ) `sd ∧2 match e0 with {p1 ⇒ e1 , . . . , pn ⇒ en } : Lubn≤2 (s0 (s(v1 )), . . . , s0 (s(vn ))). 47 In

fact

Ind∧ (Lub≤2 (s00 (v1 ), s00 (v2 ))) = Ind∧ (v0 ) = Ind∧ (Lub≤2 (v10 , v20 )) → 00 00 00 sd 00 ≤ Max{ Min{Ind→ (v100 ) | D; A001 `sd ∧2 e1 : v1 }, Min{Ind (v2 ) | D; A2 `∧2 e2 : v2 } } → → = Max(Ind (v1 ), Ind (v2 )) = j (by induction and Proposition 7.9). 48 The rule can be applied, since Ind∧ (Lubn≤2 (s0 (s(v1 )), . . . , s0 (s(vn )))) ≤ j ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

Rank 2 Intersection Types for Local Definitions and Conditional Expressions



449

(Completeness). The last rule applied must be (MATCHISD). We have 0 0 0 0 0 0 0 D; A00 `sd ∧2 e0 : u0 and, ∀i ∈ {1, . . . , n}, Ui Bpi : u0 , D; Ai , { y : u ∈ Ui | y ∈ n 0 0 0 0 0 0 0 0 0 FV(ei0 )} `sd ∧2 ei : vi , A = A0 + A1 + · · · + An , v = Lub≤2 (v1 , . . . , vn ), and

Ind∧ (v0 ) ≤ Max(∪1≤i≤n Min{ Ind→ (vi00 ) | 00 D; A000 `sd ∧2 e0 : u0 , 00 00 0 Ui Bpi : u0 , and 0 00 D; Ai00 , { y : u ∈ Ui00 | y ∈ FV(ei0 )} `sd ∧2 ei : vi }). By induction and Lemma 9.10 there are fresh pairs hA0 , v0 i ∈ PP(D, e0 ) and, ∀l ∈ {1, . . . , n}, hUl , { yl ,1 : ul ,1 , . . . , yl ,hl : ul ,hl }, ul i ∈ PAT(pl0 ), hAl , { yl ,1 : uil ,1 , . . . , yl ,hl : uil ,hl }, vl i ∈ PP(D, el0 ) (where { yl ,1 , . . . , yl ,hl } = Dom(Ul ) ∩ FV(el0 )), and substitutions s0 , sl0 , sl such that: 0. A00 = s0 (A0 ) and s0 (v0 ) = u00 , 1. Ul0 = sl0 (Ul , { yl ,1 : ul ,1 , . . . , yl ,hl : ul ,hl }) and sl0 (ul ) = ul0 , 2. Al0 , { y : u0 ∈ Ul0 | y ∈ FV(el0 )} = sl (Al , { yl ,1 : uil ,1 , . . . , yl ,hl : uil ,hl }) and sl (vl ) = vl0 . S Let P = {v0 ≤ α} ∪ 1≤l ≤n {ul ≤ α, uil ,1 ≤ ul ,1 , . . . , uil ,hl ≤ ul ,hl }, where α is a fresh type variable. The substitution s00 = s0 ◦s01 ◦ · · · ◦sl0 ◦s1 ◦ · · · ◦sl —is such that A00 + A01 + · · · + A0n = s00 (A0 + A1 + · · · + An ) and Lubn≤2 (s00 (v1 ), . . . , s00 (vn )) = v0 , —is a solution of the ≤∀2,1 -satisfaction problem ∃α.P , and —is a solution to the Lub≤2 -satisfaction problem h j, {s(v1 ), . . . , s(vn )}i, where s ∈ MGS(∃α.P ) is such that s ≤ s00 and j = Max(Ind→ (s(v1 )), . . . , Ind→ (s(vn ))).49 Let s000 such that s00 = s000 ◦ s, since s000 is a solution to h j, {s(v1 ), . . . , s(vn )}i, there is s0 ∈ MGS(h j, {s(v1 ), . . . , s(vn )}i) such that hs0 (s(A0 + A1 + · · · + An )), Lubn≤2 (s0 (s(v1 )), . . . , s0 (s(vn )))i ∈ PP(D, match e0 with {p1 ⇒ e1 , . . . , pn ⇒ en }) and s0 ◦s ≤ s00 . (since s0 ∈ MGS(h j, {s(v1 ), . . . , s(vn )}i)), and j = Max(Ind→ (s(v1 )), . . . , Ind→ (s(vn ))) = Max(∪1≤l ≤n Min{ Ind→ (vl0 ) | 0 D; A00 `sd ∧2 e0 : u0 , Ui0 Bpl0 : u00 , and 0 0 D; Al0 , { y : u ∈ Ul0 | y ∈ FV(el0 )} `sd ∧2 el : vi }) (by induction and Proposition 7.9). fact Ind∧ (Lubn≤2 (s00 (v1 ), . . . , s00 (vn ))) = Ind∧ (v0 ) = Ind∧ (Lubn≤2 (v10 , . . . , vn0 )) 00 ≤ Max(∪1≤i≤n Min{Ind→ (vi00 ) | D; A000 `sd ∧2 e0 : u0 , Ui00 Bpi0 : u000 , and 0 00 D; Ai00 , { y : u ∈ Ui00 | y ∈ FV(ei0 )} `sd ∧2 ei : vi }) → → = Max(Ind (s(v1 )), . . . , Ind (s(vn ))) = j

49 In

(by induction and Proposition 7.9). ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

450



Ferruccio Damiani

ACKNOWLEDGMENTS

I thank Mario Coppo, Mariangiola Dezani, Paola Giannini, Ines Margaria, Maddalena Zacchi, and the referees of earlier versions of this paper, for valuable comments and suggestions. I also thank Emiliano Leporati for much useful feedback during the preparation of his Master thesis [Leporati 2000]. I’m particularly grateful to the TOPLAS referees for insightful and constructive comments, which greatly improved the submitted version. REFERENCES ADITYA, S. AND NIKHIL, R. 1991. Incremental polymorphism. In Functional Programming Languages and Computer Architecture. LNCS 523. Springer, 379–405. BARENDREGT, H. P., COPPO, M., AND DEZANI-CIANCAGLINI, M. 1983. A filter lambda model and the completeness of type assignment. J. Symb. Logic 48, 931–940. COPPO, M. 1980. An extended polymorphic type system. In Mathematical Foundations of Computer Science. LNCS 88. Springer, 194–204. COPPO, M. AND DEZANI-CIANCAGLINI, M. 1980. An extension of basic functional theory for lambdacalculus. Notre Dame J. Formal Logic 21, 4, 685–693. COPPO, M., DEZANI-CIANCAGLINI, M., AND VENNERI, B. 1980. Principal Type Schemes and Lambdacalculus Semantics. In To H. B. Curry. Essays on Combinatory Logic, Lambda-calculus and Formalism, R. Hindley and J. Seldin, Eds. Accademic Press, London, 480–490. COPPO, M., DEZANI-CIANCAGLINI, M., AND VENNERI, B. 1981. Functional Characters of Solvable Terms. Zeith. Math. Logik Und Grund. Math. 27, 45–58. COPPO, M. AND GIANNINI, P. 1995. Principal Types and Unification for Simple Intersection Types Systems. Information and Computation 122, 1, 70–96. DAMAS, L. M. M. 1984. Type Assignment in Programming Languages. Ph.D. thesis, University of Edinburgh. DAMAS, L. M. M. AND MILNER, R. 1982. Principal type schemas for functional programs. In POPL’82. ACM, 207–212. DAMIANI, F. 2000. Typing local definitions and conditional expressions with rank 2 intersection. In FOSSACS’00 (part of ETAPS’00). LNCS 1784. Springer, 82–97. DAMIANI, F. AND GIANNINI, P. 1994. A Decidable Intersection Type System based on Relevance. In TACS’94. LNCS 789. Springer, 707–725. GIRARD, J. Y. 1972. Interpretation fonctionelle et elimination des coupures dans l’aritmetique d’ordre superieur. Ph.D. thesis, Universit´e Paris VII. HENGLEIN, F. 1993. Type inference with polymorphic recursion. ACM Trans. Prog. Lang. Syst. 15, 2, 253–289. HINDLEY, R. 1997. Basic Simple Type Theory. Number 42 in Cambridge Tracts in Theoretical Computer Science. Cambridge University Press, London. JIM, T. 1995. Rank 2 type systems and recursive definitions. Tech. Rep. MIT/LCS/TM-531, LCS, Massachusetts Institute of Technology. JIM, T. 1996. What are principal typings and what are they good for? In POPL’96. ACM, 42–53. JIM, T. 2000. A polar type system. In ICALP Workshops. Proceedings in Informatics, vol. 8. Carleton-Scientific, 323–338. KFOURY, A. J., TIURYN, J., AND URZYCZYN, P. 1993. Type reconstruction in the presence of polymorphic recursion. ACM Trans. Prog. Lang. Syst. 15, 2, 290–311. KFOURY, A. J. AND WELLS, J. B. 1994. A direct algorithm for type inference in the rank-2 fragment of the second-order lambda -calculus. In LISP and Functional Programming ’94. ACM. KFOURY, A. J. AND WELLS, J. B. 1999. Principality and Decidable Type Inference for Finite-Rank Intersection Types. In POPL’99. ACM, 161–174. LEIVANT, D. 1983. Polymorphic Type Inference. In POPL’83. ACM, 88–98. LEPORATI, E. 2000. Intersezione al rank 2 per MiniOcaml. M.S. thesis, Dipartimento di Informatica, Universita` di Torino. MARGARIA, I. AND ZACCHI, M. 1995. Principal typing in a ∀∧ discipline. J. Logic Comp. 5, 367–381. ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.

Rank 2 Intersection Types for Local Definitions and Conditional Expressions



451

MEERTENS, L. 1983. Incremental polymorphic type checking in B. In POPL’83. ACM, 265–275. MILNER, R., TOFTE, M., HARPER, R., AND MACQUEEN, D. 1997. The Definition of Standard ML Revised. MIT Press. MYCROFT, A. 1984. Polymorphic Type Schemes and Recursive Definitions. In International Symposium on Programming. LNCS 167. Springer, 217–228. O’CAML. The O’Caml Language Home Page, http://www.ocaml.org. REYNOLDS, J. C. 1974. Towards a Theory of Type Structure. In Colloque sur la Programmation. LNCS 19. Springer. RONCHI DELLA ROCCA, S. 1988. Principal Type Scheme and Unification for Intersection Type Discipline. Theoret. Comput. Sci. 59, 181–209. RONCHI DELLA ROCCA, S. AND VENNERI, B. 1984. Principal Types Schemes for an extended type theory. Theoret. Comput. Sci. 28, 151–169. SHAO, Z. AND APPEL, A. W. 1993. Smartest recompilation. In POPL’93. ACM, 439–450. URZYCZYN, P. 1997. Type reconstruction in Fω . Mathematical Structures in Computer Science 7, 4, 329–358. VAN BAKEL, S. 1993. Intersection Type Disciplines in Lambda Calculus and Applicative Term Rewriting Systems. Ph.D. thesis, Katholieke Universiteit Nijmegen. ´ NDEZ, M. 2000. Polymorphic Intersection Type Assignment VAN BAKEL, S., BARBANERA, F., AND FERNA for Rewite Systems with Intersection and beta-rule (Extended Abstract). In TYPES’99. LNCS 1956. Springer, 41–60. WELLS, J. 1994. Typability and type-checking in the second-order lambda-calculus are equivalent and undecidable. In Logic in Computer Science. IEEE, 176–185. YOKOUCHI, H. 1995. Embedding a Second-Order Type System into an Intersection Type System. Inform. Comp. 117, 206–220. Received December 2001; revised October 2002; accepted January 2003

ACM Transactions on Programming Languages and Systems, Vol. 25, No. 4, July 2003.