<<

15-819: Foundations of Quantitative Program Analysis Lecture 8: Substructural Type Systems

Jan Hoffmann

September 26, 2019

1 Introduction

In the type systems we have studied so far, we have taken so-called structural properties for granted. For example, consider the typing rule for variables.

Γ,x : τ x : τ `

In the rule, we view the context Γ0 Γ,x : τ as a function from variables to types, and are ≡ interested in the position at which x appears in Γ0 if we view it as a list. So we just assume, it appears in the right-most position in the rule. Moreover, we are not interested in the domain of Γ. Of course, Γ0 would be malformed if the variable x would appear in Γ or other variables would appear twice. But we allow arbitrary other variables in Γ in the variable rule. In substructural type systems we are more precise about such structural properties to control the use of variables. They correspond to substructural logics (such as linear logic). Substructural type systems find applications in memory management, access control, concurrent program- ming, and (of course) resource analysis.

2 Structural Properties

Before we discuss substructural type systems, we define some structural properties that we are interested in. To this end, we are very precise about type contexts. We define, as before

Γ :: Γ,x : τ . = · |

However, we now take the definition literally and view Γ as list x1 : τ1,...,xn : τn instead of a function from variables to types. In particular, we do not identify lists with the same variables and type assignments. The only requirement, we still have is that variables appear at most once in a given context. For example, we have

x : τ, y : τ0 y : τ0,x : τ 6= for well-formed contexts since x y. 6=

Exchange We say that a type systems allows for exchange if the following rule is admissible.

Γ1,x : τ1, y : τ2,Γ2 e : τ ` (EXCH) Γ , y : τ ,x : τ ,Γ e : τ 1 2 1 2 ` Intuitively, the rule states that the order of variables in type contexts does not matter in type derivations. Type systems in which the exchange rule is not admissible are called ordered. In this course, we will only study type systems that enjoy exchange.

1 Intuition Weakening Contraction structural no restriction on variable use yes yes affine variables are used at most once yes no relevant variables are used at least once no yes linear variables are used exactly once no no

Table 1: Substructural Type Systems

Weakening We say that a type system allows for weakening if the following rule is admissible.

Γ e : τ ` (WEAK) Γ,x : τ0 e : τ ` From the conclusion of the rule, we know that the variable x does not appear in Γ. An since Γ e : τ, x is not free in e. So the rule states that we can always add an unused variable to a ` context in a type derivation. Type systems without weakening are called relevant.

Contraction We say that a type systems allows for contraction if the following rule is admissible.

Γ,x1 : τ,x2 : τ e : τ ` (CNTR) Γ,x : τ [x,x/x ,x ]e : τ ` 1 2 A difference in the rule CNTR in comparison with the rules WEAK and EXCH is that the ex- pression in the conclusion is different from the expression in the premise. In the expression e0 [x,x/x ,x ]e, we rename both the occurrences of x and x2 to x. So if x and x appear free ≡ 1 2 1 1 2 in e then x appears multiple times (free) in e0. In this case, we also say that x is used multiple times. Intuitively, the contraction rule states that it does not affect type judgments if a variable is used more often. A type system that does not enjoy contraction is called affine. A type system that does not enjoy contraction and weakening is called linear.

3 Substructural Type Systems

The type systems we have studied so far enjoy exchange, weakening, and contraction. Consider a context Γ x : τ , y : τ in a typing such as Γ e : τ. In the previous type judgments, we have = 1 2 ` been able to

• use x once as in x : τ , y : τ x, 1 2 ` 〈 〈〉〉 • use x multiple times as in x : τ , y : τ x,x 1 2 ` 〈 〉 • use x not at all as in x : τ , y : τ y, 1 2 ` 〈 〈〉〉 In a substructural type system, we view variables as resources and control how these resources are used. We will focus on three types of substructural type systems: linear type systems, affine type systems, and relevant type systems. Another important class of substructural type systems are ordered type systems. There the order in which variables are introduced and used is important. Linear, affine, and relevant type systems can be characterized by weakening and contraction as in Table 1. To study substructural type systems, we use the expressions and types of the simply-typed lambda calculus with units.

e :: x x = app(e1;e2) e1(e2) lam{τ}(x.e) λ(x : τ)e triv 〈〉

2 Γ ` e : τ “expression e has type τ in context Γ” `

` Γ,x:τ0 e : τ (L:VAR) (L:UNIT) ` (L:ABS) ` ` ` x : τ x : τ triv : unit Γ lam{τ0}(x.e): τ0 τ ` · ` ` →

` ` Γ1 e1 : τ0 τ Γ2 e2 : τ0 Γ1,x : τ1, y : τ2,Γ2 e : τ ` → ` (L:APP) ` (L:EXCH) Γ ,Γ ` app(e ;e ): τ Γ , y : τ ,x : τ ,Γ e : τ 1 2 ` 1 2 1 2 1 2 `

Figure 1: Linear type rules.

So a type is either an arrow type τ τ or the unit type 1. 1 → 2 τ :: arr(τ ;τ ) τ τ = 1 2 1 → 2 unit 1

3.1 Linear Type Systems Our goal is to design a linear type system, that is, a type system that ensures that every variable is used exactly once. To this end we define the rules in Figure 1, which define the type judgment Γ ` e : τ. ` As before, we the rules L:VAR and L:UNIT axioms (or leave notes). To maintain the invariant that every variable is used once, we require that the context Γ in L:VAR contains exactly the variable x. Similarly, we require that the context is empty in L:UNIT since we do not use a ` variable in the unit expression. In the rule L:ABS, the premise Γ,x:τ0 e : τ requires that the ` variables in Γ and x have to be used exactly once in the function body e. However, the function itself will be used exactly once in the program. In the rule L:APP, we spit up the context Γ into Γ1 and Γ2. The two premises ensure that every variable in Γ1 is used exactly once in e1 and every variable in Γ2 is used exactly once in e2. For example, we can derive the judgment f : 1 1 τ,x : 1, y : 1 ` app(app(f ;x); y): τ as → → ` follows

(L:VAR) (L:VAR) f : 1 1 τ ` f : 1 1 τ x : 1 ` x : 1 → → ` → → ` (L:APP) (L:VAR) f : 1 1 τ,x : 1 ` app(f ;x): 1 τ y : 1 ` y : 1 → → ` → ` (L:APP) f : 1 1 τ,x : 1, y : 1 ` app(app(f ;x); y): τ → → ` Similarly we could derive the judgment

f : 1 1 τ,x : 1 ` app(app(f ;x); ): τ . → → ` 〈〉 However, we can not derive

f : 1 1 τ,x : 1, y : 1 ` app(app(f ;x); ): τ → → ` 〈〉 nor f : 1 1 τ,x : 1 ` app(app(f ;x);x): τ . → → ` In the following lectures, we will just assume that existence of the exchange rule without explicitly mentioning or using it.

3.2 Affine Type Systems An affine type system ensures that every variable is used at most once. There are two possibilities to turn the linear type system in Figure 1 into an affine one.

3 The fist option is to leave the existing type rules unchanged and add an additional weakening rule. We write Γ a e : τ for the judgment that we derive with these rules. ` Γ a e : τ ` a (WEAK) Γ,x : τ0 e : τ ` As discussed earlier, the idea of the rule WEAK is that we can add an unused variable x to the context of a type judgment. Using WEAK and the linear rules, we can derive the judgment f : 1 1 τ,x : 1, y : 1 a → → ` app(app(f ;x); ): τ . 〈〉 (L:VAR) (L:VAR) (L:UNIT) f : 1 1 τ a f : 1 1 τ x : 1 a x : 1 a : 1 → → ` → → ` (L:APP) · ` 〈〉 (WEAK) f : 1 1 τ,x : 1 a app(f ;x): 1 τ y : 1 a : 1 → → ` → ` 〈〉 (L:APP) f : 1 1 τ,x : 1, y : 1 a app(app(f ;x); ): τ → → ` 〈〉 We can easily show that every linear typing is also an affine typing. As the previous example shows, the converse is not true.

Theorem 1. Let e be an expression. If Γ ` e : τ then Γ a e : τ. ` ` A disadvantage of this approach that the rule WEAK is not syntax-directed, which means that it can be applied to every syntactic form. In contrast, the type rules in the linear type system are syntax directed and there is exactly one rule for every syntactic form. Such a syntax-directed type system makes type checking straightforward and simplifies type inference. The second option is to not add additional rules but to replace the axioms L:VAR and L:UNIT with the rules A:VAR and A:UNIT defined below. The intuition is that we allow to an implicit weakening of all variables in the context Γ. The advantage of this approach is that the rules are syntax directed. A disadvantage is that we have to incorporate implicit waking into multiple rules and that we restrict derivations to have a specific form.

(A:VAR) (A:UNIT) Γ,x : τ as x : τ Γ as triv : unit ` ` We write Γ as e : τ for the judgment that we derive with these rules. Using the rule A:UNIT, ` we can derive the previous type judgment as follows.

(L:VAR) (L:VAR) f : 1 1 τ as f : 1 1 τ x : 1 as x : 1 → → ` → → ` (L:APP) (A:UNIT) f : 1 1 τ,x : 1 as app(f ;x): 1 τ y : 1 as : 1 → → ` → ` 〈〉 (L:APP) f : 1 1 τ,x : 1, y : 1 as app(app(f ;x); ): τ → → ` 〈〉 We can show that the syntax-directed and declarative approaches are equivalent as formal- ized by the following theorem.

Theorem 2. Let e be an expression. Then Γ a e : τ if and only if Γ as e : τ. ` ` 3.3 Relevant Type Systems In a relevant type system, we want to ensure that each variable is used at least once. This is of course the case in the linear type system but we can be a more permissive. Like for the affine type system, we can simply leave the (syntax-directed) linear type rules unchanged and add a structural rule for contraction.

r Γ,x1 : τ,x2 : τ e : τ ` (CNTR) Γ,x : τ r [x,x/x ,x ]e : τ ` 1 2

4 Γ Γ1 Γ2 “context Γ is shared as Γ1 and Γ2” . |

Γ Γ1 Γ2 Γ Γ1 Γ2 (SHARE0) . | (SHAREL) . | (SHARER) Γ,x : τ Γ1,x : τ Γ2 Γ,x : τ Γ1 Γ2,x : τ ·.· | · . | . |

Γ Γ1 Γ2 . | (SHAREB) Γ,x : τ Γ1,x : τ Γ2,x : τ . |

Figure 2: Sharing rules.

We write Γ r e : τ for the resulting judgment. With the contraction rule we can derive the ` judgment f : 1 1 τ,x : 1 ` app(app(f ;x);x): τ. We simply apply contraction and then use → → ` the derivation linear of the linear judgment as before

··· (T:APP) f : 1 1 τ,x : 1, y : 1 ` app(app(f ;x); y): τ → → ` (CNTR) f : 1 1 τ,x : 1 ` app(app(f ;x);x): τ → → ` Clearly, every linear type derivation is also a relevant derivation.

Theorem 3. Let e be an expression. If Γ ` e : τ then Γ r e : τ. ` ` As the examples show, the converse is not true and relevant and affine type systems are incomparable. There is also a syntax directed version of the relative type system. If we start again with the linear type rules, a good idea is to modify the rule L:APP for function applications. However, the standard rule

` ` Γ e1 : τ0 τ Γ e2 : τ0 ` → ` (L:APP) Γ ` app(e ;e ): τ ` 1 2 is not quite what we want. It would result in a type system in which we have to use each variable in Γ in both, e1 and e2. Instead, have to define a sharing judgment Γ Γ1 Γ2 that states that the . | variables in Γ have to be used in Γ1, Γ2, or in both. The idea is formalized in Figure 2. We can then define the syntax-directed relevant type system by replacing the rule L:APP in the linear type system with the rule R:APP below, define the judgment Γ rs e : τ. ` rs rs Γ1 e1 : τ0 τ Γ2 e2 : τ0 Γ Γ1 Γ2 ` → ` . | (R:APP) Γ rs app(e ;e ): τ ` 1 2 We can show that this rule is equivalent to adding the contraction rule.

Theorem 4. Let e be an expression. Then Γ r e : τ if and only if Γ rs e : τ. ` ` A less elaborate way of obtaining a syntax-directed contraction rule is to introduce a syntactic form that makes multiple uses of a variable explicit in the syntax.

e :: ... = share(e1;x1,x2.e2) share e1 as x1,x2 in e2

The syntactic form share(e1;x1,x2.e2) is like a let binding that binds the result of e1 to both x1 and x2. The rule of evaluation dynamics is as follows.

e1 v1 [v1,v1/x1,x2]e2 v ⇓ ⇓ (E:SHARE) share(e1;x1,x2.e2)

5 The type rule that encodes contraction is as expected.

rs rs Γ1 e1 : τ0 Γ2,x1 : τ0,x2 : τ0 e2 : τ ` ` (E:SHARE) Γ ,Γ rs share(e ;x ,x .e ): τ 1 2 ` 1 1 2 2 3.4 Controlling Structural Properties In the remainder of this course, we will often use a linear type system that is extended with both weakening and contraction. This leads to a “standard” structural type discipline but it enables us to precisely control the structural properties. For example, we can mix linear and unrestricted types in the same context by allowing sharing and weakening for some types only. If we write Γ e : τ for the regular typing judgment from the cost-semantics lecture and ` Γ u e : τ for the judgment we obtain by extending the linear rules from Figure 1 with the rules ` WEAK and CNTR then we can prove the following theorem.

Theorem 5. Let e be an expression. Then Γ e : τ if and only if Γ u e : τ. ` `

6