University of Pennsylvania ScholarlyCommons

Departmental Papers (CIS) Department of Computer & Information Science

1-23-2010

Lightweight linear types in System F°

Karl Mazurak University of Pennsylvania

Jianzhou Zhao University of Pennsylvania

Stephan A. Zdancewic University of Pennsylvania, [email protected]

Follow this and additional works at: https://repository.upenn.edu/cis_papers

Part of the Computer Sciences Commons

Recommended Citation Karl Mazurak, Jianzhou Zhao, and Stephan A. Zdancewic, "Lightweight linear types in System F°", . January 2010.

Karl Mazurak, Jianzhou Zhao, and Steve Zdancewic. Lightweight linear types in System Fo. In ACM SIGPLAN International Workshop on Types in Languages Design and Implementation (TLDI), pages 77-88, 2010. doi>10.1145/1708016.1708027 © ACM, 2010. This is the author's version of the work. It is posted here by permission of ACM for your personal use. Not for redistribution. The definitive version was published in ACM SIGPLAN International Workshop on Types in Languages Design and Implementation, {(2010)} http://doi.acm.org/10.1145/1708016.1708027" Email [email protected]

This paper is posted at ScholarlyCommons. https://repository.upenn.edu/cis_papers/591 For more information, please contact [email protected]. Lightweight linear types in System F°

Abstract We present Fo, an extension of System F that uses kinds to distinguish between linear and unrestricted types, simplifying the use of linearity for general-purpose programming. We demonstrate through examples how Fo can elegantly express many useful protocols, and we prove that any protocol representable as a DFA can be encoded as an Fo type. We supply mechanized proofs of Fo's soundness and parametricity properties, along with a nonstandard operational semantics that formalizes common intuitions about linearity and aids in reasoning about protocols.

We compare Fo to other linear systems, noting that the simplicity of our -based approach leads to a more explicit account of what linearity is meant to capture, allowing otherwise-conflicting interpretations of linearity (in particular, restrictions on aliasing versus restrictions on resource usage) to coexist peacefully. We also discuss extensions to Fo aimed at making the core language more practical, including the additive fragment of linear logic, algebraic datatypes, and recursion.

Disciplines Computer Sciences

Comments Karl Mazurak, Jianzhou Zhao, and Steve Zdancewic. Lightweight linear types in System Fo. In ACM SIGPLAN International Workshop on Types in Languages Design and Implementation (TLDI), pages 77-88, 2010. doi>10.1145/1708016.1708027

© ACM, 2010. This is the author's version of the work. It is posted here by permission of ACM for your personal use. Not for redistribution. The definitive version was published in ACM SIGPLAN International Workshop on Types in Languages Design and Implementation, {(2010)} http://doi.acm.org/ 10.1145/1708016.1708027" Email [email protected]

This other is available at ScholarlyCommons: https://repository.upenn.edu/cis_papers/591 Lightweight Linear Types in System F◦

Karl Mazurak Jianzhou Zhao Steve Zdancewic University of Pennsylvania {mazurak,jianzhou,stevez}@cis.upenn.edu

Abstract Given these success stories, it is perhaps surprising that we have ◦ yet to see general linear types seriously considered for inclusion in We present System F , an extension of System F that uses kinds to 1 distinguish between linear and unrestricted types, simplifying the a mainstream functional . But alas, linear use of linearity for general-purpose programming. We demonstrate types can easily lead to awkward programming models and poten- through examples how System F◦ can elegantly express many use- tially complicated language designs that are difficult both to imple- ment and to program with. This paper seeks to address these issues ful protocols, and we prove that any protocol representable as a ◦ DFA can be encoded as an F◦ type. We supply mechanized proofs by introducing System F —pronounced “F-pop”—a language that ◦ is intended to be a simple foundation for practical linear program- of System F ’s soundness and parametricity properties, along with ◦ a nonstandard operational semantics that formalizes common intu- ming. Rather than aiming at one particular problem, System F lets itions about linearity and aids in reasoning about protocols. programmers enforce their own protocol abstractions through the We compare System F◦ to other linear systems, noting that the power of linearity and polymorphism, yet its typing discipline is lightweight enough to expose in a surface language. simplicity of our kind-based approach leads to a more explicit ac- ◦ count of what linearity is meant to capture, allowing otherwise- System F is simply the Girard–Reynolds polymorphic λ- conflicting interpretations of linearity (in particular, restrictions on calculus [14, 23] extended with two base kinds: ?, classifying aliasing versus restrictions on resource usage) to coexist peace- ordinary, unrestricted types, and ◦, classifying linear types. A sub- fully. We also discuss extensions to System F◦ aimed at making kinding relation ? ≤ ◦ makes explicit the observation that values the core language more practical, including the additive fragment of unrestricted types may safely be treated linearly; i.e., since vari- of linear logic, algebraic datatypes, and recursion. ables of unrestricted type may be used any number of times and linear variables must be used exactly once, it is always safe to use Categories and Subject Descriptors D.3.3 [Programming Lan- unrestricted variables as though they were linear. Any System F◦ guages]: Language Constructs and Features expression with kinds erased is a well-typed System F expression. In introducing System F◦, this paper contributes the following: General Terms Design, Languages, Theory • The design of System F◦, and in particular its use of kinds and Keywords Linear logic, Polymorphism, Type systems kind subsumption, which is lightweight and structured so as to integrate well with existing functional languages. (Section 2) 1. Introduction • Mechanized proofs of standard soundness and parametricity re- sults for System F◦, which ensure that the properties functional Linear logic [15, 16] models resource usage by restricting the prop- programmers rely on continue to hold. (Section 2.1) erties of contraction (the ability to duplicate a resource) and weak- ◦ ening (the ability to discard a resource). In the context of program- • A second, linearity-aware semantics for System F , which for- ming languages, ideas from linear logic were quickly adopted, at malizes common intuitions about linearity and shows that these first to eliminate garbage collection [21] and shortly thereafter to intuitions do indeed hold. (Section 4) handle mutable state [29]. • Several examples—including all regular languages—along Since their introduction, variants, refinements, and improve- with extensions and proposals for compiler support, remark- ments on linear type systems have been proposed for many ap- able primarily for their simplicity, which showcase System F◦’s plications, including explicit memory management and control of potential usefulness. (Sections 3 and 5) aliasing [2, 13, 17, 28, 36], capabilities [9, 10], and tracking state In the rest of this section we discuss the design of System F◦ in changes for program analysis [11, 32]. Of particular interest is work ◦ on typestates, which ensure that a sequence of API calls is well- the context of prior work, and we showcase System F ’s ability to behaved [13, 12], and on session types, which check that the end- enforce programmer-defined protocols with a familiar example. points of a channel agree on the next message to be sent or re- 1.1 Prior work: Linear design considerations ceived [18, 25, 27]. Walker has a more comprehensive survey [33]. There are many variants on linear type systems in the litera- ture [33], but the crucial design decision from our perspective is how linear and unrestricted variables are differentiated and how that mechanism interacts with polymorphism. Our use of kinds Permission to make digital or hard copies of all or part of this work for personal or and kind subsumption is intended to capture the essence of linear- classroom use is granted without fee provided that copies are not made or distributed for profit or commercial advantage and that copies bear this notice and the full citation ity simply and generally while remaining faithful to the standard on the first page. To copy otherwise, to republish, to post on servers or to redistribute to lists, requires prior specific permission and/or a fee. 1 Clean is often seen as the exception to this, but there are subtle differences TLDI’10 January 23, 2010, Madrid, Spain. between its uniqueness types, which concern aliasing, and standard linear Copyright c 2010 ACM 978-1-60558-891-9/10/01. . . $5.00 types (see Section 3.1). semantics and programming model of System F. This division be- become overwhelming if exposed to the programmer. As we are tween linear and unrestricted types is inspired by that proposed for incorporating the full power of System F, exposing at least some monomorphic systems by Wadler [29] and Benton [5]. Here we types is unavoidable; we also believe that System F◦ convincingly contrast our approach with some alternatives from the literature. demonstrates that just the simple distinction between linear and un- Broadly speaking, there are two other approaches to distinguish- restricted types has much to offer. ing linear from unrestricted variables. The first approach, which closely follows linear logic, is to treat all types as linear and in- 1.2 System F◦ by example: Types for filehandles troduce the modal constructor ! to account for unrestricted terms, which must be closed with respect to linear variables. This inter- Linearity lets us specify a filesystem interface that requires a file- acts easily enough with polymorphism, since all types are treated handle to be closed exactly once and forbids its use thereafter. A 3 uniformly—any type can be substituted for any type variable. first approximation for an idealized linear filesystem might be Unfortunately, assuming linearity by default requires very ex- FileHandle : ◦ plicit handling of unrestricted terms; the standard approach uses a let ! construct to introduce unrestricted variables from suspended open : String →? FileHandle computations !e [6, 30]. Because unrestricted values are common in read : FileHandle →? (Char, FileHandle) practice, this can prove quite cumbersome, and the burden extends ? ? Int !Int write : Char → FileHandle → FileHandle even to base types—the constant 3 would be of type , not . ? Further, full inference of !s has been shown to be impossible [22]. close : FileHandle → Unit A second approach distinguishes linear from unrestricted types ? by means of qualifiers lin (for “linear”) and un (for “unrestricted”) readLine : FileHandle → (String, FileHandle) applied to a collection of pre-types [1, 33]. These qualifiers (which do not nest) constrain usage (or aliasing), while the pre-types de- Here open, read, write, and close are intended to be primitive op- termine the introduction and elimination forms of values. This sep- erations over the linear (note the kind ascription) type FileHandle, aration facilitates implicit copying and discarding for unrestricted while readLine is one of many library functions defined to make file access more convenient. The ? decorating the arrow in a type types, yielding a less burdensome programming model. ? Type qualifiers, however, have more complex interactions with like open : String → FileHandle indicates that open is an unre- polymorphism. To retain both soundness and expressivity, one is stricted function, which may be used more than once; each time led to introduce quantification over qualifiers, pre-types, and types open is invoked, it will return a new FileHandle value that must be independently. This quickly leads to large and complex types; for used linearly. Unrestricted functions are also free to take arguments of linear type, as can be seen in the other operations. Similarly, a instance, the type of plus has five qualifiers: ◦ linear function of type τ1 → τ2 should be invoked exactly once, but q4 q5 plus :(q1 Int) → (q2 Int) → (q3 Int) this has no bearing on the kind of either τ1 or τ2. Because operations like read and write consume a FileHandle The relationships among such qualifiers are often nontrivial (e.g. as input and return a linear FileHandle as output, and because such q5 should be lin if q1 is), which can be captured (at the expense of values cannot be duplicated, client programs are forced to sequence 2 additional complexity) by qualifier-level bounded quantification. the calls to these functions, fixing their order of evaluation. Since Qualifiers thus ease the use of unrestricted types but are too un- FileHandle values cannot be discarded, the program—unless its wieldy for a polymorphic source language—indeed, others have overall type indicates that it contains a filehandle—must eventually argued against qualifiers even for intermediate languages [34]. use close to dispose of any FileHandles it has created. Linearity en- Our use of kinds in lieu of ! or type qualifiers strikes a good sures that no aliased or duplicated FileHandles representing closed balance on these issues. As with qualifiers, programming with un- files remain to be improperly accessed. Clients of this interface are restricted types is natural; as with !, polymorphism remains simple. thus constrained, after opening a file, to access that file according Subkinding also plays well with base types: 3 has type Int, which to the regular protocol (read|write)∗close. has kind ? (and, by subsumption, ◦), while the type of plus is the Unfortunately, today’s operating systems do not understand lin- ? ? simple Int → Int → Int. We thus have flexible polymorphic types earity and instead provide unrestricted interfaces, which make no without the need for bounded quantification or other complexities guarantees about correct filehandle usage: of subtyping in a higher-order setting. Closest in design to System F◦ is probably Ahmed, Fluet, and UnsafeFH : ? Morrisett’s language for substructural state [1], though they use qualifiers as described above. Due to their focus on aliasing in mu- unsafeOpen : String →? UnsafeFH table state, their language does not admit subtyping, which would unsafeRead : UnsafeFH →? Char be the analog in their setting of our subkinds. Our subkind relation unsafeWrite : Char →? UnsafeFH →? Unit ? ≤ ◦ agrees with the interpretation of linearity as related to usage; unsafeClose : UnsafeFH →? Unit it does not reflect linearity as alias-freedom, in which linear types are analogous to uniqueness types [17, 28]. Nevertheless, we show System F◦ makes it easy to create a safe interface protecting the in Section 3.1 that matters of aliasing can indeed be addressed in above from misuse. First, for α of kind ◦—our abstract representa- System F◦ given an appropriate representation of references. tion of an actual filehandle—we define a record of safe file opera- Ahmed et al. also admit affine types, for which only weak- tions: ening is permitted, and relevant types, which allow only contrac- File(α) = { read : α →? (Char, α), tion. Such concepts would fit well with our subkinding relation, write : Char →? α →? α, but would increase the complexity of typing context management. ? close : α → Unit } Other systems have considered notions of usage much more fine- grained than ours [19], but the types in such systems can quickly 3 This example uses roughly the same interface given by DeLine and 2 Making Int a proper type rather than a pre-type simplifies the type of plus Fahndrich¨ to motivate Vault [11] and discussed by Kiselyov and Shan [20] but prohibits certain polymorphic functions from accepting integers. as an alternative to their filehandle regions. ˛ κ κ ::= ? ˛ ◦ kinds [E-APPLAM] (λ x:τ. e) v −→ {x 7→ v}e ˛ κ ˛ τ ::= α ˛ τ → τ ˛ ∀α:κ. τ types [E-TAPPLAM] (Λα:κ. v)[τ] −→ {α 7→ τ}v ˛ κ ˛ ˛ ˛ e ::= x ˛ λ x:τ. e ˛ e e ˛ Λα:κ. v ˛ e [τ] expressions κ ˛ 0 0 v ::= λ x:τ. e ˛ Λα:κ. v values e1 −→ e1 e −→ e [E-APP1] [E-APP2] e e −→ e0 e v e −→ v e0 ˛ ˛ 1 2 1 2 Γ ::= · ˛ Γ, α:κ ˛ Γ, x:τ unrestricted typing contexts ˛ ∆ ::= · ˛ ∆, x:τ linear typing contexts e −→ e0 [E-TAPP] e [τ] −→ e0 [τ] Figure 1. System F◦ Figure 2. Evaluation rules for System F◦ Now we can define open to return both the hidden filehandle and its associated operations: typing context ∆, binding only term variables, in addition to the open : String →? ∃α:◦. (α, File(α)) ? standard unrestricted context Γ, which binds both type and term open = λ f:String. let handle = unsafeOpenf in variables; following Barber’s DILL [3], this greatly simplifies the pack α = UnsafeFH in mechanization of our soundness proofs. At the kind level, note ( handle, κ that the rule K-ARROW gives τ1 → τ2 the kind κ regardless of { read = λ?h:UnsafeFH. (unsafeRead h, h), ? ? the kinds of τ1 and τ2. As described in Section 1.2, this decouples write = λ c:Char. λ h:UnsafeFH. ◦ the notion of a linear function (i.e., of type τ1 → τ2), which must unsafeWrite c h; h, be used exactly once, from a function that takes a linear argument close = unsafeClose (i.e., where τ1 has kind ◦), which must use its argument exactly } ):(α, File(α)) once. Rule K-ALL, by contrast, simply gives ∀α:κ.τ the same kind Note that, while the type UnsafeFH is unrestricted within the scope as τ—this is a design choice made in the interests of keeping F◦ of open, the outside world sees its occurrences at the existentially simple, as little seems to be gained by allowing these kinds to differ; bound linear type variable α. If open treats filehandles correctly, this choice is also compatible with a type-erasure interpretation. then any use of an existential package created by open must treat Type application must check that the kind of the supplied type them correctly as well. argument is compatible with the kind of the variable for which it We no longer read, write, and close as separate functions, but li- will be substituted. As mentioned in Section 1, we see linearity as brary functions like readLine, are still useful to have. We could sim- constraining the permitted usage of a variable, which means that ply replace the FileHandles in the first type proposed for readLine it should always be safe to replace a linear type variable with an with open’s return type, ∃α:◦. (File(α), α), but a smarter choice is unrestricted type; we thus allow subkinding via the rule K-SUB. ? ? Subsumption turns out to be key in many useful examples: for readLine : ∀α:◦. File(α) → α → (String, α) instance, it is what allowed the unrestricted type UnsafeFH to be This makes clear that File(α) contains only the (unrestricted) file protected by a linear interface. operations, not the filehandle itself, and by separating out unpacks Weakening—neglecting to use a variable—and contraction— and packs from calls to both primitive operations and library func- using a variable more than once—should only be possible with tions, our types can reflect the fact that the filehandle returned by variables of unrestricted type. Rather than add explicit contraction readLine is the same one that it was given. Writing our functions and weakening rules, we have built these properties into the rules this way allows for useful type coercions; for example, suppose we that require them. The separation of linear and unrestricted typing are also able to open files in read-only mode, resulting in restricted contexts makes this fairly straightforward; rules T-LVAR and T- existential packages of the form UVAR permit weakening by allowing an arbitrary Γ at the leaves of typing derivations, while rule T-APP duplicates Γ but splits ∆ ROFile(α) = { read : α →? (Char, α), via the relation. We can thus prove:4 close : α →? Unit } d Lemma 1 (Weakening). If Γ , Γ ; ∆ ` e : τ 0 and Γ ` τ : ?, Many functions, including readLine, may be defined over this 1 2 1 then Γ , x:τ, Γ ; ∆ ` e : τ 0. weaker interface, and we can always construct a record of type 1 2 0 ROFile(α) out of a record of type File(α) to allow a read-write Lemma 2 (Contraction). If Γ1, x:τ, y:τ, Γ2; ∆ ` e : τ and 0 filehandle to be treated as though it were read-only. Γ1 ` τ : ?, then Γ1, x:τ, Γ2; ∆ ` {y 7→ x}e : τ . Of course, such a filesystem interface is of little use if it is too cumbersome for everyday programming. In Section 5.2 we discuss Linear variables must not inadvertently be captured by unre- modest compiler support that ensures that this is not the case. stricted function closures. To this end, rule T-LAM constrains its linear context ∆ according to the λ’s kind annotation κ: ∆ must be ◦ empty if κ is ?. We thus ensure that an unrestricted function cannot 2. System F Defined capture linear variables in its closure, even though it may well take The syntax of System F◦ is given in Figure 1; Figure 2 shows its an argument of linear type. call-by-value (and kind-agnostic) operational semantics, which is Only unrestricted function arguments should be placed in Γ, but completely standard. Type variables are annotated with their kinds subkinding allows any type to be considered as linear and hence when bound (by Λ in expressions or by ∀ in types); kinds also any expression variable to be bound in ∆—a fact which proves κ κ ◦ appear in functions (λ x:τ. e) and function types (τ1 → τ2). F crucial in the proof of preservation. We write this potentially non- 0 0 adopts the value restriction [35], permitting type abstraction only deterministic context extension as [Γ; ∆], x:τ c Γ ; ∆ . over values, for reasons that will become clear later. ◦ Typing and kinding rules for System F , along with auxiliary 4 The lemmas in this section of the paper have all been proved in Coq; the judgments, are given in Figure 3. Our typing rules take a linear source scripts of our proofs are available from the last author’s web pages. 0 Γ ` τ : ? Γ ` τ1 : κ1 Γ ` τ2 : κ2 α:κ ∈ Γ Γ, α:κ ` τ : κ α∈ / Γ [K-SUB] [K-ARR] κ [K-TVAR] [K-ALL] 0 Γ ` τ : ◦ Γ ` τ1 → τ2 : κ Γ ` α : κ Γ ` ∀α:κ. τ : κ

∆1 d ∆2 = ∆ x∈ / ∆ ∆1 d ∆2 = ∆ x∈ / ∆ [U-EMPTY] · d · = · [U-LEFT] [U-RIGHT] ∆1, x:τ d ∆2 = ∆, x:τ ∆1 d ∆2, x:τ = ∆, x:τ

Γ ` τ : ◦ x∈ / Γ, ∆ Γ ` τ : ? x∈ / Γ, ∆ x:τ ∈ Γ [B-LIN] [B-UN] [T-LVAR] Γ; x:τ ` x : τ [T-UVAR] [Γ; ∆], x:τ c Γ; (∆, x:τ) [Γ; ∆], x:τ c (Γ, x:τ); ∆ Γ; · ` x : τ

0 0 0 0 [Γ; ∆], x:τ1 c Γ ; ∆ Γ ; ∆ ` e : τ2 ∆ = · ∨ κ = ◦ Γ, α:κ; ∆ ` v : τ α∈ / Γ [T-LAM] κ κ [T-TLAM] Γ; ∆ ` λ x:τ1. e : τ1 → τ2 Γ; ∆ ` Λα:κ. v : ∀α:κ. τ

κ 0 Γ; ∆1 ` e1 : τ1 → τ2 Γ; ∆2 ` e2 : τ1 ∆1 d ∆2 = ∆ Γ; ∆ ` e : ∀α:κ. τ Γ ` τ : κ [T-APP] [T-TAPP] 0 Γ; ∆ ` e1 e2 : τ2 Γ; ∆ ` e [τ]: {α 7→ τ}τ

Figure 3. Kinding and typing rules for System F◦

Lemma 3 (Progress). If ·; · ` e : τ, then either e is a value or 0 0 0 ◦ 0 there exists some e such that e −→ e . let x = e in e , (λ x:τ. e ) e where e has type τ Proof. Induction on typing derivations, completely standard.

? Unit , ∀α:◦. α → α Preservation, on the other hand, requires a bit of care. As usual, ? unit , Λα:◦. λ x:α. x it depends on various substitution lemmas, and we must keep lin- e1; e2 , let = e1 in e2 earity in mind when formulating them.

◦ ◦ ◦ Lemma 4 (Substitution). (τ1, τ2) , ∀α:◦. (τ1 → τ2 → α) → α ? ◦ 0 0 0 (, ) , Λα:◦. Λβ:◦. λ x:α. λ y:β. 1. If Γ1, α:κ , Γ2 ` τ : κ and Γ1 ` τ : κ then ◦ ◦ ◦ 0 0 Λγ:◦. λ f:α → β → γ. f x y Γ1, {α 7→ τ }Γ2 ` {α 7→ τ }τ : κ. 0 0 ◦ ◦ 0 0 0 0 let (x, y) = e in e , e [τ ](λ x:τ1. λ y:τ2. e ) 2. If Γ1, α:κ , Γ2; ∆ ` e : τ and Γ1 ` τ : κ then 0 0 0 0 0 0 where e has type τ Γ1, {α 7→ τ }Γ2; {α 7→ τ }∆ ` {α 7→ τ }e : {α 7→ τ }τ. 0 0 0 3. If Γ1, x:τ , Γ2; ∆ ` e : τ and Γ1; · ` e : τ then 0 0 ◦ κ0 0 ∃α:κ. τ , ∀β:◦. (∀α:κ. τ → β) → β Γ1, Γ2; ∆ ` {x 7→ e }e : τ. 0 4. If Γ; ∆ , x : τ 0, ∆ ` e : τ and Γ; ∆0 ` e0 : τ 0 then pack α:κ = τ in e : τ , let x = e in 1 2 0 0 0 Λβ:◦. λκ f:(∀α:κ. τ 0 →◦ β). f [τ] x Γ; ∆1, ∆ , ∆2 ` {x 7→ e }e : τ. unpack α, x = e in e0 e [τ 0] (Λα:κ. λ◦x:τ. e0) , Proof. Each case by induction on the first derivation. The result re- where e0 has type τ 0 lies heavily on various strengthening, weakening, and permutation lemmas (with respect to typing, context well-formedness, and the d relation) regarding the handling of typing contexts. Figure 4. System F encodings in F◦ Note that Substitution (3) does not hold if e0 is permitted to

◦ contain free linear variables. Call-by-value reduction allows us to It is easy to see that, modulo the value restriction, System F is consider only values, however, and—because we have adopted the an extension of System F. With this in mind, Figure 4 gives several 5 value restriction—we can prove that unrestricted values contain no well-known System F encodings that we make use of . Aside from free linear variables: kind annotations, these are all standard; the linear annotations on type variables are for generality—the pairs so encoded are linear, Lemma 5. If Γ; ∆ ` v : τ and Γ ` τ : ? then ∆ = ·. for instance—while those that are on arrows account for captured Lemma 6 (Preservation). If Γ; ∆ ` e : τ and e −→ e0, then linear variables in the arguments. Γ; ∆ ` e0 : τ. 2.1 Metatheory of System F◦ From preservation and progress, soundness follows naturally: ◦ Type Soundness We have verified in Coq that System F enjoys Theorem 7 (Type soundness). If ·; · ` e:τ, then it is never the case type safety—a crucial but unsurprising result, given its similarity that e −→∗ e0 where e0 is not a value but cannot step further. to System F. As is standard, we define soundness in terms of two properties: progress and preservation. Progress, which states that a Strong normalization and parametricity System F also has other closed, well-typed non-value can always take an evaluation step, is properties of interest: it is strongly normalizing—evaluation always no different than in ordinary System F: eventually reaches a value—and it enjoys relational parametric- ity [24]. We are able to cheat somewhat in proving the former for ◦ ◦ 5 We also make use of records of unrestricted type; their encodings would F by observing that a well-typed System F expression becomes a generalize that of pairs, but with more ? annotations. well-typed System F expression upon erasure of kind annotations. As the two systems have identical operational behavior, strong nor- cated or discarded directly, naive attempts to do so are unsound— malization follows immediately. for precisely the same reasons that, as discussed in Section 2.1 and Parametricity for F◦ cannot be proved by such an erasure, but, Section 4, we require call-by-value reduction and the value restric- as one might hope from the similarity to System F, it is possible to tion in System F◦—and sound formulations end up being heavier directly adapt the standard logical relations proof with only minor than those that make this distinction [31, 4]. syntactic differences due to our separation of unrestricted and linear We can encode the above system in ours easily enough; we first contexts. We have thus proved (in Coq), for the standard relation define a translation on types [[σ]] as between type substitutions ρ ≈ ρ :Γ, relation between term 1 2 [[α]] = α substitutions ρ ` γ1 ≈ γ2 : Γ; ∆, and computation closure C[[τ]]ρ ◦ of relations induced by a type τ, where ρ maps type variables to [[σ1 ( σ2]] = [[σ1]] → [[σ2]] [[∀α. σ]] = ∀α:◦. [[σ]] term relations and pairs of types and Γ and ∆ bind the variables in ? the domain of the various substitutions: [[!σ]] = Unit → [[σ]] The corresponding translation on terms is straightforward. The only Lemma 8 (Parametricity). If Γ; ∆ ` e : τ, ρ1 ≈ ρ2 :Γ, and interesting cases involve unrestricted variables and the ! modality: ρ ` γ1 ≈ γ2 : Γ; ∆, then (ρ1(γ1(e)), (ρ2(γ2(e))) ∈ C[[τ]]ρ. Succinctly, this means that an expression e with type τ, under [[x]] = x unit [[!t]] = λ? :Unit. [[t]] appropriate closing substitutions, is related to itself by (the compu- ◦ ? tation closure of) the relation induced logically by τ. [[let !x = t1 in t2]] = (λ x:Unit → [[σ1]]. [[t2]]) [[t1]] Of course, this is only the simplest parametricity result we could where t1 has type !σ1 provide; it does not take into account the extensions we propose Here we treat terms !t as suspended computations which may be in Section 5, nor does it take advantage of linearity in any way. evaluated more than once—or not at all—which is standard. The interactions between linearity and relational parametricity have Translating in the other direction is much less straightforward been explored by Birkedal et al. [8] and Bierman et al. [7, 6] and space constraints preclude us from including the translation have explored program equivalences in the presence of !, both of here. The translation on types is kind-directed and, at the term which suggest avenues for future investigation in the context of ◦ level, the insertion of ! and let ! operations is not trivial: a function System F . Our appeals to parametricity in Section 3.2, however, that takes an unrestricted type must now take a ! type and bind it require nothing beyond what we have proved. so that the variable need not appear linearly, but such arguments We view the ease with which we can adapt standard results from ◦ must be repackaged under ! in order to be passed to any subsequent System F to System F as a significant benefit of this design. A di- functions. Polymorphic types and expressions also need care—for rect correspondence between these metatheoretic properties and in- example, there are four cases needed to translate type instantiation, tuitions about what linearity provides is not immediately obvious, one for each combination of linear/unrestricted for the polymorphic however. In Section 4 we will show, by means of elaborated oper- term and its type argument. ational semantics, that the restrictions required for our soundness We see this asymmetry in the translations as evidence of Sys- proofs are exactly those needed to satisfy our intuitions. tem F◦’s expressive power and its ability to handle unrestricted terms (the bulk of any most programs) in a concise way, justify- 2.2 Comparison to traditional formulations ing our claim that it provides linearity in a lightweight fashion. In contrast to our approach, linear type systems are more tradition- ally presented without kinds, assuming linearity by default and us- 3. Examples ing the modality ! to allow unrestricted variables (see, for exam- ple [3, 6]). For the polymorphic λ-calculus, this gives us To demonstrate System F◦’s applicability, we now turn to two cat- ◦ ˛ ˛ ˛ egories of examples. First, we demonstrate that, while System F σ ::= α ˛ σ ( σ ˛ ∀α. σ ˛ !σ does not build in notions of references and aliasing, protocols defin- ˛ ˛ ˛ ˛ ˛ ing correct memory management can indeed be enforced by Sys- t ::= a ˛ x ˛ λa:σ. t ˛ t t ˛ Λα. t ˛ t [σ] ◦ ˛ ˛ tem F types. Second, we prove that any protocol expressible as ˛ !t ˛ let !x = t in t a finite automaton has a corresponding F◦ type; in addition to es- tablishing that a rather large class of protocols can be encoded in ˛ ˛ Φ ::= · ˛ Φ, α ˛ Φ, x:σ our type system, this proof also highlights intuitions about linearity ˛ Ψ ::= · ˛ Ψ, a:σ that still need formalization, which we will tackle in Section 4. (It is easy to see, however, that the regular languages are not an upper For clarity, we distinguish between linear variables a, bound by λ ◦ limit on System F ’s expressivity; the classic non-regular parenthe- terms, and non-linear variables x, bound by let !. The interesting sis matching example has an obvious protocol type.) typing rules concern the ! modality: Φ; · ` t : σ 3.1 Reference cells Φ; · ` !t :!σ The filesystem interface in Section 1.2 can, under an appropriate renaming and abstraction over the contents type, also be seen as an 6 Φ; Ψ1 ` t1 :!σ1 Φ, x:σ1;Ψ2 ` t2 : σ2 Ψ1 d Ψ2 = Ψ interface for linear reference cells: ? ? Φ; Ψ ` let !x = t1 in t2 : σ2 Ref[τ](α) = { set : τ → α → α, get : α →? (τ, α), In other words, the type !σ indicates a term of type σ which uses ? no linear variables—the same constraint we place on unrestricted free : α → Unit } functions—and such a term can be captured by the let ! operation ? and subsequently used in an unrestricted fashion. Note, however, mkRef : ∀β:?. β → ∃α:◦. (α, Ref[β](α)) that the type !σ itself is still linear, even though terms of that type allow for the introduction of unrestricted assumptions; while it is 6 Here and elsewhere, we separate the “type parameters” like τ from the possible to formulate systems where terms of ! types can be dupli- linear “state parameters” like α using the notation [τ](α). On its own this is not particularly interesting, as a linear reference Here α ⊕ β is a standard sum type; as mentioned in Section 2, cell simply encodes the practice of threading a value through a pro- these are not encodable in System F◦ as presented so far, but gram. Indeed, as with Haskell’s State monad, we could instantiate they are an easy extension and are discussed in Section 5.1. The mkRef such that α is τ. Instead, however, let us consider varia- claim function exchanges a shared β for an exclusive α when the tions on Ref that make more sense as safe interfaces wrapping true, underlying counter indicates that only one alias exists; in all other potentially unsafe reference cells, much as File in Section 1.2 pro- cases it simply returns the supplied shared capability. tected the primitive, unchecked filehandle calls. We can do still more if we extend System F◦ with quantifica- While the above Ref could be such a safe interface, a more ob- tion over higher kinds, an extension which meshes well with Sec- vious one—which itself requires no linearity—is the type GCRef: tion 5.1’s datatypes. For instance, we can define linear references

? ? that support strong updates—that is, updates that change the type GCRef[τ](α) = { set : τ → α → α, contained in the reference cell—by abstracting the type of the ac- ? get : α → (τ, α) } cess capability over the type of the contents, giving it kind ? ⇒ ◦:

? ? mkGCRef : ∀β:?. β →? ∃α:?. (α, GCRef[β](α)) SURef[τ](α) = { set : ∀β:?. ∀γ:?. γ → α β → α γ, get : ∀β:?. α β →? (β, α β), The operations given by GCRef[τ](α) are, of course, those of a free : ∀β:?. α β →? Unit } garbage-collected reference cell of type τ. By hiding the reference type behind α we ensure that such garbage-collected references mkSURef : ∀β:?. β →? ∃α:? ⇒ ◦. (α β, SURef[β](α)) cannot be freed, and, in this case, α can be unrestricted. In System F◦, however, we can also define references that be- Operation records of type SURef[τ](α) can easily be coerced to gin their lives as linear (and manually managed) but later are put type Ref[τ](α τ) by partial application of member functions. Aug- under the garbage collector’s control. Ref[τ](α) simply needs an menting SURef along the lines of ShareRef could further allow for additional function to serve as the appropriate coercion: sharable reference cells that support strong updates only when they are not shared, a fairly sophisticated feature. gc : α →? ∃β:?. (β, GCRef[τ](β)) By consuming and not returning α, gc prevents free from being 3.2 Regular protocols called on the now garbage-collected (but unrestricted) reference. Apart from memory cells and file operations, what other protocols We thus have a coercion from alias-free to potentially aliased point- can System F◦ enforce? Rather than present more individual ex- ers, a fact that, had we conflated linearity with alias-freedom, would amples, we will show how any protocol expressible as a regular run counter to our subkinding relation of ? 6 ◦. (Whether gc needs language can be written in F◦. to do any work at run time depends on the implementation of the We take the standard definition of a DFA as a tuple M = memory management system.) (Q, Σ, δ, q0,F ), where Q is a finite set of states, Σ is a finite set of We can take other approaches to memory management as well. alphabet symbols (in our context, protocol actions), δ is a subset of For instance, an intermediate point between a strictly linear and a Σ×Q×Q (that is, a ternary relation among actions, current states, garbage collected reference is a reference that must be explicitly and next states), q0 is a distinguished initial state, and F is a set of aliased, and where aliases must be explicitly discarded. We can final states. The file access protocol from Section 1.2, for instance, define this easily enough: can be thought of as a very simple automaton with states Open and Closed and an alphabet consisting of read, write, and close, with RCRef[τ](α) = { set : τ →? α →? α, ? open as the creator of such an automaton. get : α → (τ, α), For ease of notation, we extend our metavariable conventions to ? alias : α → (α, α), allow q and r as type variables. Taking Q = {q0, . . . , qn}, we can ? drop : α → Unit } now define the automaton type for the DFA M as

mkRCRef : ∀β:?. β →? ∃α:◦. (α, RCRef[β](α)) τM = ∃q0:◦, . . . , qn:◦. ( q0, { a takes q to q0 : q →? q0 A straightforward implementation of mkRCRef could return a for every (a, q, q0) ∈ δ pair of the desired reference cell and an additional cell to act as . a counter, along with alias and drop operations that adjust this . counter. Both the primary cell and this counter could safely be done at q : q →? Unit freed when the count reaches zero. for every q ∈ F } ) However, while our access capability is still linear with RCRef, we can never be certain that we possess the only reference to cell in Such type is trivially inhabited: one can supply an existential pack- question. To remedy this, as is often done in capability calculi [2, age of this type where all type variables are bound to Unit. 9], we can give our cells both an exclusive capability α and a shared We say that the evaluation to a value of an expression e contain- capability β, with possession of the exclusive capability implying ing a subexpression of type τM reflects a word w = a0 . . . ak if the that no outstanding copies of the shared capability remain. If, for sequence of record fields used is exactly example, the cell contents should not be altered if any aliases exist, a0 takes q0 to r0, . . . ak takes rk−1 to rk we can use for some states r through r . To prove that τ is an accurate rep- ShareRef[τ](α, β) = { set : τ →? α →? α, 0 k M ? ? resentation of M, we need to show, first, that each w = a0 . . . ak getE : α → (τ, α), getS : β → (τ, β), ? ? ? accepted by M corresponds to an expression of type τM → Unit share : α → β, claim : β → α ⊕ β, w f τ →? Unit ? ? that reflects and, second, that each of type M reflects alias : β → (β, β), drop : β → Unit, some w accepted by M. The former is fairly straightforward: free : α →? Unit } Lemma 9. For any w = a0 . . . ak accepted by M, there exists f ? ? mkShareRef : ∀γ:?. γ → ∃α:◦. ∃β:◦. (α, ShareRef[γ](α, β)) such that · ` f : τM → Unit and for any n : τM , f n reflects w. Proof. Recall that, if w = a0 . . . ak is accepted by M, we have κ [L-APPLAM](λ x:τ. e) v (v:τ)−→ {x 7→ (v:τ)}e a trace of M on w of the form q0a0r0 . . . rk−1akrk, where  (a0, q0, r0) ∈ δ, (ai, ri−1, ri) ∈ δ, and rk ∈ F . Knowing this  and the definition of τM , we can construct [L-TAPPLAM]Λα:κ. v [τ] −→ {α 7→ (τ:κ)}v ? f = λ n:τM . unpack (q0, . . . , qn, p) = n in e C−→ e0 let (start, ops) = p in  D [L-TAG](v:τ) (v:τ)−→ v [L-TAPP] let s0 = ops.a0 takes q0 to r0 start in e [τ] C−→ e0 [τ] . D . C 0 C 0 let sk = ops.ak takes rk−1 to rk sk−1 in e1 D−→ e1 e D−→ e [L-APP1] [L-APP2] x.done at rk sk C 0 C 0 e1 e2 D−→ e1 e2 v e D−→ v e This clearly reflects w, and, if w is indeed accepted by M, it will typecheck successfully. Γ ` τ : κ Γ; ∆ ` v : τ [K-TTAG] [T-TAG] Γ ` (τ:κ): κ Γ; ∆ ` (v:τ): τ The other direction depends on arguments from parametricity (which we have already proved) and the nature of linearity (which Γ; ∆ ` e : τ we will formalize and prove in Section 4). Γ ` τ : κ Γ; ∆ ` e :(τ:κ) ? [T-TTAG1] [T-TTAG2] Lemma 10. If · ` f : τM → Unit, then there exists some w such Γ; ∆ ` e :(τ:κ) Γ; ∆ ` e : τ that M accepts w and f n reflects w for any n where · ` n : τM .

Proof. Because τM is linear, f must eliminate n before it can Figure 5. Linearity-aware semantics for linear System F return anything of type Unit. This will require first unpacking the existential and then pattern-matching against the pair, leaving the linear start and unrestricted ops. discard the subexpression, leaking memory, even though this is precisely the sort of error we hoped to rule out. Similar concerns If q0 ∈ F , then f might immediately apply ops.done at q0. for uniqueness types are known in the Clean community [28]. This reflects the empty word , and, indeed, if q0 ∈ F , then Call-by-value, with its assurance that function arguments are M accepts . Alternatively, regardless of whether q0 ∈ F , start evaluated exactly once, seems well-suited to avoiding these prob- can become some other state type (or even q0 again) by repeated applications of the ops.a takes q to q0 functions. If, after such lems, and indeed, in a call-by-value setting—with the addition of the value restriction—we are not able to construct such problem- applications, the result can be eliminated by some ops.done at qj , atic examples. In other words, the restrictions already in place to then it must be that qj ∈ F . Moreover, because of the construction 0 ensure soundness in Section 2.1 are everything we need to support of τM , each ops.a takes q to q application must represent a valid transition of δ. Thus we are reflecting some w accepted by M. our intuitions about linearity. To prove that this is so, the remain- der of this section provides an extended operational semantics with In the above proof, familiar intuitions about parametricity jus- which we can reason about linearity at runtime. tify the arguments that f behaves the same way for any argument of ◦ type τM and that expressions whose types are variables can only be 4.1 Annotated F used in certain ways. The assurance what w is properly reflected, What does it mean to “use” a subexpression? We might mean by however, also depends on the connection between the static prop- this that an expression is evaluated to a value, that it is passed to a erty of linear typing and the behavior of expressions at runtime. We function, or that it is applied to an argument. In order to understand would like type soundness to guarantee that our intuitions about the run-time effects of linearity, however, we focus on the use of a the behavior of linear expressions are valid; in the next section we value, which we divide into two phases: prove that this is indeed the case. 1. A value is conscripted when it is substituted into a function 4. Linear Semantics body in place of a variable. 2. A previously conscripted value is discharged when it is used The preceding section makes clear that we have yet to formalize all as a value to allow evaluation to continue—in a context where, of our intuitions about what linearity means for run-time behavior. were it replaced by a free variable, evaluation would be stuck. 7 This is not as straightforward as it might appear, because some of our intuitions about linearity turn out to be misleading. In essence, From this linearity’s contribution is clear: in the course of evalua- this is because linearity restricts variables of linear type, while we tion every conscripted linear value not contained within the final re- want to reason, at runtime, about the behavior of expressions. sult will be discharged exactly once. To formalize this, we define a For instance, linearity does not guarantee that subexpressions— linearity-aware operational semantics on expressions extended with or even values—of linear type will be used exactly once. Nor would tagged values (representing the arguments passed to functions) and we want it to: recall that the encoding of let expressions in Figure 4 tagged types (representing type arguments): involves a linear function, and we certainly want to allow for let ˛ τ ::= ... ˛ (τ:κ) expressions of unrestricted type. ˛ However, there are examples which, in a call-by-name or call- e ::= ... ˛ (v:τ) by-need setting, do behave in ways we’d like to prevent. For ex- ˛ ˛ ample, if we have unpacked a reference cell from Section 3.1 as C,D ::=  ˛ (v:τ) ˛ C,C (r, ops) e C 0 , we can dispose of it and continue with the expression Our new semantics is given in Figure 5: we write e −→ e if via D e steps to e0 while conscripting the sequence of tagged values C (λ? :Unit. e)(ops.free r) But this call to free will only be evaluated in call-by-value—since 7 As variables are not values, a free variable on either side of an application its result is not used, other evaluation strategies would simply results in a stuck expression by the semantics in Figure 2. and discharging the sequence D. Values are conscripted in rule We write {C} to denote the treatment of a sequence as a multiset, L-APPLAM, and, in a slight but critical departure from the usual and, if S is a multiset of tagged values, we write S\κ for the subset operational semantics, it is the argument value tagged with the type of S that omits any (v:τ) where · ` τ : κ. expected by the function that is substituted into the function body. We define proper expressions as those in which no unrestricted Similarly, while L-TAPPLAM does not conscript, it does tag its value contains a value as a subexpression tagged with linear type— type argument with its expected kind, thus keeping a record of the that is, a well-typed expression e is proper iff, for every value kind at which said argument will be considered within its body. subexpression v in e, if v has some type τ and τ can be given kind Since a tagged value (v:τ) is not itself a value, we have the ?, then T(v)\? = ∅. This property is preserved by evaluation: rule L-TAG, which both discharges the value and removes its tag. C 0 Lemma 11 (Proper expressions). If e is proper and e D−→ e , Intuitively this means that the argument to a previous function 0 application is either about to be used again—regardless of which then e is also proper. side of an application it is on—or that it is being returned as the final result of the computation. Of course, discharging may Proof. Values can only become tagged in a subexpression by func- be delayed for some time, as tagged values may linger beneath tion application. Because of the value restriction, in order for a function closures. As with the presentation in Section 2, evaluation linear value to be substituted into an unrestricted value, a linear does not depend on typing—types and kinds are simply recorded— variable bound at an outer scope would need to appear under an and, in particular, our new operational semantics does not treat unrestricted λ. Rule T-LAM forbids this. expressions of non-linear type differently from those of linear type. The kinding and typing rules in Figure 5 are straightforward; Thus, as long as we write our source expressions in the language the ability to conclude e : τ from e :(τ:κ) regardless of κ makes described in Section 2, we will never evaluate to an improper kind annotations completely transparent, but the same is not true of result—this is essentially the runtime version of Lemma 5. If we type annotations. The soundness results in Section 2.1 carry over to add new constructs, this property will continue to hold as long as the extended system without complication. 1. constructs under which evaluation can proceed (like conven- As an example, consider an application of the linear polymor- tional tuples) are given unrestricted types only if all of their phic identity function Λα:◦. λ◦x:α. x to the natural number 42 of components are also unrestricted, and type Nat. This expression steps as follows: 2. constructs that suspend computation either contain only values (Λα:◦. λ◦x:α. x)[Nat] 42 (like Λ) or only typecheck at an unrestricted type given an  ◦ −→ (λ x:(Nat:◦). x) 42 L-TAPPLAM empty linear context (like λ). (42:(Nat:◦)) −→ (42:(Nat:◦)) L-APPLAM (Of course, it also suffices to require that a new construct always be  (42:(Nat:◦))−→ 42 L-TAG typed linearly, as we do for additive conjunction in Section 5.1.)

C ∗ We are now equipped to prove our main result, that linearity Or, taking the obvious tag-concatenating closure D−→ : guarantees a correspondence between values conscripted and dis- ◦ (42:(Nat:◦)) ∗ charged at linear type: (Λα:◦. λ x:α. x)[Nat] 42 (42:(Nat:◦))−→ 42 C 0 Theorem 12 (Run time linearity). If e is proper and e D−→ e , In other words, over the course of evaluation, the value 42 was 0 passed to a function and used (in this case, returned as the final then T(e)\? ]{C}\? = T(e )\? ]{D}\?. result) exactly once, and it was considered at type (Nat:◦). Were it to appear more than once in the lower annotation, we would know Proof. By straightforward induction over the annotated evaluation that linearity had failed us—although 42 is of type Nat, here it relation; L-APPLAM is the only interesting case. From T-UVAR is being considered as a linear type because α was declared to be and Lemma 11 we know that, unless the argument occurs exactly linear, so after being conscripted at this type it should be discharged once in the function body, it will be of unrestricted type and contain exactly once. Were it to instead appear as (42:Nat) , however, there no linear tags. We thus preserve our tag balance. should be no such restrictions on its use, as we can indeed write In other words, at runtime, arguments treated linearly are never functions from Nat to Nat which use their arguments more than duplicated or discarded, exactly as we would hope. We can also im- once or ignore them altogether. mediately prove the following corollary, summarizing everything This semantics is similar in scope to heap semantics for linear we know about expressions with unrestricted type: functional languages [26], and indeed we could have taken this ap- proach by tracking, instead of the traces C and D, a single heap H. Corollary 13 (Unrestricted results). If e is proper, · ` e : τ, C ∗ Such a semantics would perform substitution at application only if and · ` τ : ?, then there exists some v such that e D−→ v, the argument type is unrestricted; for linear types, we would sim- T(e)\? ]{C}\? = {D}\?, and T(v)\? = ∅. ply associate the variable with its argument in the heap, remov- ing it when the variable is used. But, while we could still prove Proof. Follows directly from soundness, strong normalization, Theorem 12 with such a semantics, we need the ability to track Lemma 11, and Theorem 12. unrestricted arguments—typically not placed in the heap—and to reason about the order of function calls in order to support the rea- 4.3 Applications soning we used in Section 3, which we will return to in Section 4.3. To demonstrate how the above applies to the DFA encoding given 4.2 Linearity at run time in Section 3.2, we first examine the simpler encodings of products and existential types from Section 2. Before we can formalize our intuitions about linearity, we need some auxiliary definitions. We write T(e) for the multiset of tagged Products Our traces treat pairs exactly as we would expect. Given e C1−→∗ v e C2−→∗ v e τ e values appearing within e, defined simply as: 1 D1 1 and 2 D2 2, where 1 has type 1 and 2 has κ type τ2, recall that T(x) = ∅ T(λ x:σ1. e) = T(e) ? ◦ T((v:τ)) = {(v:τ)}] T(v) T(Λα:κ. v) = T(v) (e1, e2) = (Λα:◦. Λβ:◦. λ x:α. λ y:β. Λγ:◦. ◦ ◦ ◦ T(e1 e2) = T(e1) ] T(e2) T(e [τ]) = T(e) λ f:α → β → γ. f x y)[τ1][τ2] e1 e2 C ∗ ◦ κ1 ◦ e2 D−→ (λ x:{α 7→ τ}τ1. Λβ:◦. λ f:(∀α:κ. τ1 → β). f [τ] x) v1 (v1:{α 7→ τ}τ1) κ1 ◦ −→ Λβ:◦. λ f:(∀α:κ. τ1 → β). f [τ](v1:{α 7→ τ}τ1)

 κ1 ◦ 0 ◦ 0 e3 −→ (λ f:(∀α:κ. τ1 → (τ :◦)). f [τ](v1:{α 7→ τ}τ1)) (Λα:κ. λ x:τ1. e ) ◦ 0 ◦ 0 (Λα:κ. λ x:τ1. e :∀α:κ. τ1 → (τ :◦)) ∗ ◦ 0 ◦ 0 ◦ 0 −→ (Λα:κ. λ x:τ1. e )[τ](v1:{α 7→ τ}τ1) (Λα:κ. λ x:τ1. e :∀α:κ. τ1 → (τ :◦))  ◦ 0 −→ (λ x:{α 7→ (τ:κ)}τ1. {α 7→ (τ:κ)}e )(v1:{α 7→ τ}τ1) −→ (λ◦x:{α 7→ (τ:κ)}τ . {α 7→ (τ:κ)}e0) v (v1:{α 7→ τ}τ1) 1 1 (v1:{α 7→ (τ:κ)}τ1) 0 −→ {x 7→ (v1:{α 7→ (τ:κ)}τ1)}e

Figure 6. Evaluation of annotated existentials

Clearly, then, ˛ τ ::= ... ˛ (τ, . . . , τ) C1,C2, (v1:(τ1:◦)), (v2:(τ2:◦)) ∗ ˛ ˛ (e1, e2) D ,D −→ (v1, v2) e ::= ... ˛ (e, . . . , e) ˛ let (x1, . . . , xn) = e in e 1 2 ˛ Given our representation of pairs as closures, this is reasonable; v ::= ... ˛ (v, . . . , v) though the conscription trace tags v1 and v2 with linear types, they will be discharged at these types as soon as (v1, v2) is destructed Γ ` τ1 : κ . . . Γ ` τn : κ ◦ [K-PROD] and, assuming the provided function f is of declared type τ1 → Γ ` (τ1, . . . , τn): κ ◦ τ2 → γ, reconscripted at their original, untagged types τ1 and τ2. Γ; ∆ ` e : τ ... Γ; ∆ ` e : τ Existentials Existential types are a bit more complicated. Given 1 1 1 n n n C ∗ ∆1 d ... d ∆n = ∆ e1 D−→ v1 where e1 has type {α 7→ τ}τ1, τ1 has kind κ1, and [T-PROD] τ has kind κ, let Γ; ∆ ` (e1, . . . , en):(τ1, . . . , τn)

e2 = pack α:κ = τ in e1 : τ1 Γ; ∆1 ` e1 :(τ1, . . . , τn) κ1 ◦ = let x = e1 in Λβ:◦. λ f:(∀α:κ. τ1 → β). f [τ] x 0 0 ◦ [Γ; ∆2], x1 : τ1, . . . , xn : τn c Γ , ∆2 = (λ x:{α 7→ τ}τ . Λβ:◦. 0 0 1 Γ ; ∆ ` e : τ ∆ ∆ = ∆ κ1 ◦ 2 2 1 d 2 λ f:(∀α:κ. τ1 → β). f [τ] x) e1 [T-PLET] Γ; ∆ ` let (x1, . . . , xn) = e1 in e2 : τ Letting v2 refer to the result of fully evaluating e2, we have e C, (v1:{α 7→ τ}τ1)−→∗ v ; the details of this reduction can be 2 D 2 Figure 7. Syntax and static rules for multiplicative products seen in Figure 6. This seems sensible for the encoding of an ex- istential package, as it reflects exactly that the result of evaluating e1 has been captured in a function closure, just as with the capture word becomes very simple: the DFA trace must be visible in D that occurs when applying the product constructor. 0 0 by examining the values tagged with L. Now, to use v2, take e of type τ and let We can now return to the proof given in Section 3 and consider 0 e3 = unpack α, x = v2 in e the problem in terms of value traces. After unpacking the existen- 0 ◦ 0 = v2 [τ ] (Λα:κ. λ x:τ1. e ) tial, we will have the linear initial state conscripted but not yet dis- charged, and because our entire expression has the unrestricted type The evaluation of this expression, also shown in Figure 6, is a Unit, we know from Corollary 13 that it must be discharged before bit lengthier; the interesting thing to note, though, is that, before the final result is returned. Parametricity further restricts states to the existentially wrapped v1 is passed to the function wrapping 0 being discharged on the right side of applications. Then, as before, e , it is discharged at type {α 7→ τ}τ1 and reconscripted at the it is simply a matter of following the state as functions are applied type {α 7→ (τ:κ)}τ1. This stricter reconscription stands in direct to it, noting the labels that can become attached to the value trace; contrast to what occurs in the elimination of pairs, and, if κ is ◦, we in the end, when some done at q is applied, our value trace will know that any component of v1 with type (τ:κ) must be discharged contain a clear accepting DFA trace. exactly once in e0 for each time it is conscripted, regardless of whether or not τ can also be given kind ?. Subsequently, of course, it could be reconscripted simply at type 5. Extensions: Towards Practicality 0 τ, but thanks to parametricity we know that e cannot do this on its Although System F◦ as presented so far can serve as an expressive own—as in the filesystem example, it would need to make use of a core calculus, to be usable in practice it is necessary to extend it function already present in the existential package. with features suitable for a surface language. This section shows DFAs Finally, to show how the arguments made in proving of how to add a variety of useful constructs familiar from functional Lemma 10 are made rigorous by this machinery, consider making programming. None of these extensions are particularly difficult, two more minor syntactic changes to System F◦: first, rather than though we point out a few places where linearity must be minded. writing λκx:τ. e for functions, write fnκ name x:τ. e, and second, 5.1 Language additions rather than the simple L-TAG, add rules for the left and right sides of applications which further add L and R tags to discharged values, Polykinded products System F◦ as it stands can already encode along with a final result rule which adds no further tag. It doesn’t both unrestricted and linear (multiplicative) products. In practice, matter what names we give to functions, but if we choose to use however, it is useful to build in support for n-ary tuples. As shown our record labels as function names when possible—and require in Figure 7, the typing rules are mostly standard; evaluation rules that all other names are drawn from some set disjoint from said are completely standard and have been omitted. The kinding rule record labels—then our definition of an evaluation reflecting a K-PROD, in combination with subkinding, allows the same syntax ˛ the dynamic rules are standard. We assume a signature ΣT that τ ::= ... ˛ hτ, . . . , τi 0 ˛ ˛ e −→ e maps a datatype constructor T to its (higher) kind κ, which de- e ::= ... ˛ he, . . . , ei ˛ e.i [E-ADD] ˛ e.i −→ e0.i scribes T’s type parameters; T has arity kT . Term-level constructors v ::= ... he, . . . , ei T ˛ for type T are written ctri , and their types are given by the map Σc. The type of a term-level constructor is polymorphic over the [E-CHOOSE] he1, . . . , ei, . . . , eni.i −→ ei parameters of the datatype, but it may also expect additional type parameters, which act as through they are existentially bound—this Γ ` τ1 : ◦ ... Γ ` τn : ◦ design is similar to that found in Haskell. Importantly, if the result [K-ADD] Γ ` hτ1, . . . , τni : ◦ kind of the T is ?, then the value parameters to the term-level constructors must also be of kind ?. This constraint, writ-

Γ; ∆ ` e1 : τ1 ... Γ; ∆ ` en : τn ten as part of the signature well formedness checks in Figure 10, is [T-ADD] necessary to ensure that an unrestricted datatype can’t hide a linear Γ; ∆ ` he , . . . , e i : hτ , . . . , τ i 1 n 1 n value and thus allow it to be duplicated or discarded. The additive nature of datatypes is shown in T-CASE, which Γ; ∆ ` e : hτ1, . . . , τi, . . . , τni [T-SEL] uses the same linear context ∆2 when checking each branch. Γ; ∆ ` e.i : τi The branches themselves are polymorphic linear functions— additionally abstracted over any existential type parameters—one Figure 8. Syntax and rules for the additive products of which will be applied to create a result of the appropriate type. As with additive products, each branch will capture the same linear free variables, but only one of the branches will fire at run time. e ::= ... ˛ f. v ˛ fix 5.2 Syntactic support for linearity

[E-FIX] fix f. v −→ {f 7→ (fix f. v)}v In addition to making it possible for types to express safe protocols over stateful resources, it must also be convenient for programmers Γ, f:τ; · ` v : τ Γ ` τ : ? to write client code that interacts with these interfaces. For instance, [T-FIX] a file copy program, using the interface given in Section 1.2, should Γ; · ` fix f. v : τ look like simple imperative code and not require the programmer to think explicitly about existentially bound linear type variables Figure 9. Syntax and rules for fixpoints. and the threading of linear filehandles. In the rest of this section we sketch out some possible syntactic support—partly inspired by but simpler than Haskell’s type classes—for programming with to be used for both linear and unrestricted tuples; if any component linearity, which allows us to copy files as follows8: type of a tuple is linear, so is the tuple itself. T-PLET uses an n-ary version of the nondeterministic bind operation (recall T-LAM), let copy = fix f. allowing unrestricted components of a tuple to be used arbitrarily action ([File] h1, [File] h2). but binding linear components in the linear context. y h1.read; if y = EOF then return () Additive products As mentioned in Section 2, we cannot encode else h .write y; linear sums in System F◦ as presented so far—we have no means 2 (h1, h2)..f of sharing the linear context among different subexpressions, all in but one of which will be dropped. Connectives that enable this are start [File] h = open ”InFile.txt”; referred to as additive in the terminology of linear logic; tradition- 1 start [File] h2 = open ”OutFile.txt”; ally they are written as τ1 ⊕ τ2 for sums, and τ1 & τ2 for addi- (h1, h2)..copy; tive products—lazy linear products eliminated by projection rather h .close; h .close than pattern matching. In keeping with our syntactic conventions, 1 2 however, we introduce n-ary additive products hτ1, . . . , τni; sums This program would fail to typecheck if either of the calls to close could be encoded in terms of these products but are also subsumed were omitted, if one of the file handles were closed within the body by the algebraic datatypes discussed below. of copy, or if a read or write operation were called after close. Figure 8 gives the new syntax, definitions, and static and dy- In the rest of this section we will show how to translate from this namic rules for n-ary additive products. Note that additive products syntax into System F◦ as described up to this point. necessarily denote suspended computations, as further evaluation First, we make more explicit the pattern common to the protocol progress cannot be made until a branch is chosen. Unlike multi- examples we have seen thus far. Let Θ = α1 . . . αn be a list of plicative products, additive products always have kind ◦ regardless type variables representing the states of the protocol.9 The possible of the kinds of the component types, as seen in K-ADD. actions of the protocol can be given by a record of operations, each of which causes a state transition from σin to σout. Fixpoints Adding support for fixpoint computation turns out to ? ? be remarkably straightforward: recursion implies the ability to re- Ops(Θ) = { op1 : ∀β1:κ1.τin1 → σin1 → (τout1 , σout1 ) peatedly invoke a function within its own body, which naturally ... ◦ ? ? puts us in the unrestricted portion of System F . Figure 9 shows the opm : ∀βm:κm.τinm → σinm → (τoutm , σoutm ) } new syntax and rules, where we write fix f. v for the computation Here, σin ∈ Θ is the start state of the operation and σout ∈ Θ ∪ that immediately unwinds itself to a value as shown in E-FIX. Since j j {Unit} is either the end state of the operation or Unit, indicating these operational semantics might duplicate v, T-FIX requires that

fixpoint expressions be closed with respect to the linear context; 8 note that this is compatible with Lemma 4 (3). Technically, to match up with what follows, the return type of write must be (Unit, α) rather than just α; we also assume that EOF is of type Char. 9 Algebraic datatypes Figure 10 shows the static rules for general In this section, we write ∀Θ:◦.τ as short hand for ∀α1:◦.... ∀αn:◦.τ, recursive, polymorphic datatypes—as with multiplicative products, and similarly for existentials. ˛ ˛ T ˛ T T κ¯ ::= κ ˛ κ ⇒ κ¯ e ::= ... ˛ ctri τ1 . . . τn e ˛ case e of ctr1. v1 | ... | ctrn. vn ˛ ˛ T τ ::= ... ˛ T τ1 . . . τn v ::= ... ˛ ctri τ1 . . . τn v

T ? ΣT ` T : κ1 ⇒ . . . κkT ⇒ κT Σc ` ctri : ∀α1:κ1, . . . , αn:κn.τ → T α1 . . . αkT Γ ` τ1 : κ1 ... Γ ` τkT : κkT Γ; ∆ ` e : τ Γ ` τ1 : κ1 ... Γ ` τn : κn [K-T] [T-CTR] Γ ` T τ . . . τ : κ T 1 kT T Γ; ∆ ` ctri τ1 . . . τkT , τkT +1, . . . , τn e : T τ1 . . . τkT

∆1 d ∆2 = ∆ Γ; ∆1 ` e : T τ1 . . . τkT α1 . . . αn ∈/ Γ, τ „ T ? «(i∈1...m) Σc ` ctri : ∀α1:κ1, . . . , αkT :κkT , αkT +1:κkT +1, . . . αni :κni .τi → T α1 . . . αkT ◦ Γ, α1:κ1, . . . , αkT :κkT ; ∆2 ` vi : ∀αkT +1:κkT +1, . . . αni :κni .τi → τ [T-CASE] T T (T has m constructors) Γ; ∆ ` case e of ctr1. v1 | ... | ctrm. vm : τ

T ΣT ` Σc holds if and only if for every T such that ΣT ` T : κ1 ⇒ . . . κkT ⇒ κT and ctri such that T ? Σc ` ctri : ∀α1:κ1, . . . , αni :κni .τi → T α1 . . . αkT it is the case that α1:κ1, . . . αni :κni ` τi : κT

Figure 10. Syntax and static rules for polymorphic, recursive datatypes. ΣT and Σc are global constructor contexts such that ΣT ` Σc

that the protocol is complete. We assume that each operation might Here e must have type (τout, (σout1 , . . . , σoutn )), where σoutj ∈ Θhj be polymorphic and, for simplicity, that each takes one input of and the type of hj must be some αhj in Θhj , representing the state type τinj and produces an output of type τoutj , both of which might that handle must be in when this function is called. Our syntactic contain occurrences of variables in Θ. Almost all of the protocol sugar requires that be able to determine the αhj ’s examples we have seen can be written in this form. by inspecting e. We expect this to be rather straightforward, since If αinit ∈ Θ is the start state, then an initial instance e1 of the the type is uniquely determined by the first operation invoked on protocol is represented by a value of type ∃Θ:◦.(αinit, Ops(Θ)). the handle; alternatively we could add a type annotation to hj . Thanks to αinit, this value has linear kind, so it must be unpacked Inside the body of such an action, we allow a convenient means and the resulting tuple destructed. We suggest a convenient notation of packaging the state values to be returned to the caller: to simplify this process: return e , (e, (h1, . . . , hn)) start [Ops] h = e in e unpack Θ , x = e in 1 2 , h 1 Taken together, these constraints ensure that the type of an action is let (h, ops ) = x in e h 2 a polymorphic operation over a vector of states; i.e., it has the type Here, Θh is a list of fresh type variables, h is bound to the linear ∀Θ :◦. Ops (Θ ) →? ... ∀Θ :◦. Ops (Θ )→? state, and ops is the record of operations associated with h. The h1 1 h1 hn n hn h ∀β:κ. τ →? (α , . . . , α ) →? (τ , (σ , . . . , σ )) syntax includes the annotation Ops to help with type checking and in h1 hn out out1 outn to determine what syntactic sugar applies with respect to h in the Inside the body of an action, the “method call” syntax defined body e2. Note that opsh has type Ops(Θh), which is unrestricted earlier can be used to invoke protocol operations on the handles and hence may be duplicated at will; this invariant will be main- hj . Since an action is just another sort of operation over handles— tained throughout the interpretation of our syntax. albeit a higher level one—we would like similar syntax for invoking The intuition behind our scheme is simple: we use the sin- such an operation on a list of handles. Assuming f has the type of gle name h for the linear handle associated with the thread of a an action as given above, we define: protocol—this implicit reuse can never be an issue, since the vari- y (h1, . . . , hn)..f [τ] e1; e2 , able is linear. This handle (which must be typed by a variable in let (y, s) = f[Θh1 ] opsh ... [Θhn ] opsh [τ] e1 (h1, . . . , hn) in Θh) then determines an appropriate record of operations, opsh, as- 1 n let (h1, . . . , hn) = s in e2 sociated with the protocol. The programmer never mentions opsh explicitly; rather it is threaded through the computation automati- One can easily define variants of both the above and the earlier cally, much like a typeclass dictionary. protocol operation notation that omit the argument e1 or the binding The basic notation treats the protocol operations as “methods” for y in the case that one or both of τin and τout are Unit, or of the linear handle h with implicit argument opsh, binding the that do not rebind the handle variable in cases where the handle result to the variable y and conflating the initial and result handles: is consumed, as with close. Also, if the operation invocation is last in a sequence, e2 and the corresponding the let binding may y h.opi [τ] e1; e2 , let (y, h) = opsh.opi [τ] e1 h in e2 be omitted, since the result of the operation is the result of the If the programmer wishes to write a client function that takes one sequence—this is useful, e.g., for making tail calls. or more handles, each following its own protocol, the function Of course, there are many ways of using linear types, and the must be polymorphic over the appropriate ops records. We call above does not account for all of them. We believe, however, that it such functions “actions”; it makes sense to give them a type very does show the feasibility of making System F◦ protocols palatable similar to the operations of a protocol, since they must take a vector to the programmer, and that this provides further evidence that lin- of resource handles each in some protocol state and return a new earity as implemented in System F◦ deserves to be considered for vector of protocol states. inclusion in more mainstream languages.

action ([Ops1] h1,..., [Opsn] hn) β:κ (x:τin). e , ΛΘ :◦. λ?ops :Ops (Θ ).... ΛΘ :◦. λ?ops :Ops (Θ ). 6. Conclusion h1 h1 1 h1 hn hn 1 hn ? ◦ We have presented System F◦, a simple variant of the linear poly- Λβ:κ. λ x:τin. λ s:(αh1 , . . . , αhn ). let (h1, . . . , hn) = s in e morphic λ-calculus that nevertheless can enforce a rich variety of protocols. System F◦ is sound and enjoys parametricity, and we ’04: Proceedings of the 4th international symposium on Memory man- have proved that protocol enforcement is faithful—that is, linear agement, pages 73–84, New York, NY, USA, 2004. ACM. resources are never misused—thanks to these properties. We have [18] Kohei Honda, Vasco T. Vasconcelos, and Makoto Kubo. Language ◦ demonstrated the applicability of System F through a variety of primitives and type discipline for structured communication-based examples and by showing how to extend it with features geared programming. In ESOP98, volume 1381 of LNCS, pages 122–138. towards practical programming with linear types. Springer-Verlag, 1998. [19] Atsushi Igarashi and Naoki Kobayashi. Resource usage analysis. ACM Trans. Program. Lang. Syst., 27(2):264–313, 2005. References [20] Oleg Kiselyov and Chung-chieh Shan. Lightweight monadic regions. [1] Amal Ahmed, Matthew Fluet, and Greg Morrisett. A step-indexed In Haskell ’08: Proceedings of the first ACM SIGPLAN symposium on model of substructural state. In ICFP ’05: Proceedings of the tenth Haskell, pages 1–12, New York, NY, USA, 2008. ACM. ACM SIGPLAN international conference on Functional programming, [21] Yves Lafont. The linear abstract machine. Theoretical Computer pages 78–91, New York, NY, USA, 2005. ACM. Science, 59:157–180, 1988. Some corrections in volume 62 (1988), [2] Amal Ahmed, Matthew Fluet, and Greg Morrisett. L3: A linear pp. 327–328. language with locations. Fundam. Inf., 77(4):397–449, 2007. [22] Patrick Lincoln and John Mitchell. Operational aspects of linear [3] Andrew Barber. Linear Type Theories, Semantics and Action Calculi. . In 7th Symposium on Logic in Computer Science, PhD thesis, Edinburgh University, 1997. IEEE, pages 235–246. IEEE Computer Society Press, 1992. [4] Nick Benton, G. M. Bierman, J. Martin E. Hyland, and Valeria [23] John C. Reynolds. Towards a theory of type structure. In Programming de Paiva. A term calculus for intuitionistic linear logic. In M. Bezem Symposium, volume 19 of Lecture Notes in Computer Science, pages and J. F. Groote, editors, Proceedings of the International Conference 408–425. Springer-Verlag, Paris, France, April 1974. on Typed Lambda Calculi and Applications, pages 75–90. Springer- [24] John C. Reynolds. Types, abstraction, and . Verlag LNCS 664, 1993. In R.E.A Mason, editor, Information Processing, pages 513–523. El- [5] P. N. Benton. A mixed linear and non-linear logic: proofs, terms sevier Science Publishers B.V., 1983. and models. In Proceedings of Computer Science Logic (CSL ’94), [25] Kaku Takeuchi, Kohei Honda, and Makoto Kubo. An interaction- Kazimierz, Poland., pages 121–135. Springer-Verlag, 1995. based language and its typing system. In Proceedings of PARLE’94, [6] G. M. Bierman, A. M. Pitts, and C. V. Russo. Operational properties of pages 398–413. Springer-Verlag, 1994. Lecture Notes in Computer lily, a polymorphic linear lambda calculus with recursion. In Fourth Science number 817. International Workshop on Higher Order Operational Techniques in [26] David N. Turner and . Operational interpretations of lin- Semantics, Montral, volume 41 of Electronic Notes in Theoretical ear logic. Theoretical Computer Science, 227(1-2):231–248, Septem- Computer Science. Elsevier, 2000. ber 1999. [7] Gavin M. Bierman. Program equivalence in a linear functional lan- [27] Vasco T. Vasconcelos, Simon J. Gay, and Antonio´ Ravara. Type check- guage. Journal of Functional Programming, 10(2), 2000. ing a multithreaded functional language with session types. Theoreti- [8] Lars Birkedal, Rasmus Ejlers Møgelberg, and Rasmus Lerchedahl cal Computer Science, 368(1–2):64–87, 2006. Petersen. Category-theoretic models of Linear Abadi & Plotkin Logic. [28] Edsko Vries, Rinus Plasmeijer, and David M. Abrahamson. Unique- Theory and Applications in Categories, 20(7), 2008. ness typing simplified. In Implementation and Application of Func- [9] Arthur Chargueraud´ and Franc¸ois Pottier. Functional translation of tional Languages: 19th International Workshop, IFL 2007, Freiburg, a calculus of capabilities. In ICFP ’08: Proceeding of the 13th Germany, September 27-29, 2007. Revised Selected Papers, pages ACM SIGPLAN international conference on Functional programming, 201–218, Berlin, Heidelberg, 2008. Springer-Verlag. pages 213–224, New York, NY, USA, 2008. ACM. [29] Philip Wadler. Linear types can change the world! In M. Broy [10] Karl Crary, David Walker, and Greg Morrisett. Typed memory man- and C. Jones, editors, Progarmming Concepts and Methods, Sea of agement in a calculus of capabilities. In Proc. 26th ACM Symp. on Galilee, Israel, April 1990. North Holland. IFIP TC 2 Working Con- Principles of Programming Languages (POPL), pages 262–275, San ference. Antonio, Texas, January 1999. [30] Philip Wadler. There’s no substitute for linear logic. In 8th Interna- [11] Robert DeLine and Manuel Fahndrich.¨ Enforcing high-level protocols tional Workshop on the Mathematical Foundations of Programming in low-level software. In Proc. of the SIGPLAN Conference on Pro- Semantics, 1992. gramming Language Design, pages 59–69, Snowbird, UT, June 2001. [31] Philip Wadler. A taste of linear logic. In Mathematical Foundations of [12] Manuel Fahndrich,¨ Mark Aiken, Chris Hawblitzel, Orion Hodson, Computer Science, volume 711 of Lecture Notes in Computer Science, Galen Hunt, James R. Larus, and Steven Levi. Language support pages 185–210. Springer-Verlag, 1993. for fast and reliable message-based communication in singularity os. [32] David Walker. A type system for expressive security policies. In Proc. SIGOPS Oper. Syst. Rev., 40(4):177–190, 2006. 27th ACM Symp. on Principles of Programming Languages (POPL), [13] Manuel Fahndrich¨ and Robert DeLine. Adoption and focus: Practical pages 254–267. ACM Press, Jan 2000. linear types for imperative programming. In Proc. of the SIGPLAN [33] David Walker. Advanced Topics in Types and Programming Lan- Conference on Programming Language Design, pages 13–24, Berlin, guages, chapter Substructural Type Systems. MIT Press, 2005. Germany, June 2002. [34] Keith Wansbrough and Simon Peyton Jones. Once upon a polymor- [14] Jean-Yves Girard. Interpretation´ fonctionnelle et elimination´ des phic type. In POPL ’99: Proceedings of the 26th ACM SIGPLAN- coupures de l’arith me´ tique d’ordre superieur´ . These` d’etat,´ Univer- SIGACT symposium on Principles of programming languages, pages sity of Paris VII, 1972. Summary in J. E. Fenstad, editor, Scandinavian 15–28, New York, NY, USA, 1999. ACM. Logic Symposium, pp. 63–92, North-Holland, 1971. [35] Andrew K. Wright and Matthias Felleisen. A syntactic approach to [15] Jean-Yves Girard. Linear logic. Theoretical Computer Science, 50:1– type soundness. Information and Computation, 115(1):38–94, 1994. 102, 1987. Preliminary version in Rice TR 91-160. [16] Jean-Yves Girard, Y. Lafont, and P. Taylor. Proofs and Types. Cam- [36] Dengping Zhu and Hongwei Xi. Safe Programming with Pointers bridge University Press, 1989. through Stateful Views. In Proceedings of the 7th International Sym- [17] Michael Hicks, Greg Morrisett, Dan Grossman, and Trevor Jim. Expe- posium on Practical Aspects of Declarative Languages, pages 83–97, rience with safe manual memory-management in Cyclone. In ISMM Long Beach, CA, January 2005. Springer-Verlag LNCS vol. 3350.