Names and Higher-Order Functions

Ian David Bede Stark Queens’ College

A dissertation submitted to the University of Cambridge towards the degree of Doctor of Philosophy

December 1994

University of Cambridge Computer Laboratory Technical Report No. 363

April 1995

Abstract

Many functional programming languages rely on the elimination of ‘impure’ features: assignment to variables, exceptions and even input/output. But some of these are genuinely useful, and it is of real interest to establish how they can be reintroducted in a controlled way. This dissertation looks in detail at one example of this: the addition to a functional language of dynamically generated names. Names are created fresh, they can be compared with each other and passed around, but that is all. As a very basic example of state, they capture the graduation between private and public, local and global, by their interaction with higher-order functions.

The vehicle for this study is the nu-calculus, an extension of the simply-typed lambdacalculus. The nu-calculus is equivalent to a certain fragment of Standard ML, omitting side-effects, exceptions, datatypes and recursion. Even without all these features, the interaction of name creation with higher-order functions can be complex and subtle.

Various operational and denotational methods for reasoning about the nu-calculus are developed. These include a computational metalanguage in the style of Moggi, which distinguishes in the type system between values and computations. This leads to categorical models that use a strong monad, and examples are devised based on functor categories.

The idea of logical relations is used to derive powerful reasoning methods that capture some of the distinction between private and public names. These techniques are shown to be complete for establishing contextual equivalence between first-order expressions; they are also used to construct a correspondingly abstract categorical model.

All the work with the nu-calculus extends cleanly to Reduced ML, a larger language that introduces integer references: mutable storage cells that are dynamically allocated. It turns out that the step up is quite simple, and both the computational metalanguage and the sample categorical models can be reused.

Preface

I would like to thank my supervisor, Andrew Pitts, for his continuing encouragement, support, guidance and instruction. I am very grateful to the numerous friends, both within and without the Computer Laboratory, who have brightened these last three years in Cambridge. Extraordinary thanks are due to my wife, Judith, for everything.

I would also like to acknowledge the financial support of the Science and Engineering Research Council, the EC Basic Research Action ‘Categorical Logic in Computer Science’, the EC SCIENCE project ‘Programming Language Semantics and Program Logics’, the Computer Laboratory, and Queens’ College.

Except where otherwise stated, all the work described in this dissertation is the product of my own original research. Some of the results presented have also appeared in the conference papers [91] and [92] (joint with Andrew Pitts), and in the journal article [120].

This document was prepared using L^{A}TEX 2ε, with Michael Barr’s diagram macros. Thanks to some code originating with Andy Gordon, each reference in the bibliography is followed by a list of the pages on which it is cited.

Preface to the Technical Report

I wish to thank my examiners, Samson Abramsky and Robin Milner, for their comments, suggestions, and discussion of the work in this dissertation. This technical report edition contains alterations suggested by them, together with a number of minor textual corrections. It is otherwise identical to the version originally submitted.

Contents

Abstract -7

Preface -5

1 Introduction 1 1 Background . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 2 Basic Concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 3 Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 4 Outline of Dissertation . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

2 The Nu-Calculus 11 1 Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2 Evaluation Semantics . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 3 Reduction Semantics . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 4 Contextual Equivalence . . . . . . . . . . . . . . . . . . . . . . . . . . 22 5 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 6 A Context Lemma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 7 Applicative Equivalence . . . . . . . . . . . . . . . . . . . . . . . . . . 32

3 Categorical Models 37 1 A Computational Metalanguage . . . . . . . . . . . . . . . . . . . . . . 38 2 Interpreting the Nu-Calculus . . . . . . . . . . . . . . . . . . . . . . . . 43 3 Reasoning in the Metalanguage . . . . . . . . . . . . . . . . . . . . . . 48 4 Constructing Categorical Models . . . . . . . . . . . . . . . . . . . . . 51 5 The Functor Category Set^{I} . . . . . . . . . . . . . . . . . . . . . . . . 57 6 Properties of the Model in Set^{I} . . . . . . . . . . . . . . . . . . . . . . 59 7 Continuous G-sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63

4 Logical Relations 67 1 Operational Logical Relations . . . . . . . . . . . . . . . . . . . . . . . 68 2 Completeness at First-Order Types . . . . . . . . . . . . . . . . . . . . 73 3 Categories with Relations . . . . . . . . . . . . . . . . . . . . . . . . . 78 4 The Parametric Functor Category P . . . . . . . . . . . . . . . . . . . . 80 5 Properties of the Model in P . . . . . . . . . . . . . . . . . . . . . . . 83 6 Predicated Logical Relations . . . . . . . . . . . . . . . . . . . . . . . . 88 5 A Language with Store 92

1 Syntax of Reduced ML . . . . . . . . . . . . . . . . . . . . . . . . . . 93 2 Operational Semantics . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 3 Contextual Equivalence . . . . . . . . . . . . . . . . . . . . . . . . . . 100 4 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 5 Proof Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 6 A Computational Metalanguage for Store . . . . . . . . . . . . . . . . . 108 7 Interpretation of Reduced ML . . . . . . . . . . . . . . . . . . . . . . . 112 8 Categorical Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 9 Example Categories . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119

6 Conclusion 122 1 Directions for Future Research . . . . . . . . . . . . . . . . . . . . . . 122 2 Related Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 3 Summary of Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126

A The Meyer-Sieber Examples 128

Bibliography 131

List of Figures

2.1 Rules for assigning types to expressions of the nu-calculus . . . . . . . 13 2.2 Rules for evaluating expressions of the nu-calculus . . . . . . . . . . . 15 2.3 Step reduction for the nu-calculus . . . . . . . . . . . . . . . . . . . . . 18 2.4 The extended nu-calculus . . . . . . . . . . . . . . . . . . . . . . . . . 30

3.1 Rules for assigning types to terms of the metalanguage . . . . . . . . . 39 3.2 Rules for equational reasoning in the metalanguage (I) . . . . . . . . . 40 3.3 Rules for equational reasoning in the metalanguage (II) . . . . . . . . . 41 3.4 Interpretation of the nu-calculus in the computational metalanguage … 44 3.5 Rules for constructing morphisms to interpret terms of the metalanguage 55

5.1 Expressions of Reduced ML . . . . . . . . . . . . . . . . . . . . . . . 94 5.2 Rules for assigning types to expressions of Reduced ML . . . . . . . . 96 5.3 Rules for evaluating expressions of Reduced ML . . . . . . . . . . . . 98 5.4 Some additional typing rules for the metalanguage . . . . . . . . . . . . 109 5.5 Some extra rules for equational reasoning in the metalanguage (I) …. 110 5.6 Some extra rules for equational reasoning in the metalanguage (II) … 111 5.7 Interpretation of Reduced ML in the computational metalanguage …. 113 5.8 Additional morphisms to interpret terms of the metalanguage . . . . . . 118

Chapter 1

Introduction

Functional languages are good for writing programs that work. Clear and well-defined semantics mean that there is agreement between a programmer’s expectation and what actually happens, while simplicity in design allows practical methods for reasoning and program verification. What you intend to write is what I read and what the computer executes.

The route to achieving this often includes the elimination of language features judged to be ‘impure’: direct access to memory and other physical devices, expressions with concealed side-effects, or unstructured control methods (don’t even think of goto).^{∗} Out with these go assignment to variables or arrays, exceptions, and even input/output. By way of compensation, functional languages provide a high level of abstraction and the powerful techniques of recursion and higher-order functions.

But many of these ‘impure’ features are genuinely useful, and their absence is given by some as a reason to avoid functional programming. So it is of real interest to establish how they can be reintroduced in a controlled way, without losing the advantages of a purely functional language. A. Gordon, for example, has addressed this problem for input/output [25]. For each other language feature, we can ask: why not give it another chance?

This dissertation looks in detail at one particular example: the addition of state to a functional programming language, in the form of dynamically generated names. Names are created fresh, they can be compared with each other and passed around, but that is all. As a very basic example of state, they capture the graduation between private and public, local and global, by their interaction with higher-order functions. We examine their behaviour, develop methods for reasoning about it, and construct categorical models to capture the meaning of names. As a more substantial example of state, we then extend all this to a functional language with integer references: mutable storage cells that are dynamically allocated. It turns out that the step up is quite simple and much of the work on names can be reused.

While the theory of state in functional languages is far from complete, this work shows that the apparently ‘impure’ feature of dynamically generated names can be introduced in a safe and well-behaved way. In particular there are good, strong reasoning methods that can handle names without removing their usefulness.

∗“The purpose of Newspeak was not only to provide a medium of expression for the world-view and mental habits proper to the devotees of Ingsoc, but to make all other modes of thought impossible”. George Orwell, 1984

1 Background

Purely functional languages are based on Church’s lambda-calculus [10], where everything is a function, and the only operation is application of a function to an argument. In principle, a program is executed by rewriting the corresponding lambda-calculus expression according to certain rules: this is called reduction. There are two natural strategies for reduction, which give rise to two families of functional languages:

• In a strict functional language, the arguments to a function are evaluated before they are passed to the function body. This is call-by-value parameter passing; it is efficient and easy to compile. Strict languages include LISP and Standard ML.

• In a lazy functional language, arguments are given to a function unevaluated, and are only examined when their value is required. This is call-by-name parameter passing, generally implemented as call-by-need, where an argument is evaluated when first used and the value saved to avoid recomputation. Lazy languages are tricky to compile well on standard machine architectures, but they do introduce some novel programming techniques, most notably infinite data structures. Ponder, Miranda, Haskell and Gofer are all lazy languages [128, 130, 33, 35].

In practice the division is not always quite so clear, with certain disputes about the exact requirements for laziness; see Riecke [112] or Abramsky [4] for a discussion of this.

These languages remain close to their mathematical roots, and compilers often base optimizations on the behaviour of programs as mathematical objects. For example, this may allow repeated large-scale code transformations, leading to efficient implementation. All this eschews many of the features developed for conventional imperative languages; stepping outside the mathematical purity of the lambda-calculus is carefully avoided. But there are several practical reasons why such ‘impure’ features are important:

• The real world. Most programs have to interact with the external world, yet the original lambda-calculus quite reasonably made no provision for input/output.

• They might be simply a good idea. The raising and handling of exceptions is a prime example of a sensible and powerful control mechanism that lies outside the purely functional.

• Algorithms require them. Some algorithms rely on particular structures, such as an array that can be updated in place, to execute efficiently [98]. Often there are alternative algorithms, perhaps less well known, that use the data structures of functional languages; queues are a good example of this [86]. But sometimes no such method is known, as is presently the case with various graph traversal algorithms [38].

• They match the machine. Many traditional language features exist because they accurately represent some aspect of computer hardware; by ignoring this, functional languages are inevitably inefficient. Today this argument has lost much of its force, as programs in any high-level language are often drastically transformed under compilation for modern architectures and operating systems.

References in Standard ML are a good example of this. Mutable storage cells would seem to map well onto real memory; but they cause surprising difficulties for generational garbage collection, as they break the rule that all pointers should be directed at objects older than themselves.

For various reasons then, real functional languages usually incorporate some ‘impure’ features: for example, LISP has the destructive rplca and rplcd, while Haskell has I/O primitives. Sometimes these features are not added to the language itself, but effected by writing programs in a standard way. This preserves the purity of the language, though it may distort programming style; monads and their associated ‘plumbing’ are a well-known example [133, 134].

The language most relevant to this dissertation is Standard ML. This is a language with a formal definition [62] and a number of implementations. It is strongly typed, with polymorphic types and a sophisticated module system of ‘structures’ and ‘functors’. Evaluation is strict, though there is a variant ‘Lazy ML’ [8]. Standard ML provides exceptions, references and I/O primitives. Of all these we shall look only at references: these are mutable storage cells, dynamically allocated on a heap and cleared away by a garbage collector.

No-one could reasonably describe ML as a purely functional language. But much of it is functional in style and spirit, and the work presented here is evidence that such a language can still provide the benefits of functional programming, including a well-defined denotational semantics and powerful reasoning methods.

2 Basic Concepts

This dissertation looks at a single ‘impure’ addition to a functional language: dynamically generated names. These are brought together with higher-order functions in the nucalculus, a small experimental language. In this section we introduce each of these concepts in turn; the next section describes methods for studying them.

2.1 Names

The idea of a name is one of the most widely used abstractions in programming languages, from the specification of surface syntax, through the formal meaning of programs, to the details of implementation. An alphanumeric identifier in C may name a variable, a value of reference type in ML names a storage cell, and a machine address names a memory location. The basic, and rather simple, property required of a name is that it should be distinct from all others. It is usual to assume also that names are drawn from some infinite supply, so that a fresh one can always be obtained; thus names lie behind many generative programming constructions.

Although the abstract concept of ‘name’ is relevant to many aspects of programming, its presence is not always obvious. Here are a few examples:

• Clearest is the inclusion of names within a language itself: the gensym operation of LISP produces a new symbol every time it is called.

• Some notion of name may be needed in a formal description: in the definition of Standard ML, every structure created is tagged with a distinct name [62, rule 53].

• The implementation of a language may have generative features: a local variable in a procedural language is one created distinct from all others, usually allocated on a stack or heap.

• Weakest of all, a user may simply be expected to manage something as if it were a name: for example, in an exhortation that global identifiers should be chosen distinct.

A more subtle aspect of naming is its connection with privacy. A name cannot be guessed, or adjusted, or manipulated, except to pass it on: names are a first example of an abstract type. Though any actual representation of names must have some internal structure, this should be invisible. The most striking example of this in practice is the use of ‘capabilities’ in the Cambridge CAP computer [138], where such restrictions are enforced by the processor instruction set; more recent memory protection schemes use similar ideas.

Failure to suitably conceal the implementation details of names can cause problems. For example in C the unrestricted use of pointer arithmetic means that privacy is not respected, and it is quite possible to write to memory locations at random; though this is generally considered poor programming practice.

But privacy is not always so clear-cut: a module may export the names of some of its components but not others; one pointer may lead to another in a linked list; a file may be referred to by two different handles, one for reading and one for writing. Names can be used to capture all these different degrees of access and shades of visibility. Names also lie behind ‘object identity’, an important concept in the design of objectoriented databases [85]. They are well known to be of significance in distributed and other concurrent systems: they are a key idea in Milner’s pi-calculus [60, 61], and receive attention in the specification of real distributed systems [131]. This field highlights some of the more complex aspects of privacy, and leads to the area of security, secure communication, authentication and so forth.

In summary then, the idea of a name is a simple one, relevant to a wide variety of concepts used in the design, implementation and use of programming languages. This flexibility has a price: the exact properties of names, and how they are used, can be subtle and difficult to pin down.

2.2 Higher-Order Functions

In a typed programming language, a function maps values of one type to values of another type. It is higher-order if either the argument or result is also a function. For example most functional languages provide a map function that takes a function f and a list l as arguments and applies f to every element of l, returning a list l′ as result. Higherorder functions implement the idea that functions should be ‘first-class citizens’ in a programming language: all that can be done with values of ground type (integers, booleans etc.) should also be possible with functions.

Higher-order functions are not restricted to functional languages. Reynolds’ ‘Idealized Algol’ [107] and the original Algol 60 [71] are imperative languages in which functions and procedures can be passed as arguments or returned as results. However the treatment of functions as first-class citizens does require the manipulation of closures: a function paired with an environment giving values for its free variables. This can cause difficulties for stack-based languages, so for example C, Modula 3 [72] and Algol 68 [48, 132] cannot make full use of higher-order functions.

Operations like map increase generality, but the direct manipulation of functions can also be used to build procedures ‘on the fly’ and then execute them. A simple example is a function that takes two functions f, g and returns their composition (f ∘ g). Much more sophisticated are the combinators to construct parsers described by Hutton [34], or the use of continuations to manage the flow of control during execution [7].

This facility is like the LISP eval operator, but more closely integrated into the language: instead of manipulating list representations of procedures and then evaluating them, we work with the procedures themselves. In a sense, higher-order functions provide the versatility of run-time code generation without the danger. There remains the issue of how efficiently any particular compiler manages this technique; even so it seems likely that its full power has yet to be exploited.

The treatment of functions on a level with other values is also good for the abstraction of data handling away from the details of representation. For example, a ‘dictionary’ datatype is best seen as a function from keys to value, even though it may be implemented by a binary tree, hash table or whatever. If treated purely as a function, any particular dictionary can choose whichever representation is most efficient without affecting the code that uses it. As another example, Matthews’ language Poly represents assignable variables as a pair of procedures, one that extracts the current value and one that changes it [56]. The same is possible in Reynolds’ Gedanken, and is also seen in his semantics for Algol, where a variable is an acceptor paired with an expression [103, 107]. Again, this leaves the way open for whatever implementation is most appropriate.

An extreme example of the power of higher-order functions is that they can be used to encode all the other usual datatypes: products, sums, integers, lists and so forth. This can be done immediately in the untyped lambda-calculus; in a typed setting we need the second-order lambda-calculus of Girard’s System F [23], discovered independently by Reynolds [104]. The technique is presented by Girard in [24, Chapter 11] and extended by Wraith in [139], while Abadi and Plotkin’s paper [97] gives methods for reasoning about such constructions. Ingenious though it is, the use of higher-order functions to encode other datatypes usually attracts only theoretical interest; though Fairbairn does argue for it as a practical implementation method in the design of the language Ponder [17, 18].

2.3 The Nu-Calculus

The nu-calculus is a simple language providing higher-order functions and the dynamic creation of names. It was identified by Pitts as a sensible subset of ML, and is close to Stoughton’s ‘identity calculus’. In all respects the nu-calculus is chosen to be as simple as possible: the only ground types are booleans and names, there is no recursion, and all evaluation is deterministic and terminating. Even so, one of the abiding lessons of computer science is that small, simple systems may yet have complex and subtle behaviour, and we shall see that the nu-calculus is no exception.

The chief use of names in the nu-calculus is to look at questions of visibility. If a certain name is known to a function, then it can be handled specially; if the name is unknown, then it must be treated the same as any freshly created name. Or perhaps a function may not have access to a name itself, but only a test for it: such a function cannot generate the name, but can recognise it as an argument. Even more complex, a function might only give out a private name as result if it is given some other particular name as an argument; this is the case with the function F_{p} on page 25. The possibilities are endless, and all capture some subtlety of names, privacy and scope.

The purpose of the nu-calculus then is not to provide a practical programming language, but rather to bring out a particular aspect of larger languages, so that it can be examined for itself. As it turns out, the interaction between dynamically generated names and higherorder functions is worthy of the attention.

3 Methods

Given a language, the nu-calculus, that combines names with higher-order functions, we want to study its behaviour and find methods for reasoning about it. To this end we use contextual equivalence to describe the properties of the language, categorical models to capture its meaning, and logical relations to refine our reasoning. This section describes these techniques and outlines the motivation behind them.

3.1 Contextual Equivalence

The benchmark relation for describing the operational behaviour of expressions in a functional language is contextual equivalence, originating with Morris [70] and used by Milner [59] and Plotkin [94, 95]. Two expressions are judged equivalent if they can be freely exchanged in any program; there is no way in the language itself to distinguish between them.

A simple use of contextual equivalence is to explain the properties of particular language features: for example in ML the equivalence

let val r = ref i in !r end ≈ i i ∈ ℤ

illustrates the initialisation of reference cells. This approach is conveniently self-regulating in that details which properly belong to the implementation simply cannot be expressed; in this case for example, it does not matter what strategy the compiler uses for heap allocation.

More formally, such equivalences can be used to verify code transformations made during compilation. This applies to small, even trivial, manipulations as much as it does to complex and ingenious optimizations: in all cases contextual equivalence is the correct notion to check against. At a higher level, contextual equivalence is the right way to show that a programmer can use one algorithm instead of another.

This approach differs considerably from a traditional logic of programs such as Hoare logic, where assertions are made about machine state before, during and after the execution of a program [28, 15]. Nor do we have any distinct notion of a specification that some program must meet, beyond simple type-checking. Nevertheless contextual equivalence can serve in both these rôles. Assertions of a program logic can be replaced by tests within the language: for example, the equivalence above captures the following proposition in Hoare logic:

{T } val r = ref i {contents(r) = i}.

Similarly a specification can be replaced either by a test expressed in the programming language, or a requirement that a program should be equivalent to some clear example.

For a sorting routine these methods might give

xs : int list ⊢ sorted(clever sort xs) ≈ true

and

xs : int list ⊢ clever sort xs ≈ insertion sort xs

respectively. In all these cases it is a clear advantage that we work entirely within the programming language itself; in essence, this gives assertion and specification languages with just the right level of abstraction.

Useful though contextual equivalence is, it can be rather a difficult relation to prove in specific instances. It is convenient therefore to identify other relations that imply contextual equivalence but are simpler to demonstrate. For example, an equivalence relation between expressions is a congruence if it is preserved by all constructions of the language; and it is usually not hard to show that any congruence which respects the operational semantics of the language, and distinguishes true from false, implies contextual equivalence. The complementary relation is rather simpler: to show that two expressions are not contextually equivalent it is enough to demonstrate some program context that distinguishes them.

3.2 Categorical Models

Methods for reasoning about programming languages can be divided broadly into the operational and the denotational. Operational methods work explicitly with expressions of the language and their reduction or evaluation to canonical form. This has an appealing directness, and many of the relations described in this dissertation are described operationally. Denotational methods on the other hand first interpret the language in some mathematical setting, and then work within this model. The intention is to abstract away from particular details of a programming language and capture its essential ‘meaning’: for example, a function might be translated from program text into a map between sets. Such a translation is adequate if equality in the model implies contextual equivalence; it is fully abstract if this can be used to prove all contextual equivalences. The method is flexible in that different models can be developed to demonstrate particular equivalences.

Denotational semantics is not just for proving equivalences: a good model will illustrate how the features of a programming language fit together, and can be an aid to further language design. Two examples of this approach applied to functional languages are Milner on the typed lambda-calculus [59] and Plotkin on PCF [95]. A more general background on denotational semantics for programming languages is given by Stoy in [122].

Category theory is a general theory of mathematical structures, and provides a suitable setting for models of functional languages. Mac Lane’s book [51] is the standard introductory text on categories; Mac Lane and Moerdijk [52] on topos theory is considerably more comprehensive. Two important examples of how categories assist with denotational semantics are the interpretation of the simply-typed lambda-calculus in any cartesian closed category [42], and the solution of recursive domain equations in O-categories [119]. The first of these forms the basis of all the categorical models used in this dissertation. We shall also use the fact that any category has its own internal language: this provides a logic to carry out equational reasoning about the structure of the category, with an excellent correspondence between categorical properties and constructions in the language [52, §VI.5].

Moggi observed that various aspects of computation in a programming language could be captured by the categorical concept of a strong monad; this has turned out to be a powerful abstraction, unifying several disparate language features [66, 67, 68]. The corresponding internal language is known as the computational lambda-calculus and is notable for its type system which separates values from computations. Various rules of the language describe how to reason correctly about computations, and these are enhanced in Pitts’ evaluation logic by the addition of certain computation modalities [90].

These ideas lead to a particular denotational approach that falls naturally into two stages: we first interpret the nu-calculus in a metalanguage based on the computational lambda-calculus, and then interpret this within a category;

nu-calculus ⟶ computational metalanguage ⟶ category with strong monad.

The metalanguage can be used to reason about contextual equivalence in the nu-calculus, and is also the internal language of the categorical model. This division into two translation steps allows us to build more than one model on the same foundations, and this framework is reused when we extend the nu-calculus to a language with store.

3.3 Logical Relations

While the methods described above provide a solid basis for reasoning about the behaviour of the nu-calculus, some extra ingredient is necessary if we are to prove results about privacy and the visibility of names; if we want to move from the merely correct to the genuinely informative. The techniques we introduce are based on logical relations.

The discussion of any typed language inevitably involves a number of type-indexed collections: whether of expressions, elements in semantic domains or morphisms in a category. A type-indexed relation between such collections is said to be logical when elements of function type are related if and only if they take related arguments to related results. Typically this means that a logical relation is fixed by its value at ground types, with the remaining type hierarchy built on top. Clearly this description is rather loose, and the idea of a logical relation can be reinterpreted in many settings.

The concept was introduced by Plotkin, at the suggestion of M. Gordon, to reason about definable elements in models of the simply-typed lambda-calculus [96]. There are similarities with Reynolds’ idea of relational parametricity [109, 50], and with some constructions of Statman [121]. Its importance is that in general all expressions definable using the original language are related to themselves; this is the ‘fundamental theorem of logical relations’ and can usually be proved by induction on the structure of expressions. For example, Sieber has used this to describe a notion of ‘sequentiality’ in models of the language PCF; by factoring out non-sequential (and hence unused) elements of models, he obtains a model that is fully abstract up to third-order types [115].

Logical relations can be of any arity: we use only unary and binary relations. Traditionally they have been defined over set-based models of languages, in a denotational approach. However for the nu-calculus we begin by developing logical relations at the operational level, in a manner similar to Abramsky’s applicative bisimulation [4]. We then go on to cover the denotational side, constructing models that use categories with relations, as introduced by O’Hearn and Tennent [82, 83].

This turns out to be a powerful reasoning method for the nu-calculus, as relations between sets of names capture something of how different expressions use their own private names. Probably the strongest result of the dissertation is that logical relations, whether operational or denotational, are complete for reasoning about contextual equivalence in the nu-calculus up to first-order function types.

4 Outline of Dissertation

The four central chapters of this dissertation are of roughly equal size: Chapter 2 introduces the nu-calculus, Chapter 3 constructs categorical models, Chapter 4 applies logical relations, and Chapter 5 extends all this to a language with store. Chapter 6 concludes. The descriptions below cover the contents of each chapter in more detail.

Chapter 2: The nu-calculus Here we present the nu-calculus, illustrate its behaviour and develop a basic operational reasoning method. We begin with syntax and type structure, and go on to give an operational semantics based on that for Standard ML. We present this in a ‘big step’ evaluation style and also a ‘small step’ reduction style, with a proof that the two are equivalent.

We define contextual equivalence for the nu-calculus, and give a collection of examples that illustrate the interaction between higher-order functions and name creation. Contextual equivalence is hard to show directly, and we give a context lemma that simplifies the process; proof of this involves a close analysis of the behaviour of nu-calculus expressions under reduction.

Finally, we describe applicative equivalence, a simpler relation defined by induction over types, and show that it implies contextual equivalence. This provides an operational method for reasoning about expressions of the nu-calculus that is straightforward but not especially powerful.

Chapter 3: Categorical models This chapter falls into two parts: in the first half we describe a metalanguage that captures the properties needed to model the nu-calculus, and in the second we turn these into requirements for a category and give two specific example.

The metalanguage extends Moggi’s computational lambda-calculus by adding names and suitable rules for reasoning about them; this allows us to interpret the nu-calculus in a way that respects its operational semantics. We show that the metalanguage can be used to reason about contextual equivalence, with power similar to that of applicative equivalence.

We then detail the construction of a categorical model for the nu-calculus, and explain how this works in two particular cases. The first is a functor category Set^{I}, the second a category BG of continuous G-sets for a certain group G. We investigate which contextual equivalences these models can and cannot verify: up to second-order types these are the same as for applicative equivalence.

Chapter 4: Logical relations This chapter refines the operational methods of Chapter 2, and the denotational methods of Chapter 3, by the introduction of logical relations that capture how expressions use local names. We define operational logical relations first, and show that they can be used to reason about contextual equivalence through the more general notion of contextual relations. Most importantly, we show that this method is complete up to types of first order; this is a significant improvement over the methods described earlier.

We also present a denotational analogue, using categories with relations to construct a model P of the nu-calculus that is fully abstract up to first-order types. Just one equivalence from the examples of Chapter 2 remains unverified, and to prove this we develop predicated logical relations, which provide an even finer description of how expressions use their local names.

Chapter 5: A language with store In this chapter we show how the techniques developed for the nu-calculus can be applied to generative features within a larger programming language. The example that we choose is integer references, and we devise a language ‘Reduced ML’ that combines these with higher-order functions. As the name suggests, Reduced ML is a proper subset of Standard ML, and it has the same operational semantics.

We recapitulate all that was done with the nu-calculus, beginning with a definition of contextual equivalence and an assortment of examples. We look at operational reasoning methods: applicative equivalence and various logical relations. We describe a metalanguage for store that is simply an extension of that for names, and set out the properties required for a categorical model. Remarkably, all the categories built to model the nucalculus can also be used to interpret Reduced ML.

Although many of the details are omitted, this chapter does illustrate how a thorough understanding of dynamically generated names can make a significant contribution to reasoning about references in Standard ML.

Chapter 6: Conclusion We summarise the results of the dissertation, discuss its relation to other work in this area, and suggest directions for further research.

The Nu-Calculus

In this chapter we introduce the nu-calculus, a small language designed to show the interaction between dynamically generated names and higher-order functions. We give its syntax and describe an operational semantics based on that for Standard ML [62]. We go on to define a notion of equivalence for expressions of the language, based on their observable behaviour, and present some ways to prove examples of this.

The nu-calculus is a typed call-by-value lambda-calculus extended with the notion of a name; names have their own type ν, they can be created fresh, passed around and tested for equality. Higher-order functions and booleans are also available, but to ensure termination functions cannot be defined recursively. New names are created in expressions of the form νn.M, which binds a fresh name to the identifier n and then evaluates M. The use of a call-by-value semantics means that although only the expression M can refer to n explicitly, the new name itself may escape from this scope. For example, (λx:ν.x = x)(νn.n) evaluates to true, with x bound to a name rather than to νn.n itself.

The nu-calculus is equivalent to a fragment of Standard ML. In particular, names correspond to values of type unit ref, cells that can only contain the value (). The form νn.M corresponds to

let val n = ref () in M end.

The operational semantics of the nu-calculus is based on that of ML, with call-by-value (strict) function application and left-to-right evaluation order. In fact the evaluation order turns out to be irrelevant for the nu-calculus, as there are no side-effects. It is still worth taking care over this though, because the storage of values, to be considered in Chapter 5, is sensitive to the order of evaluation.

We present the operational semantics of the nu-calculus in two forms; primarily in a ‘big step’ evaluation style, but also in a ‘small step’ reduction style. We prove that the two forms are entirely equivalent, and that the evaluation of expressions always terminates. This is the reason for omitting recursion from the nu-calculus: non-termination would complicate the language without helping us to understand the behaviour of names.

Expressions of the nu-calculus are judged to be equivalent if they can be freely exchanged in any program; we use this as the basis of a notion of contextual equivalence for the language. We give a number of examples of expressions that are equivalent or inequivalent. These demonstrate the subtle and complex behaviour that can arise from the combination of names with higher-order functions.

Contextual equivalence is hard to prove directly, and we give a context lemma that simplifies the process. The proof of this result requires a close analysis of the behaviour of nu-calculus expressions under reduction.

An alternative approach is to define other relations between expressions and show that they entail contextual equivalence. We describe applicative equivalence and logical equivalence, both defined by induction over types, and show that they have certain useful properties. In fact they turn out to be equivalent for the nu-calculus, both implying contextual equivalence; in general the reverse implication does not hold, so this is not a complete proof method.

1 Syntax

The syntax of the nu-calculus is based on the simply-typed lambda-calculus. Types are built up from ground types o of booleans and ν of names by formation of function types σ → σ′. We frequently omit parentheses in types, with → associating to the right. Each type has an order, given by

Order(o) = Order(ν) = 0
Order(σ → σ′) = max(Order(σ) + 1, Order(σ′)).

So for example first-order types are all of the form σ_{1} → σ_{2} → ⋯ → σ_{n} where n > 1 and σ_{i} ∈ {o, ν} for i = 1, …, n. We shall use σ, τ and decorated variants to range over types.

Expressions of the nu-calculus have the form:

M ::= x  variable
| n  name
| true | false  truth values
| if M then M else M conditional
| M = M  compare names
| νn.M  create new name
| λx:σ.M  function abstraction
| MM  function application.

There are separate infinite supplies of typed variables and names. Function abstraction λx:σ.M binds the variable x of type σ, and name creation νn.M binds the name n. We implicitly identify expressions which only differ in their choice of bound variables and names (α-conversion). An expression is closed if it has no free variables; a closed expression may still have free names.

We shall use M to represent general expressions, and B, N, F to suggest expressions of boolean, name and function type respectively. Variables are usually taken from x, y, z, with n for names and variants of s for finite sets of names. A useful abbreviation is new for νn.n; this is the expression that generates a new name and then immediately returns it.

We denote by M[M′/x] (respectively M[M′/n]) the result of substituting the expression M′ for free occurrences of the variable x (respectively, the name n) in the expression M. The substitution is capture avoiding: the free names and variables of M′ should be disjoint from the bound names and variables of M. This can always be arranged by \overline{s, Γ ⊢ x : σ} (x : σ ∈ Γ) \overline{s, Γ ⊢ n : ν} (n ∈ s) \overline{s, Γ ⊢ b : o} (b = true, false)

\frac{s, Γ ⊢ B : o  s, Γ ⊢ M : σ  s, Γ ⊢ M′ : σ}{s, Γ ⊢ if B then M else M′ : σ}

\frac{s, Γ ⊢ N : ν  s, Γ ⊢ N′ : ν}{s, Γ ⊢ (N = N′) : o}  \frac{s ⊕ \{n\}, Γ ⊢ M : σ}{s, Γ ⊢ νn.M : σ}

\frac{s, Γ ⊕ \{x : σ\} ⊢ M : σ′}{s, Γ ⊢ λx:σ.M : σ → σ′}  \frac{s, Γ ⊢ F : σ → σ′  s, Γ ⊢ M : σ}{s, Γ ⊢ F M : σ′}

Figure 2.1: Rules for assigning types to expressions of the nu-calculus

α-converting M. Simultaneous substitution is also to be capture avoiding; we write this as M[M_{1}/x_{1}, …, M_{n}/x_{n}], often abbreviated to M[M⃗/x⃗].

Expressions are given types according to the rules in Figure 2.1. The type assertion

s, Γ ⊢ M : σ

says that in the presence of s and Γ the expression M has type σ. Here s is a finite set of names, Γ is a finite set of typed variables, and M is an expression with free names in s and free variables in Γ. The symbol ⊕ represents disjoint union, here in s ⊕ {n} and Γ ⊕ {x : σ}. We may omit Γ when it is empty.

From now on we shall consider only well-typed expressions. The assignment of types behaves much as we might expect:

Lemma 2.1 If s, Γ ⊢ M : σ holds then the type σ is unique. Further, if the expression M has free names in s and free variables in Γ, then

s, Γ ⊢ M : σ ⟺ s ⊕ s′, Γ ⊕ Γ′ ⊢ M : σ

for any s′ and Γ′.

Proof Both follow by induction on the structure of M.

An expression is in canonical form if it is either a name, a variable, one of the boolean constants true or false, or a function abstraction. These are to be the values of the nucalculus, and correspond to weak head normal form in the lambda-calculus. We define the sets

Exp_{σ}(s, Γ) = { M | s, Γ ⊢ M : σ }
Can_{σ}(s, Γ) = { C | C ∈ Exp_{σ}(s, Γ), C canonical}
Exp_{σ}(s) = Exp_{σ}(s, ∅)
Can_{σ}(s) = Can_{σ}(s, ∅)

of expressions and canonical expressions at any type σ and for any finite sets s,Γ of names and typed variables.

2 Evaluation Semantics

The operational semantics of the nu-calculus is specified by the inductively defined evaluation relation given in Figure 2.2. Elements of the relation take the form

s ⊢ M ⇓_{σ} (s′)C

where s and s′ are disjoint finite sets of names, M ∈ Exp_{σ}(s) and C ∈ Can_{σ}(s ⊕ s′). This is intended to mean that in the presence of the names s, expression M of type σ evaluates to canonical form C and creates fresh names s′. We may omit s or s′ when they are empty.

The sets s and s ⊕ s′ can be seen as initial and final states of the computation. The arrangement of these states shows the left to right order of evaluation. For example, with the expression N = N′, the rules (EQ1) and (EQ2) both evaluate N before N′. The callby-value nature of the nu-calculus is captured by the choice of a strict (APP) rule. Here the argument M is evaluated to canonical form C before being substituted in the body of the abstraction λx:σ.M′.

Occasionally, in applying these rules it is necessary to relabel bound names. For example, to evaluate νn.n = νn.n we do not use ⊢ νn.n = νn.n ⇓_{o} (n, n)true because it is not well formed; new names have to be distinct, and this is enforced by the use of disjoint union ⊕ in the (LOCAL) rule. Instead we relabel one of the n’s to obtain ⊢ νn.n = νn′.n′ ⇓_{o} (n, n′)false. As we have previously identified expressions up to αconversion, this is quite legitimate, but perhaps surprising. The phenomenon is identical to the reduction of a term such as (λy.λx.yx)x in the traditional lambda-calculus, where the bound occurrence of x has to be relabelled to allow

(λy.λz.yz)x ⟶ λz.xz.

In principle, these difficulties can be resolved by using de Bruijn indices, but at the cost of a considerable loss of clarity. In practice we simply avoid the problem wherever we can by choosing sensible bindings to begin with.

The abbreviation new for νn.n was introduced earlier. This has the derived evaluation rule

(NEW)  \overline{s ⊢ new ⇓_{ν} (\{n\})n} n ∉ s.

The side condition confirms that the name generated by new is fresh, and corresponds precisely to the disjoint union s ⊕ {n} in the premise of the (LOCAL) rule for evaluating νn.M. Indeed the rules (LOCAL) and (NEW) are entirely equivalent, and we could formulate the nu-calculus with new as primitive and νn.M an abbreviation for (λn:ν.M)new. This then makes precise the connection between the relabelling of names bound by ν and of variables bound by λ, mentioned above as necessary to avoid capture. In a setting with new primitive, they are the same thing.

Unfortunately both of the forms νn.M and (λn:ν.M)new tend to blur the distinctions between a name, a location bound to a name, and a variable of type ν. Rather than resort to heavy meta-syntactic machinery for a solution, we shall simply choose whichever of new and νn.M seems appropriate.

The evaluation of a nu-calculus expression is independent of any unused names:

(CAN)  \overline{s ⊢ C ⇓_{σ} C} C canonical

(COND1)  \frac{s ⊢ B ⇓_{o} (s_{1})true  s ⊕ s_{1} ⊢ M ⇓_{σ} (s_{2})C}{s ⊢ if B then M else M′ ⇓_{σ} (s_{1} ⊕ s_{2})C}

(COND2)  \frac{s ⊢ B ⇓_{o} (s_{1})false  s ⊕ s_{1} ⊢ M′ ⇓_{σ} (s_{2})C′}{s ⊢ if B then M else M′ ⇓_{σ} (s_{1} ⊕ s_{2})C′}

(EQ1)  \frac{s ⊢ N ⇓_{ν} (s_{1})n  s ⊕ s_{1} ⊢ N′ ⇓_{ν} (s_{2})n}{s ⊢ (N = N′) ⇓_{o} (s_{1} ⊕ s_{2})true} n ∈ s

(EQ2)  \frac{s ⊢ N ⇓_{ν} (s_{1})n  s ⊕ s_{1} ⊢ N′ ⇓_{ν} (s_{2})n′}{s ⊢ (N = N′) ⇓_{o} (s_{1} ⊕ s_{2})false} n, n′ distinct

(LOCAL)  \frac{s ⊕ \{n\} ⊢ M ⇓_{σ} (s_{1})C}{s ⊢ νn.M ⇓_{σ} (\{n\} ⊕ s_{1})C} n ∉ (s ⊕ s_{1})

(APP)  \frac{\begin{matrix}s ⊢ F ⇓_{σ→σ′} (s_{1})λx:σ.M′  s ⊕ s_{1} ⊢ M ⇓_{σ} (s_{2})C \\ s ⊕ s_{1} ⊕ s_{2} ⊢ M′[C/x] ⇓_{σ′} (s_{3})C′ \end{matrix}}{s ⊢ F M ⇓_{σ′} (s_{1} ⊕ s_{2} ⊕ s_{3})C′}

Figure 2.2: Rules for evaluating expressions of the nu-calculus Lemma 2.2 For any M ∈ Exp_{σ}(s),

s ⊢ M ⇓_{σ} (s′)C ⟺ s ⊕ s′′ ⊢ M ⇓_{σ} (s′)C

whenever s′′ is disjoint from s′.

Proof By induction on the structure of the derivation of the evaluation judgement.

Evaluation always terminates, and is deterministic up to choice of new names. This might seem obvious, as the nu-calculus has no explicit construction for recursively defined functions. Nevertheless there are many surprising ways to encode recursion in other language features; for example, we shall see later that a mutable store of functions can do this. So it is as well to have a formal proof of termination in the nu-calculus. The proof is our first use of a (unary) logical relation, as described in the introductory chapter. We define the two predicates

P_{σ}(s) ⊆ Can_{σ}(s) and \overline{P}_{σ}(s) ⊆ Exp_{σ}(s)

according to

P_{o}(s) = {true, false}
P_{ν}(s) = s
P_{σ→τ} (s) = \{λx:σ.M ∈ Can_{σ→τ} (s) | ∀s′, C ∈ P_{σ}(s ⊕ s′) . M[C/x] ∈ \overline{P}_{τ} (s ⊕ s′)\}

and

M ∈ \overline{P}_{σ}(s) ⟺ There are s′ and C ∈ P_{σ}(s ⊕ s′) such that s ⊢ M ⇓_{σ} (s′)C, and these are unique up to renaming the elements of s′ and α-conversion of C.

The idea now is to show that P and \overline{P} are both total, and then use the fact that \overline{P} implies termination. To make the induction work, we use an intermediate result on open expressions.

Lemma 2.3 If M ∈ Exp_{σ}(s, Γ), where Γ = {x_{1} : σ_{1}, …, x_{n} : σ_{n}}, and C_{i} ∈ P_{σ_{i}}(s ⊕ s′) for i = 1, …, n and some s′, then M[C⃗/x⃗] ∈ \overline{P}_{σ}(s ⊕ s′).

Proof By induction over the structure of the derivation of s, Γ ⊢ M : σ. We consider three example cases:

• Function abstraction. Suppose that the type derivation ends with

\frac{s, Γ ⊕ \{x : σ\} ⊢ M : σ′}{s, Γ ⊢ λx:σ.M : σ → σ′}

and that the C_{i} are as above. By the induction hypothesis, if C ∈ P_{σ}(s ⊕ s′ ⊕ s′′) for some s′′ then M[C⃗/x⃗, C/x] ∈ \overline{P}_{σ}(s ⊕ s′ ⊕ s′′). But this is precisely the condition for (λx:σ.M)[C⃗/x⃗] ∈ P_{σ→σ′}(s ⊕ s′), from which it follows trivially that (λx:σ.M)[C⃗/x⃗] ∈ \overline{P}_{σ→σ′}(s ⊕ s′).

• Function application. Suppose that the type derivation ends with

\frac{s, Γ ⊢ F : σ → σ′ s, Γ ⊢ M : σ}{s, Γ ⊢ F M : σ′}

and that the C_{i} are as before. Then by the induction hypothesis:

s ⊕ s′ ⊢ F [C⃗/x⃗] ⇓_{σ→σ′} (s_{1})λx:σ.M′

with λx:σ.M′ ∈ P_{σ→σ′}(s ⊕ s′ ⊕ s_{1}), and

s ⊕ s′ ⊕ s_{1} ⊢ M[C⃗/x⃗] ⇓_{σ} (s_{2})C

with C ∈ P_{σ}(s ⊕ s′ ⊕ s_{1} ⊕ s_{2}). This then means that

s ⊕ s′ ⊕ s_{1} ⊕ s_{2} ⊢ M′[C/x] ⇓_{σ′} (s_{3})C′

with C′ ∈ P_{σ′}(s ⊕ s′ ⊕ s_{1} ⊕ s_{2} ⊕ s_{3}). Combining these with the (APP) rule gives

s ⊕ s′ ⊢ F M[C⃗/x⃗] ⇓_{σ′} (s_{1} ⊕ s_{2} ⊕ s_{3})C′.

Moreover all these evaluations are unique up to renaming and α-conversion, so F M[C⃗/x⃗] ∈ \overline{P}_{σ′}(s ⊕ s′) as required.

• Name abstraction. Suppose that the type derivation ends with

\frac{s ⊕ \{n\}, Γ ⊢ M : σ}{s, Γ ⊢ νn.M : σ}

and that C_{i} ∈ P_{σ}(s ⊕ s′). Applying the induction hypothesis gives

s ⊕ {n} ⊕ s′ ⊢ M[C⃗/x⃗] ⇓_{σ} (s′′)C

with C ∈ P_{σ}(s ⊕ {n} ⊕ s′ ⊕ s′′). We can then apply the (LOCAL) rule to obtain

s ⊕ s′ ⊢ (νn.M)[C⃗/x⃗] ⇓_{σ} ({n} ⊕ s′′)C.

Again these evaluations are unique up to renaming and α-conversion, so as required (νn.M)[C⃗/x⃗] ∈ \overline{P}_{σ}(s ⊕ s′).

The remaining cases are similar.

Theorem 2.4 (Termination) If M ∈ Exp_{σ}(s) then there are s′, C with s ⊢ M ⇓_{σ} (s′)C. Moreover, these are unique up to relabelling the elements of s′ and α-conversion of C.

Proof This is Lemma 2.3 applied to the type assertion s ⊢ M : σ.

18 CHAPTER 2. THE NU-CALCULUS Reduction expressions:

E⟨−⟩ :: = ⟨−⟩M | (λx:σ.M)⟨−⟩
| if ⟨−⟩ then M else M′ | ⟨−⟩ = N | n = ⟨−⟩

Redexes:

if true then M else M′ →_{σ} M  n = n →_{ν} true
if false then M else M′ →_{σ} M′ n = n′ →_{ν} false n ≠ n′
(λx:σ.M)C →_{σ′} M[C/x]

Rules:

(REDEXP)  \frac{M →_{σ} M′}{E⟨M⟩ →_{σ′} E⟨M′⟩}
(ABSTRACT)  \frac{M →_{σ} M′}{νn.M →_{σ} νn.M′}
(EXTRUDE)  \overline{E⟨νn.M⟩ →_{σ′} νn.E⟨M⟩} n ∉ fn(E⟨−⟩)

Derived forms:

M →_{σ}^{0} M \frac{M →_{σ}^{n} M′ M′ →_{σ} M′′}{M →_{σ}^{n+1} M′′}

M →_{σ}^{∗} M′ if there is some n with M →_{σ}^{n} M′ Figure 2.3: Step reduction for the nu-calculus

3 Reduction Semantics

The evaluation relation gives a ‘big step’ operational semantics for the nu-calculus, taking expressions directly to canonical form. We can also give a ‘small step’ semantics which illustrates how it happens. This uses a reduction relation whose elements are of the form

M →_{σ} M′

and indicate that the expression M of type σ reduces in a single step to the expression M′. Here M, M′ ∈ Exp_{σ}(s) for some set of names s. The relation corresponds to Plotkin’s left reduction M →_{V} N for the λ_{V} -calculus [94].

The rules specifying the reduction relation are in Figure 2.3. This also defines the derived relations

M →_{σ}^{n} M′ and M →_{σ}^{∗} M′

of n-step and finite step reduction respectively. For brevity we use reduction expressions to describe some of the rules: these are expressions with a single typed hole ⟨−⟩, taking one of the forms

E⟨−⟩ ::= ⟨−⟩M | (λx:σ.M)⟨−⟩
| if ⟨−⟩ then M else M′ | ⟨−⟩ = N | n = ⟨−⟩.

We write ⟨−:σ⟩ if we wish to make explicit the type of the hole. If M is an expression of the appropriate type then E⟨M⟩ denotes the expression E⟨−⟩ with M replacing the single occurrence of the hole. There is no possibility of name or variable capture. The free names fn(E⟨−⟩) of a reduction expression are the free names of its subexpressions. It is significant that we use reduction expressions simply as an abbreviation; they could be avoided by replacing (REDEXP) and (EXTRUDE) with ten more specific rules.

A more complex notion is that of a reduction context. This is also an expression with a single typed hole, fitting the description

R⟨−⟩ :: = ⟨−⟩ | R⟨−⟩M | (λx:σ.M)R⟨−⟩
| if R⟨−⟩ then M else M′ | R⟨−⟩ = N | n = R⟨−⟩.

It is clear that a reduction context is just a nested sequence of reduction expressions. Again there can be no name or variable capture by the reduction context: the hole may be filled by an open expression, but the free variables of such M remain free in R⟨M⟩. For example, we write λx:σ.R⟨x⟩ for the abstraction with variable x replacing the hole.

Reduction contexts were introduced by Felleisen and Friedman in [19]; their purpose is to identify where in an expression the first reduction lies. Section 6 examines this in detail, so for the moment we observe only that the rules

(RCONTEXT)  \frac{M →_{σ} M′}{R⟨M⟩ →_{σ′} R⟨M′⟩}

and

(EXTRUDE∗)  \overline{R⟨νn.M⟩ →_{σ′}^{∗} νn.R⟨M⟩} n ∉ fn(R⟨−⟩)

can be derived for any reduction context R⟨−:σ⟩.

Unlike the evaluation relation, the reduction semantics is not entirely deterministic, as some expressions have more than one reduction available. However reduction is still confluent, and this choice makes no difference to the eventual outcome. In fact the relation → obeys the diamond property:

Lemma 2.5 (Diamond) If M →_{σ} M_{1} and M →_{σ} M_{2} are valid reductions, then there is some expression M′ such that M_{1} →_{σ} M′ and M_{2} →_{σ} M′.

Proof The base case where an expression has two distinct reductions is

\frac{\frac{M →_{σ} M′}{νn.M →_{σ} νn.M′}}{E⟨νn.M⟩ →_{σ′} E⟨νn.M′⟩} and E⟨νn.M⟩ →_{σ′} νn.E⟨M⟩,

where M,M′ ∈ Exp_{σ}(s) and s ⊢ E⟨−:σ⟩: σ′ is a reduction expression. These two choices can immediately be reconciled by

E⟨νn.M′⟩ →_{σ′} νn.E⟨M′⟩ and \frac{\frac{M →_{σ} M′}{E⟨M⟩ →_{σ′} E⟨M′⟩}}{νn.E⟨M⟩ →_{σ′} νn.E⟨M′⟩.}

All other cases are instances of this within a series of reduction expressions and name abstractions.

We can avoid this indeterminacy by only allowing reduction under name abstraction at the top level. By always choosing the (EXTRUDE) rule over (ABSTRACT), we obtain a deterministic reduction for any expression; we call it the standard reduction. It is possible to enforce this, if we introduce another reduction relation ‘−▷’ and replace the (ABSTRACT) rule with

\frac{M →_{σ} M′}{M −▷_{σ} M′}  and  \frac{M −▷_{σ} M′}{νn.M −▷_{σ} νn.M′} .

The relation ‘−▷’ now follows only the standard reduction sequence.

There is an exact correspondence between the reduction and evaluation semantics, if we consider taking an expression to canonical form. This is the analogue of Plotkin’s result relating the evaluation and reduction semantics for λ_{V} [94, Section 4, Theorem 4]. Define M →_{σ}^{∗} νs′.C to mean that there is an ordering on the names in s′ = {n′_{1}, …, n′_{k}} such that M →_{σ}^{∗} νn′_{1} … νn′_{k}.C.

Theorem 2.6 For any closed expressions M ∈ Exp_{σ}(s) and C ∈ Can_{σ}(s),

s ⊢ M ⇓_{σ} (s′)C ⟺ M →_{σ}^{∗} νs′.C .

Proof The forward direction follows by induction on the structure of the proof of the evaluation judgement s ⊢ M ⇓_{σ} (s′)C. This requires a proof step for each of the rules of Figure 2.2. We give a couple of examples; the others follow a similar format.

• (CAN) The evaluation of a canonical s ⊢ C ⇓_{σ} C is axiomatic; but so is the reduction C →_{σ}^{0} C.

• (COND1) Suppose that s ⊢ if B then M else M′ ⇓_{σ} (s′)C, with the last rule of the proof being (COND1). Then we must have s′ = s_{1} ⊕ s_{2} with

s ⊢ B ⇓_{o} (s_{1})true and s ⊕ s_{1} ⊢ M ⇓_{σ} (s_{2})C .

By the induction hypothesis the first of these gives B →_{o}^{∗} νs_{1}.true and so

if B then M else M′ →_{σ}^{∗} νs_{1}.(if true then M else M′).

We have

if true then M else M′ →_{σ} M

and from the second evaluation above, by the induction hypothesis

M →_{σ}^{∗} νs_{2}.C .

Putting these together gives

if B then M else M′ →_{σ}^{∗} νs_{1}.νs_{2}.C

as required.

For the reverse direction we start by showing that

M →_{σ} M′ & s ⊢ M′ ⇓_{σ} (s′)C ⟹ s ⊢ M ⇓_{σ} (s′)C.

We do this by induction on the structure of the proof of M →_{σ} M′; again, a couple of cases are enough to show the method.

• Consider the judgements if true then M else M′ →_{σ} M and s ⊢ M ⇓_{σ} (s′)C. We can use the evaluation rules (CAN) and (COND1) to obtain

\frac{s ⊢ true ⇓_{o} true s ⊢ M ⇓_{σ} (s′)C}{s ⊢ if true then M else M′ ⇓_{σ} (s′)C}

as required.

• Suppose that F M →_{σ′} F′M and s ⊢ F′M ⇓_{σ} (s′)C′. The last rules in the proofs

of these must have been

\frac{F →_{σ→σ′} F′}{F M →_{σ′} F′M}

and

\frac{\begin{matrix}s ⊢ F′ ⇓_{σ→σ′} (s_{1})λx:σ.M′ s ⊕ s_{1} ⊢ M ⇓_{σ} (s_{2})C \\ s ⊕ s_{1} ⊕ s_{2} ⊢ M′[C/x] ⇓_{σ′} (s_{3})C′ \end{matrix}}{s ⊢ F′M ⇓_{σ′} (s′)C′}

where s′ = s_{1} ⊕ s_{2} ⊕ s_{3}. By the induction hypothesis we obtain s ⊢ F ⇓_{σ→σ′} (s_{1})λx:σ.M′ and then build

\frac{\begin{matrix}s ⊢ F ⇓_{σ→σ′} (s_{1})λx:σ.M′ s ⊕ s_{1} ⊢ M ⇓_{σ} (s_{2})C \\ s ⊕ s_{1} ⊕ s_{2} ⊢ M′[C/x] ⇓_{σ′} (s_{3})C′ \end{matrix}}{s ⊢ F′M ⇓_{σ′} (s′)C′}

as desired.

It now follows that

M →_{σ}^{n} M′ & s ⊢ M′ ⇓_{σ} (s′)C ⟹ s ⊢ M ⇓_{σ} (s′)C.

by induction on the number of steps n. The particular case when the expression M′ is of the form νs′.C, for some ordering of s′, gives

M →_{σ}^{∗} νs′.C ⟹ s ⊢ M ⇓_{σ} (s′)C

which is the required result.

4 Contextual Equivalence

We construct a notion of equivalence for expressions of the nu-calculus, based on their behaviour when used in larger expressions. Informally, two expressions are equivalent if they can be freely exchanged; there is no way in the language itself to distinguish between them. To capture this formally requires a little preliminary work.

Define a program to be a closed expression of boolean type. All that we can observe of a program is whether it evaluates to true or false; the creation of new names is not directly observable. In calculi with the possibility of non-termination, it is common to use termination as the basic observable. We cannot do this for the nu-calculus, as all expressions evaluate to some canonical form; in particular, no observation at all can be made of expressions of function type without using them in some larger expression.

A program context P ⟨⟨−⟩⟩ is a program with zero or more occurrences of a hole ⟨⟨−⟩⟩. If M is some expression then P ⟨⟨M⟩⟩ is the program obtained by substituting M for every occurrence of this hole. Often the notion of a program context is left at that, with the possibility of type clashes and variable capture. We shall be rather more precise and annotate holes to track types and the use of free variables.

A hole of arity σ_{1}, …, σ_{n} → σ is an n-place operator added to the nu-calculus, whose arguments must be in canonical form. We have the rule

\frac{s, Γ ⊢ C_{1} : σ_{1} ⋯ s, Γ ⊢ C_{n} : σ_{n}}{s, Γ ⊢ ⟨⟨− : σ_{1}, …, σ_{n}→σ⟩⟩(C_{1}, …, C_{n}) : σ}  C_{1}, …, C_{n} canonical

where the annotation ⟨⟨−: σ_{1},…,σ_{n}→σ⟩⟩ indicates the arity of the hole. We write M⟨⟨−⟩⟩ to denote an expression formed with zero or more occurrences of some hole. Such a hole can be filled by any open expression of type σ whose free variables have types σ_{1}, …, σ_{n}. That is:

\frac{s, \{x_{1} : σ_{1}, …, x_{n} : σ_{n}\} ⊢ M : σ s, Γ ⊢ M′⟨⟨− : σ_{1}, …, σ_{n}→σ⟩⟩ : σ′}{s, Γ ⊢ M′⟨⟨(x_{1}:σ_{1}, …, x_{n}:σ_{n})M⟩⟩ : σ′}

where (x_{1}:σ_{1}, …, x_{n}:σ_{n})M is a ‘meta-abstraction’ that makes explicit the free variables of M. The filled holes are then removed by replacing

⟨⟨(x_{1}:σ_{1}, …, x_{n}:σ_{n})M⟩⟩(C_{1}, …, C_{n}) with M[C_{1}/x_{1}, …, C_{n}/x_{n}],

where the substitution on the right hand side is capture avoiding as usual. It is possible that some of the C_{i} will themselves contain uses of ⟨⟨−⟩⟩, and these must be substituted first. Despite this complication, it is still a finite and well behaved procedure.

For brevity we shall generally omit the arity σ_{1}, …, σ_{n} → σ of a hole, and abbreviate the substitution M′⟨⟨(x_{1}:σ_{1}, …, x_{n}:σ_{n})M⟩⟩ to M′⟨⟨(x⃗)M⟩⟩ or even M′⟨⟨M⟩⟩ when M is closed. The arguments (C_{1}, …, C_{n}) we shall write as (C⃗) and the instantiation M[C_{1}/x_{1}, …, C_{n}/x_{n}] as M[C⃗/x⃗].

With this machinery the substitution M′⟨⟨(x⃗)M⟩⟩ is certain to be a well-typed expression, without capture of free variables. We can safely relabel bound and even free variables of M and M′ without worry. In particular we implicitly identify program contexts P ⟨⟨−⟩⟩ up to α-conversion. The usual arrangement, allowing the capture of free variables from M, can be simulated by forbidding α-conversion and always using the hole in the form ⟨⟨−⟩⟩(x_{1}, …, x_{n}), where the x_{i} are the free variables of M.

Now that we have fixed how we substitute an open expression M in a program context P ⟨⟨−⟩⟩, we can use this to describe the behaviour of M. In calculi where nontermination is possible, it is convenient to do this through a preorder. Here we go directly to an equivalence relation:

Definition 2.7 (Contextual Equivalence) If M_{1}, M_{2} ∈ Exp_{σ}(s, Γ) then the assertion

s, Γ ⊢ M_{1} ≈_{σ} M_{2}

means that for all suitably typed program contexts P ⟨⟨−⟩⟩ defined over s, and each boolean value b ∈ {true, false},

( ∃s_{1} . s ⊢ P ⟨⟨(x⃗)M_{1}⟩⟩ ⇓_{o} (s_{1})b) ⟺ ( ∃s_{2} . s ⊢ P ⟨⟨(x⃗)M_{2}⟩⟩ ⇓_{o} (s_{2})b).

That is, P ⟨⟨−⟩⟩ always evaluates to the same boolean value, whether the hole is filled by M_{1} or M_{2}. When this holds, we say that M_{1} and M_{2} are contextually equivalent. If both s and Γ are empty then we write simply M_{1} ≈_{σ} M_{2}.

This is the most general notion of equivalence for nu-calculus expressions that we shall consider, and the one that most interests us; as discussed in the introductory chapter, it combines powerful applications with a sensible and intuitive meaning. Other equivalences are useful if they imply contextual equivalence, and are easier to compute.

5 Examples

Much of the work of this dissertation is concerned with methods for proving contextual equivalence or inequivalence for particular expressions of the nu-calculus. This section gives a summary of results, in increasing order of difficulty of proof.

It is straightforward to show from the definition that contextual equivalence is a congruence:

1.  s, Γ ⊢ M_{1} ≈_{σ} M_{2} ⟹ s ⊕ s′, Γ ⊕ Γ′ ⊢ M′[M_{1}/x] ≈_{σ′} M′[M_{2}/x]

where M′ ∈ Exp_{σ′}(s ⊕ s′, Γ ⊕ Γ′ ⊕ {x : σ}).

Unused names are irrelevant, as is the order in which names are generated:

\begin{aligned}2. & s, Γ ⊢ & νn.M & ≈_{σ} & M & n ∉ fn(M) \\ 3. & s, Γ ⊢ & νn.νn′.M & ≈_{σ} & νn′.νn.M . \end{aligned}

For any finite set of names s we define νs.M to be νn_{1} … νn_{k}.M when s = {n_{1}, …, n_{k}} and M when s is empty. By the above, this is unambiguous up to contextual equivalence even though s is unordered.

Evaluation and reduction both respect contextual equivalence:

\begin{aligned}4. & s ⊢ M ⇓_{σ} (s′)C & ⟹ & s ⊢ M ≈_{σ} νs′.C \\ 5. & M →_{σ} M′ & ⟹ & s ⊢ M ≈_{σ} M′ \end{aligned}

where M, M′ ∈ Exp_{σ}(s) and C ∈ Can_{σ}(s ⊕ s′).

In Section 3 we defined the notion of a reduction context R⟨−⟩, an expression with a single typed hole in a position where reduction can occur. We can use this to state some equivalences that rearrange expressions without materially affecting the evaluation order. Suppose that s, Γ ⊢ R⟨−:σ⟩ : σ′ is a reduction context, then:

\begin{aligned}6. & s, Γ ⊢ & (λx:σ.R⟨x⟩)M & ≈_{σ′} & R⟨M⟩ \\ 7. & s, Γ ⊢ & R⟨νn.M⟩ & ≈_{σ′} & νn.R⟨M⟩ \\ 8. & s, Γ ⊢ & R⟨(λx:σ′′.M)M′⟩ & ≈_{σ′} & (λx:σ′′.R⟨M⟩)M′ \end{aligned}

where M and M′ have the appropriate types. The first of these is a weak form of βequivalence; the last is the β_{lift} rule from Sabry and Felleisen’s axiomatization of the call-by-value lambda-calculus [114]. Some simple instances of these are:

s, Γ ⊢  M ≈_{σ} (λx:σ.x)M
s, Γ ⊢ if (νn.B) then M else M′ ≈_{σ} νn.(if B then M else M′)
s, Γ ⊢ (λy:τ.Q)((λx:σ.P)M) ≈_{σ′′} (λx:σ.(λy:τ.Q)P)M.

Function application also satisfies Plotkin’s β_{v}-equivalence [94]: if C ∈ Can_{σ}(s, Γ) and M ∈ Exp_{σ′}(s, Γ ⊕ {x : σ}) then

9.  s, Γ ⊢ (λx:σ.M)C ≈_{σ′} M[C/x].

However, general β-equivalence fails because the nu-calculus is call-by-value:

10.  (λx:ν.x = x)new ≉_{o} (new = new).

The left-hand side here reduces to true and the right-hand side to false. Local name declaration and function abstraction do not in general commute:

11.  νn.λx:o.n ≉_{o→ν} λx:o.νn.n .

These can be distinguished by the context (λf : o → ν . (ftrue = ftrue)) ⟨⟨−⟩⟩, giving true and false respectively.

Expressions may be contextually equivalent if they differ only in their use of ‘private’ names:

12.  νn.λx:ν.(x = n) ≈_{ν→o} λx:ν.false
13.  νn.νn′.λf:ν→o.(fn = fn′) ≈_{(ν→o)→o} λf:ν→o.true .

In this last example the boolean test fn = fn′ is an abbreviation for

if fn then fn′ else (if fn′ then false else true).

The idea in (12) is that no external context can supply the private name n. Similarly in (13) no externally produced function can distinguish the private names n and n′.

It is however extraordinarily hard to make precise this notion of privacy, particularly where higher-order functions are involved. The next case shows two expressions which look at first sight to be contextually equivalent for the same reason as those in (13):

14.  νn.λf:ν→o.νn′.(fn = fn′) ≉_{(ν→o)→o} λf:ν→o.true .

These are distinguished by the context

(λF : (ν → o) → o . F (λx:ν.F (λy:ν.x = y))) ⟨⟨−⟩⟩.

The problem here is that although the name bound to n remains private, the function λx:ν.F (λy:ν.x = y) is able to distinguish n from the fresh names successively bound to n′.

Another tricky example shows that it may be necessary to apply functions repeatedly in order to distinguish them, without any private names being revealed:

15.

νn.νn′.λf : ν → o . if fn = fn′ then (λx:ν. if x = n then true else if x = n′ then false else fx) else (λx:ν.true)

≉_{(ν→o)→(ν→o)} λf : ν → o . f .

These are distinguished by

(λF : (ν → o) → (ν → o) . F (F (λx:ν.false))new) ⟨⟨−⟩⟩.

What is happening here is that the two functions differ noticeably only on arguments of type (ν → o) that can distinguish n from n′. As both names are private, we cannot construct such a function directly. However when we pass the first expression an argument that we can construct, such as (λx:ν.false), we get back one that does distinguish n from n′, in this case (λx:ν.(x = n)). Although this is externally no different from what we started with (see equivalence (12) above), it is a suitable argument to separate the two original expressions.

Up to contextual equivalence, the only closed expressions of type o are true and false, and the only closed expressions of type ν are the names in the name context and new. Higher types are more complicated, and there are infinitely many operationally distinct closed expressions of type (ν → ν). Consider for each p ≥ 1 the expression which creates (p + 1) local names n_{0}, …, n_{p} and then acts as the function which cyclically permutes them, and maps any other name to n_{0}:

F_{p} = νn_{0} … νn_{p}.λx:ν. if x = n_{0} then n_{1} else if x = n_{1} then n_{2} ⋮ else if x = n_{p} then n_{0} else n_{0} .

Take the test function

B_{q} = λf : ν → ν . νn . (f^{(q+2)}(n) = f(n))

where f^{(q+2)} is an abbreviation for f iterated (q + 2) times. This satisfies

⊢ B_{q}F_{p} ⇓_{o} (n_{0}, …, n_{p})false q ∈ {1, …, p − 1}
⊢ B_{p}F_{p} ⇓_{o} (n_{0}, …, n_{p})true

and so can be used to distinguish the various F_{p}, giving

16.  F_{p} ≉_{ν→ν} F_{p′}  whenever p ≠ p′.

The F_{p} can be regarded as numerals; we can even define addition by taking

A = λf : ν → ν . λg : ν → ν . νn . λx : ν . if f(fx) = fn then gx else if gx = gn then fx else gx

of type (ν → ν) → (ν → ν) → (ν → ν), which satisfies

17.  AF_{p}F_{q} ≈_{ν→ν} F_{p+q}.

For example, suppose that F_{p} cycles the private names n_{0}, …, n_{p} and F_{q} the names n′_{0}, …, n′_{q}, then AF_{p}F_{q} does the same thing over the names n_{0}, …, n_{p−1}, n′_{0}, …, n′_{q}. The trick here is that the test (f(fx) = fn) is only true when x is n_{p−1}, while (gx = gn) is true when x is any of n_{0}, …, n_{p−1}, n′_{q} or some unknown name. These are then used to select which name to return.

These examples show that the nu-calculus has all the properties we might expect for a language of names, and for a call-by-value lambda-calculus. They also illustrate the subtle and perhaps surprising behaviour that can arise from the interaction between names and higher-order functions.

6 A Context Lemma

While contextual equivalence is the relation on expressions of the nu-calculus that we would like to work with, there are certain problems in doing so. The most obvious is that program contexts P ⟨⟨−⟩⟩ are far too numerous and varied; a direct proof that two expressions behave similarly in all program contexts is generally too unwieldy to be attempted. In this section we show that a smaller collection of contexts is sufficient. Later we consider other equivalences that are simpler to demonstrate yet imply contextual equivalence

A result showing that it is not necessary to consider all program contexts, but only those having a certain form, is called a context lemma, after Milner’s result for the simplytyped lambda-calculus [59]. The equivalent result for our system would be that it is only necessary to consider applicative contexts, which take the form

⟨⟨−⟩⟩(C⃗)M_{1} … M_{n}

where an expression is instantiated and then applied to some arguments. Milner’s context lemma is particularly useful because the types of the M_{i} are all structurally simpler than that of the hole. This means that various results on contextual equivalence can be proved by induction on the structure of types.

Unfortunately the context lemma in this form is not valid for the nu-calculus. The simplest counter-example is the inequivalence (11) of Section 5 above:

νn.λx:o.n ≉_{o→ν} λx:o.νn.n .

Both of these expressions, when applied to either true or false, return a fresh name. Only by using a context such as (λf:o → ν.(ftrue = ftrue))⟨⟨−⟩⟩ can we detect that the first always returns the same name, while the second repeatedly generates new ones. The inequivalences (15) and (16) also provide counterexamples. However we can give a weaker result that is suitable for the nu-calculus:

Theorem 2.8 (Context Lemma) Two expressions are contextually equivalent

s, Γ ⊢ M_{1} ≈_{σ} M_{2}

if and only if for all name sets s′, functions λx:σ.B ∈ Can_{σ→o}(s ⊕ s′), instantiations [C⃗/x⃗] defined over (s ⊕ s′), and boolean values b ∈ {true, false},

( ∃s_{1} . s ⊕ s′ ⊢ (λx:σ.B)M_{1}[C⃗/x⃗] ⇓_{o} (s_{1})b)
⟺
( ∃s_{2} . s ⊕ s′ ⊢ (λx:σ.B)M_{2}[C⃗/x⃗] ⇓_{o} (s_{2})b).

We call a context of the form νs′.(λx:σ.B)(⟨⟨−⟩⟩(C⃗)) an argument context, and (λx:σ.B) a test function. Although less dramatic than the usual result, this still narrows down the contexts that we have to consider. In the first place, because the nu-calculus is call-by-value, an argument context only evaluates the contents of its hole to canonical form once. Additionally, in a general context the arguments to the hole can have free variables, or even contain holes themselves. In an argument context the (C⃗) are closed and have no holes. Unfortunately the technique mentioned above, using a context lemma to prove other results by induction on the structure of types, fails to go through as the type of (λx:σ.B) is larger than the type of the hole.

Results similar to Theorem 2.8 have been found for other calculi. A. Gordon in his thesis shows that ‘experimental order’ coincides with ‘contextual order’ for the language μνML [25, Lemma 4.4.7]. Honsell, Mason, Smith and Talcott consider an untyped lambda-calculus extended with storage cells and show that to establish ‘operational equivalence’ it is enough to consider all ‘closed instantiations of use’ (ciu) of an expression [30, §2.3.2].

For expressions with no free variables, we can further simplify the range of contexts required:

Corollary 2.9 Two closed expressions are contextually equivalent s ⊢ M_{1} ≈_{σ} M_{2} if and only if for all test functions λx:σ.B ∈ Can_{σ→o}(s) and all b ∈ {true, false},

( ∃s_{1} . s ⊢ (λx:σ.B)M_{1} ⇓_{o} (s_{1})b) ⟺ ( ∃s_{2} . s ⊢ (λx:σ.B)M_{2} ⇓_{o} (s_{2})b).

Proof Observe that for any test function (λx:σ.B) ∈ Can_{σ→o}(s ⊕ s′) applied to a closed expression M ∈ Exp_{σ}(s),

s ⊕ s′ ⊢ (λx:σ.B)M ⇓_{o} (s′′)b ⟺ s ⊢ (λx:σ.νs′.B)M ⇓_{o} (s′ ⊕ s′′)b.

So with no free variables to instantiate, the argument context νs′.(λx:σ.B)⟨⟨−⟩⟩ from Theorem 2.8 can be replace by the test function (λx:σ.νs′.B)⟨⟨−⟩⟩.

Before we can prove the context lemma, we have to examine more closely the process of reduction. In Section 3 we defined reduction expressions E⟨−⟩ and reduction contexts R⟨−⟩ to be expressions with a single typed hole, taking the following forms:

E⟨−⟩ :: = ⟨−⟩M | (λx:σ.M)⟨−⟩
| if ⟨−⟩ then M else M′ | ⟨−⟩ = N | n = ⟨−⟩
R⟨−⟩ :: = ⟨−⟩ | R⟨−⟩M | (λx:σ.M)R⟨−⟩
| if R⟨−⟩ then M else M′ | R⟨−⟩ = N | n = R⟨−⟩.

Any reduction context can be represented uniquely as a nested sequence of reduction expressions. A redex is an expression taking one of the forms

(λx:σ.M)C | if true then M else M′ | if false then M else M′ | n = n′ | n = n.

As shown in Figure 2.3, all of these have immediate reductions, regardless of the nature of the subexpressions M, M′ or C. We can use this classification to break down closed expressions of the nu-calculus and identify their first reduction step.

Lemma 2.10

1. Each closed expression of the nu-calculus is just one of the following:

• in canonical form

• a redex

• a name abstraction

• a reduction expression with the hole ⟨−⟩ filled by some non-canonical expression.

2. Any M ∈ Exp_{σ}(s) decomposes uniquely as one of the following:

νs′.C  C canonical
νs′.R⟨E⟨νn.M′⟩⟩  E⟨−⟩ a reduction expression
νs′.R⟨M′⟩  M′ a redex, M′ →_{σ} M′′

where s′ is some ordered set of names, possibly empty, and R⟨−⟩ is a reduction context.

Proof Item (1) is straightforward, giving consideration to each of the forms of nu-calculus expressions. For example:

• A lambda abstraction (λx:σ.M) is always in canonical form.

• An expression of the form F M is a redex if F and M are both in canonical form. Otherwise, F M is a reduction expression with a non-canonical in ⟨−⟩, as either F ⟨M⟩ or ⟨F ⟩M according as F is in canonical form or not, respectively.

To obtain (2) we apply (1) repeatedly, using the fact that a succession of nested reduction expressions is precisely a reduction context.

For any M ∈ Exp_{σ}(s) this result determines its unique standard reduction as:

νs′.C  none
νs′.R⟨E⟨νn.M′⟩⟩ →_{σ} νs′.R⟨νn.E⟨M′⟩⟩
νs′.R⟨M′⟩ →_{σ} νs′.R⟨M′′⟩.

The next lemma is a weak β-rule that we need later. It is related to equivalence (6) from Section 5 above.

Lemma 2.11 Suppose that s ⊢ R⟨−:σ⟩ : σ′ is a reduction context and M ∈ Exp_{σ}(s).

1. If M →_{σ}^{∗} νs′.C where C is in canonical form, then

R⟨M⟩ →_{σ′}^{∗} νs′.R⟨C⟩  and  (λx:σ.R⟨x⟩)M →_{σ′}^{∗} νs′.R⟨C⟩ .

2. For canonical form C,

s ⊢ R⟨M⟩ ⇓_{σ′} (s′)C ⟺ s ⊢ (λx:σ.R⟨x⟩)M ⇓_{σ′} (s′)C.

Proof The first part of (1) is derived by applying the (REDEXP) and (EXTRUDE) rules repeatedly, while for the second part we combine

(λx:σ.R⟨x⟩)M →_{σ′}^{∗} νs′.((λx:σ.R⟨x⟩)C)

with

(λx:σ.R⟨x⟩)C →_{σ′} R⟨C⟩.

For (2), suppose that s ⊢ M ⇓_{σ} (s′)C′. Then by (1), both R⟨M⟩ and (λx:σ.R⟨x⟩)M reduce to νs′.R⟨C′⟩, from which the result follows.

To understand the behaviour of expressions in context, we must go a stage further. Define an extended expression M̄ to be what we have previously termed a context: an expression of the nu-calculus with a hole ⟨⟨− : σ_{1}, …, σ_{n}→σ⟩⟩ appearing zero or more times. We also need extended versions of canonical form, reduction expression, reduction context and redex; the details are given in Figure 2.4.

To determine the complexity of an extended expression, we use a measure for holes that takes account of their nesting in arguments for other holes. Define the hole count for an extended expression to be a list of the number of holes at each depth of nesting, deepest first. For example the extended expression

if ⟨⟨− : o, ν→o⟩⟩(C_{1}, C_{2}) then true else ⟨⟨−⟩⟩(⟨⟨−⟩⟩(C_{3}, C_{4}), C_{5})

has a hole count [1, 2]. Hole counts are ordered by list length and then lexicographically, for example:

[4] ⊑ [1, 3] ⊑ [3, 1] ⊑ [1, 1, 1].

The set of hole counts is well ordered: there are no strictly decreasing infinite sequences. Another way to look at this ordering is to attach weights to holes, with nested holes being infinitely heavier.

We can break down extended expressions as we did ordinary expressions, using an extended form of Lemma 2.10.

30 CHAPTER 2. THE NU-CALCULUS Extended expressions:

M̄ ::= ⟨⟨−⟩⟩ hole | x variable | n name
| true | false | if M̄ then M̄ else M̄
| νn.M̄ | M̄ = M̄
| λx:σ.M̄ | M̄M̄

Extended canonical form:

C̄ ::= x | n | true | false | λx:σ.M̄

Extended reduction expressions:

Ē⟨−⟩ ::= ⟨−⟩M̄ | (λx:σ.M̄)⟨−⟩
| if ⟨−⟩ then M̄ else M̄′ | ⟨−⟩ = N̄ | n = ⟨−⟩

Extended reduction contexts:

R̄⟨−⟩ ::= ⟨−⟩ | R̄⟨−⟩M̄ | (λx:σ.M̄)R̄⟨−⟩
| if R̄⟨−⟩ then M̄ else M̄′ | R̄⟨−⟩ = N̄ | n = R̄⟨−⟩

Extended redexes:

if true then M̄ else M̄′ →_{σ} M̄  n = n →_{ν} true
if false then M̄ else M̄′ →_{σ} M̄′ n = n′ →_{ν} false n ≠ n′
(λx:σ.M̄)C̄ →_{σ′} M̄[C̄/x]

Figure 2.4: The extended nu-calculus Lemma 2.12

1. Each closed extended expression is just one of the following:

• an application of the hole ⟨⟨−⟩⟩(C̄_{1}, …, C̄_{n})

• in extended canonical form

• an extended redex

• a name abstraction of some extended expression

• an extended reduction expression with the hole ⟨−⟩ filled by some noncanonical extended expression.

2. If s ⊢ M̄ : σ is some closed extended expression, then it takes exactly one of the following forms:

νs′.C̄  C̄ an extended canonical
νs′.R̄⟨⟨⟨−⟩⟩(C̄)⟩
νs′.R̄⟨Ē⟨νn.M̄′⟩⟩  Ē⟨−⟩ an extended reduction expression
νs′.R̄⟨M̄′⟩  M̄′ an extended redex, M̄′ →_{σ} M̄′′

where s′ is some ordered set of names and R̄⟨−⟩ is an extended reduction context.

Proof As for Lemma 2.10, part (1) follows by consideration of the structure of the extended expression, while (2) comes by repeated application of (1).

In part (2) above, suppose that M_{0} ∈ Exp_{σ}(s, Γ) is some open expression suitable to fill the hole in M̄. Then in the last two cases the standard reduction for M̄⟨⟨(x⃗)M_{0}⟩⟩ is independent of M_{0}:

νs′.R̄⟨Ē⟨νn.M̄′⟩⟩⟨⟨(x⃗)M_{0}⟩⟩ →_{σ} νs′.R̄⟨νn.Ē⟨M̄′⟩⟩⟨⟨(x⃗)M_{0}⟩⟩
νs′.R̄⟨M̄′⟩⟨⟨(x⃗)M_{0}⟩⟩ →_{σ} νs′.R̄⟨M̄′′⟩⟨⟨(x⃗)M_{0}⟩⟩.

This pinpoints the nature of reduction sufficiently for us to prove the context lemma:

Proof of Theorem 2.8 The ‘only if’ direction is immediate as an argument context

νs′.(λx:σ.B)(⟨⟨−⟩⟩(C⃗))

is clearly a restricted form of context. For the ‘if’ direction, suppose that we have two expressions M_{1}, M_{2} ∈ Exp_{σ}(s, Γ) satisfying

( ∃s_{1} . s ⊕ s′ ⊢ (λx:σ.B)M_{1}[C⃗/x⃗] ⇓_{o} (s_{1})b)
⟺
( ∃s_{2} . s ⊕ s′ ⊢ (λx:σ.B)M_{2}[C⃗/x⃗] ⇓_{o} (s_{2})b)

for all suitable s′, (λx:σ.B), (C⃗) and b. By symmetry it is enough to show that for any extended program s ⊢ P̄ : o and boolean b that

( ∃s_{1} . s ⊢ P̄⟨⟨(x⃗)M_{1}⟩⟩ ⇓_{o} (s_{1})b) ⟹ ( ∃s_{2} . s ⊢ P̄⟨⟨(x⃗)M_{2}⟩⟩ ⇓_{o} (s_{2})b).

We prove this by a double induction over the length of the left-hand reduction, under the semantics of Section 3, and the hole count of P̄.

By Lemma 2.12(2) there are four possible forms for P̄. In the simplest case, it is a name abstraction of some extended canonical, necessarily true or false, and the result is immediate. If P̄ = νs′.R̄⟨Ē⟨νn.M̄⟩⟩ then as we saw above the first reduction step is the same however the hole ⟨⟨−⟩⟩ is filled. So if we set P̄′ = νs′.R̄⟨νn.Ē⟨M̄′⟩⟩ then

P̄⟨⟨(x⃗)M_{1}⟩⟩ →_{o} P̄′⟨⟨(x⃗)M_{1}⟩⟩ and P̄⟨⟨(x⃗)M_{2}⟩⟩ →_{o} P̄′⟨⟨(x⃗)M_{2}⟩⟩.

Now P̄′⟨⟨(x⃗)M_{1}⟩⟩ will have a shorter reduction to b, and the result follows by the induction hypothesis. A similar approach applies if P̄ = νs′.R̄⟨M̄′⟩ where M̄′ is an extended redex.

The final possibility is that P̄ = νs′.R̄⟨⟨⟨−⟩⟩(C̄)⟩. In this case we fill this particular occurrence of the hole ⟨⟨−⟩⟩ and consider the extended expression νs′.R̄⟨M_{1}[C̄/x⃗]⟩, which has a lower hole count than P̄. We have

P̄⟨⟨(x⃗)M_{1}⟩⟩ = νs′.R̄⟨M_{1}[C̄/x⃗]⟩⟨⟨(x⃗)M_{1}⟩⟩

and use this to reason as follows:

∃s_{1} . s ⊢ P̄⟨⟨(x⃗)M_{1}⟩⟩ ⇓_{o} (s_{1})b ; \begin{matrix}⟺ & ∃s_{1} . s ⊢ νs′.R̄⟨M_{1}[C̄/x⃗]⟩⟨⟨(x⃗)M_{1}⟩⟩ ⇓_{o} (s_{1})b \\ ⟹ & ∃s_{3} . s ⊢ νs′.R̄⟨M_{1}[C̄/x⃗]⟩⟨⟨(x⃗)M_{2}⟩⟩ ⇓_{o} (s_{3})b \\ ⟺ & ∃s_{3} . s ⊕ s′ ⊢ ((λx:σ.R̄⟨x⟩)(M_{1}[C̄/x⃗]))⟨⟨(x⃗)M_{2}⟩⟩ ⇓_{o} (s_{3})b \\ ⟹ & ∃s_{2} . s ⊕ s′ ⊢ ((λx:σ.R̄⟨x⟩)(M_{2}[C̄/x⃗]))⟨⟨(x⃗)M_{2}⟩⟩ ⇓_{o} (s_{2})b \\ ⟺ & ∃s_{2} . s ⊢ νs′.R̄⟨M_{2}[C̄/x⃗]⟩⟨⟨(x⃗)M_{2}⟩⟩ ⇓_{o} (s_{2})b \\ ⟺ & ∃s_{2} . s ⊢ P̄⟨⟨(x⃗)M_{2}⟩⟩ ⇓_{o} (s_{2})b. \end{matrix}

Here we use in turn induction on the hole count, Lemma 2.11(2), the original hypothesis of equality under test functions, and Lemma 2.11(2) again.

7 Applicative Equivalence

In this section we define two notions of equivalence for expressions of the nu-calculus, each with particular good properties. We then show that these are in fact the same relation, and that they imply contextual equivalence. This gives a technique sufficient to prove all but two of the examples in Section 5.

Abramsky introduced the notion of applicative bisimulation for the untyped lambdacalculus, based on bisimulation of labelled transition systems [4]. Loosely, one lambdaexpression simulates another if it is no less defined and behaves similarly at all arguments. Howe’s relation ≤ is a similar construction for lazy computation systems [31]. A. Gordon’s applicative similarity is a version of this for a typed lambda-calculus [25, §4.5]. As usual, because there is no non-termination in the nu-calculus, we work with an equivalence, rather than a preorder.

Definition 2.13 (Applicative Equivalence) We define the relations s ⊢ C_{1} ∼_{σ}^{can} C_{2} for C_{1}, C_{2} ∈ Can_{σ}(s) and s ⊢ M_{1} ∼_{σ}^{exp} M_{2} for M_{1}, M_{2} ∈ Exp_{σ}(s) inductively over the structure of the type σ, according to:

s ⊢ b_{1} ∼_{o}^{can} b_{2} ⟺ b_{1} = b_{2}
s ⊢ n_{1} ∼_{ν}^{can} n_{2} ⟺ n_{1} = n_{2}
s ⊢ λx:σ.M_{1} ∼_{σ→σ′}^{can} λx:σ.M_{2} ⟺ \begin{matrix}∀s′, C ∈ Can_{σ}(s ⊕ s′) . \\ s ⊕ s′ ⊢ M_{1}[C/x] ∼_{σ′}^{exp} M_{2}[C/x] \end{matrix}

s ⊢ M_{1} ∼_{σ}^{exp} M_{2} ⟺ ∃s_{1}, s_{2}, C_{1} ∈ Can_{σ}(s ⊕ s_{1}), C_{2} ∈ Can_{σ}(s ⊕ s_{2}) . s ⊢ M_{1} ⇓_{σ} (s_{1})C_{1} & s ⊢ M_{2} ⇓_{σ} (s_{2})C_{2} & s ⊕ (s_{1} ∪ s_{2}) ⊢ C_{1} ∼_{σ}^{can} C_{2}.

It is immediate that ∼_{σ}^{exp} coincides with ∼_{σ}^{can} on canonical forms; we write them indiscriminately as ∼_{σ} and call the relation applicative equivalence.^{∗} We can extend the relation to open expressions: if M_{1}, M_{2} ∈ Exp_{σ}(s, Γ) where Γ = {x_{1} : σ_{1}, …, x_{n} : σ_{n}} then we define

s, Γ ⊢ M_{1} ∼_{σ} M_{2} ⟺ \begin{matrix}∀s′, C_{i} ∈ Can_{σ_{i}}(s ⊕ s′) i = 1, …, n . \\ s ⊕ s′ ⊢ M_{1}[C⃗/x⃗] ∼_{σ} M_{2}[C⃗/x⃗]. \end{matrix}

Lemma 2.14 If M_{1}, M_{2} ∈ Exp_{σ}(s, Γ) then

s, Γ ⊢ M_{1} ∼_{σ} M_{2} ⟺ s ⊕ s′, Γ ⊕ Γ′ ⊢ M_{1} ∼_{σ} M_{2}

for any s′, Γ′.

Proof Induction on the structure of the type σ gives the result for closed expressions, and the general result follows.

Lemma 2.15 Applicative equivalence is an equivalence relation.

Proof Also by induction on the structure of types.

Applicative equivalence is only a useful relation if we can show that it implies contextual equivalence; however, it is well known that a direct proof is problematic. Abramsky uses the technique of domain logic to solve this [3]. Howe defines an auxiliary relation, roughly the congruence closure of applicative simulation, and shows that this satisfies the same defining properties; this is also the approach taken by Gordon [31, 25].

Because the nu-calculus is simply typed, we can use an original and much simpler method based on logical relations. As described in Chapter 1, these were introduced by Plotkin as a tool to show the undefinability of certain elements in models of the simplytyped lambda-calculus [96]. Our logical relation remains entirely in the syntax of the nu-calculus; nevertheless it keeps the basic idea that functions are related if they take related arguments to related results.

∗This is a different relation to the applicative equivalence of [91, Definition 13] and [92, Definition 3.4] which (rather unfortunately) turns out not to be an equivalence at all.

Definition 2.16 (Logical Equivalence) We define the two relations s ⊢ C_{1} ≃_{σ}^{can} C_{2} for C_{1}, C_{2} ∈ Can_{σ}(s) and s ⊢ M_{1} ≃_{σ}^{exp} M_{2} for M_{1}, M_{2} ∈ Exp_{σ}(s) inductively over the structure of the type σ, according to:

s ⊢ b_{1} ≃_{o}^{can} b_{2} ⟺ b_{1} = b_{2}
s ⊢ n_{1} ≃_{ν}^{can} n_{2} ⟺ n_{1} = n_{2}

s ⊢ λx:σ.M_{1} ≃_{σ→σ′}^{can} λx:σ.M_{2} ⟺ ∀s′, C_{1}, C_{2} ∈ Can_{σ}(s ⊕ s′) . s ⊕ s′ ⊢ C_{1} ≃_{σ}^{can} C_{2} ⟹ s ⊕ s′ ⊢ M_{1}[C_{1}/x] ≃_{σ′}^{exp} M_{2}[C_{2}/x]

s ⊢ M_{1} ≃_{σ}^{exp} M_{2} ⟺ ∃s_{1}, s_{2}, C_{1} ∈ Can_{σ}(s ⊕ s_{1}), C_{2} ∈ Can_{σ}(s ⊕ s_{2}) . s ⊢ M_{1} ⇓_{σ} (s_{1})C_{1} & s ⊢ M_{2} ⇓_{σ} (s_{2})C_{2} & s ⊕ (s_{1} ∪ s_{2}) ⊢ C_{1} ≃_{σ}^{can} C_{2}.

Again ≃_{σ}^{exp} and ≃_{σ}^{can} coincide on canonicals and we write ≃_{σ} indiscriminately, calling the relation logical equivalence. We extend the relation to open expressions; for M_{1}, M_{2} ∈ Exp_{σ}(s, Γ) with Γ = {x_{1} : σ_{1}, …, x_{n} : σ_{n}} we take

s, Γ ⊢ M_{1} ≃_{σ} M_{2} ⟺ \begin{matrix}∀s′, C_{ij} ∈ Can_{σ_{j}}(s ⊕ s′) i = 1, 2 j = 1, …, n . \\ ( &_{j=1}^{n} . s ⊕ s′ ⊢ C_{1j} ≃_{σ_{j}} C_{2j} ) \\ ⟹ s ⊕ s′ ⊢ M_{1}[C⃗_{1}/x⃗] ≃_{σ} M_{2}[C⃗_{2}/x⃗]. \end{matrix}

Lemma 2.17 If M_{1}, M_{2} ∈ Exp_{σ}(s, Γ) then

s, Γ ⊢ M_{1} ≃_{σ} M_{2} ⟺ s ⊕ s′, Γ ⊕ Γ′ ⊢ M_{1} ≃_{σ} M_{2}

for any s′, Γ′.

Proof Induction on the structure of the type σ gives the result for closed expressions, and the general result follows. An irritating detail is the necessity to show that there are at least some related canonical expressions of each type, which is also shown by induction over types.

Unlike applicative equivalence, it is not immediately obvious that logical equivalence is reflexive, transitive or symmetric. However it is a congruence; it is preserved by all the rules for forming expressions of the nu-calculus. From this it follows that logical equivalence is reflexive and that it implies contextual equivalence.

Proposition 2.18 Logical equivalence is a congruence.

Proof Definition 2.16 and the evaluation rules of Figure 2.2 are enough to show that each of the expression-forming rules of Figure 2.1 preserves logical equivalence.

Proposition 2.19 Logical equivalence is reflexive:

s, Γ ⊢ M ≃_{σ} M M ∈ Exp_{σ}(s, Γ).

Proof By induction on the structure of the expression M, using Proposition 2.18.

Proposition 2.20 Logical equivalence implies contextual equivalence:

s, Γ ⊢ M_{1} ≃_{σ} M_{2} ⟹ s, Γ ⊢ M_{1} ≈_{σ} M_{2}.

Proof By Proposition 2.19, any test function is related to itself s ⊕ s′ ⊢ λx:σ.B ≃_{σ→o} λx:σ.B. The result then follows from the Context Lemma (Theorem 2.8) and the definition of logical equivalence at function types and booleans.

Applicative and logical equivalence are clearly very close, with the only difference being in the treatment of values of function type. Logical equivalence places the stronger constraint here, so it is not too surprising that it implies applicative equivalence; less expected is the result that the reverse implication also holds.

Lemma 2.21 If s, Γ ⊢ M_{1} ≃_{σ} M_{2} then s, Γ ⊢ M_{1} ∼_{σ} M_{2}.

Proof We show each of the following:

1. s ⊢ C_{1} ≃_{σ}^{can} C_{2} ⟹ s ⊢ C_{1} ∼_{σ}^{can} C_{2}.

2. s ⊢ M_{1} ≃_{σ}^{exp} M_{2} ⟹ s ⊢ M_{1} ∼_{σ}^{exp} M_{2}.

3. s, Γ ⊢ M_{1} ≃_{σ} M_{2} ⟹ s, Γ ⊢ M_{2} ∼_{σ} M_{2}.

The first two are proved by mutual induction over the structure of σ. Case (1) at ground types is immediate. For function types, suppose that s ⊢ λx:σ.M_{1} ≃_{σ→σ′}^{can} λx:σ.M_{2} and C ∈ Can_{σ}(s ⊕ s′). By Proposition 2.19 above we have s ⊕ s′ ⊢ C ≃_{σ} C, and so s ⊕ s′ ⊢ M_{1}[C/x] ≃_{σ′}^{exp} M_{2}[C/x]. Applying the induction hypothesis gives s ⊕ s′ ⊢ M_{1}[C/x] ∼_{σ′}^{exp} M_{2}[C/x] which confirms that s ⊢ λx:σ.M_{1} ∼_{σ→σ′}^{can} λx:σ.M_{2}.

For (2) suppose that s ⊢ M_{1} ≃_{σ}^{exp} M_{2}. We must have s ⊢ M_{1} ⇓_{σ} (s_{1})C_{1} and s ⊢ M_{2} ⇓_{σ} (s_{2})C_{2} with s ⊕ (s_{1} ∪ s_{2}) ⊢ C_{1} ≃_{σ}^{can} C_{2}. By (1) this gives s ⊕ (s_{1} ∪ s_{2}) ⊢ C_{1} ∼_{σ}^{can} C_{2} and so s ⊢ M_{1} ∼_{σ}^{exp} M_{2} as required.

Finally, for (3) suppose that s, Γ ⊢ M_{1} ≃_{σ} M_{2} and C_{i} ∈ Can_{σ_{i}}(s ⊕ s′) for some s′ and i = 1, …, n. By Proposition 2.19 each s ⊢ C_{i} ≃_{σ_{i}} C_{i} and so s ⊕ s′ ⊢ M_{1}[C⃗/x⃗] ≃_{σ} M_{2}[C⃗/x⃗]. By (2) then s ⊕ s′ ⊢ M_{1}[C⃗/x⃗] ∼_{σ} M_{2}[C⃗/x⃗] and hence s, Γ ⊢ M_{1} ∼_{σ} M_{2} as desired.

Lemma 2.22 If s, Γ ⊢ M_{1} ∼_{σ} M_{2} then s, Γ ⊢ M_{1} ≃_{σ} M_{2}.

Proof We show each of the following:

1. s ⊢ C_{1} ∼_{σ}^{can} C_{2} ⟹ s ⊢ C_{1} ≃_{σ}^{can} C_{2}.

2. s ⊢ M_{1} ∼_{σ}^{exp} M_{2} ⟹ s ⊢ M_{1} ≃_{σ}^{exp} M_{2}.

3. s, Γ ⊢ M_{1} ∼_{σ} M_{2} ⟹ s, Γ ⊢ M_{2} ≃_{σ} M_{2}.

Again the first two are proved by mutual induction over the structure of σ. Implication (1) at ground types is immediate. Suppose now that s ⊢ λx:σ.M_{1} ∼_{σ→σ′}^{can} λx:σ.M_{2} and that we have some C_{1}, C_{2} ∈ Can_{σ}(s ⊕ s′) with s ⊕ s′ ⊢ C_{1} ≃_{σ}^{can} C_{2}. The definition of applicative equivalence at function types gives

s ⊕ s′ ⊢ M_{1}[C_{1}/x] ∼_{σ′}^{exp} M_{2}[C_{1}/x]

while Proposition 2.19 for s ⊕ s′, {x : σ} ⊢ M_{2} : σ′ gives

s ⊕ s′ ⊢ M_{2}[C_{1}/x] ≃_{σ′}^{exp} M_{2}[C_{2}/x]

which by Lemma 2.21 implies

s ⊕ s′ ⊢ M_{2}[C_{1}/x] ∼_{σ′}^{exp} M_{2}[C_{2}/x].

Now ∼_{σ′}^{exp} is transitive, so

s ⊕ s′ ⊢ M_{1}[C_{1}/x] ∼_{σ′}^{exp} M_{2}[C_{2}/x]

and the induction hypothesis gives s ⊕ s′ ⊢ M_{1}[C_{1}/x] ≃_{σ′}^{exp} M_{2}[C_{2}/x], from which we obtain s ⊢ λx:σ.M_{1} ≃_{σ→σ′}^{can} λx:σ.M_{2} as required.

For (2) suppose that s ⊢ M_{1} ∼_{σ}^{exp} M_{2}. We must have s ⊢ M_{1} ⇓_{σ} (s_{1})C_{1} and s ⊢ M_{2} ⇓_{σ} (s_{2})C_{2} with s⊕(s_{1} ∪ s_{2}) ⊢ C_{1} ∼_{σ}^{can} C_{2}. By (1) then s⊕(s_{1} ∪ s_{2}) ⊢ C_{1} ≃_{σ}^{can} C_{2} and so s ⊢ M_{1} ≃_{σ}^{exp} M_{2}.

Finally, for (3) suppose s, Γ ⊢ M_{1} ∼_{σ} M_{2} and that we have C_{ij} ∈ Can_{σ_{j}}(s ⊕ s′) with s ⊕ s′ ⊢ C_{1j} ≃_{σ_{j}} C_{2j} for j = 1, …, n and some s′. Then

s ⊕ s′ ⊢ M_{1}[C⃗_{1}/x⃗] ∼_{σ}^{exp} M_{2}[C⃗_{1}/x⃗]

and by Proposition 2.19, s, Γ ⊢ M_{2} ≃_{σ} M_{2} from which

s ⊕ s′ ⊢ M_{2}[C⃗_{1}/x⃗] ≃_{σ}^{exp} M_{2}[C⃗_{2}/x⃗],

giving

s ⊕ s′ ⊢ M_{2}[C⃗_{1}/x⃗] ∼_{σ}^{exp} M_{2}[C⃗_{2}/x⃗],

by Lemma 2.21. Transitivity of ∼_{σ}^{exp} gives

s ⊕ s′ ⊢ M_{1}[C⃗_{1}/x⃗] ∼_{σ}^{exp} M_{2}[C⃗_{2}/x⃗]

which by (2) implies s ⊕ s′ ⊢ M_{1}[C⃗_{1}/x⃗] ≃_{σ}^{exp} M_{2}[C⃗_{2}/x⃗]. Thus s, Γ ⊢ M_{1} ≃_{σ} M_{2} as required.

Theorem 2.23 Applicative and logical equivalence are the same relation; it is an equivalence, a congruence and implies contextual equivalence.

Proof We simply combine Lemma 2.21, Lemma 2.22, Lemma 2.15, Proposition 2.18 and Proposition 2.20.

Applicative equivalence verifies examples (2)–(9) of Section 5: these concern unused names, order of name generation, evaluation, reduction, rearrangement around reduction contexts and β_{v}-equivalence. It also confirms the equivalence AF_{p}F_{q} ≈_{ν→ν} F_{p+q} that represents addition in example (17). However it is unable to capture the notion of ‘private’ names, and does not prove examples (12) or (13).

The difficulty is that the definition of applicative equivalence at function types quantifies over every possible argument, and an external context may be unable to construct all of these. The refinements of logical equivalence described in Chapter 4 begin to tackle this problem.

Categorical Models

Consideration of the nu-calculus has so far been entirely operational; we now develop a denotational semantics for the language, using category theory. This provides abstract models for the behaviour of nu-calculus expressions, and further methods for reasoning about contextual equivalence. A particular feature is that we follow Moggi in using a categorical strong monad to encapsulate the notion of ‘computation’ [67].

This chapter falls into two parts. In the first three sections we describe a metalanguage, based on Moggi’s computational lambda-calculus [66, 68, 90]. This captures the general properties required for a model of the nu-calculus. In the last four sections we turn these into conditions for a categorical model, and give two specific examples. This two stage technique of

nu-calculus ⟶ computational metalanguage ⟶ category with strong monad

makes the construction simpler, and allows us to build more than one categorical model on the same foundations. Both parts are significant; the metalanguage serves as the internal language of the category, while the existence of categorical models proves the consistency of the metalanguage.

The most important feature of the metalanguage is that it distinguishes between values and computations; for the nu-calculus, a computation will create some names and then return a value. This separation makes explicit the order of computation, which in the operational semantics was only implicit. It also allows equational reasoning, with the reintroduction of β and η axioms at function types.

We give an interpretation of the nu-calculus in the metalanguage, and show that it respects the operational semantics. The translation is adequate, so we can use the metalanguage to reason about contextual equivalence; it is also fully abstract for expressions of ground type. Further, if two expressions of first-order type are applicatively equivalent, then their translations can be proved equal in the metalanguage.

Section 4 explains the conditions for a category to model the metalanguage, and hence the nu-calculus. The interpretation is in many ways quite standard, with all the usual machinery of products, exponentials and so forth; only the monad is affected by names and their equality test. All the results on reasoning in the metalanguage immediately carry over to the categorical setting. The final sections describe two particular models: the functor category Set^{I}, where I is the category of finite sets and injections, and the category BG of continuous G-sets, where G is a certain topological group.

Although these categories provide an adequate denotational semantics for the nucalculus, they are not fully abstract. We still cannot prove equivalences (12) or (13) of the last chapter, concerning private names. However the methods used here are quite general, and in the next chapter we shall see how more abstract models can be built on the same framework.

1 A Computational Metalanguage

The types of the metalanguage are given by:

A ::= Bool  booleans
| Name names
| A → A functions
| T A  computations.

There is a unary type constructor T: if A is a type, then elements of T A are computations of type A. In this particular metalanguage the difference between a value and a computation is that a computation may generate new names before returning a value. We shall use A, B and their variants to range over the types of the metalanguage.

The term forming operations of the metalanguage are as follows:

a :: = x  variable
| tt | ff  truth values
| cond(a, a, a) conditional
| eq(a, a)  compare names
| new  generate new name
| λx:A.a  function abstraction
| aa  function application
| [a]  value as trivial computation
| let x⇐a in a sequential computation.

There is an infinite supply of typed variables, where x : A indicates that variable x is of type A. Function abstraction λx:A.a binds the variable x in the term a, and sequential computation let x⇐e in e′ binds the variable x within the term e′. We implicitly identify terms up to α-conversion, which allows us to require substitution, written a[a′/x] and a[a_{1}/x_{1}, …, a_{n}/x_{n}], to be capture avoiding. A term is closed if it has no free variables; there is no possibility of free names. We shall generally denote terms by variants on a, b, c, and take variables from x, y, z. Terms of computation type are usually represented by variants of e, terms of function type by f, g and terms of type Name by n.

There are three forms of term involving computation. If a is a value, then [a] is the trivial computation which simply returns a. The sequential form let x⇐e in e′ carries out the computation e, binds the result to x and then computes e′. Both of these are standard constructions of the computational lambda-calculus. To them we add the constant new of type T Name which denotes the computation that generates a fresh name.

Type judgements of the metalanguage are of the form

Γ ⊢ a : A

\overline{Γ ⊢ x : A} (x : A ∈ Γ)  \overline{Γ ⊢ new : T Name}  _{\overline{Γ ⊢ tt : Bool}  \overline{Γ ⊢ ff : Bool}}

\frac{Γ ⊢ n, n′ : Name}{Γ ⊢ eq(n, n′) : Bool}  \frac{Γ ⊢ b : Bool  Γ ⊢ a, a′ : A}{Γ ⊢ cond(b, a, a′) : A}

\frac{Γ ⊢ a : A}{Γ ⊢ [a] : T A}  \frac{Γ, x : A ⊢ b : B}{Γ ⊢ λx:A.b : A → B}

\frac{Γ ⊢ e : T A  Γ, x : A ⊢ e′ : T A′}{Γ ⊢ let x⇐e in e′ : T A′}  \frac{Γ ⊢ f : A → B  Γ ⊢ a : A}{Γ ⊢ fa : B}

Figure 3.1: Rules for assigning types to terms of the metalanguage

which asserts that in the presence of Γ, term a has type A. Here Γ is a finite set of typed variables; unlike the nu-calculus, there is no set of free names. The rules for forming type judgements are given in Figure 3.1, where we abbreviate Γ ⊕ {x : A} by Γ, x : A and write Γ ⊢ a_{1}, …, a_{n} : A to indicate that all of the judgements Γ ⊢ a_{1} : A, …, Γ ⊢ a_{n} : A hold. From now on we shall consider only well-typed terms.

Lemma 3.1 If Γ ⊢ a: A holds then the type A is unique. Moreover, if the term a has free variables in Γ, then

Γ ⊢ a : A ⟺ Γ ⊕ Γ′ ⊢ a : A

for any Γ′.

Proof Both results follow by induction on the structure of a.

We reason about terms of the metalanguage with an equational logic of Horn clauses. This could be extended to a full evaluation logic with modalities [90], but we shall manage without this sophistication. If the type judgements Γ ⊢ a: A and Γ ⊢ a′ : A are valid then

Γ ⊢ a = a′ : A

is an equation in context Γ; we usually omit the type and write Γ ⊢ a = a′. A sequent is a judgement

Γ; Φ ⊢ ϕ

where Γ is a finite set of typed variables, Φ is a finite set of equations in context Γ and ϕ is a single equation in context Γ. We may omit Γ or Φ when empty, and write Φ, a = a′ for Φ ⊕ {a = a′ : A}. The free variables fv(Φ) of Φ are the free variables of its component terms.

Figures 3.2 and 3.3 detail the rules for deriving sequents. Figure 3.2 gives the usual rules for Horn clauses and equational logic, congruence rules for all the term forming operations and β, η axioms at function types. Figure 3.3 contains rules particular to this metalanguage. The rules for computations are those described by Moggi for any computational lambda-calculus, and include the (MONO) rule, that the operation [−] taking values to computations is an inclusion. The rules for boolean values and the comparison of names are straightforward; a derived property is that eq(−, −) is an equivalence relation.

40 CHAPTER 3. CATEGORICAL MODELS Horn clauses:

\overline{Γ; Φ ⊢ ϕ} (ϕ ∈ Φ) \frac{Γ; Φ ⊢ ϕ Γ; Ψ, ϕ ⊢ ψ}{Γ; Φ ∪ Ψ ⊢ ψ}

Equality:

\frac{Γ ⊢ a : A}{Γ ⊢ a = a} \frac{Γ ⊢ a, a′ : A}{Γ; a = a′ ⊢ a′ = a} \frac{Γ ⊢ a_{1}, a_{2}, a_{3} : A}{Γ; a_{1} = a_{2}, a_{2} = a_{3} ⊢ a_{1} = a_{3}}

Congruence:

\overline{Γ ⊢ x = x} (x : A ∈ Γ) \overline{Γ ⊢ new = new} \overline{Γ ⊢ tt = tt} \overline{Γ ⊢ ff = ff}

\frac{Γ ⊢ b, b′ : Bool Γ ⊢ a_{1}, a′_{1}, a_{2}, a′_{2} : A}{Γ; b = b′, a_{1} = a′_{1}, a_{2} = a′_{2} ⊢ cond(b, a_{1}, a_{2}) = cond(b′, a′_{1}, a′_{2})}

\frac{Γ ⊢ n_{1}, n′_{1}, n_{2}, n′_{2} : Name}{Γ; n_{1} = n′_{1}, n_{2} = n′_{2} ⊢ eq(n_{1}, n_{2}) = eq(n′_{1}, n′_{2})}

\frac{Γ ⊢ f, f′ : A → B Γ ⊢ a, a′ : A}{Γ; f = f′, a = a′ ⊢ fa = f′a′}

\frac{Γ ⊢ a, a′ : A}{Γ; a = a′ ⊢ [a] = [a′]}  \frac{Γ, x : A; Φ ⊢ b = b′ : B}{Γ; Φ ⊢ λx:A.b = λx:A.b′} (x ∉ fv(Φ))
\frac{Γ ⊢ e_{1}, e′_{1} : T A  Γ, x : A; Φ ⊢ e_{2} = e′_{2} : T B}{Γ; Φ, e_{1} = e′_{1} ⊢ let x⇐e_{1} in e_{2} = let x⇐e′_{1} in e′_{2}} (x ∉ fv(Φ))

Functions:

β \frac{Γ, x : A ⊢ b : B Γ ⊢ a : A}{Γ ⊢ (λx:A.b)a = b[a/x]} η \frac{Γ ⊢ f : A → B}{Γ ⊢ f = λx:A.fx}

Figure 3.2: Rules for equational reasoning in the metalanguage (I)

1. A COMPUTATIONAL METALANGUAGE 41 Computations:

\frac{Γ ⊢ e : T A}{Γ ⊢ let x⇐e in [x] = e}  (MONO) \frac{Γ ⊢ a, a′ : A}{Γ; [a] = [a′] ⊢ a = a′}

\frac{Γ ⊢ a : A Γ, x : A ⊢ e : T B}{Γ ⊢ let x⇐[a] in e = e[a/x]}

\frac{Γ ⊢ e : T A Γ, x : A ⊢ e′ : T A′ Γ, x′ : A′ ⊢ e′′ : T A′′}{Γ ⊢ let x′⇐(let x⇐e in e′) in e′′ = let x⇐e in (let x′⇐e′ in e′′)}

Booleans:

\frac{Γ; Φ, b = tt ⊢ ϕ Γ; Φ, b = ff ⊢ ϕ}{Γ; Φ ⊢ ϕ} \frac{Γ; Φ ⊢ tt = ff}{Γ; Φ ⊢ ϕ}
\frac{Γ ⊢ a, a′ : A}{Γ ⊢ cond(tt, a, a′) = a}  \frac{Γ ⊢ a, a′ : A}{Γ ⊢ cond(ff , a, a′) = a′}

Testing names:

\frac{Γ ⊢ n : Name}{Γ ⊢ eq(n, n) = tt}  \frac{Γ ⊢ n, n′ : Name}{Γ; eq(n, n′) = tt ⊢ n = n′}

Generating names:

(DROP)  \frac{Γ ⊢ e : T A}{Γ ⊢ e = let n⇐new in e} (n : Name ∉ Γ)
(SWAP) \frac{Γ, n, n′ : Name ⊢ e : T A}{Γ ⊢ let n⇐new in let n′⇐new in e = let n′⇐new in let n⇐new in e}
(FRESH) \frac{Γ ⊢ n : Name Γ, n′ : Name; Φ, eq(n, n′) = ff ⊢ e = e′}{Γ; Φ ⊢ let n′⇐new in e = let n′⇐new in e′}

Figure 3.3: Rules for equational reasoning in the metalanguage (II)

The final three rules describe the behaviour of the computation new, asserting that unused names are ignored, the order of generating names is irrelevant, and new names are distinct from all others. The choice of these particular rules is rather ad hoc; in their favour we argue that they are sufficient to carry through the interpretation of the nu-calculus, and that there are models to validate them. Stronger versions of the first two are

(DROP^{+})  \frac{Γ ⊢ e : T A  Γ ⊢ e′ : T A′}{Γ ⊢ e = let x⇐e′ in e} (x : A′ ∉ Γ)

(SWAP^{+}) \frac{Γ ⊢ e : T A  Γ ⊢ e′ : T A′  Γ, x : T A, x′ : T A′ ⊢ e′′ : T A′′}{Γ ⊢ let x⇐e in let x′⇐e′ in e′′ = let x′⇐e′ in let x⇐e in e′′} .

These say that any computation whose value is unused may be discarded and that all computations can be reordered. They are not essential to model the nu-calculus, and would be false in a metalanguage extended to handle store or exceptions, for example. Nevertheless, all the categorical models to follow satisfy them.

An equivalent formulation of the last rule (FRESH) is

(FRESH′)  \frac{Γ, b : Bool, n′ : Name ⊢ e : T A  Γ ⊢ n : Name}{Γ ⊢ let n′⇐new in e[eq(n, n′)/b] = let n′⇐new in e[ff /b]}.

The alternative candidate

\frac{Γ ⊢ n : Name}{Γ ⊢ let n′⇐new in [eq(n, n′)] = let n′⇐new in [ff ]}

can be derived, but appears to be strictly weaker. In particular it is not strong enough to complete the proof of Lemma 3.2 and hence Proposition 3.6, that the metalanguage correctly interprets the nu-calculus.

As it stands the rule (FRESH) only allows for comparison of a new name with one other. This is no restriction, as the following derived rule shows:

Lemma 3.2 For any finite set of terms {n_{1}, …, n_{k}} of type Name the rule

\frac{Γ ⊢ n_{1}, …, n_{k} : Name Γ, n : Name; Φ, eq(n_{1}, n) = ff , …, eq(n_{k}, n) = ff ⊢ e = e′}{Γ; Φ ⊢ let n⇐new in e = let n⇐new in e′}

is derivable.

Proof We proceed by induction on k. The case k = 0 follows from the congruence rules for new and let. The rule (FRESH) is the case k = 1. Suppose then that we have derived the rule for k and wish to prove the it for (k + 1). Simple equational reasoning gives

\frac{Γ, n : Name; Φ, eq(n_{1}, n) = ff , …, eq(n_{k+1}, n) = ff ⊢ e = e′}{Γ, n : Name; Φ, eq(n_{1}, n) = ff , …, eq(n_{k+1}, n) = ff ⊢ cond(eq(n_{k+1}, n), e, e′) = e}

and also

Γ, n : Name; Φ, eq(n_{1}, n) = ff , …, eq(n_{k}, n) = ff ,

eq(n_{k+1}, n) = tt ⊢ cond(eq(n_{k+1}, n), e, e′) = e

from which we can eliminate eq(n_{k+1}, n) and obtain

\frac{Γ, n : Name; Φ, eq(n_{1}, n) = ff , …, eq(n_{k+1}, n) = ff ⊢ e = e′}{Γ, n : Name; Φ, eq(n_{1}, n) = ff , …, eq(n_{k}, n) = ff ⊢ cond(eq(n_{k+1}, n), e, e′) = e}.

The induction hypothesis then provides the rule

\frac{Γ, n : Name; Φ, eq(n_{1}, n) = ff , …, eq(n_{k}, n) = ff ⊢ cond(eq(n_{k+1}, n), e, e′) = e}{Γ; Φ ⊢ let n⇐new in cond(eq(n_{k+1}, n), e, e′) = let n⇐new in e}.

It is straightforward that

Γ, n : Name; Φ, eq(n_{k+1}, n) = ff ⊢ cond(eq(n_{k+1}, n), e, e′) = e′

which by the (FRESH) rule gives

Γ; Φ ⊢ let n⇐new in cond(eq(n_{k+1}, n), e, e′) = let n⇐new in e′.

Combining all these we have

\frac{Γ, n : Name; Φ, eq(n_{1}, n) = ff , …, eq(n_{k+1}, n) = ff ⊢ e = e′}{Γ; Φ ⊢ let n⇐new in e = let n⇐new in e′}

as required, and the proof is complete.

The rule

\frac{Γ ⊢ n_{1}, …, n_{k} : Name Γ, b_{1}, …, b_{k} : Bool, n : Name ⊢ e : T A}{Γ ⊢ let n⇐new in e[eq(n_{1}, n)/b_{1}, …, eq(n_{k}, n)/b_{k}] = let n⇐new in e[ff /b_{1}, …, ff /b_{k}]}

extending (FRESH′) is also valid.

2 Interpreting the Nu-Calculus

Now that we have a metalanguage for reasoning about names and higher-order functions, we describe a suitable interpretation of the nu-calculus. This must be chosen to respect the operational semantics, in particular call-by-value function application and left-to-right evaluation order. We use an extension of Moggi’s call-by-value interpretation of the simply-typed lambda-calculus in the computational lambda-calculus [68]. The translation is correct with respect to the operational semantics of the nu-calculus, in both evaluation and reduction forms.

Types are translated from the nu-calculus to the metalanguage according to:

[[o]] = Bool
[[ν]] = Name
[[σ → σ′]] = [[σ]] → T [[σ′]].

Function types use the constructor T: the application of a function to a value may result in a computation, that is, the generation of new names.

There are two mutually defined schemes that translate nu-calculus expressions into terms of the metalanguage. Figure 3.4 describes |−| for expressions in canonical form and [[−]] for general expressions, name and variable contexts. The interpretation respects types and substitution of values; it also treats reduction expressions and contexts in a uniform way. The following results make this precise.

44 CHAPTER 3. CATEGORICAL MODELS Canonical forms:

|x| = x
|n| = n
|true| = tt
|false| = ff
|λx:σ.M| = λx:[[σ]].[[M]]

Expressions:

[[C]] = [|C|]
[[if B then M else M′]] = let b⇐[[B]] in cond(b, [[M]], [[M′]])
[[N = N′]] = let n⇐[[N]] in let n′⇐[[N′]] in [eq(n, n′)]
[[νn.M]] = let n⇐new in [[M]]
[[F M]] = let f⇐[[F]] in let m⇐[[M]] in fm

Contexts:

[[s, Γ]] = n_{1}, …, n_{k} : Name, x_{1} : [[σ_{1}]], …, x_{n} : [[σ_{n}]]
where s = {n_{1}, …, n_{k}}
Γ = {x_{1} : σ_{1}, …, x_{n} : σ_{n}}

Figure 3.4: Interpretation of the nu-calculus in the computational metalanguage Lemma 3.3 For any well-typed nu-calculus expression M, or expression C in canonical form:

s, Γ ⊢ M : σ ⟺ [[s, Γ]] ⊢ [[M]] : T [[σ]]
s, Γ ⊢ C : σ ⟺ [[s, Γ]] ⊢ |C| : [[σ]].

Proof By induction over the structure of the type judgement in the nu-calculus, using uniqueness of types in the metalanguage.

Lemma 3.4 If M ∈ Exp_{σ}(s, Γ ⊕ {x : σ}) and C ∈ Can_{σ}(s, Γ) then

[[s, Γ]] ⊢ [[M[C/x]]] = [[M]][|C|/x]

in the metalanguage.

Proof By induction on the structure of M, using only the fact that equality in the metalanguage is a congruence.

Lemma 3.5 If M ∈ Exp_{σ}(s, Γ) and s, Γ ⊢ E⟨−:σ⟩ : σ′ is a reduction expression then

[[s, Γ]] ⊢ [[E⟨M⟩]] = let m⇐[[M]] in [[E⟨m⟩]]

and for any reduction context s, Γ ⊢ R⟨−:σ⟩ : σ′,

[[s, Γ]] ⊢ [[R⟨M⟩]] = let m⇐[[M]] in [[R⟨m⟩]].

Proof Consider for example the reduction expression s, Γ ⊢ ⟨−⟩M : σ′, and suppose that F ∈ Exp_{σ→σ′}(s, Γ). Then, using the equalities of the computational lambda-calculus,

[[s, Γ]] ⊢ let f⇐[[F]] in [[fM]] = let f⇐[[F]] in let f′⇐[f] in let m⇐[[M]] in f′m
= let f⇐[[F]] in let m⇐[[M]] in fm
= [[F M]].

The other reduction expressions are similar. For the second result, we recall that a reduction context is a nested series of reduction expressions, and proceed by induction on the length of this series. Suppose that we already have the result for the reduction context s, Γ ⊢ R⟨−:σ⟩ : σ′, and that s, Γ ⊢ E⟨−:σ′⟩ : σ′′ is a reduction expression. Then we can reason:

[[s, Γ]] ⊢ [[E⟨R⟨M⟩⟩]] = let r⇐[[R⟨M⟩]] in [[E⟨r⟩]]
= let r⇐(let m⇐[[M]] in [[R⟨M⟩]]) in [[E⟨r⟩]]
= let m⇐[[M]] in let r⇐[[R⟨m⟩]] in [[E⟨r⟩]]
= let m⇐[[M]] in [[E⟨R⟨m⟩⟩]]

which is the result for the reduction context s, Γ ⊢ E⟨R⟨−:σ⟩⟩ : σ′′.

The interpretation of the nu-calculus in the metalanguage is correct with respect to its operational semantics: if s ⊢ M ⇓_{σ} (s′)C then the terms [[M]] and [[νs′.C]] can be proved equal in the metalanguage, under the assumption that all the names in s are distinct. A similar result holds for the reduction relation M →_{σ} M′. To make this formal we need two abbreviations:

(≠s) = {eq(n_{i}, n_{j}) = ff | 1 ≤ i < j ≤ k}

for the assertion that all the names in s = {n_{1}, …, n_{k}} are distinct, and

let s′⇐new^{⟶} in e = let n′_{1}⇐new in … let n′_{k′}⇐new in e

which is the expression that assigns new names to all of s′ = {n′_{1}, …, n′_{k′}} and then computes e. The ordering of names from s and s′ does not matter, up to provable equality in the metalanguage. A particular consequence of Lemma 3.2 is then the derived rule:

\frac{[[s ⊕ s′, Γ]]; (≠ s ⊕ s′) ⊢ e = e′ : T A}{[[s, Γ]]; (≠s) ⊢ let s′⇐new^{⟶} in e = let s′⇐new^{⟶} in e′} .

We can now demonstrate:

Proposition 3.6 (Correctness of Translation) If s ⊢ M ⇓_{σ} (s′)C is a valid evaluation judgement then

[[s]]; (≠s) ⊢ [[M]] = let s′⇐new^{⟶} in [[C]]

is provable in the metalanguage. Further, if M, M′ ∈ Exp_{σ}(s) and M →_{σ}^{∗} M′ is a valid reduction then

[[s]]; (≠s) ⊢ [[M]] = [[M′]]

can be proved in the metalanguage.

Proof By induction over the derivation of s ⊢ M ⇓_{σ} (s′)C or M →_{σ}^{∗} M′ respectively. We need to confirm that every rule of Figures 2.2 and 2.3 translates to a derivation that is provable in the metalanguage. We give some example cases:

• (LOCAL) The translation of the rule

\frac{s ⊕ \{n\} ⊢ M ⇓_{σ} (s_{1})C}{s ⊢ νn.M ⇓_{σ} (\{n\} ⊕ s_{1})C}

is

\frac{[[s]], n : Name; (≠ s ⊕ \{n\}) ⊢ [[M]] = let s_{1}⇐new^{⟶} in [[C]]}{[[s]]; (≠s) ⊢ let n⇐new in [[M]] = let n⇐new in let s_{1}⇐new^{⟶} in [[C]]}

which is an instance of the Lemma 3.2.

• (EQ2) This is the rule

\frac{s ⊢ N ⇓_{ν} (s_{1})n  s ⊕ s_{1} ⊢ N′ ⇓_{ν} (s_{2})n′}{s ⊢ (N = N′) ⇓_{o} (s_{1} ⊕ s_{2})false}  n, n′ distinct.

We combine

\frac{[[s ⊕ s_{1} ⊕ s_{2}]]; (≠ s ⊕ s_{1} ⊕ s_{2}) ⊢ [eq(n, n′)] = [ff ]}{[[s ⊕ s_{1}]]; (≠ s ⊕ s_{1}) ⊢ let s_{2}⇐new^{⟶} in [eq(n, n′)] = let s_{2}⇐new^{⟶} in [ff ]}

with

\frac{[[s ⊕ s_{1}]]; (≠ s ⊕ s_{1}) ⊢ [[N′]] = let s_{2}⇐new^{⟶} in [n′]}{[[s ⊕ s_{1}]]; (≠ s ⊕ s_{1}) ⊢ let a′⇐[[N′]] in [eq(n, a′)] = let s_{2}⇐new^{⟶} in [eq(n, n′)]}

and obtain [[s]]; (≠s) ⊢ let s_{1}⇐new^{⟶} in let a′⇐[[N′]] in [eq(n, a′)] = let (s_{1} ⊕ s_{2})⇐new^{⟶} in [ff ]. The addition of

\frac{[[s]]; (≠s) ⊢ [[N]] = let s_{1}⇐new^{⟶} in [n]}{[[s]]; (≠s) ⊢let a⇐[[N]] in let a′⇐[[N′]] in [eq(a, a′)] = let s_{1}⇐new^{⟶} in let a′⇐[[N′]] in [eq(n, a′)]}

gives the rule

\frac{[[s]]; (≠s) ⊢ [[N]] = let s_{1}⇐new^{⟶} in [n] [[s ⊕ s_{1}]]; (≠ s ⊕ s_{1}) ⊢ [[N′]] = let s_{2}⇐new^{⟶} in [n′]}{[[s]]; (≠s) ⊢ [[N = N′]] = let (s_{1} ⊕ s_{2})⇐new^{⟶} in [[false]]}

which as required is the translation of (EQ2).

• Application redex. Take the reduction

(λx:σ.M)C →_{σ′} M[C/x]

where C ∈ Can_{σ}(s) and M ∈ Exp_{σ′}(s, {x: σ}). We can reason in the metalanguage thus:

[[s]]; (≠s) ⊢ [[(λx:σ.M)C]] = let f⇐[λx:[[σ]].[[M]]] in let a⇐[|C|] in fa
= (λx:[[σ]].[[M]])|C|
= [[M]][|C|/x]
= [[M[C/x]]]

using the β rule and Lemma 3.4 on substitution.

• Reduction expressions. Consider the rule scheme

\frac{M →_{σ} M′}{E⟨M⟩ →_{σ′} E⟨M′⟩}

where E⟨−⟩ is one of the five forms of reduction expression. The premise translates to

[[s]]; (≠s) ⊢ [[M]] = [[M′]]

and we can use Lemma 3.5 to deduce

[[s]]; (≠s) ⊢ [[E⟨M⟩]] = let m⇐[[M]] in [[E⟨m⟩]]
= let m⇐[[M′]] in [[E⟨m⟩]]
= [[E⟨M′⟩]]

which is the interpretation in the metalanguage of the rule consequence. The other cases are all similar to these.

3 Reasoning in the Metalanguage

Proposition 3.6 above shows that the interpretation of the nu-calculus in the metalanguage is correct with respect to its operational semantics. A consequence of this is that we can use the metalanguage to reason about contextual equivalence; if two expressions of the nu-calculus are interpreted by terms that are provably equal in the metalanguage, then those expressions are contextually equivalent. Moreover, equational reasoning in the metalanguage is complete for contextual equivalence at ground types. It is also complete with respect to applicative equivalence at first-order types; if two expressions of firstorder type are applicatively equivalent, then their translations can be proved equal in the metalanguage.

These properties all rely the metalanguage being consistent: the equation ⊢ tt = ff is not provable. This is justified by the categorical models of Sections 5 and 7 where tt and ff are distinct.

The first result is that the metalanguage is suitable for reasoning about contextual equivalence:

Proposition 3.7 (Adequacy of Translation) Suppose that M_{1},M_{2} ∈ Exp_{σ}(s, Γ) and that we can derive

[[s, Γ]]; (≠s) ⊢ [[M_{1}]] = [[M_{2}]]

in the metalanguage. Then the expressions are contextually equivalent s, Γ ⊢ M_{1} ≈_{σ} M_{2}.

Proof Suppose that P ⟨⟨−⟩⟩ is some program context defined over s. By the compositionality of the translation [[−]], and Lemma 3.4 on the substitution of values,

[[s]]; (≠s) ⊢ [[P ⟨⟨(x⃗)M_{1}⟩⟩]] = [[P ⟨⟨(x⃗)M_{2}⟩⟩]].

From Theorem 2.4, evaluation in the nu-calculus is deterministic and terminating, so there are evaluation judgements

s ⊢ P ⟨⟨(x⃗)M_{i}⟩⟩ ⇓_{o} (s_{i})b_{i} i = 1, 2

for some name sets s_{1}, s_{2} and unique choice of booleans b_{1}, b_{2}. The correctness result above gives

[[s]]; (≠s) ⊢ [[P ⟨⟨(x⃗)M_{i}⟩⟩]] = let s_{i}⇐new^{⟶} in [|b_{i}|] i = 1, 2

and hence

[[s]]; (≠s) ⊢ let s_{1}⇐new^{⟶} in [|b_{1}|] = let s_{2}⇐new^{⟶} in [|b_{2}|].

Using the rules (DROP) and (MONO) we obtain

[[s]]; (≠s) ⊢ |b_{1}| = |b_{2}| : Bool

from which b_{1} = b_{2} and hence s, Γ ⊢ M_{1} ≈_{σ} M_{2} as required.

For closed boolean and name expressions the converse to this holds and any contextual equivalence can be proved in the metalanguage:

Theorem 3.8 (Completeness at Ground Types) If σ ∈ {o, ν} and M_{1}, M_{2} ∈ Exp_{σ}(s) then

s ⊢ M_{1} ≈_{σ} M_{2} ⟹ [[s]]; (≠s) ⊢ [[M_{1}]] = [[M_{2}]].

Proof We take each type in turn. If σ = o then there must be some b ∈ {true, false} such that

s ⊢ M_{i} ⇓_{o} (s_{i})b i = 1, 2

for suitable sets s_{1}, s_{2} of names. By Proposition 3.6 and repeated use of the (DROP) rule we can reason thus:

[[s]]; (≠s) ⊢ [[M_{1}]] = let s_{1}⇐new^{⟶} in [|b|]
= [|b|]
= let s_{2}⇐new^{⟶} in [|b|]
= [[M_{2}]]

which is the desired equality. If σ = ν then there are two possibilities:

• There is some name n ∈ s such that

s ⊢ M_{i} ⇓_{ν} (s_{i})n i = 1, 2

for suitable sets s_{1}, s_{2} of names. The reasoning is then exactly as in the boolean case.

• There is some name n ∉ s and name sets s_{1}, s_{2} such that

s ⊢ M_{i} ⇓_{ν} ({n} ⊕ s_{i})n i = 1, 2.

Correctness and (DROP) then give:

[[s]]; (≠s) ⊢ [[M_{1}]] = let n⇐new in let s_{1}⇐new^{⟶} in [n]
= new
= let n⇐new in let s_{2}⇐new^{⟶} in [n]
= [[M_{2}]].

In all cases, contextual equivalence implies provable equality in the metalogic.

Using the metalanguage to reason about contextual equivalence gives results broadly similar to the applicative equivalence of the last chapter. In particular we can confirm examples (2)–(9) and (17) from Section 5 of Chapter 2, but not examples (12) or (13) concerning private names. The correspondence with applicative equivalence can be made precise up to first-order types:

Theorem 3.9 If σ is a ground or first-order type of the nu-calculus, Γ is a set of variables of ground type, and M_{1}, M_{2} ∈ Exp_{σ}(s, Γ) for some set of names s, then

s, Γ ⊢ M_{1} ∼_{σ} M_{2} ⟹ [[s, Γ]]; (≠s) ⊢ [[M_{1}]] = [[M_{2}]].

Proof We show first that the result holds for closed expressions, by induction on the structure of the type σ. The proof follows the form of Definition 2.13 describing applicative equivalence; in particular, we distinguish the case when both expressions are in canonical form.

The base case is immediate:

s ⊢ C_{1} ∼_{σ}^{can} C_{2} ⟹ [[s]]; (≠s) ⊢ [[C_{1}]] = [[C_{2}]] σ ∈ {o, ν}.

Suppose that for some σ we have the result at ∼_{σ}^{can}, and wish to show it at ∼_{σ}^{exp}. Now

s ⊢ M_{1} ∼_{σ}^{exp} M_{2}  ⟺  ∃s_{1}, s_{2}, C_{1} ∈ Can_{σ}(s ⊕ s_{1}), C_{2} ∈ Can_{σ}(s ⊕ s_{2}) . s ⊢ M_{1} ⇓_{σ} (s_{1})C_{1} & s ⊢ M_{2} ⇓_{σ} (s_{2})C_{2} & s ⊕ (s_{1} ∪ s_{2}) ⊢ C_{1} ∼_{σ}^{can} C_{2}.

By hypothesis then

[[s ⊕ (s_{1} ∪ s_{2})]]; (≠ s ⊕ (s_{1} ∪ s_{2})) ⊢ [[C_{1}]] = [[C_{2}]]

and so

[[s]]; (≠s) ⊢ let (s_{1} ∪ s_{2})⇐new^{⟶} in [[C_{1}]] = let (s_{1} ∪ s_{2})⇐new^{⟶} in [[C_{2}]].

We can now reason as follows:

[[s]]; (≠s) ⊢ [[M_{1}]] = let s_{1}⇐new^{⟶} in [[C_{1}]]
= let (s_{1} ∪ s_{2})⇐new^{⟶} in [[C_{1}]]
= let (s_{1} ∪ s_{2})⇐new^{⟶} in [[C_{2}]]
= let s_{2}⇐new^{⟶} in [[C_{2}]]
= [[M_{2}]]

which is the required result.

For function types, we assume the result at ∼_{σ}^{exp} and consider ∼_{o→σ}^{can} and ∼_{ν→σ}^{can}. Firstly

s ⊢ λx:o.M_{1} ∼_{o→σ}^{can} λx:o.M_{2} ⟺ s ⊢ M_{1}[true/x] ∼_{σ}^{exp} M_{2}[true/x] & s ⊢ M_{1}[false/x] ∼_{σ}^{exp} M_{2}[false/x]

which by the induction hypothesis gives

[[s]], x:Bool; (≠s), x = tt ⊢ [[M_{1}]] = [[M_{2}]]
[[s]], x:Bool; (≠s), x = ff ⊢ [[M_{1}]] = [[M_{2}]]

from which we can deduce in turn

[[s]], x:Bool; (≠s) ⊢ [[M_{1}]] = [[M_{2}]]
[[s]]; (≠s) ⊢ λx:Bool.[[M_{1}]] = λx:Bool.[[M_{2}]]
[[s]]; (≠s) ⊢ [λx:[[o]].[[M_{1}]]] = [λx:[[o]].[[M_{2}]]]
[[s]]; (≠s) ⊢ [[λx:o.M_{1}]] = [[λx:o.M_{2}]]

the last of which is the desired result.

The proof for functions of type (ν → σ) is slightly tricky. We have

s ⊢ λx:ν.M_{1} ∼_{ν→σ}^{can} λx:ν.M_{2} ⟺ \begin{aligned}∀n ∈ s. s ⊢ M_{1}[n/x] & ∼_{σ}^{exp} & M_{2}[n/x] \\ & s ⊕ \{n\} ⊢ M_{1}[n/x] & ∼_{σ}^{exp} & M_{2}[n/x]. \end{aligned}

Suppose that s = {n_{1}, …, n_{k}}, then by the induction hypothesis we obtain all of

[[s]], x:Name; (≠s), eq(x, n_{1}) = ff , …, eq(x, n_{k−1}) = ff , eq(x, n_{k}) = ff ⊢ [[M_{1}]] = [[M_{2}]]
[[s]], x:Name; (≠s), eq(x, n_{1}) = ff , …, eq(x, n_{k−1}) = ff , eq(x, n_{k}) = tt ⊢ [[M_{1}]] = [[M_{2}]]
[[s]], x:Name; (≠s), eq(x, n_{1}) = ff , …, eq(x, n_{k−1}) = tt  ⊢ [[M_{1}]] = [[M_{2}]]
⋮
[[s]], x:Name; (≠s), eq(x, n_{1}) = tt  ⊢ [[M_{1}]] = [[M_{2}]].

Eliminating the eq(x, n_{i}) in turn gives

[[s]], x:Name; (≠s) ⊢ [[M_{1}]] = [[M_{2}]]

from which follows as before:

[[s]]; (≠s) ⊢ [[λx:ν.M_{1}]] = [[λx:ν.M_{2}]].

This completes the proof for closed expressions. For open expressions we proceed by induction on the number of free variables. From the definition

s, Γ ⊕ {x : σ} ⊢ M_{1} ∼_{σ′} M_{2} ⟺ s, Γ ⊢ λx:σ.M_{1} ∼_{σ→σ′} λx:σ.M_{2}.

As σ is a ground type, the induction hypothesis applies and we can reason:

[[s, Γ]]; (≠s) ⊢ [λx:[[σ]].[[M_{1}]]] = [λx:[[σ]].[[M_{2}]]]
(MONO)  [[s, Γ]]; (≠s) ⊢ λx:[[σ]].[[M_{1}]] = λx:[[σ]].[[M_{2}]]
(β)  [[s, Γ ⊕ {x : σ}]]; (≠s) ⊢ [[M_{1}]] = [[M_{2}]]

which is the desired result.

At second or higher orders this fails: applicative equivalence does not necessarily imply provable equality in the metalanguage. This is because terms in the metalanguage of function type do not necessarily denote expressions of the nu-calculus.

4 Constructing Categorical Models

It is standard that the simply-typed lambda-calculus can be modelled in any cartesian closed category, with objects for types and morphisms for terms [42]. Moggi extends this to a model of the computational lambda-calculus in any cartesian closed category equipped with a strong monad T [68]. We now specialise to the particular case of the computational metalanguage for names, as described above.

The method is that if a category C satisfies certain requirements then its internal language will include the metalanguage of Section 1. The translation of Section 2 then extends to a model of the nu-calculus in C that is sound with respect to the operational semantics.

If C is not degenerate then the translation is also adequate, and the category can be used to reason about contextual equivalence. This will be at least as powerful as the basic metalanguage. In particular reasoning in such C is complete for contextual equivalence at ground types, and for applicative equivalence up to first-order types. Of course the intention is that a suitable choice of category might prove more than the metalanguage alone.

A category C is suitable to model the metalanguage if the following conditions hold:

• It is cartesian closed: that is, it has finite limits and exponentials. In particular, we use products to interpret contexts, and exponentials for function types.

• It has a strong monad T, used to interpret the computation types. This can be described as a endofunctor T : C → C together with a unit natural transformation η: 1 → T and a lift operation taking a morphism f : A × B → T C to f^{∗}: A × T B → T C. The lift operation must be natural and satisfy

(η_{B} ∘ snd_{A,B})^{∗} = snd_{A,T B}
f^{∗} ∘ (id_{A} × η_{B}) = f
g^{∗} ∘ ⟨fst_{A,T B}, f^{∗}⟩ = (g^{∗} ∘ ⟨fst_{A,B}, f⟩)^{∗}

whenever f : A × B → T C and g : A × C → T D. These correspond precisely to the computation rules for let in Figure 3.3. The lift operation for a strong monad is a generalisation of that for a Kleisli triple, a particular presentation of an ordinary categorical monad. The generalisation is necessary to carry around contexts of letexpressions, as Moggi explains in [68, Remark 3.1].

A strong monad can also be presented as a monad (T, η, μ) together with natural maps t_{A,B} : A × T B → T (A × B). Here η: 1 → T and μ: T^{2} → T are the usual unit and multiplication natural transformations for a monad, and the strength t_{A,B} must satisfy certain equations. Moggi gives a detailed explanation of this, and further comments on the characterisation of strong monads in [68, Definition 3.2 et seq.].

• The monad T satisfies the mono requirement, that all η_{A} : A → T A are monic. This corresponds to the (MONO) rule of Figure 3.3.

• The coproduct 1 + 1 of the terminal object 1 with itself exists and is disjoint, meaning that the square

[figure: 1; 1 + 1; tt; 0; 1; ff]

is a pullback. Here tt and ff are the left and right inclusion maps. This is used to model the type of booleans; given that C is cartesian closed, we can define for each object A a morphism

cond_{A} = eval ∘ ([⌜fst_{A,A}⌝, ⌜snd_{A,A}⌝] × id_{A×A})
: (1 + 1) × (A × A) ⟶ A

to interpret the conditional.

• There is a distinguished object N, used to interpret the type of names. This must be decidable, which requires a morphism eq : N × N → 1 + 1 such that

[figure: 1; 1 + 1; tt; N; N × N; Δ; eq]

is a pullback square, where Δ is the diagonal map. The morphism eq interprets the equality test on names. In the internal language of C, the pullback condition corresponds to the rules for testing names in Figure 3.3.

• There is a distinguished morphism new : 1 → T N such that for any morphisms f : A → T B, g : A × N × N → T B and h : A × (1 + 1) × N × N → T B the following equations in the internal language of C are satisfied:

a : A ⊢ let n⇐new in f(a) = f(a)
a : A

⊢

let n⇐new in (let n′⇐new in g(a, n, n′))
= let n′⇐new in (let n⇐new in g(a, n, n′))

a : A, n : N ⊢ let n′⇐new in h(a, eq(n, n′), n, n′)

= let n′⇐new in h(a, ff , n, n′)

It is clear that these are simply the rules for generating names of Figure 3.3, with the alternate form of (FRESH) as given on page 42. We could express these equations by commutative diagrams asserting the equality of certain morphisms in C, but their essence becomes lost in a mass of variable manipulation.

The first two of these equations hold automatically if the monad T is respectively affine and commutative. These are notions due to Kock [39, 40]. A strong monad is affine if

fst_{T A,T B} = fst_{T A,B}^{∗} : T A × T B → T A

for all objects A, B; equivalently, if η_{1} : 1 → T 1 is an isomorphism. It is commutative if the two evident maps from T A × T B to T (A × B) are equal:

(η_{A×B}^{∗} ∘ tw_{T B,A})^{∗} ∘ T tw_{A,B} = ((η_{A×B} ∘ tw_{B,A})^{∗} ∘ tw_{T A,B})^{∗}.

Here tw_{X,Y} : X × Y → Y × X is the twist map. These stronger conditions correspond to the rules (DROP^{+}) and (SWAP^{+}) for the metalanguage.

In summary, a category C is suitable to model the metalanguage, and hence the nu-calculus, if the following hold:

• It is cartesian closed.

• It has a strong monad T satisfying the mono requirement.

• It has a disjoint coproduct 1 + 1.

• There is a distinguished decidable object N.

• There is a distinguished morphism new : 1 → T N satisfying certain equations.

Given such a category, the embedding of the metalanguage of Section 1 in its internal language is quite standard. Types are interpreted by objects of the category: Bool by 1 + 1, Name by N, function types by exponentials and computation types using the strong monad T. A context Γ = {x_{1} : A_{1}, …, x_{n} : A_{n}} is interpreted by the product Γ = A_{1} × ⋯ × A_{n}. A term in context is interpreted by a morphism:

Γ ⊢ a : A ⟼ a : Γ → A.

The derivation of such a morphism uses the rules on the right of Figure 3.5, which match those on the left for terms of the metalanguage. An equation in context is then interpreted by equality of morphisms:

Γ ⊢ a = a′ : A ⟼ a = a′ : Γ → A.

The sequent

Γ; a_{1} = a′_{1} : A_{1}, …, a_{n} = a′_{n} : A_{n} ⊢ a = a′ : A

is interpreted by equality of the morphisms

[figure: E; e; Γ; A; a; a′; a ∘ e = a′ ∘ e]

where e : E → Γ is the simultaneous equaliser of all the equations on the left hand side:

[figure: E; Γ; e; a_{1}; A_{1}; a′_{1}; a′_{n}; A_{n}; a′_{n}; ⋮]

Under this embedding the conditions on C correspond exactly to the rules of Figures 3.2 and 3.3 for reasoning in the metalanguage, so any equation provable in the metalanguage will also hold in C. As a result, any non-degenerate model demonstrates that the metalanguage is consistent.

The translation of Section 2 now becomes an interpretation of the nu-calculus in the category C. For each valid type assertion s, Γ ⊢ M : σ there is a morphism

[[M]] : N^{|s|} × [[Γ]] → T [[σ]] where [[Γ]] = ∏_{x_{i}:σ_{i}∈Γ}[[σ_{i}]].

For an expression C in canonical form this morphism factors through η : [[σ]] → T [[σ]] and there is

|C| : N^{|s|} × [[Γ]] → [[σ]] with [[C]] = η_{[[σ]]} ∘ |C|.

Here N^{|s|} is the object of |s|-tuples of names. We define the subobject (≠s) ↣ N^{|s|} of distinct |s|-tuples as the simultaneous equaliser of all the pairs

[figure: N^{|s|}; 1 + 1  1 ≤ i < j ≤ |s|.; eq ∘ ⟨π_{i}, π_{j}⟩; ff ∘!]

\overline{Γ ⊢ x : A} ⟼ \overline{π_{x} : Γ → A}  (x : A ∈ Γ)

Γ ⊢ new : T Name

⟼
\overline{Γ ⟶^{!} 1 ⟶^{new} T N}
\overline{Γ ⊢ tt : Bool} ⟼ \overline{Γ ⟶^{!} 1 ⟶^{tt} 1 + 1}

\overline{Γ ⊢ ff : Bool} ⟼ \overline{Γ ⟶^{!} 1 ⟶^{ff} 1 + 1}

\frac{Γ ⊢ n, n′ : Name}{Γ ⊢ eq(n, n′) : Bool} ⟼ \frac{n : Γ → N  n′ : Γ → N}{Γ ⟶^{⟨n,n′⟩} N × N ⟶^{eq} 1 + 1}

\frac{Γ ⊢ b : Bool  Γ ⊢ a, a′ : A}{Γ ⊢ cond(b, a, a′) : A} ⟼ \frac{b : Γ → 1 + 1 a : Γ → A a′ : Γ → A}{Γ ⟶^{⟨b,a,a′⟩} (1 + 1) × A × A ⟶^{cond_{A}} A}

\frac{Γ ⊢ a : A}{Γ ⊢ [a] : T A} ⟼ \frac{a : Γ → A}{Γ ⟶^{a} A ⟶^{η_{A}} T A}

\frac{Γ, x : A ⊢ b : B}{Γ ⊢ λx:A.b : A → B} ⟼ \frac{b : Γ × A → B}{curry(b) : Γ → B^{A}}

\frac{Γ ⊢ e : T A  Γ, x : A ⊢ e′ : T A′}{Γ ⊢ let x⇐e in e′ : T A′} ⟼ \frac{e : Γ → T A  e′ : Γ × A → T A′}{Γ ⟶^{⟨1,e⟩} Γ × T A ⟶^{(e′)^{∗}} T A′}

\frac{Γ ⊢ f : A → B  Γ ⊢ a : A}{Γ ⊢ fa : B} ⟼ \frac{f : Γ → B^{A}  a : Γ → A}{Γ ⟶^{⟨f,a⟩} B^{A} × A ⟶^{eval} B}

Figure 3.5: Rules for constructing morphisms to interpret terms of the metalanguage 56 CHAPTER 3. CATEGORICAL MODELS In the internal language, this corresponds to the conjunction

x_{1} : N, …, x_{|s|} : N ⊢ ⋀_{1≤i<j≤|s|}(eq(x_{i}, x_{j}) = ff ).

We then define the composite morphisms:

[[M]]_{Γ,≠s} = ((≠s) × [[Γ]] ↣ N^{|s|} × [[Γ]] ⟶^{[[M]]} T [[σ]]) M ∈ Exp_{σ}(s, Γ)
|C|_{Γ,≠s} = ((≠s) × [[Γ]] ↣ N^{|s|} × [[Γ]] ⟶^{|C|} [[σ]]) C ∈ Can_{σ}(s, Γ)
[[M]]_{≠s} = ((≠s) ↣ N^{|s|} ⟶^{[[M]]} T [[σ]])  M ∈ Exp_{σ}(s)
|C|_{≠s} = ((≠s) ↣ N^{|s|} ⟶^{|C|} [[σ]])  C ∈ Can_{σ}(s)

The results of Section 2 and 3 now carry over to the categorical model: Proposition 3.10 (Correctness) If s ⊢ M ⇓_{σ} (s′)C is a valid evaluation judgement then

[[M]]_{≠s} = [[νs′.C]]_{≠s}.

Further, if M, M′ ∈ Exp_{σ}(s) and M →_{σ}^{∗} M′ is a valid reduction then

[[M]]_{≠s} = [[M′]]_{≠s}

Proof Follows from Proposition 3.6. Proposition 3.11 (Adequacy) Suppose that the category C is non-degenerate in that the objects 0 and 1 are not isomorphic. Then for all M_{1}, M_{2} ∈ Exp_{σ}(s, Γ):

[[M_{1}]]_{Γ,≠s} = [[M_{2}]]_{Γ,≠s} ⟹ s, Γ ⊢ M_{1} ≈_{σ} M_{2}.

Proof Exactly as for Proposition 3.7. Theorem 3.12 (Completeness at Ground Types) If σ ∈ {o, ν} and M_{1}, M_{2} ∈ Exp_{σ}(s) then

s ⊢ M_{1} ≈_{σ} M_{2} ⟹ [[M_{1}]]_{≠s} = [[M_{2}]]_{≠s}.

Proof Follows from Theorem 3.8. Theorem 3.13 If σ is a ground or first order type of the nu-calculus, Γ is a set of variables of ground type, and M_{1}, M_{2} ∈ Exp_{σ}(s, Γ) for some set of names s, then

s, Γ ⊢ M_{1} ∼_{σ} M_{2} ⟹ [[M_{1}]]_{Γ,≠s} = [[M_{2}]]_{Γ,≠s}.

Proof Follows from Theorem 3.9.

5. THE FUNCTOR CATEGORY SET^{I} 57

So a non-degenerate categorical model can be used to prove contextual equivalences of the nu-calculus. The more that can be shown, the more abstract a model is. It is fully abstract if the result of Theorem 3.12 holds at all types σ. More modestly, a model may be fully abstract for some restricted set of types or expressions. As with reasoning in the metalanguage, any adequate categorical model will validate at least the equivalences (2)–(9) and (17) from Section 5 of Chapter 2.

In the case of languages like PCF, the difficulties in finding fully abstract models are to do with characterising sequentiality, and arise through ingenious use of non-termination. Because evaluation in the nu-calculus always terminates, the same problems do not occur. Full abstraction is still a hard problem, but for different reasons, to do with the privacy of names.

5 The Functor Category Set^{I}

In this section we describe our first example of a category suitable to model the nucalculus. Although it is not particularly abstract, the existence of the category does prove that the metalanguage is consistent, and justifies using it to reason about contextual equivalence (Proposition 3.7 above). The construction is based on Moggi’s model of dynamic allocation [67, §4.1.4]; it is related to the ‘possible worlds’ models of Oles, Reynolds, Tennent and O’Hearn [107, 88, 81], and also to Mitchell and Moggi’s Kripkestyle models [63, 64]. After describing the model, we show that reasoning in it has the same power as applicative equivalence, up to second-order types.

We take the category Set^{I} of functors and natural transformations between I, the category of finite sets and injections, and Set, the category of sets and functions. Objects of I represent stages of computation, that is, what names have been declared. We shall use s and variants to stand for objects of I, and the symbol ‘+’ for their disjoint union. For a functor A: I → Set, the set As is composed of values defined over the names in s. Morphisms in I and their images in Set correspond to name substitutions.

It is standard that this category is cartesian closed. Finite limits and colimits are taken pointwise; for example, the object of booleans 1 + 1 is the constant functor to a twoelement set. If A, B : I → Set are functors then their exponent is defined:

B^{A}s = Set^{I}(I(s, −) × A, B)  s, s′, s′′ ∈ I
B^{A}fps′′⟨i, a′′⟩ = ps′′⟨i ∘ f, a′′⟩  f : s → s′ p ∈ B^{A}s
i : s′ → s′′ a′′ ∈ As′′.

As well as this standard construction of exponentials, the particular choice of the index category I means that there is an equivalent and simpler way to compute the object part of the functor:

B^{A}s = Set^{I}(A(s + ), B(s + )).

So a function from A to B defined at stage s includes data on how it behaves at all later stages. Naturality places some bounds on what this behaviour can be.

The monad is a colimit of shape I. We use the functor + : I × I → I and take T to be the composition

[figure: Set^{I}; Set^{I×I}; Set^{+}; (Set^{I})^{I}; ≅; Set^{I}.; lim_{⟶}]

Explicitly, on objects it is the quotient

T As = {⟨s′, a′⟩ | s′ ∈ I, a′ ∈ A(s + s′)}/ ∼

where ⟨s_{1},a_{1}⟩ ∼ ⟨s_{2},a_{2}⟩ if and only if for some s_{0} there are injective functions f_{1} : s_{1} → s_{0} and f_{2} : s_{2} → s_{0} with A(id_{s} + f_{1})a_{1} = A(id_{s} + f_{2})a_{2} in A(s + s_{0}). We write [s′, a′] to represent the equivalence class of ⟨s′, a′⟩; this element is the computation ‘create the new names s′ and return value a′’, and quotienting by the relation ‘∼’ ensures that the (DROP) and (SWAP) rules for names hold true. For any constant functor C : I → Set the monad is the identity: T C = T C. This is the case for the interpretation of any nu-calculus type that does not involve ν, for example.

The remaining parts of the monad are as follows. If f : s → s′′ in I then the map T Af : T As → T As′′ is

T Af[s′, a′] = [s′, A(f + id_{s′})a′] a′ ∈ A(s + s′).

If p : A → B is a morphism in Set^{I}, then T p : T A → T B is the natural transformation with maps T ps : T As → T Bs given by

T ps[s′, a′] = [s, p(s + s′)a′].

The unit of the monad η_{A} : A → T A has components η_{A}s : As → T As for each s ∈ I given by

η_{A}sa = [0, a] a ∈ As.

A morphism q : A × B → T C lifts to become q^{∗} : A × T B → T C whose component maps q^{∗}s : As × T Bs → T Cs are

q^{∗}s⟨a, [s′, b′]⟩ = [s′ + s′′, c′′] b′ ∈ B(s + s′)

where

[s′′, c′′] = q(s + s′)⟨A(inl_{s,s′})a, b′⟩ c′′ ∈ C(s + s′ + s′′).

Finally, the multiplication μ : T^{2} → T and strength maps t_{A,B} : A × T B → T (A × B) are described by

\begin{aligned}μ_{A}s[s′, [s′′, a′′]] & = & [s′ + s′′, a′′] & a′′ ∈ A(s + s′ + s′′) \\ t_{A,B}s⟨a, [s′, b′]⟩ & = & [s′, ⟨A(inl_{s,s′})a, b′⟩]. \end{aligned}

These are all well defined regardless of choice of representative, and satisfy the appropriate equalities. In addition the monad T is both affine and commutative.

We take the object of names N to be the inclusion functor I ↪ Set. The morphism eq : N × N → 1 + 1 is simple equality at all stages, and new names are generated by

new s = [1, inr_{s,1}] ∈ T Ns

which satisfies the necessary equations. The obect T N is isomorphic to N + 1, thanks to the quotient in the definition of T.

6. PROPERTIES OF THE MODEL IN SET^{I} 59

Thus the category Set^{I} fulfils all the conditions of the previous section, and the interpretation described there gives morphisms:

[[M′]]_{Γ,≠s} : (≠s) × [[Γ]] → T [[σ]]  M′ ∈ Exp_{σ}(s, Γ)
|C′|_{Γ,≠s} : (≠s) × [[Γ]] → [[σ]]  C′ ∈ Can_{σ}(s, Γ)
[[M]]_{≠s} : (≠s) → T [[σ]]  M ∈ Exp_{σ}(s)
|C|_{≠s} : (≠s) → [[σ]]  C ∈ Can_{σ}(s)

It happens that the object (≠s) in Set^{I} is isomorphic to I(s, −), and we may apply the Yoneda Lemma to obtain elements:

\begin{aligned}[[M′]]_{Γ,≠s} & ∈ & (T [[σ]])^{[[Γ]]}s & |C′|_{Γ,≠s} & ∈ & [[σ]]^{[[Γ]]}s \\ [[M]]_{≠s} & ∈ & T [[σ]]s & |C|_{≠s} & ∈ & [[σ]]s. \end{aligned}

These are generally easier to work with, and the results of Section 4 still hold when stated in terms of elements rather than morphisms.

The interpretation of the nu-calculus in Set^{I} only makes use of pullback-preserving functors; in particular, if A preserves pullbacks, then so does T A. So we could instead consider just the full subcategory of pullback-preserving functors from I to Set. This category A is a topos; the topos of sheaves for the atomic topology on I^{op}, sometimes called the Schanuel topos. More details can be found in Mac Lane and Moerdijk [52, Chap. III; pp. 115, 155, 158]. The model in A is no more abstract than that in Set^{I}, but it does allow a better interpretation of Moggi’s higher-order metalanguage [69, Example 4.12]. Also, it is known that A is the classifying topos for the geometric theory of an infinite decidable object [52, Chap. VIII Ex. 9, Chap. X Ex. 6; pp. 468, 570]. This seems to fit with the abstract properties that we seek for an object of names, but the exact connection is unclear.

6 Properties of the Model in Set^{I}

Regarding the sample contextual equivalences of Chapter 2, Section 5, the category Set^{I} validates only those shown by any adequate model of the nu-calculus, and not examples (12) or (13) involving private names. This is because the model makes no provision to identify functions that differ only on arguments which no external context could supply. Applicative equivalence is of similar power, and the two theorems in this section make the connection quite precise.

Theorem 3.14 For all M_{1}, M_{2} ∈ Exp_{σ}(s, Γ), equality in Set^{I} implies applicative equivalence:

[[M_{1}]]_{Γ,≠s} = [[M_{2}]]_{Γ,≠s} ⟹ s, Γ ⊢ M_{1} ∼_{σ} M_{2}.

Proof We show first that the result holds for closed expressions:

|C_{1}|_{≠s} = |C_{2}|_{≠s} ⟹ s ⊢ C_{1} ∼_{σ}^{can} C_{2}  C_{1}, C_{2} ∈ Can_{σ}(s)
[[M_{1}]]_{≠s} = [[M_{2}]]_{≠s} ⟹ s ⊢ M_{1} ∼_{σ}^{exp} M_{2}  M_{1}, M_{2} ∈ Exp_{σ}(s).

The proof is by induction on the structure of the type σ, and follows the form of Definition 2.13 describing applicative equivalence. For boolean and name expressions in canonical form, the result is immediate. For lambda abstractions we recall the definition:

s ⊢ λx:σ.M_{1} ∼_{σ→σ′}^{can} λx:σ.M_{2} ⟺ \begin{matrix}∀s′, C ∈ Can_{σ}(s ⊕ s′) . \\ s ⊕ s′ ⊢ M_{1}[C/x] ∼_{σ′}^{exp} M_{2}[C/x]. \end{matrix}

Suppose then that |λx:σ.M_{1}|_{≠s} = |λx:σ.M_{2}|_{≠s} and C ∈ Can_{σ}(s ⊕ s′) for some set of names s′. We set

f_{i} = |λx:σ.M_{i}|_{≠s} ∈ [[σ → σ′]]s = Set^{I}(I(s, −) × [[σ]], T [[σ′]]) i = 1, 2

and use Lemma 3.4 on substitution to reason

[[M_{1}[C/x]]]_{≠s⊕s′} = f_{1}s′⟨inl_{s,s′}, |C|_{≠s⊕s′}⟩
= f_{2}s′⟨inl_{s,s′}, |C|_{≠s⊕s′}⟩
= [[M_{2}[C/x]]]_{≠s⊕s′}.

By the induction hypothesis we deduce that s ⊕ s′ ⊢ M_{1}[C/x] ∼_{σ′}^{exp} M_{2}[C/x] and so s ⊢ λx:σ.M_{1} ∼_{σ→σ′}^{can} λx:σ.M_{2} as required.

For general expressions, applicative equivalence is defined by

s ⊢ M_{1} ∼_{σ}^{exp} M_{2} ⟺ ∃s_{1}, s_{2}, C_{1} ∈ Can_{σ}(s ⊕ s_{1}), C_{2} ∈ Can_{σ}(s ⊕ s_{2}) . s ⊢ M_{1} ⇓_{σ} (s_{1})C_{1} & s ⊢ M_{2} ⇓_{σ} (s_{2})C_{2} & s ⊕ (s_{1} ∪ s_{2}) ⊢ C_{1} ∼_{σ}^{can} C_{2}.

Suppose then that M_{1}, M_{2} ∈ Exp_{σ}(s) with [[M_{1}]]_{≠s} = [[M_{2}]]_{≠s}. Theorem 2.4 tells us that there are evaluation judgements

s ⊢ M_{1} ⇓_{σ} (s_{1})C_{1} and s ⊢ M_{2} ⇓_{σ} (s_{2})C_{2},

from which

[[M_{i}]]_{≠s} = [[νs_{i}.C_{i}]]_{≠s} = [s_{i}, |C_{i}|_{≠s⊕s_{i}}] ∈ T [[σ]]s i = 1, 2.

But then [s_{1}, |C_{1}|_{≠s⊕s_{1}}] = [s_{2}, |C_{2}|_{≠s⊕s_{2}}], and the definition of the monad gives injections f_{i} : s_{i} ↣ s′ for i = 1, 2 such that

[[σ]](id_{s} + f_{1})|C_{1}|_{≠s⊕s_{1}} = [[σ]](id_{s} + f_{2})|C_{2}|_{≠s⊕s_{2}}.

With suitable relabelling we can assume that the f_{i} are inclusions and so

[[σ]](id_{s} + f_{i})|C_{i}|_{≠s⊕s_{i}} = |C_{i}|_{≠s⊕s′} i = 1, 2.

We then have |C_{1}|_{≠s⊕s′} = |C_{2}|_{≠s⊕s′}, and by the induction hypothesis s ⊕ s′ ⊢ C_{1} ∼_{σ}^{can} C_{2}. This is not quite as required, but Lemma 2.14 gives s ⊕ (s_{1} ∪ s_{2}) ⊢ C_{1} ∼_{σ}^{can} C_{2} and hence s ⊢ M_{1} ∼_{σ}^{exp} M_{2}.

This completes the proof for closed expressions; for open expressions we proceed by induction on the number of free variables. Suppose that M_{1}, M_{2} ∈ Exp_{σ}(s, Γ ⊕ {x : σ}) and

[[M_{1}]]_{Γ⊕{x:σ},≠s} = [[M_{2}]]_{Γ⊕{x:σ},≠s} = f ∈ ((T [[σ′]])^{[[Γ]]×[[σ]]}) s.

There is an isomorphism

(T [[σ′]])^{[[Γ]]×[[σ]]} ≅ ((T [[σ′]])^{[[σ]]})^{[[Γ]]} = [[σ → σ′]]^{[[Γ]]},

across which the element f can be reinterpreted:

f = |λx:σ.M_{i}|_{Γ,≠s} ∈ [[σ → σ′]]^{[[Γ]]}s i = 1, 2.

This leads to

[[λx:σ.M_{1}]]_{Γ,≠s} = [f] = [[λx:σ.M_{2}]]_{Γ,≠s}

and from the induction hypothesis s, Γ ⊢ λx:σ.M_{1} ∼_{σ→σ′} λx:σ.M_{2}. By Definition 2.13 this is equivalent to s, Γ ⊕ {x : σ} ⊢ M_{1} ∼_{σ′} M_{2}, which is the desired result.

Before we can show a result in the other direction, we need to know which elements in the model denote expressions of the nu-calculus.

Lemma 3.15 (Definability) Suppose that σ is a ground or first-order type of the nucalculus and s is some set of names. If a ∈ [[σ]]s and e ∈ T [[σ]]s, then there are expressions C ∈ Can_{σ}(s) and M ∈ Exp_{σ}(s) such that a = |C|_{≠s} and e = [[M]]_{≠s}.

Proof We begin by showing that the result for values implies that for computations. Suppose that e ∈ T [[σ]]s has a representative e = [s′, a′] where a′ ∈ [[σ]](s + s′). By assumption there is C ∈ Can_{σ}(s ⊕ s′) such that a′ = |C|_{≠s⊕s′}, and then

e = [s′, a′] = [[νs′.C]]_{≠s}

as required.

We now apply induction over the structure of the type σ. For elements of [[o]]s = 1 + 1 or [[ν]]s = s the result is immediate. Suppose that f ∈ [[o → σ]]s, that is

f ∈ Set^{I}(I(s, −) × (1 + 1), T [[σ]]).

Then f is entirely determined by the elements fs⟨id_{s}, tt⟩ and fs⟨id_{s}, ff ⟩ in T [[σ]]s. From the induction hypothesis these are definable, say by M_{1}, M_{2} ∈ Exp_{σ}(s), and then f is too:

f = | λb:o.if b then M_{1} else M_{2} |_{≠s}.

A value g ∈ [[ν → σ]]s = Set^{I}(I(s, −) × N, T [[σ]]) is similarly determined by

gs⟨id_{s}, n_{1}⟩, …, gs⟨id_{s}, n_{k}⟩ ∈ T [[σ]]s

and

g(s + 1)⟨inl_{s,1}, inr_{s,1}⟩ ∈ T [[σ]](s + 1),

where s = {n_{1}, …, n_{k}}. Suppose that these are definable using M_{1}, …, M_{k} ∈ Exp_{σ}(s) and M′ ∈ Exp_{σ}(s ⊕ {n}). Then g is definable too:

g = | λx:ν. if x = n_{1} then M_{1} else if x = n_{2} then M_{2} ⋮ else if x = n_{k} then M_{k} else M′[x/n] |_{≠s},

and the result holds for all first-order σ, by induction.

Theorem 3.16 Take σ to be a nu-calculus type of ground, first or second order, and Γ a set of variables of ground or first-order type. If M_{1}, M_{2} ∈ Exp_{σ}(s, Γ) for some set of names s, then

s, Γ ⊢ M_{1} ∼_{σ} M_{2} ⟹ [[M_{1}]]_{Γ,≠s} = [[M_{2}]]_{Γ,≠s}.

If σ is third-order then the implication fails.

Proof Exactly as for Theorem 3.9, with the addition of an induction step for expressions of second-order type in canonical form. Given that σ is a ground or first order type, and that the result holds for ∼_{σ′}^{exp}, we show that it is true for ∼_{σ→σ′}^{can}. Recall that

s ⊢ λx:σ.M_{1} ∼_{σ→σ′}^{can} λx:σ.M_{2} ⟺ \begin{matrix}∀s′, C ∈ Can_{σ}(s ⊕ s′) . \\ s ⊕ s′ ⊢ M_{1}[C/x] ∼_{σ′}^{exp} M_{2}[C/x] \end{matrix}

and let

f_{i} = |λx:σ.M_{i}|_{≠s} ∈ [[σ → σ′]]s = Set^{I}(I(s, −) × [[σ]], T [[σ′]]) i = 1, 2.

We seek to prove that f_{1} = f_{2}. To do this we must have, for all name sets s′, and all elements a ∈ [[σ]](s + s′), that

f_{1}s′⟨inl_{s,s′}, a⟩ = f_{2}s′⟨inl_{s,s′}, a⟩ ∈ T [[σ′]](s + s′).

From Lemma 3.15 there is some C ∈ Can_{σ}(s ⊕ s′) such that a = |C|_{≠s⊕s′}, and so

f_{i}s′⟨inl_{s,s′}, a⟩ = [[M_{i}[C/x]]]_{≠s⊕s′} i = 1, 2.

By assumption, s ⊕ s′ ⊢ M_{1}[C/x] ∼_{σ′}^{exp} M_{2}[C/x] and the induction hypothesis gives

[[M_{1}[C/x]]]_{≠s⊕s′} = [[M_{2}[C/x]]]_{≠s⊕s′},

from which f_{1} = f_{2} as required.

To show failure at third-order types we start with the first-order example (12) from Chapter 2, Section 5:

νn.λx:ν.(x = n) ≈_{ν→o} λx:ν.false .

The model in Set^{I} cannot confirm this equivalence; if we set g_{1} = νn.λx:ν.(x = n) and g_{2} = λx:ν.false, then their denotations are not equal:

[[g_{1}]] ≠ [[g_{2}]] ∈ T [[ν → o]]0.

For example, they are distinguished by the element

h ∈ ((T (1 + 1))^{N} → T (1 + 1)) 0
hs⟨0, g⟩ = \{ \begin{matrix}[tt] & if ∀i : s → s′, n ∈ s′ . gs′⟨i, n⟩ = [tt] \\ [ff ] & otherwise \end{matrix}

where 0 : 0 → s and g ∈ (T (1 + 1))^{N}s. This h tests whether a function g returns [tt] at every name, private or public. The fact that g_{1} ≈_{ν→o} g_{2} and yet

h^{∗}0⟨id_{0}, [[g_{1}]]⟩ = [ff ] ≠ [tt] = h^{∗}0⟨id_{0}, [[g_{2}]]⟩,

7. CONTINUOUS G-SETS 63

tells us that h cannot denote any expression of the nu-calculus. Proceeding to higher types, we consider

F_{1} = λf : (ν → o) → o . f(νn.λx:ν.(x = n))
F_{2} = λf : (ν → o) → o . f(λx:ν.false).

Now [[F_{1}]] and [[F_{2}]] are distinct in the model, differing at arguments such as h that can separate [[g_{1}]] from [[g_{2}]]. But, as argued above, none of these can be defined in the nu-calculus, so F_{1} and F_{2} are applicatively equivalent. We then have the desired counterexample:

⊢ F_{1} ∼_{((ν→o)→o)→o} F_{2} but [[F_{1}]] ≠ [[F_{2}]].

It also follows that F_{1} and F_{2} are contextually equivalent.

So applicative equivalence and equality in Set^{I} prove exactly the same contextual equivalences up to second-order types, and at higher types applicative equivalence is more powerful. However, this extra strength is quite illusory; to demonstrate it, we had to use the equivalence

νn.λx:ν.(x = n) ≈_{ν→o} λx:ν.false

which neither method is able to prove.

7 Continuous G-sets

Our next example of a category suitable to model the nu-calculus is in fact equivalent to the Schanuel topos A mentioned in Section 5. Mac Lane and Moerdijk explain the connection in [52, §III.9; pp. 150–155]. A consequence is that this model is no more abstract than the last; however it does provide a quite different presentation of the category.

We consider the topological group G of automorphisms of ℕ, the natural numbers, with topology inherited from the product topology on ℕ^{ℕ}. If k is a finite subset of ℕ then the stabiliser subgroups

G_{k} = Stab_{G}(k) ≤ G

form a basis of neighbourhoods of the identity. A continuous G-set A is a set equipped with an action

G × A → A
⟨g, a⟩ ↦ g · a

which is continuous when A is given the discrete topology [52, §I.1(xi)]. Equivalently, the stabilisers of elements of A must all be open. We write |A| for the set underlying A. A morphism of continuous G-sets is a function on the underlying sets which respects the action.

The category BG of continuous G-sets is cartesian closed [52, Chap. I Ex. 6]. Finite limits and colimits correspond to those in Set, while the exponential B^{A} is the set of all the functions from |A| to |B| whose stabilisers are open in G, according to the action

(g · p)a = g · (p(g^{−1} · a)) g ∈ G, p : A → B, a ∈ A.

The interpretation of a nu-calculus type is a set of values at all possible stages, with the group action describing how values change under name substitution. If k is a finite subset of ℕ and A an object of BG, then we define

A_{k} = Fix_{A}(G_{k}) ⊆ A,

those elements of A which use only the names in k. For any a ∈ A the smallest k ⊆ ℕ such that a ∈ A_{k} is the support of a, the names which it actually needs. The condition that a G-set be continuous is equivalent to requiring every element to have finite support.

To interpret the ground types, the object of booleans 1 + 1 is the two-element set with trivial G-action, and the object of names N is ℕ with the evident G-action. The morphism eq : N × N → 1 + 1 is just the equality test on ℕ.

For a continuous G-set A, to construct the object T A we must make some preliminary definitions. If f : ℕ ↣ ℕ is an injection, then it induces a map f^{A} : |A| → |A| as follows: for a ∈ A, take any finite k ⊆ ℕ such that a ∈ A_{k}, choose g ∈ G with g|_{k} = f|_{k} and define f^{A}a = g · a. This is well defined: suppose that a ∈ A_{k′} too, and g′ ∈ G with g′|_{k′} = f|_{k′}. Then a ∈ A_{l} where l = k ∩ k′, also g|_{l} = g′|_{l} = f|_{l} and so (g^{−1}g′)|_{l} = id|_{l}, that is g^{−1}g′ ∈ G_{l}. Thus

g · a = g · ((g^{−1}g′) · a) = g′ · a

and the choice of k and g does not matter.

There is an alternative action of G on the destination |A| which makes this induced map a morphism in BG. For g ∈ G, we define f^{∗}g ∈ G by

(f^{∗}g)n = \{ \begin{matrix}n & if n ∉ Im(f) \\ f(g(f^{−1}n)) & if n ∈ Im(f). \end{matrix}

In particular (f^{∗}g) ∘ f = f ∘ g. We take fA to be the G-set with underlying set |A| and action

g ·_{fA} a = (f^{∗}g) ·_{A} a.

Then f^{A} : A → fA is a morphism in BG, and every commuting trangle of injections

[figure: ℕ; ℕ; f; f′; ℕ; h]

induces a commuting triangle in BG

[figure: A; fA; f^{A}; f^{′A}; f′A; h^{fA}]

by the action of f, f′ and h on the underlying set |A|.

The object T A is the colimit of the diagram comprising all such triangles from A. That is, we consider in turn the one object category N of ℕ and all injections into itself, the coslice category N \ℕ, the diagram this induces in BG\A and its colimit η_{A}: A → T A. In fact the injection f : ℕ ↣ ℕ induces an endofunctor f_{BG} : BG → BG, and the commuting triangle induces one of natural transformations between endofunctors:

[figure: id_{BG}; f_{BG}; f; f′; f′_{BG}; h].

The colimit of all such triangles is the endofunctor T : BG → BG.

We could use a much smaller diagram for the colimit. For example, we might take for f only injections of the form i ↦ i + t, and for h all morphisms mediating between these. Or for f just the injection i ↦ 2i and for h all maps that permute the odd numbers and fix the even numbers. Both of these give countable diagrams with the same colimit as before.

We represent elements of T A as [f, a] where f : ℕ ↣ ℕ is an injection and a ∈ fA. The natural transformations that make T a strong monad are:

\begin{matrix}η_{A} : A & → & T A \\ a & ↦ & [id_{ℕ}, a] \end{matrix}  \begin{matrix}μ_{A} : T^{2}A & → & T A \\ [f, [f′, a]] & ↦ & [f′ ∘ f, a] \end{matrix}
t_{A,B} : A × T B → T (A × B)
⟨a, [f, b]⟩ ↦ [f, ⟨f^{A}a, b⟩]

If p : A × B → T C is a morphism in BG then its lift p^{∗} : A × T B → T C is given by

p^{∗}⟨a, [f, b]⟩ = [f′ ∘ f, c] where p⟨f^{A}a, b⟩ = [f′, c].

For any G-set A with trivial G-action, the monad is the identity: T A = A. This happens with the interpretation of any nu-calculus type that does not use ν. The following are more interesting examples:

T N = N + 1  new = inr : 1 → N + 1
T (N × N) = ((N + 1) × (N + 1)) + 1
T (N → T (1 + 1)) = ((N + N) → (1 + 1))/ ∼
T (N → T N) = ((N + N) → (N + N + 1))/ ∼

For T (N × N) the action of G is on both copies of N at once. In the last two cases, the relation ‘∼’ quotients by the action of G on the second N in each (N + N), while the actual action of G is on the first.

Now that the foundations are laid, the method of Section 4 constructs a model for the nu-calculus, with a continuous G-set [[σ]] for each type σ, and morphisms for expressions. Conveniently, morphisms (≠s) → A in BG are in bijection with the elements of |A|, given some ordering on s, so expressions are also interpreted by elements:

[[M′]]_{Γ,≠s} ∈ (T [[σ]])^{[[Γ]]}  M′ ∈ Exp_{σ}(s, Γ)
|C′|_{Γ,≠s} ∈ [[σ]]^{[[Γ]]}  C′ ∈ Can_{σ}(s, Γ)
[[M]]_{≠s} ∈ T [[σ]]  M ∈ Exp_{σ}(s)
|C|_{≠s} ∈ [[σ]]  C ∈ Can_{σ}(s).

All the results of Sections 4 and 6 carry across to this model in BG: it correctly interprets the operational semantics; it is adequate for reasoning about contextual equivalence, with completeness at ground types; it validates examples (2)–(9) and (17) of Chapter 2, Section 5; and it agrees with applicative equivalence up to second order, but is weaker at higher types.

Logical Relations

The previous two chapters have provided various methods, both operational and denotational, for proving that two expressions of the nu-calculus are contextually equivalent. These are enough to confirm most of the example equivalences given in Section 5 of Chapter 2. Two however remain:

12.  νn.λx:ν.(x = n) ≈_{ν→o} λx:ν.false
13.  νn.νn′.λf:ν→o.(fn = fn′) ≈_{(ν→o)→o} λf:ν→o.true .

Both of these equivalences rely on local names remaining private; for example in (12) the function (λx:ν.(x = n)) would return the answer true, if applied to the name n, but no external context can detect this. Similarly in (13) no externally produced function can distinguish the private names n and n′.

In this chapter we develop methods that can prove both of these equivalences, by identifying the different uses an expression may make of its local names. We show that these methods are strong enough to prove all contextual equivalences between expressions of first-order type, and construct a categorical model that is fully abstract at ground and first-order types.

The techniques that can do this all use some kind of logical relation. We encountered these earlier, in the context of Definition 2.16 of logical equivalence. The basic idea is to construct (binary) relations between nu-calculus expressions by induction on the structure of their type, with functions related if they take related arguments to related results. How successful this is depends on careful choice of the relations used at ground types, and the treatment of expressions not in canonical form.

Section 1 describes an operational form of logical relations for the nu-calculus, and shows that these can be used to prove contextual equivalences, in particular example (12) above. A significant intermediate step is the extension of contextual equivalence to contextual relations between nu-calculus expressions. Section 2 gives a proof that the method of logical relations is complete for first-order types; this is probably the most powerful result of the thesis.

Sections 3, 4 and 5 develop a denotational analogue of this work. This uses the notion of a category with relations, and extends the usual categorical idea of naturality with parametricity, where relations too must be preserved and respected. The result is a category P, based on the functor category Set^{I} of Chapter 3, but incorporating a relational structure. We prove various results connecting this with operational logical relations, and show that P provides a model of the nu-calculus that is fully abstract up to first-order function types.

The final section tackles the remaining equivalence (13), between two functions of second-order type. This is not validated by ordinary logical relations, and we construct more sophisticated predicated logical relations which provide an even finer description of how expressions use their local names. While this successfully proves equivalence (13), it is a technique very much targeted at this one example, and no completeness result is proved. There are however some possibilities for further generalisation, which may yet lead to a fully abstract categorical model for the nu-calculus.

1 Operational Logical Relations

This section describes a system of binary logical relations between nu-calculus expressions, based on their operational behaviour. These take a similar form to the logical equivalence of Chapter 2, Section 7, but are extended to allow relations other than the identity at ground types. We show that they have certain good properties, and in particular can be used to demonstrate contextual equivalence. This then gives a proof of the problematic example (12) involving two first-order functions with private names.

We begin by identifying a certain kind of relation between sets of names:

Definition 4.1 (Spans) If s_{1} and s_{2} are sets of names, then a span, or partial bijection R : s_{1} ⇌ s_{2} is an injective partial map from s_{1} to s_{2}. That is, the graph R ⊆ s_{1} × s_{2} satisfies

n_{1} R n_{2} & n′_{1} R n′_{2} ⟹ ( n_{1} = n′_{1} ⟺ n_{2} = n′_{2} ).

A span can also be represented as a pair of injections s_{1} ↢ R ↣ s_{2}.

If R′ : s′_{1} ⇌ s′_{2} is another span, with s′_{1} and s′_{2} disjoint from s_{1} and s_{2} respectively, then the disjoint union of R and R′ is also a span:

R ⊕ R′ : s_{1} ⊕ s′_{1} ⇌ s_{2} ⊕ s′_{2}.

The identity span id_{s} : s ⇌ s has

n id_{s} n′ ⟺ n = n′.

The domain and codomain of definition for R : s_{1} ⇌ s_{2} are defined by:

dom(R) = { n_{1} ∈ s_{1} | ∃n_{2} ∈ s_{2} . n_{1} R n_{2} }
cod(R) = { n_{2} ∈ s_{2} | ∃n_{1} ∈ s_{1} . n_{1} R n_{2} }.

We generally represent spans by variants of R and S.

The intuition behind spans is that they should capture the use that nu-calculus expressions make of public and private names. So if R : s_{1} ⇌ s_{2}, then the bijection between dom(R) ⊆ s_{1} and cod(R) ⊆ s_{2} represents matching use of ‘visible’ names, while the remaining elements not in the graph of R are ‘unseen’ names. In this spirit, Definition 2.16 of logical equivalence now extends to a method that takes a span on names to a set of relations between expressions of all types:

Definition 4.2 (Logical Relations) If R : s_{1} ⇌ s_{2} is a span then the relations

R_{σ}^{can} ⊆ Can_{σ}(s_{1}) × Can_{σ}(s_{2})
R_{σ}^{exp} ⊆ Exp_{σ}(s_{1}) × Exp_{σ}(s_{2})

are defined by induction over the structure of the type σ, according to:

b_{1} R_{o}^{can} b_{2} ⟺ b_{1} = b_{2}
n_{1} R_{ν}^{can} n_{2} ⟺ n_{1} R n_{2}
(λx:σ.M_{1}) R_{σ→σ′}^{can} (λx:σ.M_{2}) ⟺
∀R′ : s′_{1} ⇌ s′_{2}, C_{1} ∈ Can_{σ}(s_{1} ⊕ s′_{1}), C_{2} ∈ Can_{σ}(s_{2} ⊕ s′_{2}) .
C_{1} (R ⊕ R′)_{σ}^{can} C_{2} ⟹ M_{1}[C_{1}/x] (R ⊕ R′)_{σ′}^{exp} M_{2}[C_{2}/x]
M_{1} R_{σ}^{exp} M_{2} ⟺
∃R′ : s′_{1} ⇌ s′_{2}, C_{1} ∈ Can_{σ}(s_{1} ⊕ s′_{1}), C_{2} ∈ Can_{σ}(s_{2} ⊕ s′_{2}) .
s_{1} ⊢ M_{1} ⇓_{σ} (s′_{1})C_{1} & s_{2} ⊢ M_{2} ⇓_{σ} (s′_{2})C_{2} & C_{1} (R ⊕ R′)_{σ}^{can} C_{2}.

The relations R_{σ}^{can} and R_{σ}^{exp} coincide on canonical forms, and we may write them as R_{σ} indiscriminately. We can extend the relations to open expressions: if M_{1} ∈ Exp_{σ}(s_{1}, Γ) and M_{2} ∈ Exp_{σ}(s_{2}, Γ) where Γ = {x_{1} : σ_{1}, …, x_{n} : σ_{n}} then define

Γ ⊢ M_{1} R_{σ} M_{2} ⟺ ∀R′ : s′_{1} ⇌ s′_{2}, C_{ij} ∈ Can_{σ_{j}}(s_{i} ⊕ s′_{i}) i = 1, 2 j = 1, …, n . ( &_{j=1}^{n} . C_{1j} (R ⊕ R′)_{σ_{j}}^{can} C_{2j} ) ⟹ M_{1}[C⃗_{1}/x⃗] (R ⊕ R′)_{σ}^{exp} M_{2}[C⃗_{2}/x⃗].

We use the symbol ‘¬’ to negate relations; so Γ ⊢ M_{1} ¬ R_{σ} M_{2} holds if and only if Γ ⊢ M_{1} R_{σ} M_{2} does not.

Lemma 4.3 If R : s_{1} ⇌ s_{2} and M_{1} ∈ Exp_{σ}(s_{1}, Γ), M_{2} ∈ Exp_{σ}(s_{2}, Γ) then

Γ ⊢ M_{1} R_{σ} M_{2} ⟺ Γ ⊕ Γ′ ⊢ M_{1} (R ⊕ R′)_{σ} M_{2}

for any Γ′ and R′ : s′_{1} ⇌ s′_{2}.

Proof The result for closed expressions is shown by induction on the structure of the type σ, and the general result follows. A mild complication is the need to prove that there are some related expressions at every type:

\begin{matrix}∀σ. ∀R : s_{1} ⇌ s_{2} . ∃R′ : s′_{1} ⇌ s′_{2} , \\ C_{1} ∈ Can_{σ}(s_{1} ⊕ s′_{1}), C_{2} ∈ Can_{σ}(s_{2} ⊕ s′_{2}) . C_{1} (R ⊕ R′)_{σ} C_{2}, \end{matrix}

which can also be done by induction over types.

Lemma 4.4 Logical relations are respected by all the rules for forming expressions of the nu-calculus.

Proof It is straightforward to show from the definition of logical relations that they are preserved by each of the expression-forming rules in Figure 2.1.

This last result explains why the choice of relations at ground types is restricted to the identity for booleans and partial bijections for names; more general relations would not be preserved by conditionals and the equality test on names.

The definition of the relation at function types involves quantification over all further spans. This is because functions may be applied to arguments that use additional names; two functions are related only if they take related arguments to related results at all possible later stages of computation.

The use of existential quantification in the definition of R_{σ}^{exp} is crucial: two expressions are related if there is some way to span their locally-defined names, such that the computed values are related. This gives an essential flexibility to how expressions may use their local names. There is here a similarity to Plotkin and Abadi’s work on relational parametricity for polymorphism in System F, and their definition of relations between terms of existential type [97]. There, two terms are related if there is some suitable way to relate their hidden types such that their values are related.

Note that the logical relations for closed expressions of ground type are comparatively straightforward:

• B_{1} R_{o} B_{2} if both evaluate to true, or both to false.

• N_{1} R_{ν} B_{2} if they evaluate as s_{1} ⊢ N_{1} ⇓_{ν} (s′_{1})n_{1} and s_{2} ⊢ N_{2} ⇓_{ν} (s′_{2})n_{2} with either n_{1} R n_{2}, or n_{1} ∈ s′_{1} and n_{2} ∈ s′_{2}.

Extension to logical relations of other arities seems possible, though it is not clear that it would be helpful (but see Abadi and Plotkin [2] on nullary and unary relations for System F).

Before we can state useful results for logical relations, we must define some other families of relations. These are also based on spans, extending syntactic identity and contextual equivalence respectively.

Definition 4.5 (Syntactic Relations) For any span R : s_{1} ⇌ s_{2} the relation

R_{σ}^{syn} ⊆ Exp_{σ}(s_{1}, Γ) × Exp_{σ}(s_{2}, Γ)

is defined by

Γ ⊢ M_{1} R_{σ}^{syn} M_{2} ⟺ M_{1} ∈ Exp_{σ}(dom(R), Γ) & M_{2} ∈ Exp_{σ}(cod(R), Γ) & M_{2} = M_{1}[n_{2}/n_{1} | n_{1} R n_{2}].

When this holds we say that M_{1} and M_{2} are syntactically R-related. In particular, (id_{s})_{σ}^{syn} is syntactic identity.

Definition 4.6 (Contextual Relations) For any span R : s_{1} ⇌ s_{2} the relation

R_{σ}^{cxt} ⊆ Exp_{σ}(s_{1}, Γ) × Exp_{σ}(s_{2}, Γ)

is to hold between expressions that behave similarly in all syntactically R-related contexts. So the expressions M_{1} and M_{2} are contextually R-related if

P_{1}⟨⟨−⟩⟩ R_{τ}^{syn} P_{2}⟨⟨−⟩⟩ ⟹ P_{1}⟨⟨(Γ)M_{1}⟩⟩ R_{τ} P_{2}⟨⟨(Γ)M_{2}⟩⟩

where P_{1}⟨⟨−⟩⟩ and P_{2}⟨⟨−⟩⟩ are suitable closed contexts of some type τ ∈ {o, ν}. In the light of the Context Lemma (Theorem 2.8), we actually define the relation using only argument contexts:

Γ ⊢ M_{1} R_{σ}^{cxt} M_{2} ⟺
∀R′ : s′_{1} ⇌ s′_{2}, τ ∈ {o, ν},
λx:σ.T_{i} ∈ Can_{σ→τ} (s_{i} ⊕ s′_{i}), C_{ij} ∈ Can_{σ_{j}}(s_{i} ⊕ s′_{i}) i = 1, 2 j = 1, …, n .
( &_{j=1}^{n} . C_{1j} (R ⊕ R′)_{σ_{j}}^{syn} C_{2j} ) & (λx:σ.T_{1}) (R ⊕ R′)_{σ→τ}^{syn} (λx:σ.T_{2})
⟹ (λx:σ.T_{1})M_{1}[C⃗_{1}/x⃗] (R ⊕ R′)_{τ} (λx:σ.T_{2})M_{2}[C⃗_{2}/x⃗].

So two expressions are contextually related if they agree under all syntactically related instantiations and test functions.

This definition is rather more sophisticated than that for contextual equivalence, with contexts of name as well as boolean type, and a logical relation (R ⊕ R′)_{τ} on the right hand side. Nevertheless it does specialise to give:

Γ ⊢ M_{1} (id_{s})_{σ}^{cxt} M_{2} ⟺ s, Γ ⊢ M_{1} ≈_{σ} M_{2}.

With these definitions we can extend some of the results of Chapter 2 on logical equivalence to ones about logical relations. We have that syntactically related expressions are logically related, and logically related ones are contextually related:

Proposition 4.7 If Γ ⊢ M_{1} R_{σ}^{syn} M_{2} then Γ ⊢ M_{1} R_{σ} M_{2}. In particular the relation (id_{s})_{σ} is reflexive: Γ ⊢ M (id_{s})_{σ} M for any M ∈ Exp_{σ}(s, Γ).

Proof From the definition of syntactic equivalence, M_{1} and M_{2} have the same structure, and induction over this using Lemma 4.4 shows that they are logically related.

Proposition 4.8 If Γ ⊢ M_{1} R_{σ} M_{2} then Γ ⊢ M_{1} R_{σ}^{cxt} M_{2}. In particular (id_{s})-related expressions are contextually equivalent:

Γ ⊢ M_{1} (id_{s})_{σ} M_{2} ⟹ s, Γ ⊢ M_{1} ≈_{σ} M_{2}.

Proof By Proposition 4.7, any syntactically related test functions and instantiations of Γ are logically related. The result then follows from the definitions of contextual and logical relations.

The following results show that the power of logical relations includes that of applicative equivalence:

Theorem 4.9 If R : s_{1} ⇌ s_{2} with M_{1} ∈ Exp_{σ}(s_{1}, Γ) and M_{2}, M_{3} ∈ Exp_{σ}(s_{2}, Γ) then

Γ ⊢ M_{1} R_{σ} M_{2} & s_{2}, Γ ⊢ M_{2} ∼_{σ} M_{3} ⟹ Γ ⊢ M_{1} R_{σ} M_{3}.

Proof We show each of the following:

1. C_{1} R_{σ}^{can} C_{2} & s_{2} ⊢ C_{2} ∼_{σ}^{can} C_{3} ⟹ C_{1} R_{σ}^{can} C_{3}.

2. M_{1} R_{σ}^{exp} M_{2} & s_{2} ⊢ M_{2} ∼_{σ}^{exp} M_{3} ⟹ M_{1} R_{σ}^{exp} M_{3}.

3. Γ ⊢ M_{1} R_{σ} M_{2} & s_{2}, Γ ⊢ M_{2} ∼_{σ} M_{3} ⟹ M_{1} R_{σ} M_{3}.

The first two are proved by mutual induction over the structure of σ. Case (1) is immediate at ground types. For function types, suppose that (λx:σ.M_{1}) R_{σ→σ′}^{can} (λx:σ.M_{2}) and s_{1} ⊢ λx:σ.M_{2} ∼_{σ→σ′}^{can} λx:σ.M_{3}, with C_{1} ∈ Can_{σ}(s_{1} ⊕ s′_{1}), C_{2} ∈ Can_{σ}(s_{2} ⊕ s′_{2}) such that C_{1} (R ⊕ R′)_{σ}^{can} C_{2} for some R′ : s′_{1} ⇌ s′_{2}. Then by definition M_{1}[C_{1}/x] (R ⊕ R′)_{σ′}^{exp} M_{2}[C_{2}/x] and s_{2} ⊕ s′_{2} ⊢ M_{2}[C_{2}/x] ∼_{σ′}^{exp} M_{3}[C_{2}/x]. Applying the induction hypothesis gives M_{1}[C_{1}/x] (R ⊕ R′)_{σ′}^{exp} M_{3}[C_{2}/x] and so confirms (λx:σ.M_{1}) R_{σ→σ′}^{can} (λx:σ.M_{3}).

For (2) suppose that we have M_{1} R_{σ}^{exp} M_{2} and s_{2} ⊢ M_{2} ∼_{σ}^{exp} M_{3}. That is:

s_{1} ⊢ M_{1} ⇓_{σ} (s′_{1})C_{1},  s_{2} ⊢ M_{2} ⇓_{σ} (s′_{2})C_{2}  and s_{2} ⊢ M_{3} ⇓_{σ} (s′_{3})C_{3},

with C_{1} (R ⊕ R′)_{σ}^{can} C_{2} for some R′ : s′_{1} ⇌ s′_{2}, and s_{2} ⊕ (s′_{2} ∪ s′_{3}) ⊢ C_{2} ∼_{σ}^{can} C_{3}. Using Lemma 4.3 and (1) we obtain C_{1} (R ⊕ S)_{σ}^{can} C_{3}, where S : s′_{1} ⇌ s′_{3} is defined as S = R′ ∩ (s′_{1} × s′_{3}). Thus M_{1} R_{σ}^{exp} M_{3} as required.

Finally, for (3) suppose that Γ ⊢ M_{1} R_{σ} M_{2}, that s_{2}, Γ ⊢ M_{2} ∼_{σ} M_{3}, and with some R′ : s′_{1} ⇌ s′_{2} we have C_{ij} ∈ Can_{σ_{j}}(s_{i} ⊕ s′_{i}) for i = 1, 2 and j = 1, …, n such that each C_{1j} (R ⊕ R′)_{σ_{j}}^{can} C_{2j}. Then by definition M_{1}[C⃗_{1}/x⃗] (R ⊕ R′)_{σ}^{exp} M_{2}[C⃗_{2}/x⃗] and s_{2} ⊢ M_{2}[C⃗_{2}/x⃗] ∼_{σ} M_{3}[C⃗_{2}/x⃗]. Applying (2) gives us M_{1}[C⃗_{1}/x⃗] (R ⊕ R′)_{σ}^{exp} M_{3}[C⃗_{2}/x⃗] and hence Γ ⊢ M_{1} R_{σ} M_{3} as desired.

Corollary 4.10 If s, Γ ⊢ M_{1} ∼_{σ} M_{2} then Γ ⊢ M_{1} (id_{s})_{σ} M_{2}.

Proof By Proposition 4.7, Γ ⊢ M_{1} (id_{s})_{σ} M_{1} and the result follows as an instance of Theorem 4.9 above.

So logical relations can be used to prove contextual equivalence, and are at least as strong as applicative equivalence. This at once tells us that they are enough to prove the basic examples (2)–(9) and (17) of Chapter 2. More importantly though, the relations describe private names to a degree, and can prove results like example (12). This concerns the equivalence

12.  νn.λx:ν.(x = n) ≈_{ν→o} λx:ν.false .

Now the only possible span R : {n} ⇌ {} is the empty relation, and with this we have that

(λx:ν.(x = n)) R_{ν→o}^{can} (λx:ν.false)

because both functions take R-related names to false. But then

(νn.λx:ν.(x = n)) (id_{∅})_{ν→o}^{exp} (λx:ν.false)

with the above relation R satisfying the existential quantifier, and applying Proposition 4.8 shows that the expressions are contextually equivalent as claimed.

In the next section we shall see that logical relations can prove all contextual equivalences, up to first-order function types. So the notion of a span R : s_{1} ⇌ s_{2} completely captures the privacy and visibility of names as passed between functions of the nu-calculus. At higher types difficulties can arise, with names being only partially revealed, as in example (15) from page 25. As a consequence, logical relations are not enough to prove the equivalence (13):

13.  νn.νn′.λf:ν→o.(fn = fn′) ≈_{(ν→o)→o} λf:ν→o.true .

Again the only span R : {n, n′} ⇌ {} is the empty one, and the first-order functions

(λx:ν.(x = n)) R_{ν→o}^{can} (λx:ν.false)

are related because they take R-related names to false. But the two second-order functions above differ at these arguments, so they are not related:

(λf:ν→o.(fn = fn′)) ¬ R_{(ν→o)→o}^{can} (λf:ν→o.true),

and logical relations cannot prove the stated contextual equivalence. Later we shall see how the method of relations can be enhanced to prove even this example.

A final curiosity is that the relation (id_{s})_{σ} is not necessarily transitive at higher-order types. Indeed there are expressions of second-order type which are not (id_{s})-related, but can still be shown contextually equivalent through a chain of other expressions, each logically related to the next. This makes it hard to gauge the full power of the technique; however even such a roundabout method does not seem to work for equivalence (13) above.

2 Completeness at First-Order Types

In the previous section we saw that logical relations can be used to show contextual equivalence in the nu-calculus; we now demonstrate that this technique is complete up to types of first order. This requires various results on contextual relations, beginning with the observation that for closed expressions we need not explicitly consider tests at later stages:

Proposition 4.11 For any span R : s_{1} ⇌ s_{2} and closed expressions M_{1} ∈ Exp_{σ}(s_{1}), M_{2} ∈ Exp_{σ}(s_{2}):

M_{1} R_{σ}^{cxt} M_{2} ⟺
∀τ ∈ {o, ν}, λx:σ.T_{1} ∈ Can_{σ→τ} (s_{1}), λx:σ.T_{2} ∈ Can_{σ→τ} (s_{2}) .
(λx:σ.T_{1}) R_{σ→τ}^{syn} (λx:σ.T_{2}) ⟹ (λx:σ.T_{1})M_{1} R_{τ} (λx:σ.T_{2})M_{2}.

Proof The forward direction is immediate. For the reverse, suppose that M_{1} ¬ R_{σ}^{cxt} M_{2} and that they are distinguished by the test functions

(λx:σ.T_{1}) (R ⊕ R′)_{σ→τ}^{syn} (λx:σ.T_{2})

where R′ : s′_{1} ⇌ s′_{2}. If we take t_{1} = dom(R′) ⊆ s′_{1} and t_{2} = cod(R′) ⊆ s′_{2}, then the functions

(λx:σ.νt_{1}.T_{1}) R_{σ→τ}^{syn} (λx:σ.νt_{2}.T_{2})

will generally serve instead, given that

s_{1} ⊕ s′_{1} ⊢ (λx:σ.T_{1})M_{1} ⇓_{τ} (s′′_{1})C_{1} ⟺ s_{1} ⊢ (λx:σ.νt_{1}.T_{1})M_{1} ⇓_{τ} (t_{1} ⊕ s′′_{1})C_{1}
s_{2} ⊕ s′_{2} ⊢ (λx:σ.T_{2})M_{2} ⇓_{τ} (s′′_{2})C_{2} ⟺ s_{2} ⊢ (λx:σ.νt_{2}.T_{2})M_{2} ⇓_{τ} (t_{2} ⊕ s′′_{2})C_{2}

and the fairly simple nature of the logical relation (R ⊕ R′)_{τ} at ground τ. The only exception is when τ = ν and

s_{i} ⊕ s′_{i} ⊢ (λx:σ.T_{i})M_{i} ⇓_{ν} (s′′_{i})n_{i} i = 1, 2

with n_{1} ∈ t_{1} or n_{2} ∈ t_{2} but (n_{1}, n_{2}) ∉ R′. Without loss of generality we take n_{1} ∈ t_{1} and pick n′_{2} ∈ t_{2} with n_{1} R′ n′_{2}, so n_{2} ≠ n′_{2}. Then the tests

(λx:σ.νt_{1}.(T_{1} = n_{1})) R_{σ→τ}^{syn} (λx:σ.νt_{2}.(T_{2} = n′_{2}))

give true and false when applied to M_{1} and M_{2} respectively.

We can now prove a series of lemmas about contextual relations, matching the defining clauses for logical relations:

Lemma 4.12 For canonical expressions of ground type τ ∈ {o, ν} the relations R_{τ}^{syn}, R_{τ}^{cxt} and R_{τ}^{can} all coincide.

Proof It is immediate from their definitions that R_{τ}^{syn} and R_{τ}^{can} are the same; for R_{τ}^{cxt}, consider the test function (λx:τ.x).

Lemma 4.13 Contextually related lambda abstractions, applied to syntactically related values, give contextually related results. Suppose that R : s_{1} ⇌ s_{2} and R′ : s′_{1} ⇌ s′_{2} with

(λx:σ.M_{1}) ∈ Can_{σ→σ′}(s_{1})  C_{1} ∈ Can_{σ}(s_{1} ⊕ s′_{1})
(λx:σ.M_{2}) ∈ Can_{σ→σ′}(s_{2})  C_{2} ∈ Can_{σ}(s_{2} ⊕ s′_{2}).

Then

(λx:σ.M_{1}) R_{σ→σ′}^{cxt} (λx:σ.M_{2}) & C_{1} (R ⊕ R′)_{σ}^{syn} C_{2}
⟹ M_{1}[C_{1}/x] (R ⊕ R′)_{σ′}^{cxt} M_{2}[C_{2}/x].

Proof Suppose that we have test functions

(λx:σ′.T_{1}) (R ⊕ R′)_{σ′→τ}^{syn} (λx:σ′.T_{2})

to apply to M_{1}[C_{1}/x] and M_{2}[C_{2}/x]. Then these give the same results as the functions

(λf:σ → σ′.(λx:σ′.T_{1})(fC_{1})) (R ⊕ R′)_{(σ→σ′)→τ}^{syn} (λf:σ → σ′.(λx:σ′.T_{2})(fC_{2}))

applied to (λx:σ.M_{1}) and (λx:σ.M_{2}).

This next result is central to the proof of completeness, as it shows how the use of spans between name sets really can capture the way different expressions make public their local names.

Lemma 4.14 Closed expressions are contextually R-related if and only if they evaluate to contextually (R ⊕ R′)-related canonical forms, for some R′. That is, for R : s_{1} ⇌ s_{2} and M_{1} ∈ Exp_{σ}(s_{1}), M_{2} ∈ Exp_{σ}(s_{2}):

M_{1} R_{σ}^{cxt} M_{2} ⟺ ∃R′ : s′_{1} ⇌ s′_{2}, C_{1} ∈ Can_{σ}(s_{1} ⊕ s′_{1}), C_{2} ∈ Can_{σ}(s_{2} ⊕ s′_{2}) . s_{1} ⊢ M_{1} ⇓_{σ} (s′_{1})C_{1} & s_{2} ⊢ M_{2} ⇓_{σ} (s′_{2})C_{2} & C_{1} (R ⊕ R′)_{σ}^{cxt} C_{2}.

Proof We begin with the implication from right to left. Suppose that for i = 1, 2 we have the test functions λx:σ.T_{i} ∈ Can_{σ→τ} (s_{i}) with τ ∈ {o, ν} and

(λx:σ.T_{1}) R_{σ→τ}^{syn} (λx:σ.T_{2});

then we have by hypothesis that

(λx:σ.T_{1})C_{1} (R ⊕ R′)_{τ} (λx:σ.T_{2})C_{2}.

So there must be R′′ : s′′_{1} ⇌ s′′_{2} and C′_{i} ∈ Can_{τ} (s_{i} ⊕ s′_{i} ⊕ s′′_{i}) for i = 1, 2 with

s_{i} ⊕ s′_{i} ⊢ (λx:σ.T_{i})C_{i} ⇓_{τ} (s′′_{i})C′_{i} i = 1, 2

and C′_{1} (R ⊕ R′ ⊕ R′′)_{τ} C′_{2}. Combining evaluation judgements we have that

s_{i} ⊢ (λx:σ.T_{i})M_{i} ⇓_{τ} (s′_{i} ⊕ s′′_{i})C′_{i} i = 1, 2

and then

(λx:σ.T_{1})M_{1} R_{τ} (λx:σ.T_{2})M_{2}

as required.

The forward implication is rather more difficult and requires some ingenuity. Suppose that M_{1} R_{σ}^{cxt} M_{2} and s_{i} ⊢ M_{i} ⇓_{σ} (s′_{i})C_{i} for i = 1,2; we need to pick some span R′: s′_{1} ⇌ s′_{2} such that C_{1} (R ⊕ R′)_{σ}^{cxt} C_{2}.

Take R′ to relate those names that can be simultaneously produced from C_{1} and C_{2} by syntactically R-related expressions of type (σ → ν). That is, for (n_{1}, n_{2}) ∈ s′_{1} × s′_{2} we have:

n_{1} R′ n_{2} ⟺ ∃λx:σ.N_{1} ∈ Can_{σ→ν}(s_{1}), λx:σ.N_{2} ∈ Can_{σ→ν}(s_{2}) . (λx:σ.N_{1}) R_{σ→ν}^{syn} (λx:σ.N_{2}) & s_{1} ⊕ s′_{1} ⊢ (λx:σ.N_{1})C_{1} ⇓_{ν} (s′′_{1})n_{1} & s_{2} ⊕ s′_{2} ⊢ (λx:σ.N_{2})C_{2} ⇓_{ν} (s′′_{2})n_{2}

The intuition here is that R′ should identify local names of M_{1} and M_{2} that are public, with private names being unrelated. We enumerate the elements of R′ as {(n_{1j}, n_{2j}) | j = 1, …, k} and record witnessing expressions (λx:σ.N_{ij}) for i = 1, 2 and j = 1, …, k.

To show that R′ is a partial bijection, suppose that n_{1} R′ n_{2} and n′_{1} R′ n′_{2} with witnesses (λx:σ.N_{i}) and (λx:σ.N′_{i}) respectively. Then we have the syntactically related test functions

(λx:σ.N_{1} = N′_{1}) R_{σ→o}^{syn} (λx:σ.N_{2} = N′_{2})

which, applied to M_{1} R_{σ}^{cxt} M_{2}, give

((λx:σ.N_{1} = N′_{1})M_{1}) R_{o} ((λx:σ.N_{2} = N′_{2})M_{2}).

From this it follows that n_{1} = n′_{1} if and only if n_{2} = n′_{2}, according to whether the boolean expressions above evaluate to true or false.

We now demonstrate that C_{1} (R ⊕ R′)_{σ}^{cxt} C_{2}. Suppose we have test functions

(λx:σ.T_{1}) (R ⊕ R′)_{σ→τ}^{syn} (λx:σ.T_{2}) τ ∈ {o, ν},

with

s_{i} ⊕ s′_{i} ⊢ (λx:σ.T_{i})C_{i} ⇓_{τ} (s′′_{i})C′_{i} i = 1, 2.

We need to show that C′_{1} (R ⊕ R′ ⊕ R′′)_{τ} C′_{2} for some R′′ : s′′_{1} ⇌ s′′_{2}. If we construct the test functions

\begin{matrix}λx:σ.U_{i} = λx:σ.((λy_{1}:ν … λy_{k}:ν . T_{i}[y_{j}/n_{ij} | j = 1, …, k])N_{i1} … N_{ik}) \\ ∈ Can_{σ→τ} (s_{i}) i = 1, 2 \end{matrix}

then we have

(λx:σ.U_{1}) R_{σ→τ}^{syn} (λx:σ.U_{2})

and

s_{i} ⊢ (λx:σ.U_{i})M_{i} ⇓_{τ} (s′_{i} ⊕ t_{i} ⊕ s′′_{i})C′_{i} i = 1, 2,

where the t_{i} are the additional names created by the evaluation of the N_{ij}. As M_{1} R_{σ}^{cxt} M_{2}, we have that

C′_{1} (R ⊕ S)_{τ} C′_{2} for some S : s′_{1} ⊕ t_{1} ⊕ s′′_{1} ⇌ s′_{2} ⊕ t_{2} ⊕ s′′_{2}.

If τ = o then this at once gives C′_{1} = C′_{2}, so C′_{1} (R ⊕ R′ ⊕ R′′)_{o} C′_{2} for any choice of R′′ : s′′_{1} ⇌ s′′_{2}, and C_{1} (R ⊕ R′)_{σ}^{cxt} C_{2} as required.

When τ = ν we need to consider where the names C′_{1} and C′_{2} might lie:

• If C′_{1} ∈ s_{1} then C′_{2} ∈ s_{2} and C′_{1} R C′_{2}.

• If C′_{1} ∈ s′_{1} then C′_{2} ∈ s′_{2} ⊕ s′′_{2}. Taking the syntactically R-related test functions

(λx:σ.(U_{i} = U_{i})) ∈ Can_{σ→o}(s_{i}) i = 1, 2,

we have that

s_{1} ⊢ (λx:σ.(U_{1} = U_{1}))M_{1} ⇓_{o} (s′_{1} ⊕ t_{1} ⊕ s′′_{1} ⊕ t_{3} ⊕ s′′_{3})true

where t_{3}, s′′_{3} are copies of t_{1}, s′′_{1}. Contextual equivalence then gives

s_{2} ⊢ (λx:σ.(U_{2} = U_{2}))M_{2} ⇓_{o} (s′_{2} ⊕ t_{2} ⊕ s′′_{2} ⊕ t_{4} ⊕ s′′_{4})true

with t_{4}, s′′_{4} copies of t_{2}, s′′_{2}, and this tells us that C′_{2} ∈ s′_{2}. So (C′_{1}, C′_{2}) ∈ s′_{1} × s′_{2} are a pair of names simultaneously produced from C_{1} and C_{2}, and thus C′_{1} R′ C′_{2} by the definition of R′.

• By symmetry the only remaining case is when C′_{1} ∈ s′′_{1} and C′_{2} ∈ s′′_{2}. Here we may choose any R′′ : s′′_{1} ⇌ s′′_{2} that contains (C′_{1}, C′_{2}).

In all of these cases we obtain C′_{1} (R ⊕ R′ ⊕ R′′)_{ν} C′_{2} for some R′′ : s′′_{1} ⇌ s′′_{2}, and so C_{1} (R ⊕ R′)_{σ}^{cxt} C_{2} as required.

With these results on contextual relations, so close to the defining properties of logical relations, it is not hard to show completeness:

Theorem 4.15 Suppose that σ is a ground or first-order type of the nu-calculus and Γ is a set of variables of ground type. Then for any span R : s_{1} ⇌ s_{2} and expressions M_{1} ∈ Exp_{σ}(s_{1}, Γ) and M_{2} ∈ Exp_{σ}(s_{2}, Γ),

Γ ⊢ M_{1} R_{σ}^{cxt} M_{2} ⟹ Γ ⊢ M_{1} R_{σ} M_{2}.

In particular

s, Γ ⊢ M_{1} ≈_{σ} M_{2} ⟹ Γ ⊢ M_{1} (id_{s})_{σ} M_{2}.

Proof We show first that the result holds for closed expressions, by induction on the structure of the type σ. By Lemma 4.14 we need only consider expressions in canonical form, and Lemma 4.12 gives the result for ground types.

Consider then two lambda abstractions

λx:σ.M_{1} ∈ Can_{τ→σ}(s_{1}) and λx:σ.M_{2} ∈ Can_{τ→σ}(s_{2})

where τ ∈ {o, ν} and (λx:σ.M_{1}) R_{τ→σ}^{cxt} (λx:σ.M_{2}). Suppose that R′ : s′_{1} ⇌ s′_{2} is some other span, and C_{1} ∈ Can_{τ} (s_{1} ⊕ s′_{1}), C_{2} ∈ Can_{τ} (s_{2} ⊕ s′_{2}) with C_{1} (R ⊕ R′)_{τ}^{can} C_{2}. As τ is a ground type, (R ⊕ R′)_{τ}^{can}=(R ⊕ R′)_{τ}^{syn}, and we can apply Lemma 4.13 to obtain

M_{1}[C_{1}/x] (R ⊕ R′)_{σ}^{cxt} M_{2}[C_{2}/x].

The induction hypothesis gives

M_{1}[C_{1}/x] (R ⊕ R′)_{σ}^{exp} M_{2}[C_{2}/x]

and so

(λx:σ.M_{1}) (R ⊕ R′)_{τ→σ}^{can} (λx:σ.M_{2})

as desired.

For open expressions, suppose that Γ ⊢ M_{1} R_{σ}^{cxt} M_{2}, that some C_{ij} ∈ Can_{τ_{j}}(s_{i} ⊕ s′_{i}) for i = 1,2, j = 1,…,k are suitable instantiations of Γ, and that there is a span R′: s′_{1} ⇌ s′_{2} such that

C_{1j} (R ⊕ R′)_{τ_{j}}^{can} C_{2j} j = 1, …, k.

All the τ_{j} are ground types, so (R ⊕ R′)_{τ_{j}}^{can}=(R ⊕ R′)_{τ_{j}}^{syn}, and the definition of contextual relations gives

M_{1}[C⃗_{1}/x⃗] (R ⊕ R′)_{σ}^{cxt} M_{2}[C⃗_{2}/x⃗].

By the result for closed terms:

M_{1}[C⃗_{1}/x⃗] (R ⊕ R′)_{σ}^{exp} M_{2}[C⃗_{2}/x⃗]

and so Γ ⊢ M_{1} R_{σ} M_{2} as required.

3 Categories with Relations

The logical relations of the previous sections are wholly operational, and work directly with expressions of the nu-calculus. However, there is also a corresponding denotational approach, which incorporates a relational structure into the categorical models of Chapter 3. The idea is that with a correctly chosen category and monad, the standard interpretation of the nu-calculus will automatically make identifications similar to those derived from operational logical relations.

This section describes the extra categorical tools that we need to build such a model, principally the notion of ‘categories with relations’. These were introduced by Tennent and O’Hearn to give a semantics for local variables in Algol-like languages; a good outline of this use is found in [82]. The definition below is all that we need to build models for the nu-calculus; following this are two alternative presentations which put the ideas in a wider categorical setting.

Definition 4.16 A category with relations is a category with certain additional structure. As well as objects and morphisms, it has a collection of binary relations between pairs of objects, represented R : A ↔ B, and parametric squares of the form

[figure: B; B′; g; A; A′; f; R; R′]

where R, R′ are relations and f, g are morphisms. Relations, like morphisms, are simply abstract data; they need not stand for set-based relations, though that is obviously the motivating example. Similarly parametric squares need not ‘mean’ anything particular: like composition of morphisms, they are just part of the specification of the category.

Parametric squares should compose horizontally with identity

[figure: B; B; id_{A}; A; A; id_{A}; R; R]

and there should be a distinguished identity relation id_{A} : A ↔ A for each object.

Categories with relations are a weak form of double category, and as such are akin to 2-categories [37]; parametric squares are more general than 2-cells, but they do not compose vertically.

Suppose that C and D are categories with relations. A parametric functor F : C → D is a functor between the underlying categories together with a map on relations. If R: A ↔ B is a relation in C then F R : F A ↔ F B should be a relation in D, with F id_{A} = id_{F A}, and F must take parametric squares to parametric squares.

Suppose that F, G : C → D are two parametric functors. A parametric natural transformation t : F → G is a natural transformation on the underlying categories such that for any relation R : A ↔ B of C the square

[figure: F B; GB; tB; F A; GA; tA; F R; GR]

is parametric. In both these cases the parametricity constraints are additional to the usual uniformity conditions of functorality and naturality.

We define CatR to be the 2-category whose objects are small categories with relations, morphisms are parametric functors, and 2-cells are parametric natural transformations.

The use of categories with relations is an instance of a general principle for studying programming languages categorically, as described by Moggi in [68]:

when studying a complex language the 2-category Cat of small categories, functors and natural transformations may not be adequate; however, one may replace Cat with a different 2-category, whose objects capture better some fundamental structure of the language, while less fundamental structure can be modelled by 2-categorical concepts.

In our case CatR is the more sophisticated setting, able to capture a strong notion of uniformity through the additional requirement of parametricity.

We can give another, more abstract description of CatR. A reflexive graph is a set of vertices and edges between them, where each vertex has a distinguished identity edge to itself. Essentially, this is a category without composition. There is an evident category ReflGrph of small reflexive graphs, with morphisms required to preserve the appropriate structure.

A category with relations is then a category object in ReflGrph, and CatR is the internal 2-category of categories, functors and natural transformations. That is, when working over reflexive graphs rather than sets, the ordinary notion of category automatically comes equipped with relations, while functors and natural transformations are suitably parametric.

For example, given a category with relations C as described above, the object of objects C_{0} is the reflexive graph of objects A and relations R : A ↔ B, while the object of morphisms C_{1} is the reflexive graph of morphisms f : A → A′ and parametric squares:

[figure: B; B′; g; A; A′; f; R; R′.]

Consider the categories Set of sets and functions, and Cat of small categories and functors. Then a reflexive graph has more structure than a set, but less than a category. In the same way categories with relations (internal to ReflGrph) lie between ordinary categories (internal to Set) and double categories (internal to Cat).

Alternatively, categories with relations can be seen as reflexive graphs in Cat. Take the two-object category

G : [figure: v; e; Δ; δ_{0}; δ_{1}] δ_{0} ∘ Δ = δ_{1} ∘ Δ = id_{v}.

A reflexive graph is exactly a functor from G to Set, with image

[figure: vertices; edges.; identity; domain; codomain]

Indeed if we extend ReflGrph to be a 2-category, with the appropriate structure-preserving 2-cells, then there is an equality of 2-categories:

ReflGrph = Hom_{2CAT} (G, Set).

Morphisms of graphs are natural transformations between functors into Set, and 2cells are modifications in the 3-category 2CAT of large 2-categories. This is a precise correspondence: the data needed for an item on one side of the equation exactly describes the matching item on the other side.

If we now replace Set by Cat then we obtain a description of categories with relations:

CatR = Hom_{2CAT} (G, Cat).

A functor C : G → Cat is a category with relations, where Cv is the underlying category, and Ce is the category of relations and parametric squares. If C and D are two categories with relations, then a parametric functor F : C → D is a natural transformation between the corresponding functors C, D : G → Cat. A parametric natural transformation t : F → G is a modification between natural transformations F and G into Cat. In all cases the parametricity constraints of CatR match exactly the existing structure of Cat, mediated by the two-object category G.

In practice we shall only use the direct description of Definition 4.16 to handle categories with relations. Nevertheless, the characterisations above do give them decent categorical credentials.

4 The Parametric Functor Category P

In this section we use the machinery of categories with relations to rebuild the model Set^{I} from Section 5 of Chapter 3 in a parametric setting. This gives a denotational semantics for the nu-calculus that directly validates all the contextual equivalences of Chapter 2, 4. THE PARAMETRIC FUNCTOR CATEGORY P 81

except for (13). In the next section we prove various properties of the model, in particular that it is fully abstract at ground and first-order types.

We take the index category I of finite sets and injections as before, and extend it to a category with relations. A relation R : s_{1} ↔ s_{2} on I consists of a finite set R and a pair of injections s_{1} ↢ R ↣ s_{2}. This is exactly the notion of a span from Definition 4.1. The operation ‘+’ on I extends to relations: if R : s_{1} ↔ s_{2} and R′ : s′_{1} ↔ s′_{2} then R + R′ : s_{1} + s′_{1} ↔ s_{2} + s′_{2}. A square in I is parametric

[figure: s_{2}; s′_{2}; f_{2}; s_{1}; s′_{1}; f_{1}; R; R′; if and only if both squares in; R; R′; s_{1}; s′_{1}; s_{2}; s′_{2}; are pullbacks.]

This is a stronger condition than just requiring it to commute as a square of relations. In fact, up to isomorphism, all parametric squares in I are of the form

[figure: s_{2}; s_{2} + s′_{2}; inl_{s_{1},s′_{2}}; s_{1}; s_{1} + s′_{1}; inl_{s_{1},s′_{1}}; R; R + R′.]

Some delicacy is required to manage the connection between the structure of I and constructions made previously in an operational setting: we shall write R : s_{1} ⇌ s_{2} for a span between name sets, and R : s_{1} ↔ s_{2} for the corresponding relation in I; similarly with s ⊕ s′ and s + s′.

For the base category we take Set with ordinary binary relations and squares parametric

[figure: B; B′; g; A; A′; f; R; R′] if and only if

∀a ∈ A, b ∈ B . (a, b) ∈ R ⟹ (fa, gb) ∈ R′.

We then take the ordinary category P of parametric functors and parametric natural transformations from I to Set. As before, objects of I represent stages of computation, and if A : I → Set is a parametric functor then elements of As are values defined over the names in s.

The category P is cartesian closed. Finite limits and colimits are taken pointwise: the object of booleans is the constant parametric functor to the two-element set 1 + 1, taking all relations to id_{1+1}. Thanks to a relational version of the Yoneda Lemma, exponentials are defined in a manner reminiscent of the ordinary functor category:

B^{A}s = P(I(s, −) × A, B)  s, s′, s′′ ∈ I
B^{A}fps′′⟨i, a′′⟩ = ps′′⟨i ∘ f, a′′⟩  f : s → s′ p ∈ B^{A}s
i : s′ → s′′ a′′ ∈ As′′
(p_{1}, p_{2}) ∈ B^{A}R ⟺  s_{1}, s_{2} ∈ I p_{1} ∈ B^{A}s_{1}

for all parametric squares

[figure: s_{2}; s′_{2}; f_{2}; s_{1}; s′_{1}; f_{1}; R; R′]

and elements a′_{1} ∈ As′_{1}, a′_{2} ∈ As′_{2} it holds that

(a′_{1}, a′_{2}) ∈ AR′ ⟹ (p_{1}s′_{1}⟨f_{1}, a′_{1}⟩, p_{2}s′_{2}⟨f_{2}, a′_{2}⟩) ∈ BR′.

R : s_{1} ↔ s_{2} p_{2} ∈ B^{A}s_{2}

As with the model in Set^{I}, there is a simpler form for the object part of the exponential:

B^{A}s = P(A(s + ), B(s + )).

So a function from A to B defined at stage s includes data on how it behaves at all later stages. Both naturality and parametricity place bounds on what this behaviour can be.

We define the monad explicitly. On objects it is the quotient

T As = {⟨s′, a′⟩ | s′ ∈ I, a′ ∈ A(s + s′)}/ ∼

where ⟨s′_{1}, a′_{1}⟩ ∼ ⟨s′_{2}, a′_{2}⟩ if and only if there is some R′ : s′_{1} ↔ s′_{2} such that (a′_{1}, a′_{2}) ∈ A(id_{s} + R′). The relation ‘∼’ is not necessarily transitive, so really the quotient is by its transitive closure. We take [s′, a′] to represent the equivalence class of ⟨s′, a′⟩; as before, this denotes the computation ‘create the new names s′ and return value a′’.

The remaining details of the monad are specified exactly as for the Set^{I} model. The only addition is that if R : s_{1} ↔ s_{2} in I then the relation T AR : T As_{1} ↔ T As_{2} is given by

(e_{1}, e_{2}) ∈ T AR ⟺ \begin{matrix}∃R′ : s′_{1} ↔ s′_{2}, a′_{1} ∈ A(s_{1} + s′_{1}), a′_{2} ∈ A(s_{2} + s′_{2}) . \\ e_{1} = [s′_{1}, a′_{1}] & e_{2} = [s′_{2}, a′_{2}] & (a′_{1}, a′_{2}) ∈ A(R + R′) \end{matrix}

where e_{1} ∈ T As_{1} and e_{2} ∈ T As_{2}. It is significant that the definition of T AR makes implicit use of the quotient by ‘∼’: to see if e_{1} and e_{2} are related, it is necessary to check all possible representatives [s′_{1}, a′_{1}] and [s′_{2}, a′_{2}]. The resulting strong monad T is both affine and commutative.

The object of names N is the parametric inclusion functor I ↪ Set, and the test eq : N × N → 1 + 1 is equality at all stages. Fresh names are produced by

new s = [1, inr_{s,1}] ∈ T Ns

which satisfies the necessary equations.

5. PROPERTIES OF THE MODEL IN P 83

In certain cases, the action of the monad T is quite simple. If A : I → Set is a constant parametric functor that takes all relations to the identity, then T A = A. This applies to the interpretation of any nu-calculus type that does not use ν; so for example T [[o]]s = [[o]]s = 1 + 1 and T [[o]]R = id_{1+1}. For computations of type ν itself:

T [[ν]]s = T Ns = s + 1

and

T [[ν]]R = T NR = R + id_{1} : s_{1} + 1 ↔ s_{2} + 1.

The interpretation of Chapter 3, Section 4 takes expressions of the nu-calculus to morphisms in P:

[[M′]]_{Γ,≠s} : (≠s) × [[Γ]] → T [[σ]]  M′ ∈ Exp_{σ}(s, Γ)
|C′|_{Γ,≠s} : (≠s) × [[Γ]] → [[σ]]  C′ ∈ Can_{σ}(s, Γ)
[[M]]_{≠s} : (≠s) → T [[σ]]  M ∈ Exp_{σ}(s)
|C|_{≠s} : (≠s) → [[σ]]  C ∈ Can_{σ}(s).

As with Set^{I}, the object (≠s) is isomorphic to I(s, −), and we obtain elements

\begin{aligned}[[M]]_{≠s} & ∈ & T [[σ]]s & |C|_{≠s} & ∈ & [[σ]]s \\ [[M′]]_{Γ,≠s} & ∈ & (T [[σ]])^{[[Γ]]}s & |C′|_{Γ,≠s} & ∈ & [[σ]]^{[[Γ]]}s \end{aligned}

using a version of the Yoneda Lemma adapted for categories with relations. By Proposition 3.11 this model in P is adequate, and equality in the category implies contextual equivalence in the nu-calculus.

5 Properties of the Model in P

Although many of the details above are given precisely as for the model in Set^{I}, the underlying relational structure makes an important difference. Function spaces are smaller, and more computations are identified in T As, with the consequence that more contextual equivalences of the nu-calculus are validated.

The main result of this section is that the model in P is fully abstract at first-order types. This arises from a close connection with operational logical relations, and the fact that relations in the category can be used to show contextual relations between expressions of the nu-calculus.

First though, we fix when expressions of the nu-calculus are related by the model in P:

Definition 4.17 Given some span R : s_{1} ⇌ s_{2}, two expressions M_{1} ∈ Exp_{σ}(s_{1}, Γ) and M_{2} ∈ Exp_{σ}(s_{2}, Γ) are P-R-related if

([[M_{1}]]_{Γ,≠s_{1}}, [[M_{2}]]_{Γ,≠s_{2}}) ∈ (T [[σ]])^{[[Γ]]}R.

Usually the choice of R is clear, and we say that the expressions are P-related.

We now need to establish how P-relations compare to the other relations described earlier in this chapter. A few technical lemmas lay the foundations:

Lemma 4.18 Logical relations and P-relations coincide at ground types. For any span R : s_{1} ⇌ s_{2} and closed expressions M_{1} ∈ Exp_{τ} (s_{1}), M_{2} ∈ Exp_{τ} (s_{2}) of type τ ∈ {o, ν}:

([[M_{1}]]_{≠s_{1}}, [[M_{2}]]_{≠s_{2}}) ∈ T [[τ]]R ⟺ M_{1} R_{τ} M_{2}.

Proof Follows directly from the description of T [[o]] = 1 + 1 and T [[ν]] = N + 1 given earlier, and the straightforward nature of logical relations at ground types.

Lemma 4.19 Syntactically related expressions are related in P:

Γ ⊢ M_{1} R_{σ}^{syn} M_{2} ⟹ ([[M_{1}]]_{Γ,≠s_{1}}, [[M_{2}]]_{Γ,≠s_{2}}) ∈ T [[σ]]^{[[Γ]]}R
Γ ⊢ C_{1} R_{σ}^{syn} C_{2} ⟹  (|C_{1}|_{Γ,≠s_{1}}, |C_{2}|_{Γ,≠s_{2}}) ∈ [[σ]]^{[[Γ]]}R.

Proof By induction on the structure of the expressions.

Lemma 4.20 Syntactically related substitutions preserve P-relations. Suppose

([[M_{1}]]_{Γ,≠s_{1}}, [[M_{2}]]_{Γ,≠s_{2}}) ∈ T [[σ]]^{[[Γ]]}R

and that Γ can be instantiated by C_{1j} (R ⊕ R′)_{σ_{j}}^{syn} C_{2j} where j = 1, …, n, then

( [[M_{1}[C⃗_{1}/x⃗]]]_{≠s_{1}⊕s′_{1}}, [[M_{2}[C⃗_{2}/x⃗]]]_{≠s_{2}⊕s′_{2}} ) ∈ T [[σ]](R + R′).

Proof For each of i = 1, 2 we have

[[M_{i}]]_{Γ,≠s_{i}} ∈ T [[σ]]^{[[Γ]]}s_{i} = P(I(s_{i}, −) × [[Γ]], T [[σ]])

and, looking back to Lemma 3.4 on substitution,

[[M_{i}[C⃗_{i}/x⃗]]]_{≠s_{i}⊕s′_{i}} = [[M_{i}]]_{Γ,≠s_{i}}(s_{i} + s′_{i}) ⟨inl_{s_{i},s′_{i}}, ⟨|C_{i1}|_{≠s_{i}⊕s′_{i}}, …, |C_{in}|_{≠s_{i}⊕s′_{i}}⟩⟩

By Lemma 4.19

(|C_{1j}|_{≠s_{1}⊕s′_{1}}, |C_{2j}|_{≠s_{2}⊕s′_{2}}) ∈ [[σ_{j}]](R + R′) j = 1, …, n,

and thus

( ⟨|C_{11}|_{≠s_{i}⊕s′_{i}}, …, |C_{1n}|_{≠s_{i}⊕s′_{i}}⟩, ⟨|C_{21}|_{≠s_{i}⊕s′_{i}}, …, |C_{2n}|_{≠s_{i}⊕s′_{i}}⟩) ∈ [[Γ]](R + R′).

So from the definition of relations at exponentials in P,

([[M_{1}[C⃗_{1}/x⃗]]]_{≠s_{1}⊕s′_{1}}, [[M_{2}[C⃗_{2}/x⃗]]]_{≠s_{2}⊕s′_{2}}) ∈ T [[σ]](R + R′)

as required.

Lemma 4.21 Syntactically related lambda abstractions, applied to P-related expressions, give P-related results:

\begin{matrix}(λx:σ.M_{1}) R_{σ→σ′}^{syn} (λx:σ.M_{2}) & ([[M′_{1}]]_{≠s_{1}}, [[M′_{2}]]_{≠s_{2}}) ∈ T [[σ]]R \\ ⟹ ([[(λx:σ.M_{1})M′_{1}]]_{≠s_{1}}, [[(λx:σ.M_{2})M′_{2}]]_{≠s_{2}}) ∈ T [[σ′]]R. \end{matrix}

Proof Choose representatives [[M′_{1}]]_{≠s_{1}} = [s′_{1}, a′_{1}] and [[M′_{2}]]_{≠s_{2}} = [s_{2}, a′_{2}] so that there is R′ : s′_{1} ⇌ s′_{2} with (a′_{1}, a′_{2}) ∈ [[σ]](R + R′). Then for i = 1, 2,

[[(λx:σ.M_{i})M′_{i}]]_{≠s_{i}} = let m⇐[[M′_{i}]]_{≠s_{i}} in (|λx:σ.M_{i}|_{≠s_{i}}m)
= [s′_{i} + s′′_{i}, b′′_{i}]

where

[s′′_{i}, b′′_{i}] = |λx:σ.M_{i}|_{≠s_{i}} s′_{i} ⟨inl_{s_{i},s′_{i}}, a′_{i}⟩ b′′_{i} ∈ [[σ′]](s_{i} + s′_{i} + s′′_{i}).

From Lemma 4.19, (|λx:σ.M_{1}|_{≠s_{1}}, |λx:σ.M_{2}|_{≠s_{2}}) ∈ [[σ → σ′]]R, so there must be some R′′ : s′′_{1} ⇌ s′′_{2} such that (b′′_{1}, b′′_{2}) ∈ [[σ′]](R + R′ + R′′). Then

( [[(λx:σ.M_{1})M′_{1}]]_{≠s_{1}}, [[(λx:σ.M_{2})M′_{2}]]_{≠s_{2}} ) = ( [s′_{1} + s′′_{1}, b′′_{1}], [s′_{2} + s′′_{2}, b′′_{2}] )
∈ T [[σ′]]R

as required.

We can now put these together to show an adequacy result, that P-relations imply contextual relations. This enhances the previous result of Proposition 3.11, that equality in a categorical model implies contextual equivalence.

Proposition 4.22 (Relational Adequacy) Expressions related in P are contextually related:

([[M_{1}]]_{Γ,≠s_{1}}, [[M_{2}]]_{Γ,≠s_{2}}) ∈ (T [[σ]])^{[[Γ]]}R ⟹ Γ ⊢ M_{1} R_{σ}^{cxt} M_{2}
(|C_{1}|_{Γ,≠s_{1}}, |C_{2}|_{Γ,≠s_{2}}) ∈ [[σ]]^{[[Γ]]}R  ⟹ Γ ⊢ C_{1} R_{σ}^{cxt} C_{2}.

Proof The result for closed expressions follows from Lemmas 4.21 and 4.18 above, with Lemma 4.20 extending this to open expressions.

Moving to a different set of relations, there is clearly a close connection between the clauses of Definition 4.2 for operational logical relations, and the construction of the category P. In fact the categorical model came first, and the form of the relations B^{A}R and T AR motivated the definition of logical relations at R_{σ→σ′}^{can} and R_{σ}^{exp} respectively. We make the link precise by showing when P-relations imply logical relations, and vice versa.

Theorem 4.23 Suppose that σ is a nu-calculus type of ground or first order, that Γ is a set of variables of ground type, and R: s_{1} ⇌ s_{2} is some span. Then P-related expressions over these are logically related:

([[M_{1}]]_{Γ,≠s_{1}}, [[M_{2}]]_{Γ,≠s_{2}}) ∈ (T [[σ]])^{[[Γ]]}R ⟹ Γ ⊢ M_{1} R_{σ} M_{2}
(|C_{1}|_{Γ,≠s_{1}}, |C_{2}|_{Γ,≠s_{2}}) ∈ [[σ]]^{[[Γ]]}R  ⟹ Γ ⊢ C_{1} R_{σ} C_{2}.

Proof Combine relational adequacy of P (Proposition 4.22) with the completeness of logical relations at first-order types (Theorem 4.15).

Lemma 4.24 (Definability) Suppose that σ is a ground or first order type of the nucalculus, and s is some set of names. If a ∈ [[σ]]s and e ∈ T [[σ]]s, then there are expressions C ∈ Can_{σ}(s) and M ∈ Exp_{σ}(s) such that a = |C|_{≠s} and e = [[M]]_{≠s}.

Proof Exactly as in Lemma 3.15 for the category Set^{I}.

Theorem 4.25 Suppose that σ is a nu-calculus type of ground, first or second order, that Γ is a set of variables of ground or first order, and that R : s_{1} ⇌ s_{2} is some span. Then logically related expressions over these are P-related:

Γ ⊢ M_{1} R_{σ} M_{2} ⟹ ([[M_{1}]]_{Γ,≠s_{1}}, [[M_{2}]]_{Γ,≠s_{2}}) ∈ (T [[σ]])^{[[Γ]]}R
Γ ⊢ C_{1} R_{σ} C_{2} ⟹  (|C_{1}|_{Γ,≠s_{1}}, |C_{2}|_{Γ,≠s_{2}}) ∈ [[σ]]^{[[Γ]]}R.

Proof We show first that the result holds for closed expressions, by induction on the structure of the type σ. Lemma 4.18 deals with expressions of ground type, so we consider (σ → σ′) where σ is a ground or first-order type. Suppose we have two lambda abstractions

(λx:σ.M_{1}) R_{σ→σ′}^{can} (λx:σ.M_{2})

and wish to show that

(f_{1}, f_{2}) ∈ [[σ → σ′]]R,

where

f_{i} = |λx:σ.M_{i}|_{≠s_{i}} ∈ [[σ → σ′]]s_{i} i = 1, 2.

Take any (a_{1}, a_{2}) ∈ [[σ]](R + R′), for some R′ : s′_{1} ⇌ s′_{2}. Lemma 4.24 gives some C_{i} ∈ Can_{σ}(s_{i} ⊕ s′_{i}) with a_{i} ∈ |C_{i}|_{≠s_{i}⊕s′_{i}} for i = 1, 2, and by Theorem 4.23 these are logically related C_{1} (R ⊕ R′)_{σ}^{can} C_{2}. Now for each of i = 1, 2:

f_{i} (s_{i} + s′_{i}) ⟨inl_{s_{i},s′_{i}}, a_{i}⟩ = |λx:σ.M_{i}|_{≠s_{i}} (s_{i} + s′_{i}) ⟨inl_{s_{i},s′_{i}}, |C_{i}|_{≠s_{i}⊕s′_{i}}⟩
= |(λx:σ.M_{i})C_{i}|_{≠s_{i}⊕s′_{i}},

while (λx:σ.M_{1})C_{1} (R ⊕ R′)_{σ′}^{exp} (λx:σ.M_{2})C_{2} from the definition of R_{σ→σ′}^{can}. Applying the induction hypothesis gives

( f_{1}(s_{1} + s′_{1})⟨inl_{s_{1},s′_{1}}, a_{1}⟩, f_{2}(s_{2} + s′_{2})⟨inl_{s_{2},s′_{2}}, a_{2}⟩) ∈ [[σ′]](R + R′)

and so (f_{1}, f_{2}) ∈ [[σ → σ′]]R as desired.

For general expressions, suppose that M_{1} R_{σ}^{exp} M_{2}, with s_{i} ⊢ M_{i} ⇓_{σ} (s′_{i})C_{i} for i = 1,2 and R′ : s′_{1} ⇌ s′_{2} such that C_{1} (R ⊕ R′)_{σ}^{can} C_{2}. Then

[[M_{i}]]_{≠s_{i}} = [s′_{i}, |C_{i}|_{≠s_{i}⊕s′_{i}}],

and by hypothesis (|C_{1}|_{≠s_{1}⊕s′_{1}}, |C_{2}|_{≠s_{2}⊕s′_{2}}) ∈ [[σ]](R + R′), so

([[M_{1}]]_{≠s_{1}}, [[M_{2}]]_{≠s_{2}}) ∈ T [[σ]]R

as required.

This completes the proof for closed expressions; we now extend to open expressions. Given Γ ⊢ M_{1} R_{σ} M_{2}, we wish to show that

([[M_{1}]]_{Γ,≠s_{1}}, [[M_{2}]]_{Γ,≠s_{2}}) ∈ T [[σ]]^{[[Γ]]}R.

Take any (g_{1}, g_{2}) ∈ [[Γ]](R + R′), for some R′ : s′_{1} ⇌ s′_{2}; then

g_{i} = ⟨a_{i1}, …, a_{in}⟩  a_{ij} ∈ [[σ_{j}]]s_{i}  i = 1, 2 j = 1, …, n

with each (a_{1j}, a_{2j}) ∈ [[σ_{j}]](R + R′), and by Lemma 4.24 there are C_{ij} ∈ Can_{σ_{j}}(s_{i} ⊕ s′_{i}) such that a_{ij} = |C_{i}j|_{≠s_{i}⊕s′_{i}}. From Theorem 4.23, these are related

C_{1j} (R ⊕ R′)_{σ_{j}}^{can} C_{2j} j = 1, …, n,

and so M_{1}[C⃗_{1}/x⃗] (R ⊕ R′)_{σ}^{exp} M_{2}[C⃗_{2}/x⃗]. Now for each of i = 1, 2:

[[M_{i}]]_{Γ,≠s_{i}}(s_{i} + s′_{i})⟨inl_{s_{i},s′_{i}}, g_{i}⟩
= [[M_{i}]]_{Γ,≠s} (s_{i} + s′_{i}) ⟨inl_{s_{i},s′_{i}}, ⟨|C_{11}|_{≠s_{i}⊕s′_{i}}, …, |C_{1n}|_{≠s_{i}⊕s′_{i}}⟩⟩
= [[M_{i}[C⃗_{i}/x⃗]]]_{≠s_{i}⊕s′_{i}}

and by the result for closed expressions

( [[M_{1}[C⃗_{1}/x⃗]]]_{≠s_{1}⊕s′_{1}}, [[M_{2}[C⃗_{2}/x⃗]]]_{≠s_{2}⊕s′_{2}} ) ∈ T [[σ]]R.

From the definition of the relation T [[σ]]^{[[Γ]]}R then,

([[M_{1}]]_{Γ,≠s_{1}}, [[M_{2}]]_{Γ,≠s_{2}}) ∈ T [[σ]]^{[[Γ]]}R

as required. A similar proof gives the result for open expressions in canonical form.

In Section 2 we showed that operational logical relations were complete for proving contextual equivalence in the nu-calculus, up to types of first order. We can now carry this result over to P-relations:

Corollary 4.26 (Full Abstraction) The model of the nu-calculus in the category P is fully abstract for expressions of ground and first-order type.

Proof Combine Theorem 4.25 with Theorem 4.15 on the completeness of logical relations at first-order types.

So the interpretation of the nu-calculus in P proves as many equivalences as operational logical relations, up to second-order function types. This includes the examples (2)–(9),

(12) and (17) of Chapter 2. As with operational logical relations, the equivalence (13) between two second-order functions is not validated, for the reasons outlined at the end of Section 1.

At higher types the operational and denotational methods differ, because the category P contains some elements that are not definable in the nu-calculus. This is similar to the comparison between applicative equivalence and the model in Set^{I}, as discussed in Section 6 of Chapter 3. However in contrast to Theorem 3.16 there, with logical relations neither approach is strictly more powerful: this can be shown at fourth and fifth order types, using examples built from the equivalence (13).

6 Predicated Logical Relations

Section 5 of Chapter 2 presented a number of contextual equivalences and inequivalences, almost all of which have now been validated. The only exception is the equivalence

13.  νn.νn′.λf:ν→o.(fn = fn′) ≈_{(ν→o)→o} λf:ν→o.true,

and we now extend the method of operational logical relations to prove this particular example. The technique we use is tailored to fit certain symmetries of equivalence (13), and there is no obvious completeness result. However there are possible generalisations, which may prove more powerful; we shall also look at some rather open connections to other current work on logical relations.

Informally, the two functions in (13) are contextually equivalent because they agree on all arguments that can be defined using them. As pointed out at the end of Section 1, ordinary logical relations fail to show this because they admit too many arguments, including (λx:ν.(x = n)) and (λx:ν.false) on which the functions differ.

Similarly, the heart of the completeness proof of Section 2 lies in the proof of Lemma 4.14, which shows that spans can capture this ‘definability of arguments’ at ground types. With arguments of first-order type though, the problem is more difficult (see the inequivalences (14) and (15) on page 25 for example), and spans are not enough.

Definition 4.27 (Augmented Spans) For sets of names s_{1} and s_{2}, an augmented span R̂ : s_{1} ⇌ s_{2} comprises three ordinary spans R_{1} : s_{1} ⇌ s_{1}, R : s_{1} ⇌ s_{2} and R_{2} : s_{2} ⇌ s_{2}. If we wish to make these explicit, we write R̂ : s_{1} ⇌ s_{2} as (R_{1}, R, R_{2}) : s_{1} ⇌ s_{2}.

If R̂′ : s′_{1} ⇌ s′_{2} is another augmented span, with s′_{1} and s′_{2} disjoint from s_{1} and s_{2} respectively, then there is a disjoint union of augmented spans:

R̂ ⊕ R̂′ = (R_{1} ⊕ R′_{1}, R ⊕ R′, R_{2} ⊕ R′_{2}) : s_{1} ⊕ s′_{1} ⇌ s_{2} ⊕ s′_{2}.

There is also the identity augmented span:

îd_{s} = (id_{s}, id_{s}, id_{s}) : s ⇌ s.

The intuition for enhancing the span R with R_{1} and R_{2} is that they should capture additional symmetries in how expressions use their own private names. The motivating example is

νn.νn′.λf:ν→o.(fn = fn′),

where the rôles of n and n′ are entirely interchangeable. We can now define an extended form of logical relation:

Definition 4.28 (Predicated Logical Relations) If R̂: s_{1} ⇌ s_{2} is an augmented span then the relations

R̂_{σ}^{can} ⊆ Can_{σ}(s_{1}) × Can_{σ}(s_{2})
R̂_{σ}^{exp} ⊆ Exp_{σ}(s_{1}) × Exp_{σ}(s_{2})

are defined by induction over the structure of the type σ, according to:

b_{1} R̂_{o}^{can} b_{2} ⟺ b_{1} = b_{2}
n_{1} R̂_{ν}^{can} n_{2} ⟺ n_{1} R_{1} n_{1} & n_{1} R n_{2} & n_{2} R_{2} n_{2}
(λx:σ.M_{1}) R̂_{σ→σ′}^{can} (λx:σ.M_{2}) ⟺
(λx:σ.M_{1}) (R_{1})_{σ→σ′}^{can} (λx:σ.M_{1}) & (λx:σ.M_{2}) (R_{2})_{σ→σ′}^{can} (λx:σ.M_{2})
& ∀R̂′ : s′_{1} ⇌ s′_{2}, C_{1} ∈ Can_{σ}(s_{1} ⊕ s′_{1}), C_{2} ∈ Can_{σ}(s_{2} ⊕ s′_{2}) .
C_{1} (R̂ ⊕ R̂′)_{σ}^{can} C_{2} ⟹ M_{1}[C_{1}/x] (R̂ ⊕ R̂′)_{σ′}^{exp} M_{2}[C_{2}/x]
M_{1} R̂_{σ}^{exp} M_{2} ⟺
∃R̂′ : s′_{1} ⇌ s′_{2}, C_{1} ∈ Can_{σ}(s_{1} ⊕ s′_{1}), C_{2} ∈ Can_{σ}(s_{2} ⊕ s′_{2}) .
s_{1} ⊢ M_{1} ⇓_{σ} (s′_{1})C_{1} & s_{2} ⊢ M_{2} ⇓_{σ} (s′_{2})C_{2} & C_{1} (R̂ ⊕ R̂′)_{σ}^{can} C_{2}.

Notice that we use ordinary logical relations R_{1} and R_{2} in the clause for function types. The relations R̂_{σ}^{can} and R̂_{σ}^{exp} coincide on canonical forms, and we may write them as R̂_{σ} indiscriminately. We can extend the relations to open expressions: if M_{1} ∈ Exp_{σ}(s_{1}, Γ) and M_{2} ∈ Exp_{σ}(s_{2}, Γ) where Γ = {x_{1} : σ_{1}, …, x_{n} : σ_{n}} then define

Γ ⊢ M_{1} R̂_{σ} M_{2} ⟺ Γ ⊢ M_{1} (R_{1})_{σ} M_{1} & Γ ⊢ M_{2} (R_{2})_{σ} M_{2} & ∀R̂′ : s′_{1} ⇌ s′_{2}, C_{ij} ∈ Can_{σ_{j}}(s_{i} ⊕ s′_{i}) i = 1, 2 j = 1, …, n . ( &_{j=1}^{n} . C_{1j} (R̂ ⊕ R̂′)_{σ_{j}}^{can} C_{2j} ) ⟹ M_{1}[C⃗_{1}/x⃗] (R̂ ⊕ R̂′)_{σ}^{exp} M_{2}[C⃗_{2}/x⃗].

Lemma 4.29 If R̂ : s_{1} ⇌ s_{2} and M_{1} ∈ Exp_{σ}(s_{1}, Γ), M_{2} ∈ Exp_{σ}(s_{2}, Γ) then

Γ ⊢ M_{1} R̂_{σ} M_{2} ⟺ Γ ⊕ Γ′ ⊢ M_{1} (R̂ ⊕ R̂′)_{σ} M_{2}

for any Γ′ and R̂′ : s′_{1} ⇌ s′_{2}.

Proof Exactly as for ordinary logical relations in Lemma 4.3.

The strength of predicated logical relations lies in the way they combine the ‘logical’ clauses of Definition 4.2, using the structure of the type σ, with additional predicates on either side of the relation. In this particular case, the predicates are the diagonals of the ordinary logical relations (R_{1})_{σ} and (R_{2})_{σ}. So for example the result

Γ ⊢ M_{1} R̂_{σ} M_{2} ⟹ Γ ⊢ M_{1} (R_{1})_{σ} M_{1} & Γ ⊢ M_{2} (R_{2})_{σ} M_{2}

follows directly from the definition of R̂_{σ}.

The ‘logical’ part of the definition means that we can proceed as in Section 1, and show that predicated logical relations lie between syntactic and contextual ones:

Lemma 4.30 For any span R : s_{1} ⇌ s_{2} and type τ ∈ {o, ν},

(id_{s_{1}}, R, id_{s_{2}})_{τ} = R_{τ} .

Proof Straightforward, given the simple form of R_{τ} for ground τ.

Proposition 4.31 If Γ ⊢ M_{1} R_{σ}^{syn} M_{2} then Γ ⊢ M_{1} (id_{s_{1}}, R, id_{s_{2}})_{σ} M_{2}. In particular the predicated relation (îd_{s})_{σ} is reflexive: Γ ⊢ M (îd_{s})_{σ} M for any M ∈ Exp_{σ}(s, Γ).

Proof By induction on the structure of the expressions.

Proposition 4.32 If Γ ⊢ M_{1} (id_{s_{1}}, R, id_{s_{2}})_{σ} M_{2} then Γ ⊢ M_{1} R_{σ}^{cxt} M_{2}. In particular, (îd_{s})-related expressions are contextually equivalent:

Γ ⊢ M_{1} (îd_{s})_{σ} M_{2} ⟹ s, Γ ⊢ M_{1} ≈_{σ} M_{2}.

Proof Combine the definition of contextual and predicated logical relations with Proposition 4.31 and Lemma 4.30.

So predicated logical relations can be used to prove contextual equivalence. It happens that they validate all the examples from Section 5 of Chapter 2, but we shall concentrate on the most elusive:

13.  νn.νn′.λf:ν→o.(fn = fn′) ≈_{(ν→o)→o} λf:ν→o.true .

Consider the augmented span R̂ : {n, n′} ⇌ {} where

R_{1} = {(n, n′), (n′, n)} and R = R_{2} = {}.

That is, R and R_{2} are both the empty span, while R_{1} : {n, n′} ⇌ {n, n′} is the twist map. Now the only arguments at which the function (λf:ν→o.(fn = fn′)) gives the result false, are expressions of type (ν → o) that distinguish n from n′. But such an expression cannot be R_{1}-related to itself, and so

C_{1} (R̂ ⊕ R̂′)_{ν→o}^{can} C_{2} ⟹ s_{1} ⊕ s′_{1} ⊢ (λf:ν→o.(fn = fn′))C_{1} ⇓_{o} (s′′_{1})true.

This is enough to show that

(λf:ν→o.(fn = fn′)) R̂_{(ν→o)→o}^{can} (λf:ν→o.true)

and hence

(νn.νn′.λf:ν→o.(fn = fn′)) (îd_{∅})_{(ν→o)→o}^{exp} (λf:ν→o.true)

from which the equivalence (13) follows by Proposition 4.32.

We could now give a denotational development of predicated logical relations. This would begin with a three-object category something like

[figure: v; e; t; Δ; δ_{0}; δ_{1}; ϵ_{1}; ϵ_{0}; ϵ_{2}]  \begin{matrix}δ_{0} ∘ Δ = & δ_{1} ∘ Δ = & id_{v} \\ δ_{0} ∘ ϵ_{0} = & δ_{1} ∘ ϵ_{0} = & δ_{0} ∘ ϵ_{1} \\ δ_{0} ∘ ϵ_{2} = & δ_{1} ∘ ϵ_{2} = & δ_{1} ∘ ϵ_{1} \end{matrix}

and go on to mimic the work of Sections 3, 4 and 5 by defining ‘categories with predicated relations’ and further extending the Set^{I} model. However, this is now so far from any standard categorical constructions, and so specific to example (13), that there is little insight to be gained.

Predicated logical relations are a little like the layered predicates studied by the Nielsons in [73]. Their Definition 3.3 describes a way to combine two (Kripke-indexed) relations P and Q into a relation P &Q. Again this is a technique for fine-tuning logical relations, while keeping induction on the structure of types.

In defining predicated logical relations, we could make other choices for the predicates. For example, taking the everywhere-true predicate gives ordinary logical relations. Increasing complexity, we could use the diagonals of predicated logical relations themselves, or try different forms of predicate on either side of the relation. Another approach would be to carry out the same ideas for relations of other arities. With no completeness results though, this just adds unwarranted sophistication, and the resulting systems are far too complex for any practical use.

These generalisations lead towards the work of Jung and Tiuryn on logical relations of varying arity [36], which Riecke and O’Hearn have used to give a fully abstract denotational semantics for PCF [80]. In this setting, our predicated logical relations are similar to Kripke logical relations of varying arity over the category

[figure: p; q; t; u; r; s; f; g]  \begin{matrix}fp = & fq = & t \\ gr = & gs = & u \end{matrix}

of three objects, each a two-element set. However, it is not yet clear how to make this correspondence exact, and whether or not this leads to a fully abstract model for the nucalculus.

A Language with Store

Despite its curious and interesting behaviour, the nu-calculus cannot claim to provide much useful computational power. However, many significant and useful features of programming languages include the generativity that it captures; this chapter shows by example how the techniques developed for the nu-calculus can still be applied. Note that we intend only to sketch an outline of the method, so we do not seek the same level of detail as in previous chapters.

A full programming language like Standard ML contains several features with generative aspects: Core ML has exceptions, references and datatypes, all dynamically created, as are the signatures and structures of the module system. We concentrate on references, storage cells created on a run-time heap and removed by a garbage collector. These are an imperative part of ML and various implementations use them as the basis for arrays that can be updated in place.

To study references we use Reduced ML, a language that combines higher-order functions with integer references. Sections 1 and 2 describe its syntax, type structure and operational semantics. Whereas the nu-calculus merely resembles a small fragment of ML, Reduced ML is a selected subset of the full language.

Section 3 defines contextual equivalence for Reduced ML: this is the relation that holds between two expressions of the language if they are entirely interchangeable. For example, it could show what program manipulations a compiler can safely carry out, or it might demonstrate that an algorithm matches its specification. More immediately, the examples of Section 4 use contextual equivalence to illustrate how references and higherorder functions behave together.

As with the nu-calculus, contextual equivalence in Reduced ML is expressive but difficult to work with. This is where the work of the preceding chapters pays off. All the methods for proving contextual equivalence in the nu-calculus extend smoothly to Reduced ML; the passage from dynamically generated names to dynamically generated store is truly incremental. What is more, because we restrict storage to integers alone the step turns out to be a fairly small one.

The rest of the chapter is then a recapitulation of all that we did with the nu-calculus. Section 5 looks at operational methods for reasoning about contextual equivalence: applicative equivalence and operational logical relations. For a denotational approach, we use the familiar two stage technique:

Reduced ML ⟶ computational metalanguage ⟶ category with strong monad.

Each stage builds on the matching construction for the nu-calculus.

Section 6 describes a computational metalanguage suitable for reasoning about store. Conveniently, this is simply the metalanguage of Chapter 3 with additional types, terms and rules. Under this extension, any equality proved in the metalanguage for names also holds in the metalanguage for store. The interpretation of Reduced ML is given in Section 7, which shows that the computational metalanguage can be used to reason about contextual equivalence.

Section 8 sets out the properties that a category must have to model Reduced ML, and how they are used. Section 9 gives examples of this in practice. Remarkably, all the categories used to model the nu-calculus can also model Reduced ML. This emphasises how dynamically created names really do capture the ‘difficult’ part of ML references; actual value storage is not so hard.

This analysis of Reduced ML does not go into the same detail as we did for the nucalculus, nor are reasoning methods necessarily pushed to their limits. Also, integer references alone are less versatile than full ML, where cells can hold functions, or references to other cells. Nevertheless, this chapter does illustrate how a thorough understanding of dynamically generated names can make a significant contribution to reasoning about references in Standard ML.

A closely related line of research is that initiated by Reynolds into ‘Algol-like’ languages. These are command-based imperative languages, strongly typed, with a stack discipline for local variables and a call-by-name semantics for procedure calls. There is a clear separation between commands and expressions: only commands can change the state, and only expressions can return values. An analogue to higher-order functions in ML is that procedures can be declared locally and may have parameters of procedure type. However direct comparison with Standard ML is impossible, as the programming styles appropriate to the two languages are so different: exact translation takes simple Algol-like code to convoluted ML, and vice versa. In particular there is no correspondence between the notions of ‘first-order’ and ‘second-order’ in each language, as types often go up a couple of orders under translation.

Despite this, local variables and higher-order procedures do raise many of the same problems as ML references, and this chapter contains references to the corresponding work on Algol-like languages. Reynolds’ original [107] has been followed up by Oles [87, 88], O’Hearn and Tennent [81, 82, 83, 84, 125, 126, 127], and Lent [46]. Meyer [57] and Sieber [116, 117] also describe models of Algol-like languages, and approaches connected with linear logic have been suggested by Reddy [101, 102] and O’Hearn [77, 78].

1 Syntax of Reduced ML

The types of Reduced ML are built up from various ground types by the formation of function types:

σ ::= unit | bool | int | int ref | σ → σ.

Here unit and bool are types with one and two elements respectively, and int is the type of integers. The type int ref denotes integer references, or locations: each of these provides storage for a single integer value. The order of a type is defined exactly as for the nucalculus. We again use variants of σ to range over types.

Reduced ML expressions take the forms listed in Figure 5.1. General expressions

M ::= x  variable
| l  location
| ()  unit value
| i  integer constants i = …, −1, 0, 1, 2, …
| true | false truth values
| if M then M else M conditional

|

M + M | M − M | M ∗ M  operations on integers
M < M | M > M | M = M tests on integers
M <= M | M >= M | M <> M
| ref M  create a new reference cell
| !M  fetch stored value
| M := M  alter stored value
| M = M  compare locations
| fn x:σ⇒M  function abstraction
| MM  function application

Figure 5.1: Expressions of Reduced ML are usually denoted by M, with B, N, R, F suggesting boolean, integer, reference and function expressions respectively. There is an infinite supply of typed variables, generally chosen from x, y, z and variants. Function abstraction (fn x:σ⇒M) binds the variable x of type σ; we identify expressions up to α-conversion of bound variables, and substitution of expressions for free variables is capture avoiding.

Locations, written as variants of l, are always free, taken from some infinite supply. Properly speaking, this is an extension to the syntax: a true program in Reduced ML would have no explicit locations at all. However we also need to consider program fragments, which may have free locations; explicit locations also appear during the evaluation of expressions. Finite sets of locations are represented by variants of u, for universe.

A variety of binary operations and tests on integers are assumed; we shall generally take N + N′ and N < N′ to stand for all of these.

There are four sorts of expression that act on store. The expression ref N picks a fresh location, stores the integer value of N there, and returns the location as an int ref. The stored value can be retrieved with !R and changed with R := N′. Expressions denoting locations can be compared using R = R′, not to be confused with the equality test for integers.

With no polymorphism or recursion in Reduced ML, we can define let-expressions as syntactic sugar for function application:

let val x = M in M′ end = (fn x:σ⇒M′)M
let fun f x = M in M′ end = let val f = (fn x:σ⇒M) in M′ end

where f is not free in M. This extends to multiple let-expressions:

let val x_{1} = M_{1} val x_{2} = M_{2} ⋮ val x_{n} = M_{n} in M′ end = (fn x_{1}:σ_{1} ⇒ fn x_{2}:σ_{2} ⇒ ⋮ fn x_{n}:σ_{n} ⇒ M′) M_{1}M_{2} … M_{n}

and also infix semicolon for sequencing:

M; M′ = let val x = M in M′ end

where x is chosen not free in M′.

Type judgements of Reduced ML take the form

u, Γ ⊢ M : σ

where u is some finite set of locations, and Γ a finite set of typed variables. This says that the expression M, with locations in u and free variables in Γ, is well typed with type σ. Figure 5.2 gives the rules for forming valid type judgements; some of these use the abbreviation u,Γ ⊢ M_{1},…,M_{n} : σ to indicate that all of u,Γ ⊢ M_{1} : σ,…,u,Γ ⊢ M_{n} : σ hold.

This type assignment is suitably well behaved:

\overline{u, Γ ⊢ x : σ} (x : σ ∈ Γ)  \overline{u, Γ ⊢ () : unit}

\overline{u, Γ ⊢ b : bool} (b = true, false)  \overline{u, Γ ⊢ i : int} (i ∈ ℤ)

\frac{u, Γ ⊢ B : bool u, Γ ⊢ M, M′ : σ}{u, Γ ⊢ if B then M else M′ : σ}

\frac{u, Γ ⊢ N, N′ : int}{u, Γ ⊢ N + N′ : int} (also −, ∗)

\frac{u, Γ ⊢ N, N′ : int}{u, Γ ⊢ N < N′ : bool} \begin{matrix}(also >, =, <=, \\ >= and <>) \end{matrix}

\overline{u, Γ ⊢ l : int ref} (l ∈ u)  \frac{u, Γ ⊢ R, R′ : int ref}{u, Γ ⊢ R = R′ : bool}

\frac{u, Γ ⊢ N : int}{u, Γ ⊢ ref N : int ref}  \frac{u, Γ ⊢ R : int ref}{u, Γ ⊢ !R : int}

\frac{u, Γ ⊢ R : int ref u, Γ ⊢ N : int}{u, Γ ⊢ R := N : unit}

\frac{u, Γ ⊕ \{x : σ\} ⊢ M : σ′}{u, Γ ⊢ fn x:σ⇒M : σ → σ′}

\frac{u, Γ ⊢ F : σ → σ′ u, Γ ⊢ M : σ}{u, Γ ⊢ FM : σ′}

Figure 5.2: Rules for assigning types to expressions of Reduced ML Lemma 5.1 If u, Γ ⊢ M : σ then the type σ is unique. Further, if the expression M has locations in u and free variables in Γ, then

u, Γ ⊢ M : σ ⟺ u ⊕ u′, Γ ⊕ Γ′ ⊢ M : σ

for any u′ and Γ′.

Proof By induction on the structure of M.

From now on we consider only well-typed expressions.

An expression is in canonical form if it is either a variable, a location, the unit value (), one of the boolean constants true or false, an integer constant or a function abstraction. These are the values of Reduced ML at each type. We define the sets

Exp_{σ}(u, Γ) = { M | u, Γ ⊢ M : σ }
Can_{σ}(u, Γ) = { C | C ∈ Exp_{σ}(u, Γ), C canonical}
Exp_{σ}(u) = Exp_{σ}(u, ∅)
Can_{σ}(u) = Can_{σ}(u, ∅)

of expressions and canonical expressions at any type σ and for any finite sets u, Γ of locations and typed variables.

2 Operational Semantics

With the nu-calculus, evaluation of expressions involves a state s, which is the set of names created so far. Reduced ML expressions also manipulate a state, which consists of locations and the values stored in them. Over any universe u, the possible states are:

State(u) = {s | s : u → ℤ}.

If s ∈ State(u), then s{l ↦ i} ∈ State(u) is the same state, but with the value i stored at location l ∈ u. Similarly s ⊕ {l′ ↦ i′} ∈ State(u ⊕ {l′}) extends s with an extra location l′ ∉ u, holding the value i′.

We can combine states defined over disjoint sets of locations:

s ∈ State(u) & s′ ∈ State(u′) ⟹ s ⊕ s′ ∈ State(u ⊕ u′)

by taking the disjoint union of their graphs as functions.

Evaluation judgements of Reduced ML have the form

⟨u, s⟩ M ⇓_{σ} ⟨u′, s′⟩ C

where u ⊆ u′ are finite sets of locations, s ∈ State(u), s′ ∈ State(u′), M ∈ Exp_{σ}(u) and C ∈ Can_{σ}(u′). This means that in state s, over universe u, the expression M evaluates to canonical form C, in state s′, over the extended universe u′. This evaluation relation is inductively defined by the rules in Figure 5.3. As most of these do not explicitly involve the state, we adopt a state convention from the definition of Standard ML. This says that a rule presented as

\frac{M_{1} ⇓_{σ_{1}} C_{1} M_{2} ⇓_{σ_{2}} C_{2} … M_{n} ⇓_{σ_{n}} C_{n}}{M ⇓_{σ} C}

(CAN)  \overline{C ⇓_{σ} C} C canonical

(COND1)  \frac{B ⇓_{bool} true  M ⇓_{σ} C}{if B then M else M′ ⇓_{σ} C}

(COND2)  \frac{B ⇓_{bool} false  M′ ⇓_{σ} C}{if B then M else M′ ⇓_{σ} C}

(INT+)  \frac{N ⇓_{int} i  N′ ⇓_{int} i′}{N + N′ ⇓_{int} i′′} (i′′ = i + i′)

(INT<)  \frac{N ⇓_{int} i  N′ ⇓_{int} i′}{N < N′ ⇓_{bool} true} (i < i′)

(INT≮)  \frac{N ⇓_{int} i  N′ ⇓_{int} i′}{N < N′ ⇓_{bool} false} (i ≥ i′)

(EQ1)  \frac{R ⇓_{int ref} l  R′ ⇓_{int ref} l}{R = R′ ⇓_{bool} true}

(EQ2)  \frac{R ⇓_{int ref} l  R′ ⇓_{int ref} l′}{R = R′ ⇓_{bool} false} l,l′ distinct

(CREATE)  \frac{⟨u, s⟩ N ⇓_{int} ⟨u′, s′⟩ i}{⟨u, s⟩ ref N ⇓_{int ref} ⟨u′ ⊕ \{l\}, s′ ⊕ \{l ↦ i\}⟩ l} (l ∉ u′)

(FETCH)  \frac{⟨u, s⟩ R ⇓_{int ref} ⟨u′, s′⟩ l}{⟨u, s⟩!R ⇓_{int} ⟨u′, s′⟩ i} (s′(l) = i)

(ALTER)  \frac{⟨u, s⟩ R ⇓_{int ref} ⟨u′, s′⟩ l  ⟨u′, s′⟩ N ⇓_{int} ⟨u′′, s′′⟩ i}{⟨u, s⟩ R := N ⇓_{unit} ⟨u′′, s′′\{l ↦ i\}⟩ ()}

(APP)  \frac{F ⇓_{σ→σ′} fn x:σ⇒M′  M ⇓_{σ} C  M′[C/x] ⇓_{σ′} C′}{FM ⇓_{σ′} C′}

Figure 5.3: Rules for evaluating expressions of Reduced ML is actually an abbreviation for

\frac{⟨u, s⟩ M_{1} ⇓_{σ_{1}} ⟨u_{1}, s_{1}⟩ C_{1} ⟨u_{1}, s_{1}⟩ M_{2} ⇓_{σ_{2}} ⟨u_{2}, s_{2}⟩ C_{2} … ⟨u_{n−1}, s_{n−1}⟩ M_{n} ⇓_{σ_{n}} ⟨u_{n}, s_{n}⟩ C_{n}}{⟨u, s⟩ M ⇓_{σ} ⟨u_{n}, s_{n}⟩ C} ,

where the state is simply handed from one subexpression to the next. Note that this means the ordering of the hypotheses in such rules is significant. Regarding integer arithmetic, the rules (INT+), (INT<) and (INT≮) also stand for all the other operations and tests available.

The evaluation relation for Reduced ML is taken from Standard ML, with left-to-right evaluation and call-by-value function application. However the presentation of the rules, in particular (APP), does differ slightly from the Definition [62]. There, function application is carried out by evaluating a function body in an environment; this helps with ML’s sophisticated pattern matching (and also happens to correspond more closely to most implementation methods). Reduced ML, on the other hand, directly substitutes arguments for variables. As the only possible function abstraction is the simple form (fn x:σ⇒M), the two approaches have identical effect.

A similar comment applies to the rules (COND1) and (COND2) for the conditional: these are built into Reduced ML, but in Standard ML they are syntactic sugar for a certain application.

The correspondence between these two styles of presentation is investigated by Ritter and Pitts in [113]: they use applicative bisimulation to show that these alternatives are equivalent over a much larger subset of Standard ML, including full pattern matching.

Evaluation in Reduced ML ignores any unreachable store:

Lemma 5.2 For any M ∈ Exp_{σ}(u) and s ∈ State(u),

⟨u, s⟩ M ⇓_{σ} ⟨u′, s′⟩ C ⟺ ⟨u ⊕ u′′, s ⊕ s′′⟩ M ⇓_{σ} ⟨u′ ⊕ u′′, s′ ⊕ s′′⟩ C

whenever u′′ is disjoint from u′, and s′′ ∈ State(u′′).

Proof By induction on the structure of the derivation of the evaluation judgement.

Evaluation always terminates, and is deterministic up to choice of fresh locations. The proof is a simple extension of that for the nu-calculus on pages 16–17. Define the two predicates

P_{σ}(u) ⊆ Can_{σ}(u) and \overline{P}_{σ}(u) ⊆ Exp_{σ}(u)

according to

P_{unit}(u) = {()}  P_{int}(u) = ℤ
P_{bool}(u) = {true, false}  P_{int ref}(u) = u
P_{σ→σ′}(u) = \{ fn x:σ⇒M | ∀u′ ⊇ u, C ∈ P_{σ}(u′) . M[C/x] ∈ \overline{P}_{σ′}(u′) \}

and

M ∈ \overline{P}_{σ}(u) ⟺ For all s ∈ State(u) there are u′ ⊇ u, C ∈ P_{σ}(u′) and s′ ∈ State(u′) such that ⟨u, s⟩ M ⇓_{σ} ⟨u′, s′⟩ C, and these are unique up to renaming the locations (u′ \ u) and α-conversion of C.

These form a unary logical relation over the expressions of Reduced ML. As before, the idea is to show that P and \overline{P} are both total, and then use the fact that \overline{P} implies termination.

Lemma 5.3 If u, Γ ⊢ M : σ, where Γ = {x_{1} : σ_{1}, …, x_{n} : σ_{n}}, and C_{i} ∈ P_{σ_{i}}(u′) for i = 1, …, n for some u′ ⊇ u, then M[C⃗/x⃗] ∈ \overline{P}_{σ}(u′).

Proof By structural induction on the derivation of u, Γ ⊢ M : σ. The details are almost exactly the same as for Lemma 2.3. For the case of (!R), it is significant that the values stored are integers, for these are all, by definition, in P_{int}(u).

Theorem 5.4 (Termination) If M ∈ Exp_{σ}(u) and s ∈ State(u), then there are u′ ⊇ u, C ∈ Can_{σ}(u′) and s′ ∈ State(u′), such that ⟨u, s⟩ M ⇓_{σ} ⟨u′, s′⟩ C. Moreover, these are unique up to choice of the locations (u′ \ u) and α-conversion of C.

Proof By Lemma 5.3, M ∈ \overline{P}_{σ}(u) and the result follows from the definition of \overline{P}_{σ}(u).

As noted, for this result it is essential that only values of ground type, such as int, can be kept in reference cells. If functions can be stored, then it is possible to encode recursion and so write non-terminating expressions, such as:

let val r = ref(fn x:unit⇒()) fun f x = (!r)x

in

r := f; f() end.

3 Contextual Equivalence

As with the nu-calculus, it is of particular interest to determine when one Reduced ML expression can be used to replace another. Section 4 of Chapter 2 develops this into the notion of contextual equivalence for the nu-calculus, and we now adapt this for Reduced ML. The general idea is that two, possibly open, expressions are equivalent if they cannot be distinguished by placing them in a complete program. We make this into a formal definition, and in the next section give a number of examples.

Define a program in Reduced ML to be a closed boolean expression. All that can be observed of a program is whether, in some initial state, it evaluates to true or false. The creation of new locations, and changes in the values stored, are not directly observable; though obviously the outcome of the program itself may depend on those parts of the store to which it has access.

A program context P⟨⟨−⟩⟩ is a program with zero or more occurrences of a hole ⟨⟨−⟩⟩ with a certain arity σ_{1}, …, σ_{n} → σ. The hole may be filled P⟨⟨(x⃗)M⟩⟩ by some expression M, with free variables in (x⃗) of types matching the hole’s arity. The details are exactly as on pages 22–23 for the nu-calculus; in particular, we recall that the purpose of holes with arity is to formalise the possible capture of free variables.

Definition 5.5 (Contextual Equivalence) Suppose that M_{1}, M_{2} ∈ Exp_{σ}(u, Γ) are two expressions of Reduced ML. They are contextually equivalent

u, Γ ⊢ M_{1} ≈_{σ} M_{2}

if for all suitably typed program contexts P⟨⟨−⟩⟩ defined over u, states s ∈ State(u) and boolean values b ∈ {true, false},

( ∃u_{1} ⊇ u, s_{1} ∈ State(u_{1}) . ⟨u, s⟩ P⟨⟨(x⃗)M_{1}⟩⟩ ⇓_{bool} ⟨u_{1}, s_{1}⟩ b)
⟺
( ∃u_{2} ⊇ u, s_{2} ∈ State(u_{2}) . ⟨u, s⟩ P⟨⟨(x⃗)M_{2}⟩⟩ ⇓_{bool} ⟨u_{2}, s_{2}⟩ b).

That is, P⟨⟨−⟩⟩ always evaluates to the same boolean value, whether the hole is filled by M_{1} or M_{2}. When both u and Γ are empty, we write simply M_{1} ≈_{σ} M_{2}.

Section 6 of Chapter 2 uses a detailed analysis of the evaluation process to show that, in order to establish equivalence, it is only necessary to use certain kinds of program context. Specifically, those that are just a function abstraction applied to a hole νs′.((λx:σ.B)⟨⟨−⟩⟩(C⃗)); and if the expressions to be compared are closed, the fresh names s′ and the instantiation (C⃗) can be omitted.

There seems no obvious reason why the same analysis could not be made for Reduced ML:

Conjecture 5.6 (Context Lemma) Two expressions are contextually equivalent u, Γ ⊢ M_{1} ≈_{σ} M_{2} if and only if for all u′ ⊇ u, s′ ∈ State(u′), test functions (fn x:σ⇒B) ∈ Can_{σ→bool}(u′), instantiations [C⃗/x⃗] defined over u′, and each b ∈ {true, false}, it is the case that:

( ∃u_{1} ⊇ u′, s_{1} ∈ State(u_{1}) . ⟨u′, s′⟩ (fn x:σ⇒B)M_{1}[C⃗/x⃗] ⇓_{bool} ⟨u_{1}, s_{1}⟩ b )
⟺
( ∃u_{2} ⊇ u′, s_{2} ∈ State(u_{2}) . ⟨u′, s′⟩ (fn x:σ⇒B)M_{2}[C⃗/x⃗] ⇓_{bool} ⟨u_{2}, s_{2}⟩ b ).

Further, two closed expressions are contextually equivalent u ⊢ M_{1} ≈_{σ} M_{2} if and only if for all states s ∈ State(u), test functions (fn x:σ⇒B) ∈ Can_{σ→bool}(u) and each b ∈ {true, false}, it is the case that:

( ∃u_{1} ⊇ u, s_{1} ∈ State(u_{1}) . ⟨u, s⟩ (fn x:σ⇒B)M_{1} ⇓_{bool} ⟨u_{1}, s_{1}⟩ b )
⟺
( ∃u_{2} ⊇ u, s_{2} ∈ State(u_{2}) . ⟨u, s⟩ (fn x:σ⇒B)M_{2} ⇓_{bool} ⟨u_{2}, s_{2}⟩ b ).

A proof of this requires a suitable reduction semantics for Reduced ML, a notion of reduction context, and counterparts to Lemmas 2.10, 2.11 and 2.12, breaking down the possible structure of expressions and contexts. All of these are concerned with evaluation strategy, rather than the presence of state, so they should work much as for the nu-calculus. Indeed, the (ciu) theorem described by Talcott and Mason is essentially this context lemma, but for an untyped language based on destructive LISP [30, §2.3.2].

4 Examples

We now consider a series of example contextual equivalences. These are important not only because they indicate safe program transformations, but also because they give a good idea of how private, public and shared store can be used in Reduced ML. A couple of inequivalences also show how, as with the nu-calculus, higher-order functions add significant power, but must be handled with care.

As Reduced ML builds on the nu-calculus, many of the contextual equivalences listed on pages 23–26 have analogues in the presence of store. There are also other equivalences, which rely on properties of storage and retrieval of values; often though, these too are really about the visibility of locations, private and public.

Meyer and Sieber, to illustrate their model of store in Algol-like languages, give in [57] a list of example equivalences that have become something of a benchmark in this area; these are reproduced in Appendix A as MS1–MS7. As explained in the introduction, direct comparison with Reduced ML is impossible because the programming styles appropriate to the two languages are so different. Nevertheless, there are some similarities, particularly when higher-order procedures are introduced, and most of the points raised by Meyer and Sieber appear somewhere in these examples.

It is basic from the definition that contextual equivalence is a congruence:

1.  u, Γ ⊢ M_{1} ≈_{σ} M_{2} ⟹ u ⊕ u′, Γ ⊕ Γ′ ⊢ M′[M_{1}/x] ≈_{σ} M′[M_{2}/x]

where M′ ∈ Exp_{σ′}(u ⊕ u′, Γ ⊕ Γ′ ⊕ [x : σ]).

As with names in the nu-calculus, unused locations are ignored:

2.  u, Γ ⊢ let val r = ref i in M end ≈_{σ} M  i ∈ ℤ, r ∉ fv(M)

and it does not matter in what order fresh cells are allocated:

3.  u, Γ ⊢ let val r = ref i val r′ = ref i′ in M end ≈_{σ} let val r′ = ref i′ val r = ref i in M end  i, i′ ∈ ℤ.

These are similar to the Algol-like examples MS1 and MS3.

The intermediate states of a computation are not visible:

4.  r : int ref ⊢ (r := !r + 1; r := !r − 1) ≈_{unit} ().

In addition, there is no way to detect whether or not a particular computation is carried out using store:

5.  fn (x : int) ⇒ let val r = ref x in (!r + !r) end ≈_{int→int} fn (x : int) ⇒ (x + x).

Equivalences (6)–(8) of the nu-calculus concern the rearrangement of expressions around reduction contexts; given a suitable corresponding notion for Reduced ML, it seems likely that these equivalences would still hold. Even without reduction contexts, we can formulate β_{v}-equivalence: if M ∈ Exp_{σ′}(u, Γ ⊕ [x : σ]) and C ∈ Can_{σ}(u, Γ) then

6.  u, Γ ⊢ (fn x:σ⇒M)C ≈_{σ′} M[C/x].

Example (12) from the nu-calculus has a direct analogue, that a dynamically generated location is private:

7.  let val r = ref 0 in fn (x : int ref) ⇒ (x = r) end ≈_{int ref→bool} fn (x : int ref) ⇒ false.

The expression on the left evaluates to a function that compares its argument to the location r. However this function is used, r remains private, and the result of the test is always false. With functions that may have side-effects, there seems no obvious counterpart to the second-order example (13).

The value stored in a private location cannot be altered by external code:

8.  let val r = ref i in fn (x : unit) ⇒ !r end ≈_{unit→int} fn (x : unit) ⇒ i.

Once the value i ∈ ℤ has been stored in the cell r, if the location is not revealed, and the function itself leaves the contents alone, then it will not change. This is the same principle as in the Algol-like examples MS2 and MS4.

It is possible to release partial access to a storage cell:

9.  fn (f : (unit → unit) → unit) ⇒ let val r = ref 1 fun inc x = (r := !r + 1) in f(inc); !r > 0 end ≈_{((unit→unit)→unit)→bool} fn (f : (unit → unit) → unit) ⇒ let fun skip x = () in f(skip); true end.

On the left hand side, the function f is given the facility to increase the value stored in r, but not to decrease it. Consequently, this value remains positive, and the test (!r > 0) can only return true. Algol-like example MS5 captures a similar idea of partial access; MS6 does too, combined with the privacy of example (7) above.

If a storage cell is private, then it does not matter exactly how it is used:

10. let val r = ref 0 in fn (x : int) ⇒ (r := !r + x; !r) end ≈_{int→int} let val r = ref 0 in fn (x : int) ⇒ (r := !r − x; −!r) end.

Both of these expressions give a function that maintains a running total of the integers it is applied to. The second one, perversely, represents this total internally by its negative; externally, the two appear identical. O’Hearn and Tennent give an Algol-like version of this in the introduction to [82]; this ‘counter’ object is their basic running example.

A practical application of privacy is the silent attachment of profiling code:

profile = fn (f : σ → σ′) ⇒ let val r = ref 0 fun f′ x = (r := !r + 1; f x) in f′ end.

This expression takes a function f, of type (σ → σ′), and returns an instrumented version f′ that increments a counter in r each time it is called. Within the language, f′ appears exactly the same as the original f, and so

11.  f : σ → σ′ ⊢ profile f ≈_{σ→σ′} f.

The difference is that an instrumented version of a function might be useful to a profiler or debugger, quite external to the language itself, that could track down r, and examine the counter within. Contextual equivalence guarantees that the attachment of this counter cannot affect the outcome of the program. Algol-like example MS7 embodies a restricted instance of this idea, attaching a private counter to a skip command.

Notice that, thanks to higher-order functions, we can use a single piece of code that will instrument any function f, and show once and for all that its effect is not visible within the language. This is undoubtedly preferable to attaching code to the functions themselves, and checking that this is safe in each case.

An extension of this idea is the production of memoized functions, that keep a record of previous calls so as to avoid recomputation where possible. To simplify things, we only consider modifying functions of type (int → int) to record their most recent argument and result. Again, a higher-order function is the most general approach:

memo = fn (f : int → int) ⇒ let val q = ref 0 val a = ref (f 0) in fn (x : int) ⇒ if x = !q then () else (q := x; a := f x); !a end.

However, this is rather too general for an imperative language:

12.  memo ≉_{(int→int)→(int→int)} fn (f : int → int) ⇒ f.

For example, consider memo applied to the accumulator of example (10): there it is vital that the code keeping the running total really is executed each time the function is called.

In some particular cases all is well, and it is safe to memoize functions whose results are repeatable.

13.  memo (fn (x : int) ⇒ (x + x)) ≈_{int→int} fn (x : int) ⇒ (x + x).

This does not mean that a function to be memoized cannot use store. For example, both the doubling functions of example (5) can be safely memoized; as they are contextually equivalent, memo affects them equally.

A final, rather complicated, example shows the perhaps surprising ways in which supposedly private store can interact with higher-order functions. Consider the following function:

F_{1} = let val r = ref 0 val a = ref 0 in fn (f : int → int) ⇒ (r := !r + 1; a := f(!r); r := !r − 1; !a) end.

In a roundabout way, F_{1} evaluates to a function that takes an argument f, of type (int → int), and seems to apply it to the value 1. To do this, it keeps the value 0 in a private cell r, and increments it to 1 temporarily for the function application. As with example (8), this 0 will be preserved in r between calls to F_{1}.

Taking then the rather simpler function

F_{2} = fn (f : int → int) ⇒ f(1),

it may come as a surprise that

14.  F_{1} ≉_{(int→int)→int} F_{2}.

They are distinguished by the test function

G = fn (F : (int → int) → int) ⇒ F(fn (x : int) ⇒ F(fn (y : int) ⇒ y))

as GF_{1} evaluates to 2 and GF_{2} evaluates to 1. The details are as follows:

• For GF_{1}, executing the outer F_{1} increments r and binds 1 to x; the inner F_{1} then increments r again and binds 2 to y. The contents of r is reset to 0 on the way out, but the final result is 2, as bound to y.

• For GF_{2}, the outer and inner occurrences of F_{2} bind 1 to x and y respectively; the final result is the 1 from y.

Sceptics may care to try this example in a real implementation of Standard ML. As with the nu-calculus example (14) on page 25, the heart of G lies in the fact that when building a (function) argument to be passed to F_{i}, we can make use of F_{i} itself.

Together these examples show that a language such as Reduced ML can provide private, local storage, persisting if desired between function invocations. Expressions can give surrounding code partial access to this; or the use of local store need not be externally visible at all. The combination with higher-order functions can be useful, as in the profiling and memoizing functions, but needs to be treated with care, as shown by the inequivalences (12) and (14) above.

5 Proof Methods

All of the techniques developed for the nu-calculus are also suitable for proving contextual equivalences of Reduced ML. In later sections we look at denotational methods, through a computational metalanguage; for now, we outline some operational methods. The most powerful of these, operational logical relations based on store, is sufficient to prove all the equivalences of the previous section.

Section 7 of Chapter 2 describes applicative equivalence for the nu-calculus, and shows that it implies contextual equivalence. This can be adapted to Reduced ML in two stages. The first is a relation, strong applicative equivalence, written ‘≅’, that requires expressions to allocate exactly the same private locations. Closely following Definition 2.13, we have a mutual induction between the relation on canonical forms:

u ⊢ () ≅_{unit}^{can} ()  u ⊢ b_{1} ≅_{bool}^{can} b_{2} ⟺ b_{1} = b_{2}
u ⊢ i_{1} ≅_{int}^{can} i_{2} ⟺ i_{1} = i_{2}  u ⊢ l_{1} ≅_{int ref}^{can} l_{2} ⟺ l_{1} = l_{2}
u ⊢ (fn x:σ⇒M_{1}) ≅_{σ→σ′}^{can} (fn x:σ⇒M_{2}) ⟺ ∀u′ ⊇ u, C ∈ Can_{σ}(u′) . u′ ⊢ M_{1}[C/x] ≅_{σ′}^{exp} M_{2}[C/x]

and on general expressions:

u ⊢ M_{1} ≅_{σ}^{exp} M_{2} ⟺ ∀u′ ⊇ u, s′ ∈ State(u′) . ∃u′′ ⊇ u′, s′′ ∈ State(u′′), C_{1}, C_{2} ∈ Can_{σ}(u′′) . u′′ ⊢ C_{1} ≅_{σ}^{can} C_{2} & ⟨u′, s′⟩ M_{1} ⇓_{σ} ⟨u′′, s′′⟩ C_{1} & ⟨u′, s′⟩ M_{2} ⇓_{σ} ⟨u′′, s′′⟩ C_{2}.

Notice that M_{1} and M_{2} must evaluate to the same final state ⟨u′′, s′′⟩. This then extends to a relation on open expressions:

u, Γ ⊢ M_{1} ≅_{σ} M_{2} ⟺ ∀u′ ⊇ u, C_{i} ∈ Can_{σ_{i}}(u′) i = 1, …, n . u′ ⊢ M_{1}[C⃗/x⃗] ≅_{σ}^{exp} M_{2}[C⃗/x⃗].

It remains to show that ‘≅’ is a congruence, and so implies contextual equivalence. Because Reduced ML has no recursively defined types, and only stores integers, we can proceed exactly as for the nu-calculus, by defining a relation of strong logical equivalence and proving that the two are the same. Alternatively, we could adapt the more general Howe’s method, as used in [31, 25].

Strong applicative equivalence is more or less the same as Ritter and Pitts’ applicative bisimulation, from [113]. It is able to prove only equivalences (3), (4) and (6) from Section 4, because it demands a very close correspondence on the use of private locations.

A more liberal relation, applicative equivalence, written ‘∼’, relaxes this constraint. The definition is the same, except for expressions:

u ⊢ M_{1} ∼_{σ}^{exp} M_{2} ⟺ ∀u′ ⊇ u, s′ ∈ State(u′) . ∃u_{1}, u_{2} ⊇ u′, s_{1} ∈ State(u_{1}), s_{2} ∈ State(u_{2}), C_{1} ∈ Can_{σ}(u_{1}), C_{2} ∈ Can_{σ}(u_{2}) . u_{1} ∪ u_{2} ⊢ C_{1} ∼_{σ}^{can} C_{2} & ⟨u_{1}, s_{1}⟩ ∼ ⟨u_{2}, s_{2}⟩ & ⟨u′, s′⟩ M_{1} ⇓_{σ} ⟨u_{1}, s_{1}⟩ C_{1} & ⟨u′, s′⟩ M_{2} ⇓_{σ} ⟨u_{2}, s_{2}⟩ C_{2}

and a relation between states:

\begin{aligned}⟨u_{1}, s_{1}⟩ ∼ ⟨u_{2}, s_{2}⟩ & ⟺ & ∀l ∈ u_{1} ∩ u_{2} . u_{1} ∩ u_{2} ⊢ s_{1}(l) ∼_{int}^{can} s_{2}(l) \\ & ⟺ & ∀l ∈ u_{1} ∩ u_{2} . s_{1}(l) = s_{2}(l). \end{aligned}

It is now only necessary that expressions should agree up to the production of garbage. Mason’s notion of strong isomorphism for an untyped lambda-calculus with store, as described in [54, §3.2] and [55, §2.4], is roughly this relation restricted to ground types.

Applicative equivalence verifies examples (2)–(6), and any others where dynamically generated store is used only for temporary variables. Consider the case of equivalence (5):

5.  fn (x : int) ⇒ let val r = ref x in (!r + !r) end ≈_{int→int} fn (x : int) ⇒ (x + x).

We have that for any universe u and integer i,

u ⊢ let val r = ref i in (!r + !r) end ∼_{int}^{exp} (i + i).

This is because for every u′ ⊇ u and s′ ∈ State(u′) there are evaluation judgements

⟨u′, s′⟩ let val r = ref i in (!r + !r) end ⇓_{int} ⟨u′ ⊕ {l}, s′ ⊕ {l ↦ i}⟩ 2i

and

⟨u′, s′⟩ (i + i) ⇓_{int} ⟨u′, s′⟩ 2i

with

⟨u′ ⊕ {l}, s′ ⊕ {l ↦ i}⟩ ∼ ⟨u′, s′⟩

as the two states agree at their common locations. From this and the definition of applicative equivalence at function types, we deduce that

⊢ fn (x : int) ⇒ let val r = ref x in (!r + !r) end ∼_{int→int} fn (x : int) ⇒ (x + x)

and the contextual equivalence follows. The same relation, extended to a rather larger subset of Standard ML, is studied by Pitts, Stark and de Paiva in [93].

As with the nu-calculus, for stronger proof methods we can turn to some form of logical relation. Extending the work in Section 1 of Chapter 4 gives operational logical relations based on spans R : u_{1} ⇌ u_{2} across sets of locations. These subsume applicative equivalence, and also prove equivalences like example (7), that a dynamically generated location is private. This covers the profile function of example (11) too: incrementing a private counter does not affect a function’s behaviour.

Such relations successfully capture the fact that an expression can only read certain locations. However they say little about limiting write access to store: for example, logical relations based on locations would allow an expression that reset all store to 0 indiscriminately. This affects all the remaining equivalences of Section 4, each of which relies on some preservation of private store.

The solution is to move the relations from locations to states: replace R : u_{1} ⇌ u_{2} by R ⊆ State(u_{1}) × State(u_{2}) and build a logical relation R_{σ} over this. At public locations, the relation R has to be the identity, but on private locations there is great flexibility to represent the different ways expressions may use store.

Rather than go into construction details, we consider here which relations between states capture particular aspects of privacy. For example, suppose that the private cell r is at location l. Then in example (8), we want a relation R that keeps the fixed value i at this location:

R = {⟨s ⊕ {l ↦ i}, s⟩ | s ∈ State(u), fixed i}.

In example (9), we claim that the value at l is always positive, represented by the relation:

R = {⟨s ⊕ {l ↦ i}, s⟩ | s ∈ State(u), i > 0}.

We can then use the fact that inc preserves this property. Such an invariant also arises in example (10) where two functions keep the same value in a private cell, but with a change of sign:

R = {⟨s ⊕ {l ↦ i}, s ⊕ {l ↦ −i}⟩ | s ∈ State(u), i ∈ ℤ}.

When the memo function can safely be applied, as in example (13), the invariant is that two locations l_{q} and l_{a} hold a valid pair of argument and result for the memoized function f:

R = {⟨s ⊕ {l_{q} ↦ i, l_{a} ↦ j}, s⟩ | s ∈ State(u), j = fi, fixed f : ℤ → ℤ}.

Logical relations based on store genuinely extend the simpler relations based on locations: given a span R_{l} : u_{1} ⇌ u_{2} we can define a relation R_{s} on states

⟨s_{1}, s_{2}⟩ ∈ R_{s} ⟺ ∀⟨l_{1}, l_{2}⟩ ∈ R_{l} . s_{1}(l_{1}) = s_{2}(l_{2})

with similar effect. Thus all the equivalences of Section 4 can be handled by a system of operational logical relations based on state.

O’Hearn and Tennent, in [82], and Sieber, in [117], also use relations between states, in denotational methods for reasoning about Algol-like languages. While the languages are not directly comparable, the range of store manipulations that this method can tackle seems much the same in both settings.

6 A Computational Metalanguage for Store

We now move on to denotational methods for reasoning about Reduced ML, beginning with an interpretation in a computational metalanguage. To deal with store, we enlarge the metalanguage of Chapter 3 with additional types, terms and rules.

The extra types are Unit and Int, with terms () and {…, −1, 0, 1, 2, …}, and operations like plus(i, i′) and less(i, i′). These behave in an entirely straightforward way, and make no use of computation types.

More interesting are two extra term-forming operations get(−) and set(−, −), with typing rules

\frac{Γ ⊢ n : Name}{Γ ⊢ get(n) : T Int}  and  \frac{Γ ⊢ n : Name  Γ ⊢ i : Int}{Γ ⊢ set(n, i) : T Unit} .

The intuition is that set(n, i) associates the integer i to the name n, while get(n) retrieves it; both are computations. There is no explicit store; rather, we add rules to the metalanguage that simulate the visible behaviour of a store. This allows us to use

\overline{Γ ⊢ 3 : Int}  \overline{Γ ⊢ () : Unit}

\frac{Γ ⊢ i, i′ : Int}{Γ ⊢ plus(i, i′) : Bool}  \frac{Γ ⊢ i, i′ : Int}{Γ ⊢ less(i, i′) : Bool}

\frac{Γ ⊢ n : Name}{Γ ⊢ get(n) : T Int}  \frac{Γ ⊢ n : Name  Γ ⊢ i : Int}{Γ ⊢ set(n, i) : T Unit} .

Figure 5.4: Some additional typing rules for the metalanguage

static, equational reasoning in the metalanguage, while the computation types correctly handle the dynamic aspects.

Figure 5.4 gives the additional type rules for the metalanguage. To avoid an explosion of uninteresting rules about integers, in all these rules plus, less and occasionally equal, should be taken as exemplarary. Similarly, where numeric constants are involved, we give only a single case, as illustration.

With the introduction of side-effects, a useful abbreviation is

(e; e′) = let x⇐e in e′ x ∉ fv(e′)

for sequential evaluation, with iterated form:

(e_{1}; e_{2}; …; e_{n}) = (e_{1}; (e_{2}; …; e_{n})).

This is associative, and has various other properties:

Γ ⊢ (e; (e′; e′′)) = ((e; e′); e′′)
Γ ⊢ (e; let x′⇐e′ in e′′) = let x′⇐(e; e′) in e′′
Γ ⊢ (let x⇐e in e′; e′′) = let x⇐e in (e′; e′′).

All these are easily derived from the standard computation rules.

A number of rules for store extend the equational reasoning of the metalanguage. Figure 5.5 gives congruence rules for all the extra term-forming operations, and standard properties of types Unit and Int; Figure 5.6 gives some rules for reasoning about get(−) and set(−, −). All these are in addition to the rules presented in Figures 3.2 and 3.3, on pages 40 and 41.

The rules of Figure 5.6 are chosen for entirely pragmatic reasons: they appear to be the least necessary to prove Propositions 5.9 and 5.10, that the interpretation of Reduced ML in the metalanguage is both correct and adequate. We can explain them as follows:

• The (MONO^{+}) rule subsumes the standard (MONO) rule of Figure 3.3, and states that side-effects cannot divert simple value computations. In the metalanguage of Chapter 3, it can be derived from the strong (DROP^{+}) rule of page 42; however, that is not valid in the presence of store. The full generality of the (MONO^{+}) rule is not strictly necessary: for example, if exceptions were added then restrictions on the computations e and e′ would be in order.

110 CHAPTER 5. A LANGUAGE WITH STORE Congruence:

\overline{Γ ⊢ () = ()}  \overline{Γ ⊢ 3 = 3}

\frac{Γ ⊢ i_{1}, i′_{1}, i_{2}, i′_{2} : Int}{Γ; i_{1} = i′_{1}, i_{2} = i′_{2} ⊢ plus(i_{1}, i_{2}) = plus(i′_{1}, i′_{2})}

\frac{Γ ⊢ i_{1}, i′_{1}, i_{2}, i′_{2} : Int}{Γ; i_{1} = i′_{1}, i_{2} = i′_{2} ⊢ less(i_{1}, i_{2}) = less(i′_{1}, i′_{2})}

\frac{Γ ⊢ n, n′ : Name}{Γ; n = n′ ⊢ get(n) = get(n′)}

\frac{Γ ⊢ n, n′ : Name Γ ⊢ i, i′ : Int}{Γ; n = n′, i = i′ ⊢ set(n, i) = set(n′, i′)}

Unit:

\frac{Γ ⊢ u : Unit}{Γ ⊢ u = ()}

Integers:

\overline{Γ ⊢ plus(1, 1) = 2}  \overline{Γ ⊢ less(−1, 1) = tt}
\frac{Γ ⊢ i : Int}{Γ ⊢ equal(i, i) = tt}  \frac{Γ ⊢ i : Int}{Γ ⊢ less(i, i) = ff}

\frac{Γ ⊢ i, i′ : Int}{Γ; equal(i, i′) = tt ⊢ i = i′}

Figure 5.5: Some extra rules for equational reasoning in the metalanguage (I)

6. A COMPUTATIONAL METALANGUAGE FOR STORE 111 Computations:

(MONO^{+}) \frac{Γ ⊢ a, a′ : A Γ ⊢ e, e′ : T B}{Γ; let x⇐e in [a] = let x⇐e′ in [a′] ⊢ a = a′} (x ∉ fv(a, a′))

Storage:

(READ)  \frac{Γ ⊢ n : Name  Γ ⊢ i : Int}{Γ ⊢ (set(n, i); get(n)) = (set(n, i); [i])}
(WRITE)  \frac{Γ ⊢ n : Name  Γ ⊢ i, i′ : Int}{Γ ⊢ (set(n, i); set(n, i′)) = set(n, i′)}
(SWAP′)  \frac{Γ ⊢ n : Name  Γ ⊢ i : Int  Γ, n′ : Name ⊢ e : T A}{Γ ⊢ (set(n, i); let n′⇐new in e) = let n′⇐new in (set(n, i); e)}
(SWAP′′)  \frac{Γ ⊢ n, n′ : Name  Γ ⊢ i, i′ : Int}{Γ; eq(n, n′) = ff ⊢ (set(n, i); set(n′, i′)) = (set(n′, i′); set(n, i))}

Figure 5.6: Some extra rules for equational reasoning in the metalanguage (II)

• The (READ) and (WRITE) rules assert that get(n) does indeed fetch the value associated to the name n, and that set(n, i) overwrites any previous association on n.

• The (SWAP′) and (SWAP′′) rules are restricted forms of the (SWAP^{+}) rule of page 42, and state that the ordering of certain computations does not matter. Specifically, set(−, −) and new may be interchanged, as can two set(−, −) commands, if they refer to different names. These augment the existing (SWAP) rule, that fresh names may be generated in any order.

While these are all plausible statements about storage, and indeed there are categorical models that confirm them, it is unfortunate that there is no more systematic method behind this choice of rules.

This enhanced metalanguage provides a general setting for reasoning about computation with dynamically generated storage. In the next section we see how this applies to Reduced ML in particular.

7 Interpretation of Reduced ML

The translation from nu-calculus to computational metalanguage, described in Section 2 of Chapter 3, extends smoothly to Reduced ML. This gives an interpretation that is correct with respect to the operational semantics, and adequate for reasoning about contextual equivalence.

Types are interpreted without complication:

[[unit]] = Unit  [[int]] = Int
[[bool]] = Bool  [[int ref]] = Name
[[σ → σ′]] = [[σ]] → T [[σ′]].

Figure 5.7 describes the translation of Reduced ML expressions, with |−| for canonical forms, [[−]] for expressions, and [[−]] for location and variable contexts. This is a straightforward extension of Figure 3.4 on page 44, which does the same for the nu-calculus.

In deference to the use of locations in Reduced ML, variants on l are used in the metalanguage as variables of type Name. In particular, an explicit location is interpreted by itself, regarded as such a variable. We made a similar conflation earlier, with a name n of the nu-calculus being interpreted by the variable n : Name in the metalanguage.

The interpretation respects types and substitution of values:

Lemma 5.7 For any well typed Reduced ML expression M, or expression C in canonical form:

u, Γ ⊢ M : σ ⟺ [[u, Γ]] ⊢ [[M]] : T [[σ]]
u, Γ ⊢ C : σ ⟺ [[u, Γ]] ⊢ |C| : [[σ]].

Proof By induction over the structure of the type judgement in Reduced ML, using uniqueness of types in the metalanguage.

7. INTERPRETATION OF REDUCED ML 113 Canonical forms:

|x| = x  |()| = ()
|true| = tt  |3| = 3
|false| = ff  |l| = l
|fn x:σ⇒M| = λx:[[σ]].[[M]]

Expressions:

[[C]] = [|C|]
[[if B then M else M′]] = let b⇐[[B]] in cond(b, [[M]], [[M′]])
[[N + N′]] = let i⇐[[N]] in let i′⇐[[N′]] in [plus(i, i′)]
[[N < N′]] = let i⇐[[N]] in let i′⇐[[N′]] in [less(i, i′)]
[[ref N]] = let i⇐[[N]] in let l⇐new in (set(l, i); [l])
[[!R]] = let l⇐[[R]] in get(l)
[[R := N]] = let l⇐[[R]] in let i⇐[[N]] in set(l, i)
[[R = R′]] = let l⇐[[R]] in let l′⇐[[R′]] in [eq(l, l′)]
[[FM]] = let f⇐[[F]] in let m⇐[[M]] in fm

Contexts:

[[u, Γ]] = l_{1}, …, l_{k} : Name, x_{1} : [[σ_{1}]], …, x_{n} : [[σ_{n}]]
where u = {l_{1}, …, l_{k}}
Γ = {x_{1} : σ_{1}, …, x_{n} : σ_{n}}

Figure 5.7: Interpretation of Reduced ML in the computational metalanguage Lemma 5.8 If M ∈ Exp_{σ}(u, Γ ⊕ {x : σ}) and C ∈ Can_{σ}(u, Γ) then

[[u, Γ]] ⊢ [[M[C/x]]] = [[M]][|C|/x]

in the metalanguage.

Proof By induction on the structure of M, using only the fact that equality in the metalanguage is a congruence.

Certain definitions are required before we can formulate a notion of correctness for this translation. Recall the abbreviations from page 46:

(≠u) = {eq(l_{i}, l_{j}) = ff | 1 ≤ i < j ≤ k}
let (u′ \ u)⇐new^{⟶} in e = let l′_{1}⇐new in … let l′_{k′}⇐new in e

where u = {l_{1}, …, l_{k}} and (u′ \ u) = {l′_{1}, …, l′_{k′}}. Here (≠u) asserts that all the locations in u are distinct, and let (u′ \ u)⇐new^{⟶} in e extends the available locations from u to u′ before computing e. To these we now add:

assign ⟨u, s⟩ in e = (set(l_{1}, i_{1}); …; set(l_{k}, i_{k}); e)
alter ⟨u, s⟩ to ⟨u′, s′⟩ in e = let (u′ \ u)⇐new^{⟶} in assign ⟨u′, s′⟩ in e

where s = {l_{1} ↦ i_{1},…,l_{k} ↦ i_{k}} ∈ State(u) and s′ ∈ State(u′) for some u′ ⊇ u. Thanks to the various (SWAP) rules in the metalanguage, the ordering of these sets is not important, up to provable equality.

We can now state:

Proposition 5.9 (Correctness of Translation) If ⟨u, s⟩ M ⇓_{σ} ⟨u′, s′⟩ C is an evaluation judgement of Reduced ML then

[[u]]; (≠u) ⊢ assign ⟨u, s⟩ in [[M]] = alter ⟨u, s⟩ to ⟨u′, s′⟩ in [[C]]

can be proved in the metalanguage.

Proof By structural induction on the derivation of the evaluation judgement. Each of the rules in Figure 5.3 translates to a derivation provable in the metalanguage; this is all much the same as Proposition 3.6 for the nu-calculus, and the details are omitted.

Most of the work is done by the rules

\frac{[[u′]]; (≠u′) ⊢ assign ⟨u′, s′⟩ in e = alter ⟨u′, s′⟩ to ⟨u′′, s′′⟩ in e′}{[[u]]; (≠u) ⊢ alter ⟨u, s⟩ to ⟨u′, s′⟩ in e = alter ⟨u, s⟩ to ⟨u′′, s′′⟩ in e′} (u ⊆ u′)

and

\frac{[[u]] ⊢ assign ⟨u, s⟩ in e = alter ⟨u, s⟩ to ⟨u′, s′⟩ in e′}{[[u]] ⊢ assign ⟨u, s⟩ in let x⇐e in e′′ = alter ⟨u, s⟩ to ⟨u′, s′⟩ in let x⇐e′ in e′′}

both of which follow easily from the definitions of assign and alter. The (FETCH) and (ALTER) rules accessing the store also use the derived equalities:

[[u]] ⊢ assign ⟨u, s⟩ in e = alter ⟨u, s⟩ to ⟨u, s⟩ in e
[[u]]; (≠u) ⊢ assign ⟨u, s⟩ in get(l) = assign ⟨u, s⟩ in [i]  s(l) = i
[[u]]; (≠u) ⊢ assign ⟨u, s⟩ in set(l, i) = assign ⟨u, s{l ↦ i}⟩ in [()].

The first of these is trivial, and the other two follow from (READ), (WRITE) and the various (SWAP) rules of the metalanguage.

If we assume that the metalanguage is consistent, then the interpretation is adequate with respect to contextual equivalence in Reduced ML. As with the nu-calculus, this assumption is justified by the existence of non-trivial categorical models, to be presented later.

Proposition 5.10 (Adequacy of Translation) If M_{1}, M_{2} ∈ Exp_{σ}(u, Γ) are two expressions of Reduced ML, with

[[u, Γ]]; (≠u) ⊢ [[M_{1}]] = [[M_{2}]]

provable in the metalanguage, then they are contextually equivalent u, Γ ⊢ M_{1} ≈_{σ} M_{2}.

Proof Suppose that P⟨⟨−⟩⟩ is some program context defined over u. By the compositionality of the translation [[−]], and Lemma 5.8 on the substitution of values,

[[u]]; (≠u) ⊢ [[P⟨⟨(x⃗)M_{1}⟩⟩]] = [[P⟨⟨(x⃗)M_{2}⟩⟩]].

If now s ∈ State(u), then there are evaluation judgements

⟨u, s⟩ P⟨⟨(x⃗)M_{i}⟩⟩ ⇓_{bool} ⟨u_{i}, s_{i}⟩ b_{i}

for i = 1, 2 and some b_{1}, b_{2} ∈ {true, false}. The correctness result above gives

[[u]]; (≠u) ⊢ assign ⟨u, s⟩ in [[P⟨⟨(x⃗)M_{i}⟩⟩]] = alter ⟨u, s⟩ to ⟨u_{i}, s_{i}⟩ in [|b_{i}|]

for i = 1, 2, and so

[[u]]; (≠u) ⊢ alter ⟨u, s⟩ to ⟨u_{1}, s_{1}⟩ in [|b_{1}|] = alter ⟨u, s⟩ to ⟨u_{2}, s_{2}⟩ in [|b_{2}|].

We can apply the (MONO^{+}) rule to obtain

[[u]]; (≠u) ⊢ |b_{1}| = |b_{2}|

from which b_{1} = b_{2}, and so u, Γ ⊢ M_{1} ≈_{σ} M_{2} as required.

The only significant difference between this and the proof of Proposition 3.7 for the nu-calculus is that instead of (DROP) and (MONO) we needed the stronger (MONO^{+}) rule for the final step.

Thus we can use the metalanguage to reason about the contextual equivalence of Reduced ML expressions. This has power similar to the strong applicative equivalence of Section 5: it has some uses, but is intolerant of garbage. This is improved by the addition of the rule

(DROP′)  \frac{Γ ⊢ i : Int  Γ ⊢ e : T A}{Γ ⊢ let n⇐new in (set(n, i); e) = e}

as a replacement for the ordinary (DROP) rule. With (DROP′), reasoning in the metalanguage is like applicative equivalence: it is successful in most cases where dynamically generated store is used only for temporary variables. Unfortunately, the simpler categorical models do not satisfy this extra rule.

As with the nu-calculus, directly reasoning in the metalanguage cannot cope with more subtle interactions of privacy and higher-order functions, represented by example (7) onwards. These require particular concrete models, for example using relational techniques, or perhaps some relational enhancement to the metalanguage. The first of these we discuss below, the second is work for the future.

8 Categorical Models

In Chapter 3 we saw that if a category satisfies certain requirements then it provides a model for the nu-calculus. Specifically, its internal language will include the computational metalanguage with names; correctness and adequacy results then carry over from metalanguage to category. Careful choice of category can prove a range of contextual equivalences: as with the parametric functor category P from Chapter 4, which uses categories with relations and is fully abstract at ground and first-order types.

The same method applies in the presence of store: given certain additional conditions, which correspond to the extra features of the metalanguage for store, a category can be used to model Reduced ML. Further, it happens that all the categories given earlier, as models for names, are also suitable to model store, by a general construction.

Recall from Section 4 of Chapter 3 that a category C is suitable to model the metalanguage with names if the following hold:

• It is cartesian closed.

• It has a strong monad T with units η_{A} : A → T A all monomorphisms.

• It has a disjoint coproduct 1 + 1.

• There is a distinguished decidable object N.

• There is a distinguished morphism new : 1 → T N satisfying certain equations.

To model store too, the following requirements are sufficient:

• The monad T satisfies the strong mono requirement, that all the strength maps t_{A,B} : A × T B → T (A × B) are monomorphisms. In fact, it is enough to show that all the t_{A,1} : A × T 1 → T (A × 1) are monic. This is equivalent to the (MONO^{+}) rule for computations, from Figure 5.6.

This property of the monad T does not occur elsewhere in the literature; it would certainly be interesting to know whether it arises in any other context. Roughly speaking, it asserts that elements of T -types may have side-effects, but cannot entirely divert the course of computations. Monads for exceptions, or non-termination, would not satisfy the strong mono requirement.

This condition implies the ordinary mono requirement, that all the unit maps η_{A} : A → T A are monic. Conversely, if C is affine and satisfies the mono requirement, then it satisfies the strong mono requirement. This corresponds to the metalanguage derivation of (MONO^{+}) from the (DROP^{+}) and (MONO) rules.

• There is a distinguished object I, used to interpret the type of integers. This requires an accompanying collection of morphisms, including for example

less : I × I → 1 + 1,  plus : I × I → I,  and 3 : 1 → I,

which must satisfy various arithmetic equalities. Equivalently, I must be a ‘natural numbers object’, a categorical generalisation of ℕ; see [52, p. 269].

• There are distinguished morphisms get : N → T I and set : N × I → T 1 such that the following assertions in the internal language of C are satisfied:

n : N, i : I ⊢ let x⇐set(n, i) in get(n) = let x⇐set(n, i) in [i]
n : N, i, i′ : I ⊢ let x⇐set(n, i) in set(n, i′) = set(n, i′)

n, n′ : N, i, i′ : I ⊢ (eq(n, n′) = ff ) ⟹

let x⇐set(n, i) in set(n′, i′)
= let x⇐set(n′, i′) in set(n, i)

a : A, n : N, i : I

⊢

let x⇐set(n, i) in (let n′⇐new in f(a, n′))
= let n′⇐new in (let x⇐set(n, i) in f(a, n′)).

In this last equation, f is any morphism A × N → T B. These are clearly just the storage rules of Figure 5.6; we could express them by commutative diagrams in C, but their meaning then disappears in an excess of variable manipulation.

Given such a category C, the embedding of the computational metalanguage as its internal language proceeds exactly as before. The additional types Unit and Int are interpreted by the objects 1 and I respectively, and the extra term-forming operations give morphisms as in Figure 5.8. All the other details are as described earlier, on page 54 and in Figure 3.5. Any equation provable in the metalanguage for store will hold in the category C; consequently, any non-degenerate C demonstrates that the metalanguage is consistent.

The translation of the previous section now gives an interpretation of Reduced ML in the category C. For each expression M ∈ Exp_{σ}(u, Γ) there is a morphism

[[M]] : N^{|u|} × [[Γ]] → T [[σ]] where [[Γ]] = ∏_{x_{i}:σ_{i}∈Γ}[[σ_{i}]].

For an expression C in canonical form this morphism factors through η : [[σ]] → T [[σ]] and there is

|C| : N^{|u|} × [[Γ]] → [[σ]] with [[C]] = η_{[[σ]]} ∘ |C|.

Here N^{|u|} is the object of |u|-tuples of names. As with the nu-calculus, we take the subobject (≠u) ↣ N^{|u|} of distinct |u|-tuples and define the composite morphisms:

[[M]]_{Γ,≠u} = ((≠u) × [[Γ]] ↣ N^{|u|} × [[Γ]] ⟶^{[[M]]} T [[σ]]) M ∈ Exp_{σ}(u, Γ)
|C|_{Γ,≠u} = ((≠u) × [[Γ]] ↣ N^{|u|} × [[Γ]] ⟶^{|C|} [[σ]]) C ∈ Can_{σ}(u, Γ)
[[M]]_{≠u} = ((≠u) ↣ N^{|u|} ⟶^{[[M]]} T [[σ]])  M ∈ Exp_{σ}(u)
|C|_{≠u} = ((≠u) ↣ N^{|u|} ⟶^{|C|} [[σ]])  C ∈ Can_{σ}(u)

Correctness and adequacy results carry over to the categorical model. To express them properly, we use the derived morphism constructors

\frac{e : (≠u) × [[Γ]] → T A}{assign ⟨u, s⟩ in e : (≠u) × [[Γ]] → T A} (s ∈ State(u))

\overline{Γ ⊢ () : Unit} ⟼ \overline{! : Γ → 1}
\overline{Γ ⊢ 3 : Int} ⟼ \overline{Γ ⟶^{!} 1 ⟶^{3} I}

\frac{Γ ⊢ i, i′ : Int}{Γ ⊢ plus(i, i′) : Int} ⟼ \frac{i : Γ → I  i′ : Γ → I}{Γ ⟶^{⟨i,i′⟩} I × I ⟶^{plus} I}

\frac{Γ ⊢ i, i′ : Int}{Γ ⊢ less(i, i′) : Bool} ⟼ \frac{i : Γ → I  i′ : Γ → I}{Γ ⟶^{⟨i,i′⟩} I × I ⟶^{less} 1 + 1}

\frac{Γ ⊢ n : Name}{Γ ⊢ get(n) : T Int} ⟼ \frac{n : Γ → N}{Γ ⟶^{n} N ⟶^{get} T I}

\frac{Γ ⊢ n : Name  Γ ⊢ i : Int}{Γ ⊢ set(n, i) : T Unit} ⟼ \frac{n : Γ → N  i : Γ → I}{Γ ⟶^{⟨n,i⟩} N × I ⟶^{set} T 1}

Figure 5.8: Additional morphisms to interpret terms of the metalanguage and

\frac{e′ : (≠u′) × [[Γ]] → T A}{alter ⟨u, s⟩ to ⟨u′, s′⟩ in e′ : (≠u) × [[Γ]] → T A} (u ⊆ u′, s′ ∈ State(u′)).

These represent exactly the same abbreviations as in the metalanguage: they give computations that initialise the store before doing their work.

Proposition 5.11 (Correctness) If ⟨u, s⟩ M ⇓_{σ} ⟨u′, s′⟩ C is an evaluation judgement of Reduced ML then

assign ⟨u, s⟩ in [[M]]_{≠u} = alter ⟨u, s⟩ to ⟨u′, s′⟩ in [[C]]_{≠u}

as morphisms in category C.

Proof Follows from Proposition 5.9.

Proposition 5.12 (Adequacy) Suppose that C is non-degenerate, in that 0 ≅ 1̸. Then for all M_{1}, M_{2} ∈ Exp_{σ}(u, Γ):

[[M_{1}]]_{Γ,≠u} = [[M_{2}]]_{Γ,≠u} ⟹ u, Γ ⊢ M_{1} ≈_{σ} M_{2}.

Proof Exactly as for Proposition 5.10.

So a non-degenerate category that satisfies certain conditions can be used to model Reduced ML. It validates reasoning in the metalanguage, and may be used itself to prove contextual equivalences. Any categorical model will confirm basic examples such as (3),

(4) and (6); more abstract models prove additional equivalences.

9 Example Categories

In the same way that the metalanguage for store is an extension of that for names, all the categories given earlier as models for the nu-calculus are also suitable to model Reduced ML. We need simply apply a general side-effects construction outlined by Moggi in [67, §4.1.2]. Essentially, consideration of the nu-calculus has isolated the problematic parts of ML references; actual storage of values is straightforward, if a little tedious in detail.

Suppose that we have a category C with strong monad (T, η, μ, t), object of names N and morphism new suitable to model the nu-calculus. We first require an object I to interpret the integers. In the category Set^{I} for example, the constant functor to the set ℤ will do; or in BG, the set ℤ with trivial G-action. Based on this, define the state object to be:

S = I^{N}.

For example in Set^{I}, at stage u ∈ I we have that Su ≅ {s | s : (u + 1) → ℤ}. The extra 1 in the domain of s describes its behaviour at all later stages; this gives a default value for new cells.

We can now construct another strong monad (T′, η′, μ′, t′) which allows for change of state. For any object A of C,

T′A = (T (A × S))^{S}

and if f : A → B then

T′f = (T (f × S))^{S} : T′A → T′B.

This satisfies the strong mono requirement if T does; which is automatic, as all the monads for names given earlier are both affine and satisfy the ordinary mono requirement.

For example, in Set^{I} an element of T′Au specifies, for every later stage u′ and state s ∈ Su′, a result a and final state s′, perhaps at some further stage u′′. Functorality adds a degree of uniformity to this behaviour, as does the quotient from the definition of T.

Using the internal language of the original monad, the morphisms to accompany T are defined by:

a : A ⊢ η′_{A}a = λs:S.[⟨a, s⟩] : T′A
e : T′(T′A) ⊢ μ′_{A}e = λs:S.(let ⟨e′, s′⟩⇐es in e′s′) : T′A
a : A, e : T′B ⊢ t′_{A,B}⟨a, b⟩ = λs:S.let ⟨b, s′⟩⇐es in [⟨⟨a, b⟩, s′⟩] : T′(A × B).

The same object of names N will do, with a different map

new′ = λs:S.let n⇐new in [⟨n, s⟩] : T′N.

Notice that this makes no mention of initialisation. In fact in a category such as Set^{I}, every element of the state object S will have some default value for new cells. However, this plays no part in the interpretation of Reduced ML, because the expression (ref i) always provides an initial value.

Manipulation of store is effected by the following maps:

n : N ⊢ get(n) = λs:S.[⟨sn, s⟩] : T I
n : N, i : I ⊢ set(n, i) = λs:S.[⟨(), λn′:N.cond(eq(n′, n), i, sn′)⟩] : T 1.

Here get simply looks up the value associated with the name n in state s, while set creates a modified state, which differs from s only at the name n. The various equalities that new′, get and set must satisfy follow directly from their definitions and the given properties of new. Thus in C we have a model of Reduced ML, with store managed in a simple way and the original monad T dealing with dynamic creation of cells.

This applies to all the the categories that Chapter 3 introduces: Set^{I}, the atomic topos A, and continuous G-sets BG. As it happens, these do not give particularly abstract models; they validate all reasoning in the metalanguage but go no further. They even fail to confirm the equivalence

2.  u, Γ ⊢ let val r = ref i in M end ≈_{σ} M  i ∈ ℤ, r ∉ fv(M).

Although the name creation monad T in these models will factor out all unused names, the cell r is touched once, when it is initialised with the value i.

Working over categories with relations, the parametric functor category P, from Section 4 of Chapter 4, is rather better. The model of Reduced ML in P confirms equivalences (2)–(7), (11) and any others where dynamically generated store is used only for temporary variables. The relations that do this are exactly as for the nu-calculus: spans that identify common visible locations, and ignore private locations.

To make this model still more abstract, we have to adjust the detailed construction of T′ from T. The simplest approach here would be to replace S = I^{N} with some more sophisticated state object, perhaps with extra relational structure. This mirrors the development of operational logical relations based on state, as described in Section 5. It seems that this should be enough to construct a model that validates all the equivalences of Section 4, with no need to go outside the 2-categorical structure of categories with relations.

Sieber, in [117], has an impressive full abstraction result for certain models of store in Algol-like languages, up to second-order types. This uses a sophisticated relational structure over stores, and has similarities to the functor categories described above. It is not yet known whether this result can be carried over to models for references in Reduced ML, nor how powerful it might be there.

Conclusion

In this final chapter we outline possibilities for further research, describe other published work in the same area, and summarise the results of the dissertation.

1 Directions for Future Research

There are several lines of inquiry that follow on from the work in this dissertation, some that strengthen existing results and others that suggest new ones. We first look at ideas for the nu-calculus and names in general, and then discuss extensions to the work of Chapter 5 on ML-style references.

1.1 The Nu-Calculus

The methods we have developed here are sufficient to prove all the contextual equivalences presented in Section 5 of Chapter 2; yet none are complete, or can express the equivalence ≈_{σ→σ′} simply in terms of ≈_{σ} and ≈_{σ′}. We do not know whether the metalanguage can be made complete for reasoning about contextual equivalence, and we have no fully abstract categorical model. A solution to any of these problems would neatly round off the theory of the nu-calculus.

One possibility is to adapt O’Hearn and Riecke’s recent fully abstract model of PCF, which is based on Jung and Tiuryn’s logical relations of varying arity [80, 36]. Another approach is to construct a category from the types and expressions of the nu-calculus itself, in the style of Milner’s term model for the simply-typed lambda-calculus [59]. Here full abstraction is immediate as contextual equivalence is built in from the start; however there are complications, in particular the need for equalizers in the category.

The requirements given in Chapter 3 for a categorical model of the nu-calculus are sufficient but perhaps a little arbitrary, and this might be improved. For example, it may be that if a category C has a strong monad T, then the object of names N and morphism new are characterised by some universal property, as with a natural numbers object [42]. The first example of a model was in Set^{I}, and it could be significant that this category is symmetric monoidal closed, with a multiplication ‘⊗’ and exponential ‘⊸’ derived from the operation ‘+’ on I. Such structure captures notions of support and non-interference between terms, but it remains to be seen whether this can be generalised.

The success of logical relations suggests that it might be good to add them to the metalanguage, following Plotkin and Abadi’s logic for relational parametricity in System F [97].

The idea is that this would match the ease of equational reasoning with the power of logical relations.

A logic of properties for the nu-calculus would characterise expressions by the properties that they satisfy, so for example

({n} → {true}) ∧ ({n′} → {false})

might specify how a function of type (ν → o) treats the names n and n′. This is based on the process logics of concurrency theory, with a duality between axiomatic and denotational views of properties [27, 3]. The treatment of new names is problematic; one possibility is to define quantifiers

∀n.ϕ ‘for all (fresh) names n, ϕ holds’
∃n.ϕ ‘for some (private) name n, ϕ holds’

but it is not clear how best to formalise these.

The definition of the monad T for the parametric functor category P of Chapter 4 is strikingly similar to Plotkin and Abadi’s proof rule for existential types in System F [97]. There is in fact a common origin in Reynolds’ notion of ‘relational parametricity’, but there may also be a closer connection in the form of a direct translation of the nu-calculus into System F. This would use an existential type, or possibly a bounded existential, to conceal the generation of new names [65, 14]. O’Hearn and Riecke have used polymorphism, in a different way, to interpret Algol-like state [79]; Launchbury and Peyton-Jones have also suggested existentials to manage state in Haskell [45].

Quite separate from the refinements of nu-calculus reasoning are the applications to other areas. We have already looked at references in ML, but exceptions, datatypes and structures are dynamically generated too. The same methods may help with models of names in the pi-calculus, or the ‘of course’ modality from linear logic [61, 6].

A final possibility is that the metalanguage for names of Chapter 3 could be reused to interpret a lazy nu-calculus, with [[σ → σ′]] = T [[σ]] → T [[σ′]] for call-by-name function types. The (DROP) and (SWAP) rules then express precisely how abstract names transcend the vagaries of evaluation order in a lazy language.

1.2 Reduced ML

Chapter 5 outlines a number of methods for reasoning about references in Reduced ML; the most promising are operational logical relations based on state and models that use categories with relations. An immediate task is to investigate these further, to establish their strengths and identify their limitations.

In traditional imperative languages almost all uses of assignment are mundane and predictable, even trivial. One of the triumphs of functional programming is that these are eliminated; as a consequence, only the interesting uses of store remain. Reference types in Standard ML can for example be used:

• as local ‘own’ variables, persisting over several invocations of a function;

• as variables shared between functions in a package;

• to encapsulate state within an object of user defined type;

• as pointers within a graph or similar data structure.

The examples of Chapter 5 only begin to illustrate these possibilities, and the development of reasoning systems must go hand in hand with work on using the full power of references. The interaction with higher-order functions is particularly important: the memo and profile examples are just a start in the right direction.

The step from Reduced ML to the full language has several effects on references, including:

• storage of values of function type;

• recursively defined functions that use store;

• recursively defined (user declared) datatypes that incorporate store.

In combination these create considerable difficulties for reasoning and the construction of models. Nevertheless the work on Reduced ML — in particular the identification of some categorical requirements for a model of store — should provide a good foundation for future efforts.

2 Related Work

There is a considerable body of work on the subject of functional programming and state; much of it concerned with store, and a little with the issue of names. This section surveys just a sample of the approaches taken, and most of the items cited contain further useful references.

Odersky has developed a theory λν that adds local names to the lambda-calculus, and preserves all existing contextual equivalences [74, 75]. Syntactically this language is very like the nu-calculus; differences are that λν is untyped and has a call-by-name reduction strategy, with the possibility of ‘stuck’ terms. So, taking example (10) of Chapter 2, in λν the expression (λx.x == x)(νn.n) reduces first to νn.n == νn.n and is then stuck; the equivalent nu-calculus expression evaluates to true. Odersky works around the limited scope of names by using a continuation-passing style of programming; he also shows how monadic ‘state transformers’ can be combined with names to code extensible store.

Odersky, Rabin and Hudak earlier proposed a language λ_{var} which adds variables and assignment to the lambda-calculus [76]. As with λν, this has the strong property that every contextual equivalence of the lambda-calculus also holds in the extended system.

Augustsson, Rittri and Synek describe a method for distributing a supply of names around a functional program using a binary tree [9]. This is a convenient structure, but still requires an imperative gensym for a practical implementation.

Demers and Donahue have given an equational theory for the Russell language [16], and Boehm has described an axiomatic method for reasoning about side-effects there [12, 13]. However, although Russell has both higher-order functions and storage cells, their interaction is sharply constrained by the ‘import rule’.

Mason and Talcott have developed operational methods for reasoning about LISP programs in [54, 55] and, with Honsell and Smith, in [30]. They consider an untyped language with call-by-value semantics and dynamically generated mutable cells. There are substantial example proofs of program equivalences in Mason’s thesis [53], though the techniques described are restricted to the language without lambda abstraction or higherorder functions. Mason’s notion of ‘strong isomorphism’ compares with our applicative equivalence for Reduced ML, as applied to ground types.

Felleisen and others have added variable assignment and control operators to the callby-value lambda-calculus [21, 20]. They present a syntactic, equational theory for the lambda-calculus, and show that it can be extended with certain axioms for reasoning about state.

The Imperative Lambda Calculus of Swarup, Reddy and Ireland [123, 124] is a typed lambda-calculus with references and state. The type system has three distinct layers: applicative, mutable and observer types. This makes a clear distinction between imperative and applicative programming styles.

Riecke has proposed the use of an ‘effects delimiter’ to manage imperative additions to a functional language [111]; this ensures that particular pieces of code can be treated as if they were purely functional. Gifford and Lucassen’s ‘effect system’ is a more detailed technique that annotates types to record and control possible side-effects [49].

The introduction to Chapter 5 has already described Reynolds’ ‘Algol-like’ languages, and how they compare with Reduced ML. Work on semantics for local variables in this setting has included functor categories [87, 88, 81, 127], categories with relations [82, 83], logical relations [116, 117] and parametric polymorphism [79]. The Algol type system makes a clear distinction between commands, which alter the state, and expressions, which return values. This separation has motivated attempts to formally constrain the use of state, as in Reynolds’ ‘specification logic’ [106, 108, 126, 84] and ‘syntactic control of interference’ [105, 110, 125, 78].

Various methods have been proposed for carrying out stateful programming in the purely functional language Haskell. Wadler suggests the use of monads to structure functional programs in ways that simulate features such as global state or exception handlers [133, 134, 135]. Hudak’s ‘mutable abstract datatypes’ [32] encode state-like objects using various techniques, including monadic and continuation-passing styles. Given a set of axioms with a certain linearity property, they can then be implemented efficiently using in-place update.

Most recently Launchbury and Peyton Jones have proposed an ingenious use of polymorphic types that wraps up ‘state transformers’ and presents them as pure functions [89, 43, 44, 45]. This allows efficient implementation without compromising full use of higher-order functions and lazy evaluation. It is even possible to wrap up calls to C code so that they appear functional and are executed lazily.

This work on state in Haskell is impressive, but somewhat orthogonal to the results of this dissertation; it seeks to hide state rather than understand it. As Launchbury and Peyton Jones point out [45, §10], some of the most interesting uses of state, including a distributed name supply, cannot be entirely concealed. Their approach is to use the unsafe interleaveST combinator; our results on names are the kind of reasoning that shows when this is acceptable.

Many people have paid particular attention to the issue of update-in-place and associated efficiences of implementation. Examples include the ‘unique’ types of Clean [11], Guzman and Hudak’s single-threaded lambda-calculus [26], and numerous applications of linear logic [5, 29, 41, 136, 137]. This work gives useful insights into the way functional languages make use of the store available to them; it is however quite distinct from the aim of this dissertation, which is to look at names and references as convenient and powerful programming constructs in their own right, independent of implementation details.

3 Summary of Results

In this dissertation we have used the nu-calculus, a small experimental language, to explore the interaction between higher-order functions and dynamically generated names. Contextual equivalence between expressions of the nu-calculus has provided our benchmark measure of their behaviour; we have described a collection of examples, and have put forward a number of techniques for proving them.

Interesting properties of names in the nu-calculus include their generativity and scoping, together with the issues of privacy and visibility. Contextual equivalence can capture all of these, but it is a difficult relation to demonstrate directly. To remedy this, the major part of this dissertation has comprised the development of some practical proof methods.

• A context lemma that reduces the range of settings in which expressions must be tested for equivalence.

• Applicative equivalence, an operational relation that is easy to demonstrate and proves a range of basic contextual equivalences.

• A translation from the nu-calculus to a computational metalanguage for names. This allows equational reasoning with similar power to applicative equivalence.

• A general scheme for categorical models using a strong monad, with two particular examples: the functor category Set^{I} and the category BG of continuous G-sets.

• Operational logical relations, a more sophisticated technique that distinguishes between private and public uses of names. This is complete for proving contextual equivalence up to first-order types.

• A model P based on categories with relations. This has close links to operational logical relations, and is fully abstract at ground and first-order types.

• Predicated logical relations, an operational method that uses a finer analysis of how names are used, to prove even more contextual equivalences than logical relations alone.

For each of these methods we have described a proof of correctness, and have investigated the range of contextual equivalences validated.

We have also demonstrated how the same techniques can be applied to generative features within a larger programming language, specifically integer references in a subset of Standard ML. Both operational and denotational methods can be smoothly extended to handle store; we have given various uses of logical relations and have described in outline some examples of categorical models.

In summary, this work has shown that dynamically generated names can be added to a functional language in a safe and well-behaved way. Their combination with higherorder functions exhibits subtle and interesting behaviour, and we have developed powerful methods for reasoning about this. We have also outlined how the same approach may work for the extensible, mutable store of Standard ML.

Names and ML-style references have generally been regarded as ‘impure’ language features. In the light of this dissertation, and other similar work, there is every prospect that they can be brought within the fold as powerful and intuitive programming constructs, suitable for clear and safe use in any functional language.

Appendix A

The Meyer-Sieber Examples

Meyer and Sieber, in [57], give a series of examples that illustrate the behaviour of local store in an Algol-like language. For convenience these are reproduced here as MS1– MS7. Further details can be found in the original paper, which also presents an ‘invariantpreserving’ model that validates all but the final example.

Corresponding to contextual equivalence, some of the examples use a notion of ‘observational congruence’ between expressions. Others assert that a particular block of code always diverges; equivalently, that it is observationally congruent to a diverge command.

MS1 The block below can be replaced by the call to P.

begin new x; P % P is declared elsewhere

end

MS2 The block below always diverges.

begin new x; x := 0; P; if contents(x) = 0 then diverge fi

end

In both these examples, the local variable x is invisible to the procedure P.

MS3 The blocks

begin new x; new y; x := 0; Q(x, y) end

and begin new x; new y; x := 0; Q(y, x) end

are observationally congruent. Here Q cannot distinguish the local variables x and y, and must treat them uniformly.

MS4 The block below always diverges.

begin new x; new y; procedure Twice; begin y := 2 ∗ contents(y) end; x := 0; y := 0; Q(Twice); % Q is declared elsewhere if contents(x) = 0 then diverge fi

end

In this example Q is only able to access the variable y, and not x. Rather confusingly, it happens that the procedure Q cannot in fact change the value of y from zero anyhow, due to the unfortunate choice of initial value; starting with y := 1 would perhaps make the example clearer.

MS5 The block below always diverges.

begin new x;

procedure Add 2 ;  % Add 2 is the ability to add 2 to x

begin x := contents(x) + 2 end; x := 0;

Q(Add 2 );  % Q is declared elsewhere

if contents(x) mod 2 = 0 then diverge fi end

Here the external procedure Q is given the power to change x, but only in increments of two. Thus the contents of x remains even.

MS6 The block below always diverges.

begin new x; procedure AlmostAdd 2 (z);

begin if z = x then x := 1 else x := contents(x) + 2 fi end; x := 0; P (AlmostAdd 2 ); if contents(x) mod 2 = 0 then diverge fi

end

The test z = x here compares locations, rather than their contents. As P does not know of x, the conditional in AlmostAdd 2 always takes the else branch.

MS7 The block

begin new x; procedure Add 1 ; begin x := contents(x) + 1 end; P (Add 1 )

end

and the block

begin new x; procedure Add 2 ; begin x := contents(x) + 2 end; P (Add 2 )

end

are observationally congruent. The procedure calls P (Add 1 ) and P (Add 2 ) differ only in their effect on x; for while they can alter the variable, they cannot read it. As x is then immediately deallocated, the two blocks are equivalent.

Bibliography

[1] Applications of Categories in Computer Science: Proceedings of the LMS Symposium, Durham 1991. London Mathematical Society Lecture Note Series 177. Cambridge University Press, 1992. (pp. 136, 138)

[2] M. Abadi and G. Plotkin. Arities in relational parametricity. Unpublished preprint, November 1993. (p. 70)

[3] S. Abramsky. Domain Theory and the Logic of Observable Properties. PhD thesis, Queen Mary College, University of London, October 1987. (pp. 33, 123)

[4] S. Abramsky. The lazy lambda calculus. In Research Topics in Functional Programming, pages 65–117. Addison Wesley, 1990. (pp. 2, 8, 32)

[5] S. Abramsky. Computational interpretations of linear logic. Theoretical Computer Science, 111:3–57, 1993. (p. 125)

[6] S. Abramsky and R. Jagadeesan. Games and full completeness for multiplicative linear logic. Technical Report 92/24, Department of Computing, Imperial College, September 1992. (p. 123)

[7] A. W. Appel. Compiling with Continuations. Cambridge University Press, 1992. (p. 5)

[8] L. Augustsson. A compiler for Lazy ML. In Conference Record of the 1984 ACM Symposium on Lisp and Functional Programming, pages 218–227. ACM Press, 1984. (p. 3)

[9] L. Augustsson, M. Rittri, and D. Synek. On generating unique names. Journal of Functional Programming, 4:117–123, January 1994. (p. 124)

[10] H. P. Barendregt. The Lambda Calculus: Its Syntax and Semantics. Studies in Logic and the Foundations of Mathematics 103. North Holland, 1984. (p. 2)

[11] E. Barendsen and J. E. W. Smetsers. Conventional and uniqueness typing in graph rewriting. In Proceedings of the 13th Conference on the Foundations of Software Technology and Theoretical Computer Science, Lecture Notes in Computer Science 761. Springer-Verlag, 1993. (p. 125)

[12] H.-J. Boehm. A Logic for the Russell Programming Language. PhD thesis, Cornell University, Ithaca, New York, February 1984. Also published as Technical Report 84-593, Department of Computer Science, Cornell University. (p. 124)

[13] H.-J. Boehm. Side effects and aliasing can have simple axiomatic descriptions. ACM Transactions on Programming Languages and Systems, 7(4):637–655, October 1985. (p. 124)

[14] L. Cardelli and P. Wegner. On understanding types, data abstraction, and polymorphism. ACM Computing Surveys, 17(4), December 1985. (p. 123)

[15] J. W. de Bakker. Mathematical Theory of Program Correctness. Prentice Hall, 1980. (p. 6)

[16] A. J. Demers and J. E. Donahue. Making variables abstract: An equational theory for Russell. In Conference Record of the Tenth Annual ACM Symposium on Principles of Programming Languages, pages 59–72. ACM Press, January 1983. Also published as Technical Report 82-534, Department of Computer Science, Cornell University. (p. 124)

[17] J. Fairbairn. Ponder and its type system. Technical Report 31, University of Cambridge Computer Laboratory, November 1982. (p. 5)

[18] J. Fairbairn. Design and Implementation of a Simple Typed Language based on the Lambda-Calculus. PhD thesis, University of Cambridge, May 1984. Also published as Technical Report 75, University of Cambridge Computer Laboratory. (p. 5)

[19] M. Felleisen and D. P. Friedman. Control operators, the SECD-machine and the λ-calculus. In Formal Description of Programming Concepts III, pages 193–217. North Holland, 1986. (p. 19)

[20] M. Felleisen and D. P. Friedman. A syntactic theory of sequential state. Theoretical Computer Science, 69:243–287, 1989. (p. 125)

[21] M. Felleisen and R. Hieb. The revised report on the syntactic theories of sequential control and state. Theoretical Computer Science, 103:235–271, 1992. Also published as Technical Report 100-89, Rice University. (p. 125)

[22] Functional Programming Languages and Computer Architecture: Proceedings of the 5th ACM Conference, Cambridge, MA, USA, August 26–30, 1991, Lecture Notes in Computer Science 523. Springer-Verlag, 1991. (pp. 139, 140)

[23] J.-Y. Girard. Interprétation fonctionelle et élimination des coupures dans l’arithmétique d’ordre supérieur. Thése de doctorat d’état, Université Paris VII, 1972. (p. 5)

[24] J.-Y. Girard, Y. Lafont, and P. Taylor. Proofs and Types. Cambridge Tracts in Theoretical Computer Science 7. Cambridge University Press, 1989. (p. 5)

[25] A. D. Gordon. Functional Programming and Input/Output. Cambridge University Press, September 1994. (pp. 1, 27, 32, 33, 106)

[26] J. C. Guzman and P. Hudak. Single-threaded polymorphic lambda calculus. In Proceedings of the Fifth Annual IEEE Symposium on Logic in Computer Science, pages 333–345. IEEE Computer Society Press, 1990. (p. 125)

[27] M. Hennessey. Algebraic Theory of Processes. MIT Press, 1989. (p. 123)

[28] C. A. R. Hoare. An axiomatic basis for computer programming. Communications of the ACM, 12(10):576–580, October 1969. (p. 6)

[29] S. Holmström. A linear functional language. In Proceedings of the Aspenæs Workshop on Implementation of Lazy Functional Languages, Report 53, Programming Methodology Group, University of Göteborg and Chalmers University of Technology, pages 13–52, 1988. (p. 125)

[30] F. Honsell, I. A. Mason, S. Smith, and C. Talcott. A variable typed logic of effects, 1993. To appear in Information and Computation. (pp. 27, 101, 124)

[31] D. Howe. Equality in lazy computation systems. In LICS ’89 [47], pages 198–201. (pp. 32, 33, 106)

[32] P. Hudak. Mutable abstract datatypes. Research Report YALEU/DCS/RR-914, Yale University Department of Computer Science, 1992. (p. 125)

[33] P. Hudak, S. Peyton Jones, P. Wadler, et al. Report on the programming language Haskell – a non-strict, purely functional language (version 1.2). ACM SIGPLAN Notices, 27(5), May 1992. (p. 2)

[34] G. Hutton. Higher-order functions for parsing. Journal of Functional Programming, 2(3):323–343, July 1992. (p. 5)

[35] M. P. Jones. An introduction to Gofer. Included as part of the distribution for Gofer version 2.30a, June 1994. (p. 2)

[36] A. Jung and J. Tiuryn. A new characterization of lambda definability. In TLCA ’93 [129], pages 245–257. (pp. 91, 122)

[37] G. M. Kelly and R. H. Street. Review of the elements of 2-categories. In Proceedings of the Sydney Category Theory Seminar, Lecture Notes in Mathematics 420, pages 75–103. Springer-Verlag, 1974. (p. 78)

[38] D. J. King and J. Launchbury. Functional graph algorithms with depth-first search. In Proceedings of the 1993 Glasgow Workshop on Functional Programming, pages 145–155. Springer-Verlag, July 1993. (p. 2)

[39] A. Kock. Monads on symmetric monoidal closed categories. Archiv der Mathematik, XXI:1–10, 1970. (p. 53)

[40] A. Kock. Bilinearity and cartesian closed monads. Mathematica Scandinavica, 29:161–174, 1971. (p. 53)

[41] Y. Lafont. The linear abstract machine. Theoretical Computer Science, 59:157–180, 1988. (p. 125)

[42] J. Lambek and P. J. Scott. Introduction to Higher Order Categorical Logic. Cambridge Studies in Advanced Mathematics 7. Cambridge University Press, 1986. (pp. 7, 51, 122)

[43] J. Launchbury. Lazy imperative programming. In SIPL ’93 [118], pages 46–56. (p. 125)

[44] J. Launchbury and S. L. Peyton Jones. Lazy functional state threads. In Proceedings of the 1994 ACM SIGPLAN Conference on Programming Language Design and Implementation. ACM Press, 1994. (p. 125)

[45] J. Launchbury and S. L. Peyton Jones. State in Haskell. Lisp and Symbolic Computation, 1995. To appear. (pp. 123, 125)

[46] A. F. Lent. The category of functors from state shapes to bottomless CPOs is adequate for block structure. In SIPL ’93 [118], pages 101–119. (p. 93)

[47] Proceedings of the Fourth Annual IEEE Symposium on Logic in Computer Science. IEEE Computer Society Press, 1989. (pp. 133, 135)

[48] C. H. Lindsay and S. G. van der Meulen. Informal Introduction to Algol 68. North Holland, Amsterdam, 1980. (p. 5)

[49] J. M. Lucassen and D. K. Gifford. Polymorphic effect systems. In POPL ’88 [99], pages 47–57. (p. 125)

[50] Q. Ma and J. C. Reynolds. Types, abstraction, and parametric polymorphism, part 2. In Mathematical Foundations of Programming Semantics: Proceedings of the 7th International Conference, Lecture Notes in Computer Science 598, pages 1–40. Springer-Verlag, 1992. (p. 8)

[51] S. Mac Lane. Categories for the Working Mathematician. Graduate Texts in Mathematics 5. Springer-Verlag, 1971. (p. 7)

[52] S. Mac Lane and I. Moerdijk. Sheaves in Geometry and Logic: A First Introduction to Topos Theory. Springer-Verlag, 1992. (pp. 7, 59, 63, 116)

[53] I. A. Mason. The Semantics of Destructive Lisp. PhD thesis, Stanford University, 1986. Also published as CSLI Lecture Notes Number 5, Center for the Study of Language and Information, Stanford University. (p. 124)

[54] I. A. Mason and C. Talcott. Equivalence in functional languages with effects. Journal of Functional Programming, 1(3):297–327, July 1991. (pp. 107, 124)

[55] I. A. Mason and C. Talcott. Inferring the equivalence of functional programs that mutate data. Theoretical Computer Science, 105:167–215, 1992. (pp. 107, 124)

[56] D. C. J. Matthews. Programming Language Design with Polymorphism. PhD thesis, University of Cambridge, 1983. Also published as Technical Report 49, University of Cambridge Computer Laboratory. (p. 5)

[57] A. R. Meyer and K. Sieber. Towards fully abstract semantics for local variables: Preliminary report. In POPL ’88 [99], pages 191–203. (pp. 93, 102, 128)

[58] Mathematical Foundations of Computer Science: Proceedings of the 18th International Symposium MFCS ’93, Gdańsk, Poland, August 30–September 3, 1993, Lecture Notes in Computer Science 711. Springer-Verlag, 1993. (pp. 137, 140)

[59] R. Milner. Fully abstract models of typed λ-calculi. Theoretical Computer Science, 4:1–22, 1977. (pp. 6, 7, 26, 122)

[60] R. Milner. Elements of interaction. Communications of the ACM, 36(1):78–89, January 1993. Turing Award lecture. (p. 4)

[61] R. Milner, J. Parrow, and D. Walker. A calculus of mobile processes, parts I and II. Information and Computation, 100:1–77, 1992. (pp. 4, 123)

[62] R. Milner, M. Tofte, and R. Harper. The Definition of Standard ML. MIT Press, 1990. (pp. 3, 11, 99)

[63] J. C. Mitchell and E. Moggi. Kripke-style models for typed lambda calculus. In Proceedings of the Second Annual IEEE Symposium on Logic in Computer Science, pages 303–314. IEEE Computer Society Press, 1987. (p. 57)

[64] J. C. Mitchell and E. Moggi. Kripke-style models for typed lambda calculus. Annals of Pure and Applied Logic, 51:99–124, 1991. (p. 57)

[65] J. C. Mitchell and G. Plotkin. Abstract types have existential type. ACM Transactions on Programming Languages and Systems, 10(3):470–502, July 1988. (p. 123)

[66] E. Moggi. Computational lambda-calculus and monads. In LICS ’89 [47], pages 14–23. (pp. 8, 37)

[67] E. Moggi. An abstract view of programming languages. Technical Report ECS-LFCS-90-113, Laboratory for Foundations of Computer Science, University of Edinburgh, April 1990. (pp. 8, 37, 57, 119)

[68] E. Moggi. Notions of computation and monads. Information and Computation, 93(1):55–92, July 1991. (pp. 8, 37, 43, 51, 52, 79)

[69] E. Moggi. A semantics for evaluation logic, 1993. To appear in Fundamenta Informaticae. (p. 59)

[70] J. H. Morris. Lambda Calculus Models of Programming Languages. PhD thesis, Massachusets Institute of Technology, 1968. (p. 6)

[71] P. Naur et al. Revised report on the algorithmic language Algol 60. Communications of the ACM, 6(1):1–17, January 1963. (p. 4)

[72] G. Nelson, editor. Systems Programming with Modula-3. Prentice Hall, 1991. (p. 5)

[73] F. Nielson and H. R. Nielson. Layered predicates. In Proceedings of the 1992 Workshop on Semantics: Foundations and Applications, Lecture Notes in Computer Science 666, pages 425–456. Springer-Verlag, 1992. Also published as Technical Report DAIMI PB-423, Computer Science Department, Aarhus University. (p. 91)

[74] M. Odersky. A syntactic theory of local names. Research Report YALEU/DCS/RR-965, Yale University Department of Computer Science, May 1993. (p. 124)

[75] M. Odersky. A functional theory of local names. In Conference Record of POPL ’94: 21st ACM Symposium on Principles of Programming Languages, pages 48–59. ACM Press, 1994. (p. 124)

[76] M. Odersky, D. Rabin, and P. Hudak. Call-by-name, assignment, and the lambda calculus. In POPL ’93 [100], pages 43–56. (p. 124)

[77] P. W. O’Hearn. Linear logic and interference control (preliminary report). In Category Theory and Computer Science 1991, Lecture Notes in Computer Science 530, pages 74–93. Springer-Verlag, 1991. (p. 93)

[78] P. W. O’Hearn. A model for syntactic control of interference. Mathematical Structures in Computer Science, 3:435–465, 1993. (pp. 93, 125)

[79] P. W. O’Hearn and J. G. Riecke. Fully abstract translations and parametric polymorphism. In Programming Languages and Systems — ESOP ’94, Lecture Notes in Computer Science 788, pages 454–468. Springer-Verlag, 1994. (pp. 123, 125)

[80] P. W. O’Hearn and J. G. Riecke. Kripke logical relations and PCF, June 1994. Submitted to Information and Computation. (pp. 91, 122)

[81] P. W. O’Hearn and R. D. Tennent. Semantics of local variables. In Applications of Categories in Computer Science 1991 [1], pages 217–238. (pp. 57, 93, 125)

[82] P. W. O’Hearn and R. D. Tennent. Parametricity and local variables. Technical Report SU-CIS-93-30, School of Computer and Information Science, Syracuse University, October 1993. (pp. 8, 78, 93, 103, 108, 125)

[83] P. W. O’Hearn and R. D. Tennent. Relational parametricity and local variables (preliminary report). In POPL ’93 [100], pages 171–184. (pp. 8, 93, 125)

[84] P. W. O’Hearn and R. D. Tennent. Semantical analysis of specification logic, part 2. Information and Computation, 107(1):25–57, November 1993. (pp. 93, 125)

[85] A. Ohori. Representing object identity in a pure functional language. In ICDT ’90: Proceedings of the Third International Conference on Database Theory, Lecture Notes in Computer Science 470. Springer-Verlag, 1990. (p. 4)

[86] C. Okasaki. Simple and efficient purely functional queues and deques. Journal of Functional Programming, 1994. To appear. (p. 2)

[87] F. J. Oles. A Category-Theoretic Approach to the Semantics of Programming Languages. PhD thesis, Syracuse University, 1982. (pp. 93, 125)

[88] F. J. Oles. Type algebras, functor categories and block structure. In M. Nivat and J. Reynolds, editors, Algebraic Methods in Semantics, pages 543–573. Cambridge University Press, 1985. (pp. 57, 93, 125)

[89] S. L. Peyton Jones and P. Wadler. Imperative functional programming. In POPL ’93 [100], pages 71–84. (p. 125)

[90] A. M. Pitts. Evaluation logic. In IVth Higher Order Workshop, Banff 1990, pages 162–189. Springer-Verlag, 1991. Also published as Technical Report 198, University of Cambridge Computer Laboratory. (pp. 8, 37, 39)

[91] A. M. Pitts and I. Stark. Observable properties of higher order functions that dynamically create local names, or: What’s new? In MFCS ’93 [58], pages 122– 141. (pp. -5, 33)

[92] A. M. Pitts and I. Stark. On the observable properties of higher order functions that dynamically create local names (preliminary report). In SIPL ’93 [118], pages 31–45. (pp. -5, 33)

[93] A. M. Pitts, I. Stark, and V. de Paiva. State and monadic ML. In preparation, 1995. (p. 107)

[94] G. Plotkin. Call-by-name, call-by-value and the λ-calculus. Theoretical Computer Science, 1:125–159, 1975. (pp. 6, 19, 20, 24)

[95] G. Plotkin. LCF considered as a programming language. Theoretical Computer Science, 5:223–255, 1977. (pp. 6, 7)

[96] G. Plotkin. Lambda-definability in the full type heirarchy. In J. P. Seldin and J. R. Hindley, editors, To H. B. Curry: Essays on Combinatory Logic, Lambda Calculus and Formalism, pages 363–373. Academic Press, 1980. (pp. 8, 33)

[97] G. Plotkin and M. Abadi. A logic for parametric polymorphism. In TLCA ’93 [129], pages 361–375. (pp. 5, 70, 122, 123)

[98] C. G. Ponder, P. McGeer, and A. P. Ng. Are applicative languages inefficient? ACM SIGPLAN Notices, 23(6):135–139, June 1988. (p. 2)

[99] Conference Record of the Fifteenth Annual ACM Symposium on Principles of Programming Languages, San Diego, January 1988. ACM Press, 1988. (p. 134)

[100] Conference Record of the Twentieth Annual ACM Symposium on Principles of Programming Languages, Charleston, South Carolina, January 1993. ACM Press, 1993. (p. 136)

[101] U. S. Reddy. Global state considered unnecessary. In SIPL ’93 [118], pages 120– 135. (p. 93)

[102] U. S. Reddy. Passivity and independence. In Proceedings of the Ninth Annual IEEE Symposium on Logic in Computer Science, pages 342–352. IEEE Computer Society Press, 1994. (p. 93)

[103] J. C. Reynolds. GEDANKEN — A simple typeless language based on the principle of completeness and the reference concept. Communications of the ACM, 13(5):308–319, May 1970. (p. 5)

[104] J. C. Reynolds. Towards a theory of type structure. In Paris Colloquium on Programming, Lecture Notes in Computer Science 19, pages 408–425. Springer-Verlag, April 1974. (p. 5)

[105] J. C. Reynolds. Syntactic control of interference. In Conference Record of the Fifth Annual ACM Symposium on Principles of Programming Languages, pages 39–46. ACM Press, 1978. (p. 125)

[106] J. C. Reynolds. The Craft of Programming. Prentice Hall, 1981. (p. 125)

[107] J. C. Reynolds. The essence of Algol. In Proceedings of the 1981 International Symposium on Algorithmic Languages, pages 345–372. North Holland, 1981. (pp. 4, 5, 57, 93)

[108] J. C. Reynolds. Idealized Algol and its specification logic. In D. Néel, editor, Tools and Notions for Program Construction, pages 121–161. Cambridge University Press, 1982. (p. 125)

[109] J. C. Reynolds. Types, abstraction and parametric polymorphism. In Information Processing ’83, pages 513–523. North Holland, 1983. (p. 8)

[110] J. C. Reynolds. Syntactic control of interference, part II. In Proceedings of ICALP ’89, Lecture Notes in Computer Science 372, pages 704–722. Springer-Verlag, 1989. (p. 125)

[111] J. G. Riecke. Delimiting the scope of effects. In FPCA ’93: Conference on Functional Programming Languages and Computer Architecture, pages 146–155. ACM Press, 1993. (p. 125)

[112] J. G. Riecke. Fully abstract translations between functional languages. Mathematical Structures in Computer Science, 1995. To appear. (p. 2)

[113] E. Ritter and A. M. Pitts. A fully abstract translation between a λ-calculus with reference types and Standard ML. In Typed Lambda Calculi and Applications: TLCA ’95. Springer-Verlag Lecture Notes in Computer Science, 1995. To appear. (pp. 99, 106)

[114] A. Sabry and M. Felleisen. Reasoning about programs in continuation-passing style. Lisp and Symbolic Computation, 6(3/4):287–358, 1993. (p. 24)

[115] K. Sieber. Reasoning about sequential functions via logical relations. In Applications of Categories in Computer Science 1991 [1], pages 258–269. (p. 8)

[116] K. Sieber. New steps towards full abstraction for local variables. In SIPL ’93 [118], pages 88–100. (pp. 93, 125)

[117] K. Sieber. Full abstraction for the second order subset of an Algol-like language (preliminary report). Technical Report A 01/94, Universität des Saarlandes, Saarbrücken, January 1994. (pp. 93, 108, 121, 125)

[118] Proceedings of the ACM SIGPLAN Workshop on State in Programming Languages, Copenhagen, Denmark, June 12, 1993, Yale University Department of Computer Science Research Report YALEU/DCS/RR-968, 1993. (pp. 134, 137, 138)

[119] M. B. Smyth and G. D. Plotkin. The category-theoretic solution of recursive domain equations. SIAM Journal on Computing, 11(4):761–783, November 1982. (p. 7)

[120] I. Stark. Categorical models for local names. Lisp and Symbolic Computation, 1995. To appear. (p. -5)

[121] R. Statman. Completeness, invariance and λ-definability. Journal of Symbolic Logic, 47:17–26, 1982. (p. 8)

[122] J. E. Stoy. Denotational Semantics: the Scott-Strachey Approach to Programming Language Theory. MIT Press, 1977. (p. 7)

[123] V. Swarup and U. S. Reddy. A logical view of assignments. In Constructivity in Computer Science 1991, Lecture Notes in Computer Science 613. Springer-Verlag, 1991. (p. 125)

[124] V. Swarup, U. S. Reddy, and E. Ireland. Assignments for applicative languages. In FPCA ’91 [22], pages 192–214. (p. 125)

[125] R. D. Tennent. Semantics of interference control. Theoretical Computer Science, 27:297–310, 1983. (pp. 93, 125)

[126] R. D. Tennent. Semantical analysis of specification logic. Information and Computation, 85(2):135–162, 1990. (pp. 93, 125)

[127] R. D. Tennent. Semantics of Programming Languages. Prentice Hall, 1991. (pp. 93, 125)

[128] M. Tillotson. Introduction to the functional programming language “Ponder”. Technical Report 65, University of Cambridge Computer Laboratory, May 1985. (p. 2)

[129] Typed Lambda Calculi and Applications: Proceedings of TLCA ’93, March 16–18, 1993, Utrecht, the Netherlands, Lecture Notes in Computer Science 664. Springer-Verlag, 1993. (pp. 133, 137)

[130] D. A. Turner. Miranda: a non-strict functional language with polymorphic types^{∗}. In Functional Programming Languages and Computer Architecture 1985, Lecture Notes in Computer Science 201, pages 1–16. Springer-Verlag, 1985. (p. 2)

[131] R. van der Linden. The ANSA naming model. Architecture Report APM.1003.01, Architecture Projects Management Ltd., Cambridge, UK, July 1993. (p. 4)

[132] A. van Wijngaarden et al. Revised Report On the Algorithmic Language Algol 68. Springer, 1976. (p. 5)

[133] P. Wadler. Comprehending monads. Mathematical Structures in Computer Science, 2:461–493, 1992. (pp. 3, 125)

[134] P. Wadler. The essence of functional programming. In Conference Record of the Nineteenth Annual ACM Symposium on Principles of Programming Languages, pages 1–14. ACM Press, 1992. (pp. 3, 125)

∗Miranda is a trademark of Research Software Limited

[135] P. Wadler. Monads and functional programming. In Proceedings of the 1992 Marktoberdorf Summer School on Program Design Calculi, NATO ASI Series F: Computer and System Sciences 118. Springer-Verlag, 1993. (p. 125)

[136] P. Wadler. A taste of linear logic. In MFCS ’93 [58]. (p. 125)

[137] D. Wakeling and C. Runciman. Linearity and laziness. In FPCA ’91 [22], pages 215–240. (p. 125)

[138] M. V. Wilkes and R. M. Needham. The Cambridge CAP Computer and its Operating System. North Holland, 1979. (p. 4)

[139] G. C. Wraith. A note on categorical datatypes. In Category Theory and Computer Science 1989, Lecture Notes in Computer Science 389. Springer-Verlag, 1989. (p. 5)