Ambre Par

Williams

Reader, Conor Mcbride

Épiphanie, Théo, Cécile, Maiting, Jonathan, Loïc, Irène Beaucoup À Arthur

Renaud

Ulysse, Anaël, Kenji, Basile, Damien Julie Guillaume

Najib, Aymeric, Grégoire Abel

Typq Ñ Typ

Refactoring functional programs with ornaments

Keywords:

J'aurais dû commencer par rédiger ce chapitre pour n'oublier personne, je l'écris finalement la veille de ma soutenance. J'espère que celles et ceux que j'aurai inévitablement oublié de remercier ici pourront m'en excuser.

J'ai commencé à travailler sur les ornements dans le cadre d'un stage de M2, proposé par Didier Rémy et Pierre-Évariste Dagand. Pendant ce stage, j'ai découvert l'équipe Gallium, avec qui il a été très agréable de travailler. Merci pour les cafés et Café-vous-fait, les discussions de cantine, pour les conseils pendant mes répétitions d'exposés, et merci à tous ceux avec qui j'ai partagé un bureau. Vous avez participé à me convaincre de rester pour ma thèse.

Je ne pouvais espérer meilleur directeur que Didier : il a toujours été disponible pour passer plusieurs heures à discuter de mon avancement, apportant un oeil extérieur bienvenu et des idées fraîches quand je rencontrais des difficultés. Beaucoup de cette thèse n'existe que grâce à ses retours, m'encourageant à développer les concepts intéressants, les rendre plus clairs et les généraliser.

En septembre 2018, alors que j'étais déjà en retard, j'estimais qu'il ne me manquait que deux mois avant d'avoir fini de rédiger. Avec la distraction d'un emploi à plein temps, et parce que j'avais sous-estimé le travail restant, cela m'a finalement pris deux ans, pendant lesquels certaines idées ont pu mûrir pour arriver à une présentation, je l'espère, plus clair et intéressante.

Je remercie beaucoup Didier pour m'avoir poussé à continuer pendant cette période, m'avoir rappelé des deadlines administratives que j'aurais sans doute manquées, et avoir continué à prendre régulièrement du temps avec moi pour discuter de mon avancement. J'ai aussi été beaucoup soutenue par Annalí, qui à de nombreuses occasions m'a dissuadé de simplement arrêter. Son aide pendant les derniers mois de la rédaction a été indispensable. Je la remercie aussi beaucoup de sa patience pour les soirées et les week-ends volés par la rédaction, et pour avoir supporté mon stress à une période qui n'était pas non plus facile pour elle. Merci aussi à mes parents pour m'avoir encouragée dans ce processus.

J'ai rédigé une partie de cette thèse au Mexique. Mario y Susana, muchas gracias por la hospitalidad. ¡Espero que nos podamos ver pronto! J'ai passé les deux dernières semaines de rédaction dans le très agréable village de Gratallops, en Catalogne. Moltes gràcies Mireia, una forta abraçada! I also spent a few weeks at Oscar Wilde House in Berkeley while Annalí was staying there. Thank you all for the food and the company.

Je n'ai heureusement pas pensé qu'à la thèse pendant ces six ans. Merci

Titre : Refactorisation de programmes fonctionnels par les ornements Résumé : Les ornements fournissent un moyen de définir des transformations de définitions de types de données inductifs réorganisant, spécialisant et ajoutant des champs à des types de données déjà existants. À partir d'une telle transformation, nous nous intéressons à la refactorisation semi-automatique d'un code déjà existant, écrit en ML et opérant sur le type de base pour le faire opérer sur le type ornementé. Nous décrivons un cadre pour de telles transformations, basé sur deux phases : tout d'abord, le terme de base est généralisé au maximum en ajoutant des abstractions sur les détails des types de données utilisés. Le terme est ensuite spécialisé pour opérer uniquement sur le type ornementé. Nous décrivons un langage intermédiaire fournissant les abstractions nécessaires pour présenter le terme générique, et garantissant qu'il est possible de simplifier le terme spécialisé pour ne présenter à l'utilisateur que des termes du langage de base. Le langage intermédiaire permet notamment d'exprimer des abstractions dépendantes, de représenter les égalités apprises par le filtrage de motifs, et fournit une construction permettant de se référer de façon opaque au résultats de calculs déjà effectués. Nous exploitons la paramétricité du terme généralisé pour prouver une relation de cohérence entre le terme de base et le terme ornementé, garantissant la correction de la refactorisation. Nous présentons une implémentation de cette transformation sur un langage ML noyau, et justifions de son utilité dans de nombreux cas courants de transformation de programme : refactorisation pure, ajout de nouvelles données et spécialisation. Nous présentons aussi une nouvelle technique de dépliage permise par notre transformation qui autorise à changer la structure récursive des fonctions, et illustrons son utilité pour optimiser certaines représentations de données et pour la programmation générique.

Mots clefs : ornements ; langages de programmation fonctionnelle ; types ; relations logiques ; refactorisation ; ML. Title: Refactoring functional programs with ornaments Abstract: Ornaments provide a way to express transformations of inductive datatypes that reorganize, specialize, and add fields to already existing datatypes. From such a transformation, we consider the problem of semi-automatically refactoring an al-ready existing ML program operating on the base type into a program operating on the ornamented type. We describe a framework for such transformations by decomposing them in two phases: first, the base term is maximally generalized by abstracting over the details of the manipulated datatypes. This generic term is subsequently specialized to operate only on the ornamented type. We describe an intermediate language providing the necessary abstractions to present the generic term. This language notably includes dependent abstractions, allows representing the equalities learned from pattern matching, and provide a way to refer to the opaque result of previous computations. We exploit the parametricity of the generic term to derive a coherence relation between the base term and the ornamented term, guaranteeing the correctness of the ornamented term. We present an implementation of this transformation on a core ML language, and illustrate its usefulness in many common cases of program transformation: pure refactoring, adding new data and specialization. We also present a new unfolding technique afforded by our transformation and present its use for optimizing certain data representation and for generic programming. Keywords: ornaments; functional programming languages; types; logical relations; refactoring; ML.

Résumé en français

Un programme est une description en terme précis des opérations qu'un ordinateur doit suivre afin d'accomplir une tâche donnée. Les instructions élémentaires interprétées par un ordinateur son extrêmement rudimentaires. Il faut parfois plusieurs centaines d'instructions pour trier une liste de nombres entiers ; les programmes les plus complexes, tels les navigateurs web, sont composés de dizaines de millions de ces instructions. Les langages de programmation sont des outils d'abstraction : ils permettent aux programmeurs de ne donner qu'une explication à un haut niveau d'abstraction de ce que le programme doit faire. Des compilateurs et des interprètes traduisent les représentations de haut niveau manipulées par les programmeurs en instructions de bas niveau. En libérant les programmeurs de la nécessité de penser à l'échelle des instructions élémentaires, les langages de programmation permettent aux programmeurs de construire des programmes plus complexes, plus vite.

Un programme n'est que rarement écrit d'une seule traite, sans ne rien effacer, et distribué pour n'être plus jamais modifié. Même lorsqu'on écrit la version initiale d'un programme, on peut ne pas avoir une idée exacte de la forme qu'il va prendre, et on a souvent besoin de revenir en arrière et changer certaines définitions à mesure que notre compréhension du problème s'affine. Une fois achevée l'écriture de la version initiale, on peut aussi s'apercevoir que les besoins ont changés, nécessitant un code plus général par certains aspects et moins général par d'autres : on doit alors changer certaines parties du programme pour correspondre aux nouvelles demandes. Tous ces changements ne sont pas locaux : même si l'essentiel du changement consiste en ne modifier que quelques éléments du programme, il peut demander une refactorisation très étendue pour faire circuler les nouvelles données à travers le code déjà existant. La version refactorisée d'un fragment de code peut venir remplacer le code déjà présent, ou les deux versions du code peuvent être amenées à coexister dans le programme, pour être utilisées dans des contextes différents. Ces transformations sont souvent longues, répétitives, et sans intérêt. Face à une telle tâche, un programmeur a souvent une idée générale de la transformation à réaliser, mais se retrouve obligé d'effectuer manuellement chaque changements requis pour cette refactorisation. Notre but est de fournir des outils rendant cette transformation plus rapide et facile.

Si le programmeur a pris soin d'éviter les effets de bords, les différents fragments du programme communique en échangeant des données à travers les arguments de fonctions et leurs valeurs de retours. Ces données sont contraintes : les parties du programme qui communiquent doivent s'accorder sur un format pour les données qu'elles échangent. Si le langage de programmation le permet, une partie de ces contraintes peut s'exprimer sous forme de types. Les types peuvent être vus comme un système de classification de valeurs et de programmes qui, de plus, est compréhensible par le langage de programmation. Les types forment un outil puissant : ils permettent au langage de programmation de rejeter un programme dès la compilation car il pourrait à l'exécution atteindre un état incorrect. Les types jouent aussi pour le programmeur un rôle de documentation dont l'exactitude est garantie par le langage. En lisant le type d'une fonction, on apprend des contraintes sur la façon dont elle doit être appelée, et on obtient des garanties sur le comportement et les valeurs retournées par cette fonction. Cela permet de s'assurer que des catégories entières de comportement erronés ne peuvent se produire.

Bien qu'ils ne caractérisent le comportement que d'une seule version d'un programme considéré en isolation, les types fournissent un guide utile pour la refactorisation : lorsque l'un des effets de la refactorisation est de changer le type de certaines données, le système de types peut orienter un programmeur vers les emplacements du programme qui sont maintenant mal typés. Le programmeur peut alors effectuer les changements locaux nécessaires et relancer le typeur. Le typeur va alors soit pointer vers d'autres emplacements qui sont maintenant mal typés, soit accepter le programme, concluant ainsi la refactorisation. Ce n'est pourtant pas une solution satisfaisante. Premièrement, certaines transformations ne changent pas les types, seulement la façon dont leurs valeurs sont interprétées. Par exemple, si la transformation inverse le sens d'une valeur booléenne, le système de types sera incapable d'indiquer les endroits où le code doit être modifié, et le programmeur devra garder trace de ces emplacements lui-même. De plus, cela reste un processus extrêmement manuel et ennuyeux : le programmeur ne doit plus chercher lui-même les emplacements à modifier, mais doit tout de même effectuer chaque changement manuellement. Ces changements, qui devraient être simplement mécaniques, sont aussi sources d'erreurs. Tout cela décourage les programmeurs d'effectuer de tels changements : à la place, ils choisissent souvent de laisser un commentaire indiquant qu'un refactorisation devrait être effectuée.

On attend d'un outil de refactorisation qu'il élimine autant que possible ces coûts, ne laisse que le minimum de travail au programmeur, et qu'il fournisse une garantie solide que le nouveau programme est seulement une adaptation du programmeur d'origine à de nouvelles données.

Dans la famille des langages dérivés de ML, les types de données inductifs sont l'outil principal pour décrire l'organisation des données. On les définit comme des sommes étiquetées de produits de types primitifs et d'autres types inductifs. Les produits permettent de former des valeurs composées de plusieurs autres valeurs, permettant par abstraction de les manipuler comme une valeur singulière. Par exemple, plutôt que de manipuler individuellement des paires de coordonnées, un programmeur trouvera plus pratique de manipuler un point à deux dimensions comme une unité de programmation et de pensée, et il ne considérera les deux coordonnées que pour définir des opérations basiques sur ces points. Les sommes permettent l'expression de choix : une forme géométrique est soit un triangle, défini par ses trois sommets, ou un cercle, défini par son centre et son rayon. Finalement, la récursion permet de représenter des structures de taille illimitée : une liste de formes géométriques est soit la liste vide, soit une liste formée en ajoutant un élément en tête d'une autre liste.

Une même structure de données peut souvent être représentée par plusieurs structures isomorphes, en utilisant un arrangement différent de sommes et de produits. Deux structures de données peuvent aussi n'être différente que par des éléments mineurs. Par exemple, le type des arbres binaires portant des valeurs aux feuilles et le type des arbres binaires portant des valeurs aux branches partagent une même structure où chaque noeud possède deux sous-arbres, mais les fonctions opérant sur ces deux types doivent être définies séparément.

Puisque les types de données inductifs sont la manière principale de représenter les données en ML, et puisque, dans des programmes bien structurés, des modules distants interagissent principalement par l'échange de données, la transformation des types inductifs est une catégorie importante de refactorisation en ML.

La théorie des ornements [START_REF] Mcbride | Ornamental algebras, algebraic ornaments[END_REF][START_REF] Dagand | A categorical treatment of ornaments[END_REF], 2014] fournit un cadre dans lequel exprimer ces transformations. Elle définit des conditions sous lesquelles une nouvelle définition de données peut être décrite comme un ornement d'une autre. Un ornement est essentiellement une relation entre deux types de données inductifs qui réorganise, spécialise et ajoute des données à un type de base pour obtenir un type ornementé.

Prenant les ornements comme brique de base, on peut définir des types d'ornement qui expriment une relation entre un terme de base et un terme lifté : un type d'ornement n'est pas simplement une spécification unaire qui classifie des termes pris individuellement, mais plutôt une spécification binaire qui indique comment le comportement du terme de base, qui opère sur le type de base, est lié au comportement du terme lifté, qui opère sur le type ornementé. Ces types donnent donc une spécification de l'opération de refactorisation : un lifting est correct si son résultat est lié au terme de base par la relation définie par le type d'ornement demandé.

Nous décrivons dans cette thèse une approche bien-fondée pour obtenir des liftings garantis corrects. Cette approche est basée sur la construction a posteriori d'une variante la plus générale possible en abstrayant sur les détails de la représentation de données, qui peut ensuite être spécialisée pour obtenir un lifting concret. Les abstractions nécessaires ne peuvent pas être exprimées en ML. Pour la construire, nous définissions mML, une version de ML étendue avec les mécanismes d'abstraction nécessaires, mais construire de sorte à garantir que les termes spécialisés puissent être simplifiés pour obtenir à nouveau des termes de ML. Nous montrons ensuite que le terme de base peut être exprimé comme une instance particulière du terme généralisé, où l'on sélectionne systématiquement l'ornement identité, qui lie un type avec lui-même. Cela nous permet d'exploiter la paramétricité pour prouver l'existence de la relation désirée entre le terme de base et le terme ornementé.

Ce travail théorique est accompagné d'une implémentation opérant sur une version noyau de ML avec types de données et polymorphisme. Ce prototype, disponible en ligne sur https://morphis.me/ornaments/, met en oeuvre un certain nombre de techniques, que nous décrivons dans ce manuscrit, pour générer du code proche de ce qu'un programmeur aurait écrit manuellement. Il est accompagné d'une bibliothèque d'exemples illustrant ses capacités.

La première partie de ce manuscrit introduit le concept d'ornement par le biais d'exemples illustrant différentes possibilités d'utilisation : refactorisation pure, ajout de données, spécialisation, optimisation et programmation générique. Ces exemples servent aussi d'illustration des capacités de notre implémentation. Nous donnons ensuite une vue d'ensemble du processus d'ornementation : nous faisons abstraction des détails les plus techniques et présentons les principes généraux guidant la transformation.

Dans une deuxième partie, nous laissons pour un moment de côté les ornements, et nous nous concentrons sur la conception et la formalisation des briques de base permettant de construire notre transformation. Bien qu'ils aient étés conçus pour permettre l'ornementation, ces briques sont indépendantes des ornements et pourraient être appliquées pour réaliser d'autres transformations de programme. Nous présentons tout d'abord une définition et la méta-théorie de notre ML noyau. Nous ajoutons ensuite les fonctionnalités nécessaires à la transformation désirée. Tout d'abord, les programmes font en pratique intervenir des effets de bord : ils peuvent ne pas terminer, terminer avec une erreur, tirer des nombres aléatoires, ou lire et écrire des fichiers. Ces opérations, non purement fonctionnelle, sont un obstacle à la transformation de programmes : elles ne peuvent pas être librement dupliquées, réordonnées, ou supprimées. Nous définissions un système d'étiquetage permettant de se référer au résultat d'une de ces opérations précédemment effectuée sans avoir à dupliquer l'opération elle-même. Nous utilisons ces étiquettes pour définir eML, une extension de ML ajoutant une construction de filtrage par motifs au niveau des types. Pour permettre de réduire le filtrage au niveau des types, le filtrage au niveau des termes introduit une égalité entre le terme sur lequel on filtre et le motif de la branche sélectionnée. Si le terme sur lequel on filtre contient une application de fonction, on utilise son étiquette pour s'y référer, tout en gardant l'application opaque pour les règles de raisonnement de eML. Cela permet notamment de fournir un jugement d'égalité décidable. Nous définissons ensuite un langage appelé mML en ajoutant des abstractions dépendantes à eML. Nous prêtons particulièrement attention à isoler ces abstractions pour garantir qu'il soit possible de les réduire entièrement sans évaluer les parties eML du terme : nous garantissons ainsi qu'elles peuvent être éliminées du terme lifté avant de le présenter à l'utilisateur. Afin de raisonner sur mML, nous définissons une relation logique indicée. Cette relation fournit un cadre sur lequel il sera possible de définir des ornements d'ordre supérieur à partir d'ornements de base, et d'exprimer la relation entre un type de base et un type ornementé. Finalement, nous décrivons un procédé permettant de simplifier un terme eML pour obtenir un terme ML bien typé, garantissant ainsi que les constructions puissantes utilisées pour la transformation ne soient plus apparentes dans le code généré.

Une fois les briques de base définies, nous revenons à la définition de notre transformation, et nous construisons une preuve de sa correction. Nous décrivons tout d'abord comment transformer une définition d'ornement fournie par l'utilisateur à la fois en une définition de relation compatible avec la relation logique, et en fragments de code utilisés pour spécialiser le terme générique. Nous définissons, relativement à la relation induite, un critère de correction pour ces fragments de code, et montrons qu'il est satisfait. Nous décrivons ensuite comment transformer un terme de base en terme générique. Nous définissons sa spécialisation par l'ornement identité, et prouvons qu'elle est équivalente au terme de base. Finalement, nous expliquons comment une demande de lifting fournie par l'utilisateur est transcrite en une spécialisation d'un terme générique, et prouvons le lien entre le terme de base et le terme ornementé.

Nous nous tournons ensuite à l'aspect pratique du travail : nous décrivons certains aspects clés de l'implémentation du prototype, et les stratégies utilisées pour présenter à l'utilisateur du code lisible, ainsi que les améliorations permettant de réduire le travail nécessaire pour spécifier un lifting. Nous présentons une technique de dépliage permettant de définir des liftings qui ne respectent pas la structure récursive de la fonction de base, et nous présentons des exemples de manipulations de structure de données rendues possibles par cette technique. Nous décrivons finalement quelques pistes de travail dans la continuation de cette thèse, et les liens avec des travaux existants.

Chapter 1

Introduction

A program is a description in precise terms of the operations a computer should follow to accomplish a particular task. The elementary instructions executed by computers are extremely rudimentary. Sorting a list of integers may require hundreds of instructions; complex programs, such as web browsers, are composed of tens of millions of these elementary instructions. A programming language is a tool of abstraction: it allows programmers to give a higher-level explanation of what the program should do. Compilers and interpreters translate the high-level representations manipulated by programmers into low-level instructions. By freeing the programmer from having to think at the level of the computer, programming languages enable programmers to build more complex programs faster.

Programs are rarely written in one go, without erasing anything, then shipped and never modified again. Even when writing the initial version of a program, the programmer may not have an exact idea of what a program should look like, and may often need to go back and change some definition as they understand the requirements better. After the initial version is written, they may realize that the requirements have changed, requiring more generality in some aspects, and less in some others, and change some part of the program to fit the new requirements. Some of these changes are non-local: while the core of the change may consist in modifying just a few program locations, they require extensive refactoring to weave new data and behavior throughout the existing code base. The refactored version of a piece of code may replace the existing code, or both versions of the code may co-exist in the program, to be used in different contexts. These transformations are often repetitive, timeconsuming, and uninteresting. Programmers may have a high-level view of the transformation they wish to perform, but have to manually perform every single change required by the refactoring. Our goal is to provide tools making these transformations easier.

If the programmer has been careful in avoiding side-effects, the different parts of their program communicate by exchanging data through function arguments and return values. This data is constrained: the parts of a program communicating together must agree on a format for the data they are exchanging. If the language permits it, some of these constraints may be expressed as types: types can be understood as a kind of classification of programs that is accessible to the programming language. Types are a powerful tool: they al-low the programming language to reject a program at compilation time because its execution may reach an incorrect state. Types also operate as a form of guaranteed-correct documentation to programmers: reading the type of a function gives information to the programmer about how the function ought to be called, and what kind of result may be expected. They allow the programmer to trust that whole classes of behaviors will never occur.

Even though they only characterize the behavior of one version of a program in isolation, types are useful to guide refactoring: when one effect of the refactoring is to change the type of some data, the type system is able to point the programmer to now ill-typed program locations. The programmer makes the necessary changes and runs the type checker again: the type checker will either point to new ill-typed locations, or accept the program, signalling that the refactoring is complete. This is still not a satisfying solution: First, some refactorings do not change the types, but only the way values are interpreted: if the meaning of a boolean is inverted, the type system would be unable to point us to the program location that need fixing and the programmer would have to track this location themselves. More importantly, this is still a boring and manual process: the programmer does not have to find the location to change anymore, but still has to perform all changes manually. These changes, that should often be simply mechanical, are still error-prone. This discourages programmers from attempting such changes: they may instead simply leave a note saying that a refactoring ought be performed.

A principled refactoring tool should eliminate as much as possible of these costs, leaving as little work as possible to the programmer, and providing a strong guarantee that the final program is merely an adaptation of the old one to the new data.

In the ML family of languages, inductive datatypes are the key tool used to describe the organization of data. They are defined as labeled sums and products of primitive types and other inductive datatypes. Products allow for composite values abstracting over sets of multiple values: for example, instead of manipulating pairs of coordinates, a programmer will find more convenient to manipulate two-dimensional points as a unit of programming and thought, and only look at the individual coordinates for implementing basic operations on the points. Sums allow the expression of choice: a shape is either a triangle, defined by three points, or a circle, defined by its center and radius. Finally, recursion allows representing data structures of unbounded size: a list of shapes is either the empty list, or a list formed by adding a first shape in front of another list of shapes.

However, the same data can often be represented with several isomorphic data-structures, using a different arrangement of sums and products. Two datastructures may also differ in minor ways, for instance sharing the same recursive structure, but one carrying an extra information at some specific nodes. For example, the type of leaf binary trees and the type of node binary trees both share a common binary-branching structure and are isomorphic but functions operating on them must be defined independently.

Since inductive datatypes are the main form of representing data in ML, and since distant modules in well-structured programs interact mostly through the exchange of data, the transformation of inductive datatypes is an important category of refactoring in ML.

The theory of ornaments [START_REF] Mcbride | Ornamental algebras, algebraic ornaments[END_REF][START_REF] Dagand | A categorical treatment of ornaments[END_REF], 2014] provides a framework to express these changes. It defines conditions under which a new datatype definition can be described as an ornament of another.

In essence, an ornament is a relation between two datatypes, reorganizing, specializing, and adding data to a bare type to obtain an ornamented type.

From ornaments as building blocks, we define ornament types relating a base term and a lifted term: an ornament type is not simply a unary specification classifying single terms, but a binary specification explaining how the behavior of the base term, operating on the base type, is related to the lifted term, operating on the ornamented type. These types thus give a specification for a lifting: a correct lifting is a lifting that is related to its base term at the desired ornament type.

We describe a principled approach to obtaining correct liftings. We abstract a posteriori a base term into a most general elaborated term, that can then be instantiated into a concrete lifting. This abstraction is not expressible in ML: we define a superset mML of ML that supports the necessary abstraction mechanisms, and guarantees that instantiated terms can be simplified back to terms of the original language. The base term can be seen as an instantiation of the generic term with identity ornaments, transforming a type into itself. We exploit parametricity to prove the expected relation between the base term and the ornamented term.

We implement this transformation on a core ML language with datatypes and polymorphism. Our prototype tool, available online at https://morphis.me/ ornaments/, implements a number of techniques to generate code that is close to code that would have been manually written, and comes with a collection of examples illustrating its features.

The rest of this dissertation is structured as follows. In Part I, we first give an introduction to ornaments by way of examples (Chapter 2). These examples also serve as a demonstration of our prototype tool, and show a variety of program transformations afforded by ornamentation. We then provide an overview of the ornamentation process, skipping over the most technical details to present the guiding principles of the transformation (Chapter 3).

In Part II, we forget about ornaments for a moment and design and formalize the building blocks of our transformation. Although they were designed for ornamentation, they are independent from ornaments and could be applied to other program refactorings. In Chapter 4, we present the definition and meta-theory of core ML. The next three chapters add the features necessary to present the transformation. Practical ML programs feature side-effects: they might not terminate, terminate with an error, draw random numbers, or read and write files. These impure computations are an obstacle to program transformation since they cannot be freely duplicated, reordered, or removed. We define in Chapter 5 a notion of labels allowing to refer to the results of previously performed computations in the terms evaluated subsequently, without duplicating the computations themselves. This is used in Chapter 6 to define eML, a language extending the types of ML with type-level pattern matching.

To reduce type-level pattern matching, term-level pattern matching introduces in a branch an equality between the scrutinee and the pattern of the branch. If the scrutinee contains a function application, labels allow us to refer to the result of these applications while leaving them otherwise opaque to eML's reasoning rules. To allow us to define the generic term, we define in Chapter 7 a language mML formed by adding dependent abstractions to eML. These ab-stractions are carefully isolated by enforcing staging so that they can be fully reduced without evaluating the eML parts of the term: this guarantees that they can be eliminated from the lifted term before presenting the term to the user. This is important, as we want the lifted term to be a term of the original language, that can be used as input to the same compiler. We define in Chapter 8 a binary logical relation on mML. That will give us a framework to build higher-order ornaments from datatype ornaments, and allow us to express the relation between the base type and the ornamented type. Finally, in Chapter 9, we describe how to simplify an eML term back to an ML term, ensuring that our intermediate language do not leak in the generated code.

Having defined the necessary machinery, we come back to ornaments in Part III. This part formalizes the concepts introduced in Chapter 3, and builds up to a correctness proof for lifting. In Chapter 10, we describe how to turn an ornament definition into a datatype ornament compatible with the logical relation, and into the construction and destruction functions required to instantiate the generic term. We define what it means for these functions to be correct with respect to an ornament, and prove that our elaborated definitions are indeed correct. In Chapter 11, we explain how to turn a base term into a generic term that can be instantiated. We prove that the identity instantiation of the generic term is indeed equivalent to the base term. Finally, in Chapter 12, we describe how to instantiate a generic term and compute the resulting lifting specification. We then prove that this lifting specification indeed describes the relation between the base term and the lifted term.

This theoretical work is accompanied by a proof-of-concept implementation that demonstrates the practical usefulness of ornamentation. In Part IV, we start by describing some keys aspects of the implementation (Chapter 13) and some strategies to generate readable code as output, as well as features that help reduce the work involved in specifying liftings. In Chapter 14, we describe unfolding, a way to define liftings that do not follow the recursive structure of the original function. We give examples of interesting manipulations of data structures that are allowed by unfolding. In Chapter 15, we explore some future work around possible extensions to the theory and our implementation, notably how one would adapt lifting to work on a real-world language such as OCaml.

Finally, in Part V, we describe some related work (Chapter 16) before concluding (Chapter 17).

Part I

Ornaments in practice

Chapter 2

Ornaments by example

Let us discover ornaments by means of examples. All examples preceded by a blue vertical bar have been processed by a prototype implementation1 , which follows an OCaml-like2 syntax. Output of the prototype appears with a wider green vertical bar. The code that appears without a vertical mark is internal intermediate code for sake of explanation and has not been processed.

Code refactoring

The most striking application of ornaments is the special case of code refactoring, which is an often annoying but necessary task when programming. We start with an example reorganizing a sum data structure into a sum of sums. Consider the following datatype representing arithmetic expressions, together with an evaluation function.

| Const i Ñ i | Add (u, v) Ñ add (eval u) (eval v) | Mul (u, v) Ñ mul (eval u) (eval v)
The programmer may realize that the binary operators Add and Mul can be factored, and thus prefer the following version expr' using an auxiliary type of binary operators, given below.

type binop = Add' | Mul' type expr' = | Const' of int | Binop' of binop * expr' * expr'
There is a relation between these two types, which we may describe as an ornament oexpr from the base type expr to the ornamented type expr'. when u´ñ u`and v´ñ v`in oexpr

This recursively defines the oexpr relation. A clause "x´ñ x`in orn" means that x´and x`should be related by the ornament relation orn. The first clause is the base case. By default, the absence of ornament specification for variable i (of type int) has been expanded to "when i´ñ i`in int" and means that i´and is hould be related by the identity ornament at type int, which is also named int for convenience. The next clause is an inductive case: it means that Add(u´, v´) and Binop' (Add',u`, v`) are in the oexpr relation whenever u´and u`on the one hand and v´and v`on the other hand are already in the oexpr relation.

In this example, the relation happens to be an isomorphism and we say that the ornament is a pure refactoring. Hence, the compiler has enough information to automatically lift the old version of the code to the new version. We simply request this lifting as follows:

let eval' = lifting eval : oexpr Ñ _
The expression oexpr Ñ _ is an ornament signature, which follows the syntax of types but replacing type constructors by ornaments. (The wildcard represents a part of the ornament specification that is inferred; it could have been replaced by int, the ornament specification corresponding to the identity ornament on the type int.) Here, the compiler will automatically elaborate eval' to the expected code, without any further user interaction: let rec eval' a = match a with

| Const' i Ñ i | Binop' (Add', u, v) Ñ add (eval' u) (eval' v) | Binop' (Mul', u, v) Ñ mul (eval' u) (eval' v)
Not only is this well-typed, but the semantics is also preserved-by construction. Notice that a pure refactoring also works in the other direction: we could have instead started with the definition of eval', defined the reverse ornament from expr' to expr, and obtained eval as a lifting of eval'.

Pure refactorings such as oexpr are a particular but quite interesting subcase of ornaments because the lifting process is fully automated. As a tool built upon ornamentation, we provide a shortcut for refactoring: one only has to write the definitions of expr' and oexpr, and lifting declarations are generated to transform a whole source file. Thus, pure refactoring is already a very useful application of ornaments: these transformations become almost free, even on a large code base.

Besides, proper ornaments as described next that decorate an existing node with new pieces of information can often be decomposed into a possibly complex but pure refactoring and another proper, but hopefully simpler ornament. Notice that pure code refactoring need not even define a new type. One such example is to invert values of a boolean type:

type bool = True | False type ornament not : bool ñ bool with | True ñ False | False ñ True
Then, we may define bool_or as a lifting of bool_and, and the compiler inverts the constructors.

let bool_and u v = match u with True Ñ v | False Ñ False let bool_or = lifting band : not Ñ not Ñ not let bool_or u v = match u with | True Ñ True | False Ñ v
It may also do this selectively, only at some given occurrences of the bool type. For example, we may only invert the first argument:

let bool_notand = lifting bool_and : not Ñ bool Ñ bool let bool_notand u v = match u with | True Ñ False | False Ñ v
Still, the compiler will carefully reject inconsistencies, such as:

let bool_andnot = lifting bool_and : bool Ñ not Ñ bool
Indeed, given the structure of the program, the second argument can be returned untransformed. Lifting preserves this structure: then coherent liftings must use the same ornaments for the second argument and the result.

Code refinement

Code refinement is an example of a proper ornament where the intention is to derive new code from existing code, rather than modify existing code and forget the original version afterwards. To illustrate code refinement, observe that lists can be considered as an ornament of Peano numbers:

type nat = Z | S of nat type 'a list = Nil | Cons of 'a * 'a list type ornament 'a natlist : nat ñ 'a list with | Z ñ Nil | S m ñ Cons (_, m) when m : 'a natlist
The parametrized ornamentation relation 'a natlist is not an isomorphism: a natural number S m´will be in relation with all values of the form Cons (x, m`) for any x, as long as m´is in relation with m`. We use an underscore "_" instead of x on Cons (_, m) to emphasize that it does not appear on the left-hand side and thus freely ranges over values of its type. Hence, the mapping from nat to 'a list is incompletely determined: we need additional information to translate a successor node. (Here, the ornament definition may also be read in the reverse direction, which defines a projection from 'a list to nat, the length function! but we do not use this information hereafter.)

The addition on numbers may have been defined as follows (on the left-hand side):

let rec add m n = match m with | Z Ñ n | S m' Ñ S (add m' n) val add : nat Ñ nat Ñ nat let rec append m n = match m with | Nil Ñ n | Cons (x, m') Ñ Cons(x, append m' n) val append : 'a list Ñ 'a list Ñ 'a list
Observe the similarity with append, given above (on the right-hand side). Having already recognized an ornament between nat and list , we expect append to be definable as a lifting of add.

let append0 = lifting add : _ natlist Ñ _ natlist Ñ _ natlist
However, this returns an incomplete lifting:

let rec append0 m n = match m with | Nil Ñ n | Cons (x, m') Ñ Cons ( #2 , append0 m' n)
Indeed, this requires building a cons node from a successor node, which is underdetermined. This is reported to the user by leaving a labeled hole #2 in the generated code. The programmer may use this label to provide a patch that will fill this hole. The patch may use all bindings that were already in context at the same location in the bare version. In particular, the first argument of Cons cannot be obtained directly, but only by matching on m again:

let append = lifting add : _ natlist Ñ _ natlist Ñ _ natlist with #2 Ð match m with Cons(x, _) Ñ x
The lifting is now complete, and produces exactly the code of append given above. The superfluous pattern matching in the patch has been automatically removed: the patch "match m with Cons(x0,_) Ñ x0" has not just been inserted in the hole, but also simplified by observing that x0 is actually equal to x and need not be extracted again from m. This also removes an incomplete pattern matching. This simplification process relies on the ability of the meta-language to maintain equalities between terms via dependent types ( §6), and is needed to make the lifted code as close as possible to manually written code. This is essential, since the lifted code may become the next version of the source code to be read and modified by the programmer. This is a strong argument in favor of the principled approach that we present next and formalize in the rest of the manuscript.

Although the hole cannot be uniquely determined by ornamentation alone, it is here the obvious choice: since the append function is polymorphic we need an element of the same type as the unnamed argument of Cons, so this is the obvious value to pick-but not the only one, as one could also look further in the tail of the list. Instead of giving an explicit patch, we could give a tactic that would fill in the hole with the "obvious choice" in such cases. However, while important in practice, this is an orthogonal issue related to code inference which is not the focus of this work. Below, we stick to the case where patches are always explicitly determined and we leave holes in the skeleton when patches are missing.

This example is chosen here for pedagogical purposes, as it illustrates the key ideas of ornamentation. While it may seem anecdotal, there is a strong relation between recursive data structures and numerical representations, whose relation to ornamentation has been considered by [START_REF] Ko | Analysis and synthesis of inductive families[END_REF].

Composing transformations: a practical use case

Ornamentation could be used in different scenarios: the intent of refactoring is to replace the base code with the generated code, even though the base code could also be kept for archival purposes; when enriching a data structure, both codes may coexist in the same program. To support both of these usages, we try to generate code that is close to manually written code. For other uses, the base code and the lifting instructions may be kept to regenerate the lifted code when the base code changes. This already works well in the absence of patches; otherwise, we would need a patch description language that is more robust to changes in the base code. We could also postprocess ornamentation with some simple form of code inference that would automatically try to fill the holes with "obvious" patches, as illustrated below. Our tool currently works in batch mode and is just providing the building blocks for ornamentation. The ability to output the result of a partially specified lifting makes it possible to build an interactive tool on top of our interface.

The following example shows how different use-cases of ornaments can be composed to reorganize, enrich, and cleanup an incorrect program, so that the final bug fix can be reduced to a manual but simple step. The underlying idea is to reduce manual transformations by using automatic program transformations whenever possible. Notice that since lifting preserves the behavior of the original program, fixing a bug cannot just be done by ornamentation.

Let us consider a small calculus with abstractions and applications and tuples (which we will take unary for conciseness) and projections. We assume given a type id representing variables.

type expr = | Abs of id * expr | App of expr * expr | Var of id | Tup of expr | Proj of expr
We write an expression evaluator using environments of type (id * expr) list . We assume given an assoc function of type 'a Ñ ('a * 'b) list Ñ 'b option that searches a binding in the environment. let rec eval env e = match e with

| Var x Ñ assoc x env | Abs(x, f) Ñ Some (Abs(x, f)) | App(e1,e2) Ñ begin match eval env e1 with | Some (Abs(x,f)) Ñ begin match eval env e2 with | Some v Ñ eval (Cons((x,v), env)) f | None Ñ None end | Some (Tup _) Ñ None ( * Type error * ) | None Ñ None ( * Error propagation * ) | Some _ Ñ fail () ( * Not a value ?! * )
end

The evaluator distinguishes type (or scope) errors in the program, where it returns None, and internal errors when the expression returned by the evaluator is not a value. In this case, the evaluator raises an exception by calling fail ().

We soon realize that we mistakenly implemented dynamic scoping: the result of evaluating an abstraction should not be an abstraction but a closure that holds the lexical environment of the abstraction. One path to fixing this evaluator is to start by separating the subset of values returned by the evaluator from general expressions. We define a type of values as an ornament of expressions. This ornament is intendedly partial : some cases are not lifted. Indeed, ornaments define a relation between the bare type and the ornamented type. They are defined syntactically, with both sides being linear patterns. Moreover, the pattern for the ornamented type should be total, i.e. match all expressions of the ornamented type. Conversely, the pattern of the bare type need not be total, but it must not throw away any information: in particular, it cannot use wildcards or alternative patterns. When lifting a pattern matching with a partial ornament, the inaccessible cases will be dropped. On the other hand, when constructing a value that is impossible in the lifted type, the user will be asked to construct a patch of the empty type, which could be filled for example by an assertion failure. In some cases, the holes that should be filled with values of the empty type will disappear during simplification, guaranteeing that the program will not attempt to construct such values. The notation " corresponds to the empty pattern. This ornament does not preserve the recursive structure of the original datatype: the recursive occurrences are transformed into values or expressions depending on their position. By contrast with prior works [START_REF] Williams | Ornaments in practice[END_REF][START_REF] Dagand | A categorical treatment of ornaments[END_REF], 2014], we do not treat recursion specifically. Hence, mutual recursion is not a problem; for instance, we can ornament a mutually recursive definition of trees and forests or modify the recursive structure during ornamentation. We also allow changing the recursive structure of func-tions, transforming a single recursive function into a group of mutually recursive functions (Chapter 14).

Using the ornament expr_value we transform the evaluator by making explicit the fact that it only returns values and that the environment only contains values (as long as this is initially true): Since this ornament is not one-to-one, the lifting of eval' is partial. The advanced user may realize that there should be a single hole in the lifted code that should be filled with the current environment env, and may directly write the clause " | * Ð env":

let eval'' = lifting eval' with ornament * Ð value_value', @id | * Ð env
The annotation ornament * Ð value_value', @id is another way to indicate which ornaments to use. This is sometimes more convenient than giving a signature.

For each type that needs to be ornamented, we first try value_value', and use the identity ornament if this fails (e.g. on types other than value). A more pedestrian path to writing the patch is to first look at the output of the partial lifting:

let eval'' = lifting eval' with ornament * Ð value_value', @id let rec eval'' env e = match e with | Abs(x, e) Ñ Some (VClos'(x, #32 , e)) | App (e1, e2) Ñ ... | ...

The hole has been labeled #32 which can then be used to refer to this specific program point. The patch associated to this label can access all variables in scope where the label #32 appears in the partially lifted term.

let eval'' = lifting eval' with ornament * Ð value_value', @id | #32 Ð env

An interactive tool could point the user to this hole in the partially lifted code shown above, so that they directly enters the code env, and the tool would automatically generate the lifting command just above. Notice that env is the most obvious way to fill the hole here, because it is the only variable of the expected type available in context. Hence, a very simple form of type-based code inference could pre-fill the hole with env and just ask the user to confirm. When the programmer is quite confident, they could even ask for this to be done in batch mode:

let eval'' = lifting eval' with | ornament * Ð value_value', @id | * Ð try by type
Example-based code inference would be another interesting extension of our prototype, which would increase the robustness of patches to program changes.

Here, the user could instead write:

let eval'' = lifting eval' with | ornament * Ð value_value', @id | * Ð try eval env (VAbs (_, _)) = Some (Closure (_, env, _))
providing a partial definition of eval that is sufficient to completely determine the patch.

For each of these possible specifications, the system will return the same answer: let rec eval'' env e = match e with | Abs(x, e) Ñ Some (VClos'(x, env, e))

| App(e1, e2) Ñ bind' (eval'' env e1) (function | VClos'(x, _, e) Ñ bind' (eval'' env e2) (fun v Ñ eval'' (Cons((x, v), env)) e) | VTup' _ Ñ None) | Var x Ñ assoc x env | ...
So far, we have not changed the behavior of the evaluator: the ornaments guarantee that the result of eval'' on some expression is essentially the same as the result of eval-up to the addition of an environment in closures. The final modification must be performed manually: when applying functions, we need to use the environment of the closure instead of the current environment.

Hiding administrative data

Sometimes data structures need to carry annotations, which are useful information for certain purposes but not at the core of the algorithms. A typical example is location information attached to abstract syntax trees for error reporting purposes. The problem with data structure annotations is that they often obfuscate the code. We show how ornaments can be used to keep programming on the bare view of the data structures and lift the code to the ornamented view with annotations. In particular, scanning algorithms can be manually written on the bare structure and automatically lifted to the ornamented structure with only a few patches to describe how locations must be used for error reporting.

Consider for example, the type of λ-expressions and its call-by-name evaluator:

type 'a option = | None | Some of 'a type expr = | Abs of (expr Ñ expr) | App of expr * expr | Const of int let rec eval e = match e with | App (u, v) Ñ (match eval u with Some (Abs f) Ñ Some (f v) | _ Ñ None) | v Ñ Some (v)
The datatype expr' that holds location information can be presented as an ornament of expr:

type loc = Location of string * int * int type expr' = | App' of (expr' * loc) * (expr' * loc) | Abs' of (expr' * loc Ñ expr' * loc) | Const' of int
Common branches could actually be refactored using wildcard abbreviations whenever possible, leading to the following code, but this has not been implemented yet:

let rec eval_loc e Ñ match e with | App' (u, v), loc Ñ begin match eval_loc u with | Ok (Abs' f, loc) Ñ Ok (f v) | Ok (_, _) Ñ Error loc | Error err Ñ Error err end | _ Ñ Ok e
While this example is limited to the simple case where we only read the abstract syntax tree, some compilation passes often need to transform the abstract syntax tree carrying location information around. More experiment is still needed to see how the ornament approach scales up here to more complex transformations. This might be a case where appropriate tactics for filling the holes could be helpful. This example suggests a new use of ornaments in a programming environment where the bare code and the lifted code will be kept in sync, and the user will be able to switch between the two views, using the bare code for the core of the algorithm that need not see the decorations and the lifted code only when necessary.

Higher-order types, recursive types

Lifting also works with higher-order types and recursive datatype definitions with negative occurrences. For example, we could extend arithmetic expressions with nodes for abstraction and application, with functions represented by functions of the host language:

type expr = | Const of int | Add of expr * expr | Mul of expr * expr | Abs of (expr Ñ expr option) | App of expr * expr
Then, the evaluation function is partial:

let rec eval e = match e with | Const i Ñ Some(Const i) | Add ( u , v ) Ñ begin match (eval u, eval v) with | (Some (Const i1), Some (Const i2)) Ñ Some(Const (add i1 i2)) | _ Ñ None end | Mul ( u , v ) Ñ begin match (eval u, eval v) with | (Some (Const i1), Some (Const i2)) Ñ Some(Const (mul i1 i2)) | _ Ñ None end | Abs f Ñ Some(Abs f) | App(u, v) Ñ begin match eval u with | Some(Abs f) Ñ begin match eval v with None Ñ None | Some x Ñ f x end | _ Ñ None end val eval : expr Ñ expr option
We could still prefer the following representation factoring the arithmetic operations:

type binop' = | Add' | Mul' type expr' = | Const' of int | Binop' of binop' * expr' * expr' | Abs' of (expr' Ñ expr' option) | App' of expr' * expr'
Then, we can define an ornament between these types, despite expr' recursively occurring to the left of a function arrow in its definition:

type ornament oexpr : expr ñ expr' with

| Const ( i ) ñ Const' ( i ) | Add ( u , v ) ñ Binop' ( Add' , u , v ) when u v : oexpr | Mul ( u , v ) ñ Binop' ( Mul' , u , v ) when u v : oexpr | Abs f ñ Abs' f when f : oexpr Ñ oexpr option | App ( u , v ) ñ App' ( u , v ) when u v : oexpr
In the clause of Abs, the lifting of the argument is specified by an higher-order ornament type oexpr Ñ oexpr option that recursively uses oexpr as argument of another type, and on the left of an arrow. We can then use this to lift the function eval:

let eval' = lifting eval : oexpr Ñ oexpr option with ornament * Ð @id val eval' : expr' Ñ expr' option

The annotation ornament * Ð @id indicates that, for all ornaments that are not otherwise constrained, the identity ornament should be used by default. This is necessary because we create and destruct a tuple in eval, but the type of the tuple does not appear in the signature, so we cannot specify the ornament that should be used through the signature. We give more details in Chapter 12.

Chapter 3

Overview of the lifting process

Whether used for refactoring or refinement, ornaments are about code reuse.

Code reuse is usually obtained by modularity, which itself relies on both type and value abstraction mechanisms. Typically, one writes a generic function gen that abstracts over the representation details, say described by some structures s of operations on types τ . Hence, a concrete implementation a is schematically obtained by the application gen τ s; changing the representation to small variation s1 of types τ 1 of the structures s, we immediately obtain a new implementation gen τ 1 s1 , say a 1 . Although the case of ornamentation seems quite different, as we start with a non-modular implementation a, we may still get inspiration from the previous schema: modularity through abstraction and polymorphism is the essence of good programming discipline. Instead of directly going from a to a 1 on some ad hoc track, we may first find a modular presentation of a as an application a gen τ s so that moving from a to a 1 is just finding the right parameters τ 1 and s1 to pass to a gen . This is depicted in Figure 3.1. In our case, the elaboration that finds the generic term a gen is syntactic and only depends on the source term a. Hence, the same generic term a gen may be used for different liftings of the same source code. The specialization process is actually performed in several steps, as we do not want a 1 to be just the application a gen τ 1 s1 , but be presented in a simplified form as close as possible to the term we started with and as similar as possible to the code the programmer would have manually written. Hence, after instana " a gen τ s tiation, we perform meta-reduction, which eliminates all the abstractions that have been introduced during the elaboration-but not others. This is followed by simplifications that will mainly eliminate intermediate pattern matchings.

a gen a 0 " a gen τ 1 s1 a 1 a 1 " a gen
Having recovered a modular schema, we may use parametricity results, based on logical relations. As long as the arguments s and s1 passed to the polymorphic function a gen are related-and they are by the ornamentation relation!-the two applications a gen τ s and a gen τ 1 s1 are also related. Since meta-reduction preserves the relation, it only remains to check that the simplification steps also preserve equivalence to establish a relationship between the bare term a and the lifted term a 1 (Chapter 7 and 9).

The lifting process is formally described in Chapter 12. In the rest of this section, we present it informally on the example of add and append.

Encoding ornaments

Ornamentation only affects datatypes, so a program can be lifted by simply inserting some code to translate from and to the ornamented type at occurrences where the base datatype is either constructed or destructed in the original program.

We now explain how this code can be automatically inserted. For sake of illustration, we proceed in several incremental steps. Intuitively, the append function should have the same structure as add, and operate on constructors Nil and Cons similarly to the way add proceeds with constructors S and Z.

To help with this transformation, we may see a list as a nat-like structure where just the head of the list has been transformed. For that purpose, we introduce an hybrid open version of the datatype of Peano naturals, called the skeleton, using new constructors Z' and S' corresponding to Z and S but remaining parameterized over the type of the argument of the constructor S:

type 'a nat_skel = Z' | S' of 'a
We define the head projection of a list into nat_skel 1 where the head is transformed and the tail stays a list:

let proj_nat_list : 'a list Ñ 'a list nat_skel = fun m { { " ñ match m with | Nil Ñ Z' | Cons (_, m') Ñ S' m'
We use annotated versions of abstractions fun x { { " ñ a and applications a#b called meta-abstractions and meta-applications to keep track of helper code and distinguish it from the original code, but these can otherwise be read as regular functions and applications.

Once an 'a list has been turned into 'a list nat_skel, we can pattern match on it in the same way we match on nat in the definition of add. Hence, the definition of append should look like:

let rec append1 m n = match proj_nat_list # m with | Z' Ñ n | S' m' Ñ ... S' (append1 m' n) ...
In the second branch, we must construct a list out of the nat skeleton containing a list S' (append1 m' n). We use a helper function to inject an 'a list nat_skel into an 'a list :

| S' m' Ñ inj_nat_list1 (S'(append m' n)) ...
Of course, inj_nat_list requires some supplementary information x to put in the head of the list:

let inj_nat_list : 'a list nat_skel Ñ 'a Ñ 'a list = fun n x { { " ñ match n with | Z' Ñ Nil | S' n' Ñ Cons (x, n')
As explained earlier ( §2.2), we need the patch (match m with Cons (x, _) Ñ x) to obtain append, and it must be user provided as patch #2. Hence, the lifting of add into lists is:

let rec append2 m n = match proj_nat_list # m with | Z' Ñ n | S' m' Ñ inj_nat_list # (S'(append2 m' n)) # (match m with Cons (x, _) Ñ x)
This version is correct, but not final yet, as it still contains the intermediate hybrid structure, which will eventually be eliminated. However, before we see how to do so in the next section, we first check that our schema extends to more complex examples of ornaments. Assume, for instance, that we also attach new information to the Z constructor to get lists with some information at the end, which could be defined as:

type ('a,'b) listend = Nilend of 'b | Consend of 'a * ('a, 'b) listend
We may write encoding and decoding functions as above:

let proj_nat_listend = fun l Ñ match l with | Nilend _ Ñ Z' | Consend (_,l') Ñ S' l' let inj_nat_listend = fun n x Ñ match n with | Z' Ñ Nilend x | S' l' Ñ Consend (x,l')
However, a new problem appears: we cannot give a valid ML type to the function inj_nat_listend, as the argument x should take different types depending on whether n is zero or a successor. This is solved by adding a form of dependent types to our intermediate language-and finely tuned restrictions to guarantee that the generated code becomes typeable in ML after some simplifications. The general idea of the simplifications is given next.

Eliminating the encoding

The mechanical ornamentation both creates intermediate hybrid data structures and includes extra abstractions and applications. Fortunately, these additional computations can be avoided, which not only removes sources of inefficiencies, but also helps generate code with fewer indirections that is more similar to hand-written code.

We first perform meta-reduction of append2, which removes all helper functions (we actually give different types to ordinary and meta functions so that meta functions can only be applied using meta-applications and ordinary functions can only be applied using ordinary applications):

let rec append3 m n = match (match m with Nil Ñ Z' | Cons (x, m') Ñ S' m') with | Z' Ñ n | S' m' Ñ match S'(append3 m' n) with | Z' ´> Nil | S' r' Ñ Cons ((match m with Cons(x, _) Ñ x), r')
(The grayed out branch is inaccessible). Still, append3 computes two pattern matchings that do not appear in the manually written version append. Interestingly, both of them can be eliminated. Extruding the inner match on m in append3, we get:

let rec append4 m n = match m with | Nil Ñ (match Z' with Z' Ñ n | S' m' ´> b) | Cons (x, m') Ñ (match S' m' with Z' ´> n | S' m' Ñ b)
Since we know that m is equal to Cons(x,m') in the Cons branch, we simplify b to Cons(x, append m' n). After removing all remaining dead branches, we exactly obtain the manually written version append:

let rec append = fun m n Ñ match m with | Nil Ñ n | Cons (x, m') Ñ Cons (x, append m' n)

Inferring a generic lifting

We have shown a specific ornamentation append of add. However, instead of producing such an ornamentation directly, we first generate a generic lifting of add abstracted over all possible instantiations, and only then specialize it to some specific ornamentation by passing encoding and decoding functions as arguments, as well as a set of patches that generate the additional data.

Let us detail this process by building the generic lifting add_gen of add, which we repeat below.

let rec add = fun m n Ñ match m with | Z Ñ n | S m' Ñ S(add m' n)
Because they will be passed together to the function, we group the injection and projection into a record:

type ('a,'b,'c) orn = { inj : 'a Ñ 'b Ñ 'c; proj : 'c Ñ 'a } let nat_list = { inj = inj_nat_list; proj = proj_nat_list; }
The code of append2 could have been written as:

let rec append2 m n = match nat_list.proj # m with | Z' Ñ n | S' m' Ñ nat_list.inj # (S'(add m' n)) # (match m with Cons (x, _) Ñ x) in append2
Instead of using the concrete ornament nat_list, the generic version abstracts over arbitrary ornaments of nats and over the patch:

let add_gen = fun m_orn n_orn p1 { { " ñ let rec add_gen' m n = match m_orn.proj # m with | Z' Ñ n | S' m' Ñ n_orn.inj # S'(add_gen' m' n) # (p1 # add_gen' # m # m' # n) in add_gen'
While append2 uses the same ornament nat_list for ornamenting both arguments m and n, this need not be the case in general; hence add_gen has two different ornament arguments m_orn and n_orn. The patch p1 is abstracted over all variables in scope, i.e. m, n and m'.

In general, we ask for a different ornament for each occurrence of a constructor or pattern matching on a datatype. We then apply ML inference on the generic term (ignoring the patches) allowing us to deduce that some ornaments encode to the same datatype. In order to preserve the relation between the bare and lifted terms (see Chapter 11), these ornaments are merged into a single ornament, with a single record. We thus obtain a description of all possible syntactic ornaments of the base function, i.e. those ornaments that preserve the structure of the original code. The patch p1 describes how to obtain the missing information from the environment (namely add_gen, m, n, m') when building a value of the ornamented type. While the parameters m_orn and n_orn will be automatically instantiated, the code for patches will have to be user-provided.

The generalized function abstracts over all possible ornaments, and must now be instantiated with some specific ornaments. We may for instance decide to ornament nothing, i.e. just lift nat to itself using the identity ornament on nat, which amounts to passing to add_gen the following trivial functions:

let proj_nat_nat = fun x { { " ñ match x with Z Ñ Z' | S x Ñ S' x let inj_nat_nat = fun x () { { " ñ match x with Z' Ñ Z | S' x Ñ S x let orn_nat_nat = { proj=proj_nat_nat; inj = inj_nat_nat }
There is no information added, so we may use the following unit_patch for p1:

let unit_patch = fun _ _ _ _ { { " ñ () let add1 = add_gen # orn_nat_nat # orn_nat_nat # unit_patch
As expected, meta-reducing add1 and simplifying the result returns the original program add.

We may also instantiate the generic lifting with the ornament from nat to lists and the following patch. Meta-reduction of append5 gives append2 which can then be simplified to append, as explained above.

let orn_nat_list = { proj = proj_nat_list; inj = inj_nat_list } let append_patch = fun _ m _ _ { { " ñ match m with Cons(x, _) Ñ x let append5 = add_gen # orn_nat_list # orn_nat_list # append_patch
The generic lifting is not exposed as is to the user because it is not convenient to use directly. Positional arguments are not practical, because one must reference the generic term to understand the role of each argument. We can solve this problem by attaching the arguments to program locations and exposing the correspondence in the user interface. For example, in the lifting of add to append shown in the previous section, the location #2 corresponds to the argument p1.

The next two parts formalize the intuition given in this chapter: in Part II, we define a layer over ML allowing to express the encoding of ornaments and reasoning tools that will be used to prove that ornamentation is correct; in Part III, we exploit this language to define the encoding and prove that lifting is correct.

Part II

A calculus for program transformation

In this part, we build a meta-language on top of ML as a tool to define and reason about ornamentation. We start by formally defining our subset of OCaml (Chapter 4). We then define a labeling of function applications to reuse the results of previously computed applications (Chapter 5). We build upon this concept to present eML, an extension of ML with equalities and type-level pattern matching (Chapter 6). On top of eML, we add another layer to represent meta-abstractions and meta-applications as well as richer type-level computation (Chapter 7). This layer is carefully designed so that it can disappear simply by reduction (Theorem 7.3). We present a logical relation allowing us to reason on mML terms (Chapter 8); later, we will encode ornaments into this relation. Finally, we show that eML terms can be simplified to ML in appropriate context (Chapter 9), preserving the logical relation.

Chapter 4

Core ML

The transformations done during lifiting take an ML program as input, and return an ML program as output. We will consider here a small subset of OCaml [START_REF] Leroy | The OCaml system release 4.11: Documentation and user's manual[END_REF], featuring data types and polymorphic let bindings. In particular, our core language has no references or module system. We discusses extending ornamentation to a larger language in §15.4.

Notation

We often need to write tuples and sequences of arguments. We write pQ i q iPI for a tuple pQ 1 , .. Q n q. We often omit the set I in which i ranges and just write pQ i q i , using different indices i, j, and k for ranging over different sets I, J, and K; we also write Q if we do not have to explicitly mention the components Q i . In particular, Q stands for pQ, .. Qq in syntax definitions. We write Qrz i Ð Q i s iPI , or Qrz i Ð Q i s i for short, for the simultaneous substitution of z i by Q i in Q for all i in I. We sometimes need to consider dependent indices: we write for example j P J i for j ranging on a set J i depending on the index i, and pQ ij q iPI,jPJi for the sequence ranging over the pairs of i and j. In this case, we usually keep the explicit notation. The order of the indices is relevant: we consider that the order relation ă orders the indices such that the index of an element is smaller than the indices of elements to its right.

Types and datatypes

To prepare ML for further extensions, we slightly depart from traditional presentations. Instead of defining type schemes as a generalization of monomorphic types, we do the converse and introduce monotypes as a restriction of type schemes. The reason to do so is to be able to see both ML and eML as sublanguages of mML-the most expressive of the three. We use kinds to distinguish between the types of the different languages: for ML we only need a kind Typ, to classify the monomorphic types, and its superkind Sch, to classify type schemes. The syntax of kinds (noted κ) and types (σ, τ ) is given on Figure 4.1. The monotypes include function types τ 1 Ñ τ 2 and application of type constructors d τ , while universal quantification @pα : Typq τ , restricted to monotypes, builds a 49 Figure 4.1: Types, kinds and environments for ML type scheme. Diverging from the traditional ML syntax, we take type constructors as prefix: thus, the type of lists of booleans is noted list bool instead of bool list. Type environments Γ bind a set of type variables α, all of kind Typ, and term variables x i of types τ i , which may be type schemes.

We assume given a fixed set of type constructors, written ζ. Each type constructor has a fixed signature of the form pTyp, .. Typq ñ Typ. We require that type expressions respect the kinds of type constructors and type constructors are always fully applied. We also assume given a set of data constructors. Each data constructor d comes with a type signature, which is a closed type scheme of the form @pα i : Typq i pτ j q j Ñ ζ pα i q i . The mapping between type constructors, data constructors and their signatures is stored in a datatype environment D, whose syntax is given on Figure 4.1.

By convention, we choose lowercase names for type constructors, and capitalized names for data constructors. Some well-known datatypes will be useful in examples: the datatype unit with one constructor Unit, the datatype bool with two constructors False and True, the empty datatype void with no constructors. We will also use the type of natural numbers nat with two constructors Z and S, the type of lists list α with two constructors Nil and Cons, the type option α with two constructors None and Some, the type either pα, βq, with constructors Left and Right, and the type pair pα, βq with one constructor Pair. The corresponding type environment is given on Figure 4.2

The well-formedness rules for datatype environments, type environments, and types are given in Figure 4.3. A datatype environment D is well-formed (noted $ D) if the types given to the fields of data constructors are valid (Wf-Datatype). Note that this definition permits arbitrary recursion between types, including mutually recursive types, non-strictly positive types, and nonregular types [START_REF] Bird | Nested datatypes[END_REF]

D $ H EnvVar D $ Γ Γ $ τ : Sch x # Γ D $ Γ, x : τ EnvTVar D $ Γ α # Γ D $ Γ, α : Typ K-Var D $ Γ α : Typ P Γ D; Γ $ α : Typ K-Datatype D $ Γ pζ : pTypq i ñ Typq P D pD; Γ $ τ i : Typq i D; Γ $ ζ pτ i q i : Typ K-Arr D; Γ $ τ 1 : Typ D; Γ $ τ 2 : Typ D; Γ $ τ 1 Ñ τ 2 : Typ K-SubTyp D; Γ $ τ : Typ D; Γ $ τ : Sch K-All
D; Γ, α : Typ $ τ : Sch D; Γ $ @pα : Typq τ : Sch Wf-Datatype @pd : @pα i : Typq i pτ j q j Ñ ζ pα i q i q P D , pζ : pTypq i ñ Typq P D ^pD; pα i : Typq i $ τ j : Typq j $ D Otherwise, all universal quantification must be at the head of the type (because the kind Sch cannot appear as the argument of the function arrow or a type constructor), and it has kind Sch (K-All). The rule K-SubTyp allows monotypes to be considered as an instance of type schemes. Types (and terms) are considered up to α-conversion.

Since the datatype environment D does not vary, we will almost always leave it implicit.

The syntax of explicit ML

Since we are mainly interrested in transforming ML programs, we describe an explicitly typed version of ML.

The syntax of ML is given on Figure 4.4. Terms are represented by the metavariables a and b. Instead of having a special notation for recursive functions, functions are always defined recursively, using the construction fix f px : τ 1 q : τ 2 . a. This avoids having two different syntactic forms for values of function types. For convenience, we still use the standard notation λpx : τ 1 q. a for nonrecursive functions, but we just see it as a shorthand for fix f px : τ 1 q : τ 2 . a where f does not appear free in a and τ 2 is the function's return type. Type abstraction and type application are explicit, respectively noted Λpα : Typq. a and a τ . Constructors d take as arguments both a list of types, instantiating the corresponding type arguments of the datatype, and a list of terms corresponding to their fields. We distinguish a class of non-expansive terms, noted u, whose evaluation does not involve reducing function application. We require that the body of type abstractions is non-expansive. This is a slightly relaxed version of value restriction [START_REF] Andrew | Simple imperative polymorphism. Lisp and symbolic computation[END_REF]. Non-expansive terms will be useful later on because their reduction terminates. Note that the class of non-expansive terms is not preserved by substitution of variables for arbitrary terms, but only for substitution by non-expansive terms. To preserve the syntax of terms, we must be careful to only substitute non-expansive terms for variables.

The typing judgment Γ $ a : τ (which is a shorthand for D; Γ $ a : τ , with D considered constant), expresses that a is well-typed of type τ in the typing context Γ. Its derivation rules are given on Figure 4.5. We need to ensure that all pattern matchings are non-overlapping and complete. This is done in Match through an auxiliary judgment $ pd i q i : ζ complete, defined as follows: $ pd i q i : ζ complete if and only if pd i q i contains once and only once all constructors d such that there exists pα j q j and pτ k q k such that pd i : @pα k : Typq k pτ ij q j Ñ ζ pα k q k q P D. The rules of the typing judgment ensure that if Γ $ a : τ , then Γ is well-formed and Γ $ τ : Sch; in rule Match this requires checking explicitly that Γ $ τ : Sch, i.e. that τ and Γ are well-formed, as the pattern matching can have zero branch if we are matching on a datatype without constructors. | match E with pP Ñ a | .. P Ñ aq | let x " E in a pfix x py : τ 1 q : τ . aq v ÝÑ h β arx Ð fix x py : τ 1 q : τ . a, y Ð vs pΛpα :

Typq. vq τ ÝÑ h β vrα Ð τ s let x " v in a ÝÑ h β arx Ð vs match d j τ pv i q i with pd j τ px ji q i Ñ a j q j ÝÑ h β a j rx ji Ð v i s i Context-Beta a ÝÑ h β b Eras ÝÑ β Erbs

Evaluation

The language is equipped with a weak (i.e. we disallow reduction under binders), call-by-value reduction semantics, expressed in small-step style. To match the behavior of OCaml, we evaluate applications left-to-right and constructor arguments right-to-left. The definitions of values v, of the evaluation contexts E are given in Figure 4.6. The reduction ÝÑ β is defined as performing headreductions ÝÑ h β in evaluation contexts E. While reduction does not occur under term abstractions, we reduce under type abstractions: thus evaluation occurs as if the type abstractions were absent. This is important because abstractions are not visible in the implicitly-typed language that is presented to the programmer. If type abstractions did block reduction, the programmer would have to guess where abstractions are inserted to understand the semantics of the program they wrote.

Reduction always substitutes variables by values, which are a subset of nonexpansive terms. Thus, the syntax of terms is preserved. Given the evaluation contexts we have defined, the reduction is deterministic, and values are indeed irreducible.

Lemma 4.1 (Values are irreducible for ÝÑ β ). Consider a value v. Then, there is no term a such that v ÝÑ β a.

Proof. By contradiction, consider a reduction of v. There exists a decomposition v " Erbs where E is an evaluation context, and b ÝÑ h β b 1 , and a " Erb 1 s. Let us prove by structural induction of values that this is impossible. There is no head-reduction on values (because values start with a constructor, while head-reduction reduces only terms that start with a destructor). Thus, the evaluation context E is non-empty. Let us consider the different cases for values:

• Suppose v " dpτ q i pv 1 i q i . Then E is of the form dpτ q i ppv 1 j q j , E 1 , pv 1 k q k q, therefore there is some value v 1 in pv 1 i q i that decomposes as v 1 " E 1 rbs and reduces to E 1 rb 1 s. This is impossible by induction hypothesis.

• Suppose v " fix x py : τ 1 q : τ . a. There is no possible non-empty context E such that v " Erbs.

• Suppose v " Λpα : Typq. v 1 for some value v 1 . Then E " Λpα : Typq. E 1 , thus v 1 " E 1 rbs reduces to E 1 rb 1 s. This is impossible by induction hypothesis. Proof. Let us show that any term a decomposes in at most one way as Era 1 s where a 1 is head-reducible. This implies the lemma, because head-reduction is deterministic.

We proceed by induction on a.

• If the term is a variable, the reduction is blocked.

• If it is a let binding a " let x " b in b 1 there are two cases to consider. If b is not a value, a does not head-reduce. Then, the decomposition must of the form E " let x " E 1 in b 1 and we apply the induction hypothesis on b.

If b is a value, the decomposition cannot be of this form, since that would imply that b reduces. Thus, E is necessarily the empty context.

• If the term is a function definition by fixed point, it is a value, and thus irreducible.

• If a " b b 1 is an application, there are three cases to consider. If b is not a value, the term does not head-reduce, and the only possible decomposition is of the form E " E 1 b 1 . Then we can apply the inductive hypothesis to b. If b is a value but b 1 is not, the term does not head-reduce, and the only possible decomposition is of the form E " b E 1 (b does not decompose as it is a value). The we can apply the inductive hypothesis to b 1 . Otherwise, we necessarily have E " rs.

• Similarly, for type application a " b τ , either b is not a value and a does not head-reduce, or b is a value, does not decompose further, and E is the empty context.

• For type abstraction the context is necessarily of the form E " Λpα :

Typq. E 1 , and we can apply the induction hypothesis.

• For constructors we find the first field (starting from the right) that is not a value, and apply the inductive hypothesis.

• For pattern matching, either the scrutinee is not a value and the term does not head-reduce, then we can apply the induction hypothesis, or it is a value and does not decompose so the empty context is the only possible context.

Type soundness

As usual, weakening allows us to transport a term to another context, which is useful to prove that substitution preserves types. We have two ways to enrich an environment: either add a type variable α : Typ, or add a term variable a : τ . Similarly, we have three judgments where a typing environment appears: well-formedness of environments $ Γ, well-formedness of types Γ $ τ : κ and typing Γ $ a : τ . Thus, we have six statements of weakening:

Lemma 4.3 (Weakening). Suppose $ Γ, Γ 1 . Then,

• if α # Γ, Γ 1 , we have $ Γ, α : Typ, Γ 1 ; • if x # Γ, Γ 1 and Γ $ τ : Sch, then $ Γ, x : τ, Γ 1 . Suppose Γ, Γ 1 $ τ : κ. Then, • if α # Γ, Γ 1 , we have Γ, α : Typ, Γ 1 $ τ : κ; • if x # Γ, Γ 1 and Γ $ τ 1 : Sch, then Γ, x : τ 1 , Γ 1 $ τ : κ.
Suppose Γ, Γ 1 $ a : τ . Then,

• if α # Γ, Γ 1 , then Γ, α : Typ, Γ 1 $ a : τ ; • if x # Γ, Γ 1 and Γ $ τ : Sch, then Γ, x : τ, Γ 1 $ a : τ .
Proof. By induction on the derivation. For weakening on type variables, since the variable is free for the context, the context stays valid (EnvTVar), and the only rule that accesses the context for type variables (K-Var) is monotonic with respect to the context. Similarly for term variables, with EnvVar and Var.

Similarly, substitution has six different statements:

Lemma 4.4 (Substitution). Suppose Γ $ σ : Typ. Then,

• if $ Γ, α : Typ, Γ 1 , then $ Γ, Γ 1 rα Ð σs; • if Γ, α : Typ, Γ 1 $ τ : κ, then Γ, Γ 1 rα Ð σs $ τ rα Ð σs : κ;
• if Γ, α : Typ, Γ 1 $ a : τ , then Γ, Γ 1 rα Ð σs $ arα Ð σs : τ rα Ð σs.

Suppose Γ $ u : τ .

• if $ Γ, x : τ, Γ 1 , then $ Γ, Γ 1 ; • if Γ, x : τ, Γ 1 $ τ : κ, then Γ, Γ 1 $ τ : κ; • if Γ, x : τ, Γ 1 $ a : τ , then Γ, Γ 1 $ arx Ð us : τ .
Proof. By induction on the derivations. For type substitution, substitute in subderivations by induction, replacing K-Var by the derivation of Γ $ σ : Typ.

For term substitution, substitute in subderivations by induction, replacing rule Var by the derivation of Γ $ u : τ .

The reduction preserves typing.

Lemma 4.5 (Subject reduction for head reduction). Suppose Γ $ a : τ . Then, if a ÝÑ h β a 1 , we have Γ $ a 1 : τ . Proof. Consider the different redexes.

• If a " pfix x py : τ 1 1 q : τ 1 2 . bq v, then the last derivation rule is necessarily App. Thus, there exists τ 1 such that Γ $ fix x py : τ 1 1 q : τ 1 2 . b : τ 1 Ñ τ 2 and Γ $ v : τ 1 . The last derivation rule of Γ $ fix x py : τ 1 1 q : τ 1 2 . b : τ 1 Ñ τ 2 is necessarily Fix. Thus, we have Γ, x : τ 1 Ñ τ, y : τ 1 $ b : τ . By substitution (Lemma 4.4), Γ $ arx Ð fix x py : τ 1 q : τ . b, y Ð vs : τ .

• Proceed similarly for the other redexes (type application and abstraction, match and constructor, and let and value), by inverting the typing derivation and applying substitution.

Theorem 4.1 (Subject reduction). Suppose Γ $ a : τ . Then, if a ÝÑ β a 1 , we have Γ $ a 1 : τ .

Proof. By induction on the context where head reduction takes place.

• If the context is empty, apply Lemma 4.5.

• Otherwise, notice that typing derivations are not dependent: we can change subterms as long as we keep the same type. Then apply the induction hypothesis on the reduced subterm.

Moreover, well-typed irreducible terms are values.

Lemma 4.6 (Inversion). Consider a value v, such that Γ $ v : τ .

• If τ " τ 1 Ñ τ 2 , there exists a such that v " fix x py : τ 1 q : τ 2 . a.

• If τ " @pα : Typq τ 1 , there exists w such that v " Λpα : Typq. w.

• If τ " ζ pτ i q i , there exists a constructor $ d : @pα i : Typq i pτ j q j Ñ ζ pα i q i and terms pa j q j such that a " dpτ i q i pa j q j . Proof. By examining the different cases for values, and inverting the typing derivation.

Theorem 4.2 (Progress). Consider H $ a : τ . Then, either a reduce, or it is a value.

Proof. We proceed by induction on the term, as in the proof of Lemma 4.2. In the induction, we will reduce under type abstractions. For the proof by induction to work, we need to prove a strengthened result where the typing environment can bind any number of type variables: consider a set of type variables pα i q i . Then, if pα i : Typq i $ a : τ , either a is a value or a reduces.

• Term variables are not well-typed in the empty context.

• A function definition by fixed point is a value.

• Each argument of the constructor is well-typed in Γ, thus is either a value or reduces. If all arguments are values, a is a value. Otherwise, we can reduce the rightmost non-value argument.

• The term inside a well-typed type abstraction is well-typed in an environment Γ, α : Typ enriched with one type variable, thus is either a value or reduces. If it reduces, the abstraction reduces. Otherwise a is a value. By inverting the type derivation, we know that there exists a type τ 1 such that H $ b 1 : τ 1 and H $ b : τ 1 Ñ τ . Then, by Lemma 4.6, we know that there exists a 1 such that b " fix x py : τ 1 q : τ . a 1 . Then, a reduces to a 1 rx Ð b, y Ð b 1 s.

• Proceed similarly for pattern matching and type application.

Chapter 5

Labelling ML terms

We introduce a labeling system for ML: expansive computations are labeled so that their result can be reused without recomputation later in the term, without having to introduce explicit bindings. This will be used in eML, presented in the next chapter, to refer to results of previous computations that were useful in determining, e.g. which branch is taken. eML only requires the labels being available at type-level. The language we present here also has labels at value level (and, indeed, is mostly untyped).

Overview

When lifting an ML program, we provide patches to fill in the missing parts of the term. When writing these patches, we might need to access a previously computed result after it has been computed. For example, suppose we are lifting the following term by lifting the output boolean to an integer:

match random_int_option pq with Some _ Ñ True | None Ñ False
We obtain a program of the form match random_int_option pq with Some _ Ñ Some #1 | None Ñ None

To provide a value for the hole #1 we need to access the result of the call to random_int_option, but we dropped some information. We cannot call the function a second time, as it may have side-effects, or in this case return a different result altogether. If we can recover the result of the call, we can simply match on it again to finish the transformation. This is already achievable in ML by program transformation: in that case, we simply have to bind the result of the computation to a variable that we can reuse later on:

let x " random_int_option pq in match x with Some _ Ñ True | None Ñ False
The lifted term becomes:

let x " random_int_option pq in match x with Some _ Ñ Some #1 | None Ñ None
The hole #1 can then be patched with match x with Some y Ñ y | None Ñ 0.

Note that we have another issue there: we know from the branch we are in that x is necessarily Some _, but we have to provide a complete pattern matching. In this example, we simply insert a placeholder value there. We solve this problem in Chapter 6 by teaching the type system how to use branch information to decide that some branches are unreachable. This re-uses the labelling system to refer to previously performed computations.

We don't need to give names to computations that don't involve function application: we consider them both safe and cheap to duplicate if needed.

More complicated cases can also be handled by program transformation, although at increased cost. Consider for example the program

let x 1 = match f () with | True Ñ g () != 2 | False Ñ False in C[#1]
We can only bind g () to a variable if it is actually evaluated, which means we have to extrude the match around the binding of x 1 and duplicate the context Cr_s so we can reuse the result in #1:

let y 1 = f () in match y 1 with | True Ñ let y 2 = g () in let x 1 = y 2 != 2 in C[#1] | False Ñ let x 1 = False in C[#2]
With more pattern matching, we would have to duplicate even more code, nest even more pattern matchings, and generate even more patches. Moreover, our lifting strategy does not allow us to perform only the necessary extrusions: since we want to create a completely generic term that can support any lifting of the base function, we have to perform all extrusions, even if they are unneeded. We would rather take the inverse approach: only perform the necessary extrusions at the latest possible moment, once the term has been instantiated and we are reducing it back to an ML term. We label each application in the execution of a program with an unique label p, noted above the application as in f p x. When we want to reuse the result of a previously executed application, we access the value of the label, noted ˚p. Our first example becomes: match random_int_option 1 pq with Some _ Ñ Some #1 | None Ñ None, and we can patch it with match ˚1 with Some y Ñ y | None Ñ 0.

Labels are substituted as soon as the corresponding expansive computation is evaluated: thus, labels are accessible in all subterms evaluated after the application that binds them in the ML evaluation order.

We want applications to have unique names, and application of a function can create new applications to be evaluated later by duplicating the code inside the body of the function. Therefore, we need a way for each separate application to generate its own labels. Instead of using abstract names for labels, we use paths constructed by concatenating abstract labels. We want a function application labelled by a (unique) label p to only generate applications prefixed by p with a unique suffix. This guarantees that the labels generated throughout the execution are unique. We add to each term abstraction a label variable π: all applications in execution position inside the abstraction will then have a label prefixed by π.

Our presentation here is untyped, we only add some well-labeling checks to ensure unicity of the generated labels (and later confluence, see §7.3.1). In particular, we do not worry about using labels that are only defined in some branches: the problem of knowing whether a particular label is valid to use or not is solved by the extension to eML in Chapter 6.

When reducing an application labelled with p, we immediately substitute all instances of ˚p with the result of the application. This requires some care: consider let x " pλ π py : unitq. random π¨1 pqq 1 pq in px, ˚1q. If we substituted all instances of ˚1 with the result of the application when reducing the lambda, we would obtain let x " random 1¨1 pq in px, random 1¨1 Unitq. This is wrong: we duplicated the call to random and we will probably end up with different results for the two calls. We also duplicated a label, while we want labels to uniquely identify applications. Instead, we substitute a reusable version of the term, obtained by replacing all new applications by a reuse of their label: here, this reusable version is simply ˚1 ¨1. The reduced term is thus: let x " random 1¨1 pq in px, ˚1 ¨1q.

Labelled reduction

In this section, we define the syntax of labelled terms and their reduction (Figure 5.1).

Result names, noted p and q are formed by appending a sequence of path components n to either the root name ε or a path variable π. When writing a path starting from the root component, we may omit it: we write n 1 ¨n2 for ε ¨n1 ¨n2 . If q is a path starting from the root, we note p ¨q the path formed by appending all path components of q to p. We say a path q is a suffix of p, noted p ď q, if q can be formed by adding some path components to p. It is a strict suffix if it is different from p.

The syntax of terms a is identical to the syntax of ML, with a few deviations: first, all applications are labelled: a p b is read as the application of a to b labelled with p. Second, we write ˚p the reuse of the result of the application labelled p. When the application is reduced, ˚p is replaced with the result of the reduction. Third, lambda abstractions also bind a path variable π. This variable can be used as a prefix for the labels appearing in the variable (either being defined or used). When an application is reduced, the label variable on the lambda is substituted with the label of the application in the body of the abstraction. The grammar of non-expansive terms u is also extended. As before, applications are expansive. Conversely, reused results ˚p are always nonexpansive. The grammar of values v is unchanged, except for the label variables added to abstractions.

The definition of the evaluation contexts, the head reduction, and the context rule are given on Figure 5.2. We define evaluation from elementary context layers E: they represent the possible right-to-left evaluation contexts in ML, and embed constrains about the fact that terms to the right must already be reduced to value for a subterm to be in evaluation position.

Ý Ñ vrα Ð τ s pfix π x py : τ 1 1 q : τ 1 2 . aq p v ˚pÐreuseparπÐp,xÐfix π x py:τ 1 1 q:τ 1 2 . a,yÐτ 1 1 sq Ý ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ Ñ arπ Ð p, x Ð fix π x py : τ 1 1 q : τ 1 2 . a, y Ð τ 1 1 s let x " v in a 0 Ý Ñ arx Ð vs match d j τ pv i q i with pd j τ 1 px ji q i Ñ a j q j 0 Ý Ñ a j rx ji Ð v i s i Red-NoLabel a 0 Ý Ñ b Eras 0 Ý Ñ Erbs Red-Label a ˚pÐu Ý ÝÝÝ Ñ b Eras ˚pÐu Ý ÝÝÝ Ñ pEr˚p Ð usqrbs
The reduction ÝÑ β is similar to the ML reduction, except that the reduction is labelled: a reduction 0 Ý Ñ indicates that the head-reduction was performed on a non-expansive term, while a reduction ˚pÐu Ý ÝÝÝ Ñ labelled with a substitution indicates that an expansive term with label p has been reduced to some expression to which u is a representation. Then, all occurrences of ˚p in the evaluation context are substituted by the non-expansive term u. This is done in the context rules Red-NoLabel (propagating the empty label) and Red-Label (applying the substitution and propagating it to the enclosing context).

The evaluation contexts E do not bind term variables, and only non-expansive terms occur under type abstraction; thus we do not need to take precautions to ensure that the terms substituted for labels stay well-scoped while moving up the context layers.

The head reduction rules are almost identical to the ML reduction rules. They are also labelled: reductions of non-expansive redexes (type application, let binding and pattern matching) have an empty label. Reductions of applications are labelled with a substitution ˚p Ð u of the label p of the application with a non-expansive representation u of the result of the application. The nonexpansive representation of a term a is noted reusepaq. It is formed by replacing all expansive computations in evaluation position (not under a term abstraction) by a reuse of their label. This makes it equivalent to the term, as long as the term is already evaluated once before. The definition is given in Figure 5.3: the important rule is given first, the others simply descend on the structure of the terms.

Lemma 5.1 (Values do not reduce). Values are irreducible for ÝÑ h β .

Proof. By structural induction on values. Values are never head-reducible (because they start with a constructor), and if v " Eras, then a is a value too.

reusepa p bq " ˚p reusepxq " x reusep˚pq " ˚p reusepΛpα : Typq. uq " Λpα : Typq. u reusepfix π x py : τ 1 q : τ . aq " fix π x py : τ 1 q : τ . a reuseplet x " a in bq " let x " reusepaq in reusepbq reusepa τ q " reusepaq τ reusepd i pτ j q j pa k q k q " d i pτ j q j preusepa k qq k reusepmatch a with pd i pτ k q k px ij q j Ñ b i q i q " match reusepaq with pd i pτ k q k px ij q j Ñ reusepb i qq i Lemma 5.2 (Unique decomposition). Consider a reducible term a. Then, either a is not head-reducible and there is a unique decomposition as a " Erbs where b is reducible, or a is head-reducible and there is no such decomposition.

Proof. Consider the different cases for a.

• Variables x and reused results ˚p are not reducible.

• Suppose a is let x " a 1 in a 2 . If a 1 is not a value, the term is not headreducible, and the only possible reduction context is E " let x " rs in a 2 .

Then a 1 must be reducible (otherwise a would not be reducible), and we have a " Era 1 s. If a 1 is a value, a head-reduces. The only possible reduction context is E " let x " rs in a 2 but it does not produce a decomposition because a 1 is not reducible (by Lemma 5.1).

• We proceed similarly for terms starting with destructors (application, pattern matching).

• Term abstractions are always values and do not reduce.

• For other constructors: we consider the case of data constructors, with a " dpτ q i pa j q j . Since a is reducible, there exists a decomposition of pa j q j " pb k q k bpv q such that b reduces. By Lemma 5.1, b is not a value. Other possible contexts are of the form E " dpτ q i pb k q k bpv q ăn rspv q ąn with a " Erv n s. But v n is irreducible.

Lemma 5.3 (Determinism). Suppose a is reducible. There exists a unique b and l such that

a l Ý Ñ h b.
Proof. By induction on the term, using unique decomposition: if there were two reductions, there would be two decompositions.

Full reduction

In this section, we introduce a full reduction for labeled ML. While we will not use it directly, it will serve to explain how the labeling, that seems very dependent on the evaluation order of ML, is actually compatible with full reduction. We will build upon the concepts defined here to provide full reduction for meta-abstractions in mML (Chapter 7).

pΛpα : Typq. uq τ 0 Þ Ý Ñ urα Ð τ s pfix π x py : τ 1 1 q : τ 1 2 . aq p u ˚pÐreuseparπÐp,xÐfix π x py:τ 1 1 q:τ 1 2 . a,yÐτ 1 1 sq Þ Ý ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ Ñ arπ Ð p, x Ð fix π x py : τ 1 1 q : τ 1 2 . a, y Ð τ 1 1 s let x " u in a 0 Þ Ý Ñ arx Ð us match d j pτ 2 k q k pv i q i with pd j pτ k q k px ji q i Ñ a j q j 0 Þ Ý Ñ a j rx ji Ð v i s i
The full reduction allows reduction in any position, including under a lambda. Moreover, instead of requiring values in redexes, we only require terms to be non-expansive. The definition of the head reductions is given in Figure 5.4. Other than requiring non-expansive terms instead of values, they are identical to the head reductions of the weak reduction.

The contexts of the reduction are all shallow contexts C. We enumerate them in Figure 5.5.

There is an additional wrinkle to take care of when performing full reduction. Consider the reduction of let z " let x " True in pλpy : boolq. yq p x in ˚p. If we start by reducing the abstraction, we need to propagate a result ˚p Ð x. This is fine until we leave the scope of x, but if we continue propagating this to the toplevel, we end up with let z " let x " True in x in x, which reduces to x. If we follow the weak reduction order on the same term, we end up with True: our reduction is not confluent. We need a way to keep the value of x available in the term, even if x has not been evaluated yet. Fortunately, we have exactly that: when ˚p Ð u passes through a let x " a in rs layer, we transform it into ˚p Ð urx Ð reusepaqs.

We encounter similar problems with pattern matching. We can perform the same pattern matching to get the values of the variables in a branch, but we are blocked in other branches: we know locally which branch has been taken, but there is no way to use this information to create terms to fill the other branches. We work around this (until Chapter 6 gives us a better solution) by allowing incomplete pattern matchings.

Lambda abstractions also bind term variables. There is no easy way to recover a value for these variables because lambda abstractions are detached from the term that will be used as argument. For this reason, when reducing inside of a lambda abstraction, we hide the label on the reduction from the context outside of the abstraction: the reduction becomes unlabeled. Lastly, type abstractions contain only non-expansive terms, and reducing non-expansive p˚p Ð uq Ò fix x τ rs : py : τ 1 q .

" 0 p˚p Ð uq Ò match a with P Ñ rs | . . . " ˚p Ð match reusepaq with P Ñ u p˚p Ð uq Ò let x " a in rs " ˚p Ð urx Ð reusepaqs p˚p Ð uq Ò let x " rs in a " ˚p Ð u p˚p Ð uq Ò a q rs " ˚p Ð u p˚p Ð uq Ò rs q a " ˚p Ð u p˚p Ð uq Ò d τ ppa i q i , rs, pa j q j q " ˚p Ð u p˚p Ð uq Ò rs τ " ˚p Ð u p˚p Ð uq Ò match rs with pP Ñ a | .. P Ñ aq " ˚p Ð u We express these transformations on labels by defining a translation function p˚p Ð uq Ò C that returns either a new label ˚p Ð u 1 or 0. Its definition is given in Figure 5.6. For weak reduction contexts (i.e. the last six cases), the label is propagated as-is, which is consistent with the fact that we did not need label translation in weak reduction contexts.

a 0 Þ Ý Ñ b Cras 0 Þ Ý Ñ Crbs Red-Label a ˚pÐu Þ Ý ÝÝÝ Ñ b Cras p˚pÐuqÒC Þ ÝÝÝÝÝÝÑ pCr˚p Ð usqrbs
Then, the full reduction is defined using these two functions in Figure 5.7. It generalizes the previous reduction:

Lemma 5.4 (Superset). Suppose a l Ý Ñ b. Then a l Þ Ý Ñ b.
Proof. The evaluation contexts and redexes of the weak reduction are a subset of the evaluation contexts and redexes of the full reduction, the weak head reduction is a subset of the full head reduction, and the context rules are identical for evaluation contexts.

The reduction preserves non-expansivity. Moreover, reduction of non-expansive terms does not produce a label:

Lemma 5.5 (Non-expansivity). Suppose u l Þ Ý Ñ a.
Then a is non-expansive and l " 0.

Proof. By induction on the contexts. Contexts that yield non-expansive terms either have a non-expansive term in the hole or remove the label. Non-expansive redexes do not produce a label when reducing.

An attempt at well-labelling

Unfortunately, the full reduction is not confluent. There are three causes for this. The first cause is that we can have two redexes with the same label.

Depending on which we reduce first, we get two different results. Consider for example the following two reduction paths from the same term:

p˚p, pλ π x. xq p 1, pλ π y. y p q2q p˚p, pλ π x. xq p 1, pλ π y. yq p 2q ˚pÐ1 Þ Ý ÝÝÝ Ñp1, 1, pλ π y. yq p 2q ˚pÐ2 Þ Ý ÝÝÝ Ñp2, pλ π x. xq p 1, 2q ˚pÐ2 Þ Ý ÝÝÝ Ñp1, 1, 2q ˚pÐ1 Þ Ý ÝÝÝ Ñp2, 1, 2q
Secondly, depending on the order of evaluation, a label may or may not be substituted. Consider the following example, where ˚1 ¨1 is substituted or not depending on whether we start by reducing the outer or the inner thunk:

p˚1 ¨1, pλ π y. pλ π z. xq π¨1 pqq 1 pqq p˚1 ¨1, pλ π y. pλ π z. xq π¨1 pqq 1 pqq ˚1Ð˚1¨1 Þ Ý ÝÝÝÝÝ Ñp˚1 ¨1, pλ π z. xq 1¨1 pqq H Þ Ý Ñ p˚1 ¨1, pλ π y. xq 1 pqq ˚1¨1Ðx Þ Ý ÝÝÝÝ Ñ px, xq ˚1Ðx Þ Ý ÝÝÝ Ñp˚1 ¨1, xq
Third, under branching constructs, evaluation might simply discard the expression generating a label before it is substituted: for example, in the following example, the label 1 is generated in a dead branch. But nothing prevents the full reduction from evaluating inside this dead branch:

p˚1, if False then pλ π z. xq 1 2 else 2q p˚1, if False then pλ π z. xq 1 2 else 2q ˚1Ð2 Þ Ý ÝÝÝ Ñp2, if False then 2 else 2q H Þ Ý Ñp˚1, 2q H Þ Ý Ñ p2, 2q
We can solve the first two issues by defining a set of well-labeled terms, stable by reduction. The third issue is solved by the introduction of eML in Chapter 6. We have two constraints. First, the labels produced by the reductions must be distinct. We cannot merely ask the labels present in a term to be distinct, because reduction of expansive redexes creates new redexes. To control the new labels, we require that the labels generated by reduction of a redex labeled p have labels prefixed by p. Then, a term should produce a set of labels such that no label is a prefix of another: this guarantees that replacing p with a set pp ¨ni q i will never create a conflict. Second, the order of evaluation should not influence when a label gets substituted. This is a constraint on the uses of labels: we must be certain that whatever the order of evaluation, a label will be substituted, or that whatever the order of evaluation it won't be. The second case is useful for subject reduction, because we need to handle the case where the expression producing a label was under a branch that disappeared during reduction.

To control the unicity of label, we need to define orthogonal sets of paths.

Definition 5.1 (Prefix). A path p is a prefix of q, noted p ď q, if there a exists a (possibly empty) sequence of labels pn i q i such that q " p ¨n1 ¨. . . ¨nn . This defines a partial order on the set of paths.

If neither p ď q nor q ď p, we say that p and q are orthogonal, noted p K q. ♦ Definition 5.2 (Orthogonal set, union). A set S of paths is orthogonal, noted orthogonalpSq, if there are no distinct elements p and q such that p ď q.

If S 1 and S 2 are orthogonal, and for all p 1 P S 1 , p 2 P S 2 , p 1 K p 2 , then S 1 and S 2 are said to be orthogonal, and there union S 1 Y S 2 is an orthogonal set.

♦

L-Var orthogonalpΓq Σ; Γ $ p l x ñ H L-TAbs Σ; Γ $ p l u ñ H Σ; Γ $ p l Λpα : Typq. u ñ H L-TApp Σ; Γ $ p l a ñ ∆ Σ; Γ $ p l a τ ñ ∆ L-Fix π # Σ Σ, π; Γ $ π l a ñ ∆ Σ; Γ $ p l fix π x py : τ 1 q : τ 2 . a ñ H L-App Σ; Γ $ p l a ñ ∆ 1 Σ; Γ, ∆ 1 $ p l b ñ ∆ 2 p ď q q K Γ, ∆ 1 , ∆ 2 Σ; Γ $ q l a q b ñ ∆ 1 , ∆ 2 , q L-Let Σ; Γ $ p l a ñ ∆ 1 Σ; Γ, ∆ 1 $ p l b ñ ∆ 2 Σ; Γ $ p l let x " a in b ñ ∆ 1 , ∆ 2 L-Con orthogonalpΓq pΣ; Γ, p∆ k q kąj $ p l a j ñ ∆ j q j Σ; Γ $ p l dpτ i q i pa j q j ñ p∆ j q j L-Match Σ; Γ $ p l a ñ ∆ pΣ; Γ, ∆ $ p l a i ñ ∆ i q i orthogonalp∆ i q i Σ; Γ $ p l match a with pP i Ñ a i q i ñ ∆, p∆ i q i L-Reuse orthogonalpΓq p P Γ _ p K Γ Σ; Γ $ p l ˚p ñ H Figure 5.8: Well-labeling
We define a well-labeling judgment Σ; Γ $ p l a ñ ∆, asserting that under an environment with label variables Σ and that produces the set of labels Γ, and when the current prefix for introducing new labels is p, the term a is welllabeled and may produce labels ∆. The rules of the judgment are given in Figure 5.8. They are essentially a miniature type-system that is only concerned with the existence of labels. Information flows following the evaluation order: for example, in application (L-App), the labels obtained evaluating the left-hand expression are added as input to the right-hand expression. The well-labeling judgment is only very weakly concerned with the existence of reused labels: it just wants them to be unambiguously bound, or unambiguously unbound. The latter case can happen if a reduction removes the code that would have emitted the label. A latter reduction might then remove the use of the label. For this reason, we allow reused labels (L-Reuse) to be either in Γ or independent from Γ.

The rules maintain some invariants.

Lemma 5.6 (Scoping of path variables). Suppose Σ; Γ $ p l a ñ ∆. Then, Σ does not contain duplicate variables, and all variables occurring in Γ, ∆, p, a are in Σ.

We write the reduction rules such that if Σ; Γ $ p l a ñ ∆, Γ and ∆ are orthogonal. This is enforced by requiring Γ to be orthogonal in L-Var, and requiring the different outputs to be orthogonal in L-Match. The rest is implicitly enforced:

Lemma 5.7 (Disjoint labels). Suppose Σ; Γ $ p l a ñ ∆. Then, Γ K ∆ and all labels in ∆ are prefixed by p.

Proof. Γ is orthogonal: all derivation rules have a premise whose set of input labels is Γ or a superset of Γ (then, proceed by induction), except L-Var where we check explicitly that Γ is orthogonal.

Γ K ∆: the only rule that grows Γ Y ∆ is L-App, and L-App checks that the union of input and output labels remains independent.

∆ is orthogonal: for most rules, ∆ is obtained by the union of part of the input of a premise and its output. L-App checks that the new label is independent of the already-existing output. L-Match explicitly checks that the output is orthogonal.

All labels in ∆ are prefixed by p: labels are only introduced by L-App and it checks that the label is prefixed by p.

Lemma 5.8 (Non-expansivity). Suppose Σ; Γ $ p l a ñ ∆. If a is non-expansive, then ∆ " H, and for all q, Σ; Γ $ q l a ñ H. Proof. By induction on the derivation. No rules can inspect p or add something in ∆ until passing through L-Fix because function application is expansive, and L-Fix erases the label and ∆.

We need to prove weakening and substitution: Lemma 5.9 (Weakening). Suppose Σ; Γ $ p l a ñ ∆. Then: • Suppose q ď p, and q independent of Γ, ∆. Then, Σ; Γ $ q l a ñ ∆. • Suppose π R Σ. Then, Σ, π; Γ $ p l a ñ ∆.

• Suppose q K p, Γ, ∆. Then, Σ; Γ, q $ p l a ñ ∆.

Proof. By induction on the derivation: these changes translate to weakening in the premises. The independence side-conditions stay true in the derivations.

Lemma 5.10 (Substitution). Suppose Σ; Γ $ p l a ñ ∆.

• Consider π P Σ, and q K Γ, ∆. Then, Σ ´π; Γrπ Ð qs $ prπÐqs l arπ Ð qs ñ ∆rπ Ð qs.

• Consider x and a non-expansive term u such that Σ; Γ $ p l u ñ H. Then, Σ; Γ $ p l arx Ð us ñ ∆.

Proof. By induction on the derivation.

We can prove that well-labeling is preserved by reduction (this is a form of subject reduction). Reduction can emit a label, which changes the set of possibly emitted labels: the emitted label p must be in ∆, and it is replaced by a set of labels prefixed by p. If no label is emitted, ∆ does not change.

Lemma 5.11 (Subject reduction for well-labeling). Suppose

Σ; Γ $ p l a ñ ∆. Moreover, suppose a l Þ Ý Ñ b. Then: • If l " 0, we have Σ; Γ $ p l b ñ ∆ 1 where ∆ 1 is a subset of ∆. • If l " ˚q Ð u, we have Σ; Γ $ p l b ñ ∆ 1 where ∆ 1 " ∆ ´tqu Z S
where S is an orthogonal set of labels prefixed by p.

Proof. Let us first prove the result for head reductions:

• For reduction of an application pfix π x py : τ q : τ 1 . aq q u: the application reduces to arπ Ð q, x Ð pfix π x py : τ q : τ 1 . aq, y Ð us, with label l " ˚q Ð reuseparx Ð usq. Inverting rule L-App, we obtain that p ď q and there exists ∆ 1 and ∆ 2 such that ∆ " ∆ 1 Z∆ 2 Ztqu, with Σ; Γ $ p l fix π xpy : τ q : τ 1 . a ñ ∆ 1 and Σ; Γ, ∆ 1 $ p l u ñ ∆ 2 . Since both fix π x py : τ q : τ 1 . a and u are non-expansive, ∆ 1 " ∆ 2 " H (Lemma 5.8). Further inverting the first subderivation (that must use L-Fix), we obtain that there exists ∆ 3 such that: Σ, π; Γ $ π l a ñ ∆ 3 . By substitution of term variables and path variables (Lemma 5.10), we have Σ; Γrπ Ð qs $ q l arπ Ð q, x Ð pfix π xpy : τ q : τ 1 .aq, y Ð us ñ ∆ 3 rπ Ð qsx. The path variable π does not appear in Γ (the free variables of Γ are included in Σ, thus Γrπ Ð qs " Γ. By Lemma 5.7, all labels of ∆ 3 rπ Ð qs are prefixed by q. By weakening of the path prefix (Lemma 5.9), we have Σ; Γ $ p l arπ Ð q, x Ð pfix π x py : τ q : τ 1 . aq, y Ð us ñ ∆ 3 rπ Ð qs, which is the result we are looking for (we have ∆ " tqu, and S " ∆ 3 rπ Ð qs).

• Consider the reduction of a type application: pΛp. • Consider the reduction of a let binding: let x " u in a reduces to arx Ð us with label 0. By inverting the last derivation, we get that there exists

∆ 1 , ∆ 2 such that ∆ " ∆ 1 Z ∆ 2 , and Σ; Γ $ p l u ñ ∆ 1 and Σ; Γ, ∆ 1 $ p l a ñ ∆ 2 . Since u is non-expansive, ∆ 1 " H and ∆ " ∆ 2 .
Then, by substitution (Lemma 5.10), Σ; Γ $ p l arx Ð us ñ ∆ 2 . • Consider reduction of a pattern matching:

match d j pτ 2 k q k pu i q i with pd j pτ k q k px ji q i Ñ a j q j
It reduces with label 0 to a j rx ji Ð u i s i . Let us invert the rule L-Match.

There exists ∆ 1 , p∆ j q j such that ∆ " ∆ 1 Z p∆ j q j , Σ; Γ $ p l d j pτ 2 k q k pv i q i ñ ∆ 1 , and, for all j, Σ; Γ, ∆ 1 $ p l a j ñ ∆ j . We have ∆ " H because d j pτ 2 k q k pv i q i is non-expansive. By inverting the rule L-Con, we get that, for all i, Σ; Γ $ p l u i ñ H. By substitution, Σ; Γ $ p l a j rx ji Ð u i s i ñ ∆ j . This satisfies subject reduction, since ∆ j is a subset of ∆.

Then, we proceed by induction on the reduction context. Let us consider a few different cases for context (other cases are similar):

• Suppose C " let x " rs in b, and a 0 l Þ Ý Ñ a 1 . Then, let x " a 0 in b l Þ Ý Ñ let x " a 0 in brls. Suppose let x " a 0 in b is well-labeled: then the last rule of the well-labeling derivation is L-Let and there exists Σ, Γ, p, ∆ 1 , ∆ 2 such that Σ; Γ $ p l a 0 ñ ∆ 1 , Σ; Γ, ∆ 1 $ p l b ñ ∆ 2 , and Σ; Γ $ p l let x " a 0 in b ñ ∆ 1 , ∆ 2 . By induction hypothesis, there exists ∆ 1 1 such that Σ; Γ $ p l a 1 ñ ∆ 1 1 . We have ∆ 1 1 K ∆ 2 :
this is true for ∆ 1 and the new elements of ∆ 1 1 are suffixes of elements of ∆ 1 : thus, if an element of ∆ 1 1 is a prefix of an element of ∆ 2 , then an element of ∆ 1 was a prefix of an element of ∆ 2 . Conversely, if an element of ∆ 2 is a prefix of an element of ∆ 1 1 , either it is a prefix or a suffix of the corresponding element of ∆ 1 . Moreover, we have Σ; Γ, ∆ 1 1 $ p l brls ñ ∆ 2 . This is true if ∆ 1 " ∆ 1 1 . Otherwise, the emitted label is q. By substitution, we have Σ

; Γ, ∆ 1 ´q $ brls l ∆ 2 ñ . Consider p such that p is either included in ∆ 1 or independent of ∆ 1 . If p is q, it is eliminated by substitution. Otherwise, p is either included in ∆ 1 1 or independent of ∆ 1 1 , as ∆ 1
1 is a subset of ∆ 1 ´q, and we obtain the result by weakening. Thus, we have Σ

; Γ $ p l let x " a 1 in brls ñ ∆ 1 1 , ∆ 2 . • Suppose C " fix π x py : τ 1 q : τ . rs. Suppose a 0 l Þ Ý Ñ a 1 . Then, fix π x py : τ 1 q : τ . a 0 H Þ Ý Ñ fix π x py : τ 1 q : τ . a 1 . Suppose fix π x py : τ 1 q : τ . a 0 : there exists Γ, p, ∆ such that Σ, π; Γ $ π l a 0 ñ ∆ and Σ; Γ $ p l fix π xpy : τ 1 q : τ .a 0 ñ H. By induction hypothesis, there exists ∆ 1 1 such that Σ; Γ $ p l a 1 ñ ∆ 1 1 . Then, Σ; Γ $ p l fix π x py : τ 1 q : τ . a 1 ñ H.
As mentioned before, the full reduction is not confluent, even on well-labeled terms. We could prove that two reduction paths either converge or one of them gets blocked on an unbound label. Instead, we will use equalities to develop a richer type system that allows us to encode precisely when labels are available in Chapter 6.

Chapter 6

A language for equalities

In this chapter, we construct an extension of ML with type-level pattern matching, dependent on the variables in the context: for example, a term of type match x with True Ñ τ | False Ñ σ must have a value of type τ if x is true, and of type σ otherwise. To allow the construction of terms of these types, term-level pattern matching introduces an equality witnessing the information learned by matching the term: the term that is matched upon is equal to the pattern of the current branch. Then, this equality (for instance x " True) can be used to reduce type-level pattern matching: under this equality, the type match x with True Ñ τ | False Ñ σ is equivalent to τ , and terms with these types are freely interconvertible.

This extension, called eML, is carefully designed so that it can be simplified back to ML by some well-identified code transformations.

Design constraints

The introduction of eML is motivated by the fact that, when doing ornamentation, the programmer decorates a value of the base type with some supplementary information that will be used to construct a value of the ornamented type. The type of this supplementary information depends on the original value: for example, when lifting natural numbers to lists, one has to provide an element for lifting S into a Cons, but no information (i.e. a value of type unit) is needed for lifting Z into Nil. In that case, the supplementary information depends only on the constructor. In general, it could depend on information found deeper into the term: for example, one could add a value to Some True and leave Some False as-is.

Type-level pattern matching provides an expressive way of handling the typing of the supplementary information: the ornament writer can use an arbitrarily deep (but finite) view of the base term to determine the appropriate type for the patch.

To write a term of the appropriate type, the writer of the patch can use the local information in the function: for example, if the patch is to be applied below a pattern matching Z, the type of the information required is equivalent to unit. This can be proved to the type system using an equality introduced in the context by the pattern matching, witnessing the branch that is currently 75 being executed. It is important to the design of eML that this information is local, i.e. is not propagated through function calls and returns: one key requirement on eML is that we still want to be able to output ML programs after ornamentation. Exploiting the fact that the information used to interpret type is local, it is possible (under some typing conditions) to simplify any eML term to an equivalent ML term.

The equivalence between types defined by eML depends on an equivalence between terms: one can reduce a type-level pattern matching (such as match a with Z Ñ unit | S _ Ñ bool) when one knows that, in the current context, the term that is matched is equivalent to a term of the shape of one of the branches (for example, a being equivalent to Z). This equivalence between terms needs to be appropriately limited: first, it is more convenient if it is decidable (this allows, for example, to easily eliminate dead branches in eML code when translating it to ML). A simple way to do that is to not recognize the equality between a function application and its reduction. A second reason to not recognize this equality is that, in OCaml, functions may have side-effects. If an application returns True the first time it is called, there is no guarantee that it will not return False the second time. The presence of side-effects also means that it is not sound to replace a call to a function by its result, since the call may have other effects. Equalities between an application and its result may be introduced as a witness of the result of a pattern matching: match rand_bool Unit with True Ñ a | False Ñ b introduces when typing a an equality between rand_bool Unit and True. A pattern matching on the same expression could introduce the equality between rand_bool Unit and False. Taken together, these two equalities give the equivalence of True and False, which notably proves the equivalence of any two types.

The equalities we actually mean to introduce in this case are that a particular call to rand_bool Unit returned a particular boolean, without any implications on the result of other evaluations of this expression. We express this by using the labels that we introduced to refer to the result of previous applications: each application executed in the program is attributed a different label, and one can refer using this label to the result of this specific application.

Description of eML

This section builds on the presentation of labeled ML ( §5). We combine the typing rules of ML with the well-labeling rules of labeled ML, and add constraints on labels to ensure that well-typed terms do not get stuck on unsubstituted labels (Lemma 6.24).

Extended syntax

The syntax of eML is identical to the syntax of labeled ML, except for the introduction of type-level pattern matching. The new syntax of types is given on Figure 6.1: type-level pattern matching is identical to term-level pattern matching, except that it can only match on non-expansive terms, and the branches are types instead of terms. For example, match u with True Ñ unit | False Ñ bool is a valid eML type.

match d j pτ 2 k q k pv i q i with pd j pτ k q k px ji q i Ñ σ j q j 0 Þ Ý Ñ σ j rx ji Ð v i s i Figure 6
.2: Additional head reduction rule for eML

Extended labeled reduction

The weak reduction stays the same as in labeled ML: it only reduces the terms, whose syntax is unchanged.

Since redexes can now appear in types, it is necessary to extend the full reduction to also reduce these types: this introduces new (non-expansive) evaluation contexts and places where a potential substitution is allowed. The additional reduction rule is given in Figure 6.2: it is the reduction of a type-level pattern matching. It is identical to the reduction of a term-level pattern matching, except in that the branches are types. The other rules are identical to those given in Figure 5.7. The modified contexts are given in Figure 6.3. Since none of the new contexts may contain expansive expressions, the translation function is identical to its definition in Figure 5.6.

We could also define a well-labeling relation for eML terms. Instead, we provide a typing judgment that refines the well-labeling judgment.

Combining typing and labeling

The definitions of datatypes stay unchanged. In particular, we require that they do not include type-level pattern matching. This is necessary so that they are still ML datatypes, so that we can simplify eML types to ML types.

The typing judgment for eML combines the typing of ML with the welllabeling judgment of labeled ML. The syntax of typing environments is given on Figure 6.4. They include term and type variables as in ML, but also path variables π and input labels puq˚p : τ . Input labels are guarded with a nonexpansive term u: this is a boolean expression that guards the use of the label. The typing judgment will ensure that the guard condition is true whenever we try to refer to a label. We also indicate the type τ of the computed result. The typing environments are also extended with witnesses of equalities between nonexpansive terms u 1 and u 2 at a type σ, written pu 1 » u 2 q : σ. The equalities are introduced and used implicitly, thus are unnamed. The typing judgment is of the form Γ $ p a : τ ñ ∆. It can be read similarly to a ML typing judgment Γ $ a : τ by ignoring the parts related to labeling: under context Γ, the term a has type τ . It can also be read as well-labeling judgment Σ; Γ $ p l a ñ ∆ where Σ is the set of label variables defined in Γ, and Γ represents only the labels that are defined in Γ (Γ plays both roles in the eML judgment), and under a path prefix p, the term a emits the labels specified in ∆. The output specification ∆ is similar to ∆ in the well-labeling judgment. Its syntax is defined on Figure 6.4: it is a subset of the syntax of Γ where only precomputed results are allowed. As with Γ, it associates to each output label p a condition u, and the type τ of the computed result.

For a non-expensive term u, if Γ $ p u : τ ñ ∆, the set of computed results ∆ is always empty, and p is irrelevant. In this case, we may instead write Γ $ u : τ .

The definition of the typing judgment is given in Figure 6.5. It follows the structure of both the ML typing judgment and the well-labeling judgment.

We need to keep track of which abstractions have been reduced so we can reduce the results. This is done through the output ∆ of the typing judgment: ∆ contains a list of paths and the type of the result of the application. This is not enough to guarantee that a term can be reused: in code with branches, whether or not an application has actually been evaluated may depend on which branch was taken. For instance, in let x " match u with True Ñ True | False Ñ f p y in a, when typing a, a subexpression ˚p would be valid if and only if u were equal to False. This condition is added (in Match) to ∆: a typing of b " match u with True Ñ True | False Ñ f p y could be Γ $ π b : bool ñ pmatch u with True Ñ False | False Ñ Trueq˚p : bool, indicating that ˚p is valid only when the expression match u with True Ñ False | False Ñ True is equal to True, i.e. when u is equal to False. This mechanism works well for matching on non-expansive terms. Matching on expansive terms is problematic, because we need the condition u to be non-expansive. We exploit the notion of reusable terms defined in Chapter 5: since the constraint will only be used after the evaluation of the abstraction in the expansive term, reusepaq is a valid nonexpansive substitute for a. Similarly, the type of the introduced path may use variables that are only bound in the place where the application is present in the term. To be able to use these types somewhere else, we must transform them as we leave the contexts of pattern matchings and let bindings: this is done in rules Match and Let. The transformations are similar to these done to pass the values associated to labels through let and match contexts. The notation match u 0 with d i pτ k q k px ij q j Ñ ∆ is to be interpreted as transforming each element puq˚p : τ of ∆ into pmatch u 0 with d i pτ k q k px ij q j Ñ u | pd pτ k q k px j q j Ñ Falseq ‰i q˚p : match u 0 with d i pτ k q k px ij q j Ñ τ | pd pτ k q k px j q j Ñ voidq ‰i (the type void could be replaced by any other type).

q K Γ Γ $ False : bool » True : bool Γ $ τ : Typ Γ $ p ˚q : τ ñ H
Function definitions also introduce variables in the scope of their bodies, but the results from evaluating the body do not escape the abstraction (they are blocked by the reduction rule, and removed by the typing rule), so there is no need to retain information about these variables. Abstractions on types can also avoid doing this for another reason: the body of the abstraction is non-expansive (by syntactic guarantee) and thus its evaluation cannot involve reducing an application.

In the judgment Γ $ p a : τ ñ ∆, p is a prefix that constrains the labels that can be returned in ∆. Most rules simply leave p unchanged. The application rule App checks for an application a q b that the label q is a suffix of p, and that it is independent from the labels in Γ and the labels in ∆ 1 and ∆ 2 generated by a and b. The returned set of results is composed of ∆ 1 , ∆ 2 , and the newly introduced result pTrueq˚q : τ 2 : the condition is True because in this context the application must be reduced. The fixed-point rule Fix types the body a of an abstraction fix π x py : τ q : σ . a under the path variable π introduced by the application. The computed results ∆ are discarded: they are not available outside of the body of the abstraction.

When re-using a result q (Reuse-Present and Reuse-Absurd) we need to check that the evaluation of this application did take place. As in the welllabeling judgment, there are two possibilities: either the label is present in the context as puq˚q : τ , in which case we look up its condition u and check that it is equal to True in the current context (by using the equality Γ $ u : bool » True : bool): then the type of the expression is τ . The other possibility (Reuse-Absurd) is that q is not present in the context. In that case, we require, as in the L-Reuse, that q is independent of Γ, and that the branch is dead, as execution would be stuck if we had to reduce the term. This is expressed by asking that True be equal to False in the current context. Then, we accept to type this term with any well-formed type.

The features of eML rely on the ability of the type system to track branches. This is done by adding equalities in the typing context: when under a branch, for example in the term a in the expression match u with Z Ñ a | S x Ñ b, the context contains an equality pu » Zq : nat. This equality witnesses that u must be Z when evaluating a, which allows for example reusing the results of applications computed below such a branch in a previous location in the term. When matching on a term c, not necessarily non-expansive, we introduce an equality between reusepcq and (e.g.) Z instead. This is done in Match. For convenience, we also introduce an equality for let bindings (Let): in let x " a in b, if a has type τ , the equality px » reusepaqq : τ is available when typing b. The equalities in the context are always between non-expansive terms. These equalities are not used directly in the typing judgment, but in type and term equality judgments, written Γ $ τ 1 : κ 1 » τ 2 : κ 2 and Γ $ a 1 : τ 1 » a 2 : τ 2 . The definition of these judgments is given in the next section ( §6.2.4).

Equality judgments are used in two places in the typing derivations. First, they are used to coerce terms from one type to another (Coerce): if two types

EnvEmpty $ H EnvPathVar $ Γ π # Γ $ Γ, π EnvVar $ Γ Γ $ τ : Sch x # Γ $ Γ, x : τ Figure 6
.6: Well-formedness rules of eML are equal (in a given environment), terms of one type can be used as terms of the other type. In our system, this rule is mostly to introduce and eliminate pattern matching in types. We chose to make coercion invisible in the syntax of terms: this makes the syntax much lighter and allow us to express simply transformations that would have to perform complicated transformations on equalities: indeed, we will introduce a full reduction for non-expansive parts ÝÑ ι that would need to perform complex transformations on explicit equalities. Second, they are used in Reuse-Present to check that the result that we are attempting to reuse has been computed. Before proceeding with describing equality, we describe in Figure 6.6 the well-formedness rules for type environments ($ Γ) and for types (Γ $ τ : κ).

The well-formedness judgment for Γ, as well as the typing rules, reproduce the assumption in labeled ML that the set of available names is orthogonal: EnvPathVar checks that path variable names are unique, and EnvPtr ensures that the introduced path is neither a prefix nor a suffix of an existing path, and that if it starts with a variable, this variable is present in Γ.

The non-expansive equality judgment

We define the equality judgment on type and non-expansive terms. These terms do not emit labels: the equality judgment can then be built around a simpler version of the typing judgment. We want equality to be symmetric, reflexive (on well-formed types and on well-typed non-expansive terms) and transitive. It also needs to be a congruence, and compatible with reduction of type-level and term-level pattern matching, let binding, and type application.

We start with the type equality judgment Γ $ τ 1 : κ 1 » τ 2 : κ 2 , stating that under the environment Γ, the types τ 1 and τ 2 of kinds κ 1 and κ 2 are equal. Its rules are given on Figure 6.7. We include a rule for transitivity (TEq-Trans) and for symmetry (TEq-Sym). Reflexivity can be proved using the congruence rules. For each well-formedness rules for types, we include a corresponding congruence rule that states that two types of a given syntactic shape are equal if their subtypes are equal: TEq-Var for K-Var, TEq-Datatype for K-Datatype, TEq-Arr for K-Arr, TEq-All for K-All. Since the kind of the types appear in the judgment, we also include a rule TEq-SubTyp that allows converting the left-hand side of an equality from the kind of monotypes to the kind of schemes. We can do the same transformation on the right-hand side using symmetry. The rule TEq-Match corresponding to K-Match is particular: since it compares two pattern matchings where two different (but equal) terms are matched on, we need to chose whether to include an equality with the term on the left-or right-hand side of the equality. We choose the left-hand side. The reduction of type-level pattern matching is handled through a rule TEq-ReduceMatch. Note that the reduction can be done even when the term we are matching on is not fully reduced to a value. Finally, we allow case-splitting on non-expansive terms of a datatype (TEq-Split). For each constructor, we can try to prove the equality assuming that the term starts with this constructor. If we can prove the equality in all of these cases, then it is true. This implies that, if we have a term of a datatype without constructors such as void, we can prove the equality of any two types.

The non-expansive term equality judgment Γ $ u 1 : τ 1 » u 2 : τ 2 is defined by the structural and reduction rules in Figure 6.8 and the congruence rules in Figure 6.9. While it is apparently an heterogeneous equality, we prove (Lemma 6.15) that it actually only proves equality between terms of equal types. Its structure is similar to the type equality judgment: it has a transitivity (Eq-Trans), symmetry (Eq-Sym) and case-splitting rule (Eq-Split), congruence rules for each syntactic construct of eML terms (Figure 6.9), and reduction rules for let binding (Eq-ReduceLet), type application (Eq-ReduceTApp) and pattern matching (Eq-ReduceMatch). The rule Eq-Coerce allows substituting the types on both side of the equality by equal types. Finally, the rule Eq-Subst allows using equalities in the context.

Note that when there is a contradiction in the context (such as True " False), we can deduce the equality of any two types or non-expansive terms: consider types τ 1 and τ 2 . Then, by TEq-Match, the types match True with True Ñ τ 1 | False Ñ τ 2 and match False with True Ñ τ 1 | False Ñ τ 2 are equal. Reducing these two equal types, we get τ 1 for the first and τ 2 for the second. By transitivity, we have proved pTrue » Falseq

: bool $ τ 1 : Sch » τ 2 : Sch. Similarly, pTrue » Falseq : bool $ u 1 : τ 1 » u 2 : τ 2 for any u 1 , u 2 , τ 1 , τ 2 .

Full term equality

There is a wrinkle in this definition: we only define equality on non-expansive terms, but arbitrary terms can appear under lambda abstractions. In order

Eq-ReduceTApp Γ, α : Typ $ u : σ Γ $ τ : Typ Γ $ pΛpα : Typq. uq τ 0 : σrα Ð τ 0 s » urα Ð τ 0 s : σrα Ð τ 0 s Eq-ReduceMatch $ pd i q i : ζ complete pd i : @pα k : Typq k pτ ij q j Ñ ζ pα k q k q i pΓ $ u j : τ ij rα k Ð τ 1 k s k q j Γ, px ij : τ ij rα k Ð τ k s k q j , pd i pτ k q k px ij q j » d i pτ 1 k q k pu j q j q : ζ pτ k q k $ u 1 i : σ Γ $ match d i pτ 1 k q k pu j q j with pd i pτ k q k px ij q j Ñ u 1 i q i : σ » u 1 i rx ij Ð u j s j : σ Figure 6.8: Non-expansive term equality Eq-Coerce Γ $ u 1 : τ 1 1 » u 2 : τ 1 2 Γ $ τ 1 1 : κ 1 1 » τ 1 : κ 1 Γ $ τ 1 2 : κ 1 p K Γ Γ $ False : bool » True : bool Γ $ ˚p : τ » ˚p : τ Figure 6
.9: Non-expansive term equality (congruence rules) not to get stuck, we delegate checking of equality for terms to a judgment TermsEqualpΓ $ p a 1 : τ 1 » a 2 : τ 2 q: this judgment assert that the terms a 1 and a 2 are equal at types τ 1 and τ 2 under an environment Γ and a label prefix p. This judgment does not compare the results computed when evaluating a 1 and a 2 . This does not prevent us from defining the rule Eq-Fix since ∆ is removed by the Fix typing rule, and many reasonable program transformations change labels.

Decomposition of terms

To define the equality on term, we want to separate the expansive part of a term from its non-expansive parts, and reason by equality on these two components separately. We define an extraction of expansive computations from an expansive term a. This extraction returns a mapping from computation labels to expansive atoms, i.e. applications of the form u u 1 , where both sides of the application are non-expansive terms. For example, for the term a " Some ppu 1 1 u 2 q 2 pλ π px : τ q. u 3 π¨1 u 4 qq, its decomposition is:

˚1 Þ Ñ u 1 u 2 ˚2 Þ Ñ ˚1 pλ π px : τ q. u 3 π¨1 u 4 q reusepaq Þ Ñ Some p˚2q
We need to add typing information to the decomposition: suppose Γ $ p a : τ ñ ∆. Then, we want every expansive atom to be typed in Γ, ∆ 1 , with ∆ 1 a (strict) subset of ∆, under a condition pu » Trueq : bool. Consider for example Γ equal to f : bool Ñ bool, x : bool, ∆ " pTrueq˚1 : bool, pxq˚2 : bool and the following term:

Γ $ ˆlet y " True in f 1 y, match x with True Ñ f 2 ˚1 | False Ñ x ˙: bool ˆbool ñ ∆
The expression labeled 2 depends on the expression labeled 1, thus its hypotheses will be ∆ 1 " pTrueq˚1 : bool. Moreover, the expansive atom labeled 1 is under a let binding. We use context translation (as in reduction) to express it in Γ.

Finally, the expression labeled 2 is only computed if x " True, so it is protected by a condition x. The full decomposition is then the following. Note that the expansive terms are ordered in the same order they would be evaluated in the original term.

Γ $ pTrueq ˚1 :" f True : bool Γ, ∆ 1 $ pxq ˚2 :" f ˚1 : bool Γ, ∆ $ reusepaq :" ˆlet y " True in ˚1, match x with True Ñ ˚2 | False Ñ x ˙: bool ˆbool
The general decomposition of a term, noted atomspaq, is defined in Figure 6.10: it returns the list of atoms and the set of labels that they depend on (the final non-expansive expression for the term is given by reusepaq). We note labelspaq the set of labels defined in a term, and addLabelspS, p˚p i Ð pT i , u i u 1 i qq i q " p˚p i Ð pS Y T i , u i u 1 i qq i the addition of the labels in S to the dependencies of all atoms of the second argument. We use this for example in the definition of atomspa p bq: the decomposition is obtained by concatenating atomspuq " H atomspa τ q " atomspaq atomsplet x " a in bq " atomspaq, paddLabelsplabelspaq, atomspbqqqrx Ð reusepaqs atomspmatch a with pc i τ px ik q k Ñ b i q i q " atomspaq, paddLabelsplabelspaq, match a with c i pτ j q j px ik q k Ñ atomspb i qq i atomspc τ pa j q j q " paddLabelspplabelspb k qq kąj , atomspa j qqq j atomspa p bq " atomspaq, addLabelsplabelspaq, atomspbqq, ˚p Ð plabelspaq Y labelspbq, reusepaq reusepbqq Figure 6.10: Decomposition of terms the decomposition atomspaq of a, then the decomposition atomspbq of b, with all labels of a added as dependencies, then the label ˚p corresponding to the application. The decomposition of non-expansive terms is empty. For general terms, it obeys the following typing property: Lemma 6.1. Suppose Γ $ p a : τ ñ ∆, and atomspaq " p˚p i Ð pS i , u i u 1 i qq i . Then, the labels of ∆ are the pp i q i and for all i, there exists

τ i , σ i such that Γ, ∆ X S i $ u i : τ i Ñ σ i and Γ, ∆ X S i $ u 1 i : τ i .
Proof. By induction on the typing derivation.

Reasoning on decompositions

We define an equality on decompositions that preserves the fact that equivalent expansive atoms are evaluated in the same order in both terms. We still want to allow the evaluation of a subexpression to be split, and subexpressions to be renamed: the terms f 1 x and match y with True Ñ f 2 x | False Ñ f 3 should be considered equivalent, as in the y " True case, 1 on the left will match 2 on the right, and 3 on the right will not be evaluated, and in the case of y " False, 1 will match 3 and 2 will not be evaluated. Thus, an equality should allow to provide a mapping between the labels on the left-hand side and on the right-hand side.

The evaluations are ordered and we have conditions available telling us if an expansive atom is evaluated or not: thus, we simply want the first evaluated atom on the left to match the first evaluated atom, and so on until the last evaluated atom.

We first define an indexing function that takes a list of non-expansive conditions and associated terms or types and returns the term or type corresponding to the k-th true condition. Definition 6.1 (Indexing). Consider a type end with one zero-argument constructor End. We use this type and this constructor as a special marker when indexing goes past the end. We define Index k pu i Ñ u 1 i q i as follows:

Index k pHq " End Index 0 pu i Ñ u 1 i q iPt1,...,nu " match u 1 with | True Ñ u 1 1 | False Ñ Index 0 pu i Ñ u 1 i q iPt2,...,nu Index n`1 pu i Ñ u 1 i q iPt1,...,nu " match u 1 with | True Ñ Index n pu i Ñ u 1 i q iPt2,...,nu | False Ñ Index n`1 pu i Ñ u 1 i q iPt2,...,nu
Similarly, we can define for types:

Index k pHq " end Index 0 pu i Ñ τ i q iPt1,...,nu " match u 1 with | True Ñ τ 1 | False Ñ Index 0 pu i Ñ τ i q iPt2,...,nu Index n`1 pu i Ñ τ i q iPt1,...,nu " match u 1 with | True Ñ Index n pu i Ñ τ i q iPt2,...,nu | False Ñ Index n`1 pu i Ñ τ i q iPt2,...,nu

♦

We have the following typing lemma for indexing: Lemma 6.2 (Typing of indexing). Consider an environment Γ and suppose pΓ $ u i : boolq i and pΓ, pu i » Trueq : bool $ u 1 i : σ i q i . Then for all n, Γ $ Index n pu i Ñ u 1 i q i : Index n pu i Ñ σ i q i . Proof. By induction on the list: at each stage we add a pattern matching in each of the branches to match the indexing function.

We then use the following definition: Definition 6.2 (Term equality). Consider an environment Γ, two terms a, b, and two types τ a , τ b such that there exists p, ∆ a , ∆ b such that Γ $ p a : τ a ñ ∆ a and Γ $ p b : τ b ñ ∆ b . Let S a " labelspaq, S b " labelspbq Suppose atomspaq " p˚p i Ð pT a,i , u a,i u 1 a,i qq piPlabelspaq and atomspbq " p˚q j Ð pT b,j , u b,j u 1 b,j qq qj Plabelspbq . Moreover, suppose that for all i, Γ, ∆ a Y T a,i $ u a,i : τ a,i Ñ σ a,i and Γ, ∆ a Y T a,i $ u 1 a,i : τ a,i and similarly for all j, Γ, ∆ b Y T b,j $ u b,j : τ b,j Ñ σ b,j and Γ, ∆ b Y T b,j $ u 1 b,j : τ b,j . Finally, suppose that ∆ a " ppu c a,i q˚p i : σ a,i q i and ∆ b " ppu c b,j q˚q j : σ b,j q j . We define a type app pτ, σq with one constructor App : pτ ˆpτ Ñ σqq Ñ app pτ, σq to represent function application atoms. Then, we say that a and b are equal, noted TermsEqualpΓ $ p a : τ a » b : τ b q if and only if:

• For all k: Γ, ∆ a , ∆ b , ppIndex pu c a,i Ñ p i q i » Index pu c b,j Ñ q j q j q : Index pu c a,i Ñ τ i q i q ăk $ Index k pu c a,i Ñ Apppu a,i , u 1 a,i qq i : Index k pu c a,i Ñ app pτ a,i , σ a,i qq i » Index k pu c
b,j Ñ Apppu b,j , u 1 b,j qq j : Index k pu c b,j Ñ app pτ b,j , σ b,j qq j i.e. the k-th application on the left-hand side has equal function and arguments to the k-th application on the right-hand side.

• The final expressions are equal:

Γ, ∆ a , ∆ b , ppIndex pu c a,i Ñ p i q i » Index pu c b,j Ñ q j q j q : Index pu c a,i Ñ τ i q i q ămaxpn,mq $ reusepaq : τ a » reusepbq : τ b where n and m are the number of labels appearing in a and b respectively.

♦

Note that if two non-expansive terms are equal, they are equal as terms: all indexing operation will rewrite to simply End (or end), and their reusable versions will be themselves, equal by hypothesis.

Metatheory of eML

As for ML, the reduction ÝÑ β is deterministic (ÝÑ β does not change between ML and eML).

Basic properties

We prove some basic properties of the typing judgments of eML.

First, we need to prove a weakening lemma: we can freely add variables, type variables, path variables, computed results and equalities to the environment and preserve the typing and equality judgments. Lemma 6.3 (Weakening). Consider Γ, Γ 1 and ∆, and let J be a judgment of the following forms:

• $ Γ, Γ 1 • Γ, Γ 1 $ τ : κ • Γ, Γ 1 $ p a : τ ñ ∆ • Γ, Γ 1 $ τ 1 : κ 1 » τ 2 : κ 2 • Γ, Γ 1 $ u 1 : τ 1 » u 2 : τ 2 • TermsEqualpΓ, Γ 1 $ p a 1 : τ 1 » a 2 : τ 2 q
Suppose J holds. Then:

• Suppose α # Γ, Γ 1 . Then J also holds with Γ, Γ 1 replaced by Γ, α : Typ, Γ 1 .

• Suppose x # Γ, Γ 1 and Γ $ σ : Sch. Then J also holds with Γ, Γ 1 replaced by Γ, x : σ, Γ 1 .

• Consider u 1 1 , u 1 2 and σ such that Γ $ u 1 1 : σ and Γ $ u 1 2 : σ. Then J also holds with Γ, Γ 1 replaced by Γ, pu 1 1 » u 1 2 q : σ, Γ 1 .

• Consider q, u 1 and σ such that Γ $ u 1 : bool, Γ $ τ : Sch, and suppose q starts at the root or a variable in Γ and q K Γ, Γ 1 , ∆. Then J also holds with Γ, Γ 1 replaced by Γ, pu 1 q˚q : σ, Γ 1 .

• Consider a path variable π such that π R Γ, Γ 1 . Then J also holds with Γ, Γ 1 replaced by Γ, π, Γ 1 .

Proof. Let us look at the proof in the case of type variables: By mutual induction on the derivations. For rules that grow the environment, adding Γ 2 , note that for any Γ 2 , Γ, α : Typ, Γ 1 , Γ 2 is still a weakening of Γ, Γ 1 , Γ 2 , so we can use the induction hypothesis on the subderivations. Then we copy the rule with the new environment. The only rules that access the environment instead of growing it are the variable rules Var, Eq-Var, K-Var, TEq-Var, and Eq-Subst but they only check membership in the environment so they stay true when the environment grows.

In the case of results, we also need to check that the newly introduced path q does not clash with any existing path: this is true because all results not introduced under lambdas are already in Γ, Γ 1 or ∆, and paths introduced under lambdas start with a variable that is not in Γ.

For TermsEqualpΓ $ p a 1 : τ 1 » a 2 : τ 2 q: all the judgments used in the proof are compatible with weakening.

For proving substitution, we first need reflexivity of the equality judgment on well-typed terms and types: Lemma 6.4 (Reflexivity). Consider an environment Γ, a kind κ, a type τ , and a non-expansive term a.

• If Γ $ τ : κ, then Γ $ τ : κ » τ : κ. • If Γ $ a : τ , then Γ $ a : τ » a : τ . • If Γ $ p a : τ ñ ∆, then TermsEqualpΓ $ p a : τ » a : τ q.
Proof. For type and non-expansive equality: translate each typing rule to the equivalent equality rule and apply reflexivity inductively to the subtypes/subterms.

For full term equality: all the required conditions hold by reflexivity.

Even though it does not have a transitivity rule, full term equality is transitive: Lemma 6.5 (Term equality is transitive). Suppose TermsEqualpΓ $ p a 1 : τ 1 » a 2 : τ 2 q and TermsEqualpΓ $ p a 2 : τ 2 » a 3 : τ 3 q. Then, TermsEqualpΓ $ p a 1 : τ 1 » a 3 : τ 3 q.

Proof. In all three terms, the k-th evaluated atoms are equal.

We can then show substitution for type and term variables and for equalities. For equalities, substitution means that we can remove from the environment an equality that can be derived from the rest of the environment. Lemma 6.6 (Substitution, type variables). Consider Γ, Γ 1 and α such that $ Γ, α : Typ, Γ 1 . Let σ be a type such that Γ $ σ : Typ. Then,

• we have $ Γ, Γ 1 rα Ð σs;

• if Γ, α : Typ, Γ 1 $ τ : κ, then Γ, Γ 1 rα Ð σs $ τ rα Ð σs : κrα Ð σs; • if Γ, α : Typ, Γ 1 $ p a : τ ñ ∆, then Γ, Γ 1 rα Ð σs $ p arα Ð σs : τ rα Ð σs ñ ∆rα Ð σs; Moreover, consider σ 1 , σ 2 such that Γ $ σ 1 : κ 1 , Γ $ σ 2 : κ 2 and Γ $ σ 1 : Typ » σ 2 : Typ. Then, • if Γ, α : Typ, Γ 1 $ τ 1 : κ 1 » τ 2 : κ 2 , then Γ, Γ 1 rα Ð σ 1 s $ τ 1 rα Ð σ 1 s : κ 1 rα Ð σ 1 s » τ 2 rα Ð σ 2 s : κ 2 rα Ð σ 2 s; • if Γ, α : Typ, Γ 1 $ u 1 : τ 1 » u 2 : τ 2 , then Γ, Γ 1 rα Ð σ 1 s $ u 1 rα Ð σ 1 s : τ 1 rα Ð σ 1 s » u 2 rα Ð σ 2 s : τ 2 rα Ð σ 2 s; • if TermsEqualpΓ, α : Typ, Γ 1 $ p a 1 : τ 1 » a 2 : τ 2 q, then TermsEqualpΓ, Γ 1 rα Ð σ 1 s $ p a 1 rα Ð σ 1 s : τ 1 rα Ð σ 1 s » a 2 rα Ð σ 2 s : τ 2 rα Ð σ 2 sq.
Lemma 6.7 (Substitution, term variables). Consider Γ, Γ 1 and x such that $ Γ, x : σ, Γ 1 . Let u be a type such that Γ $ u : σ. Then,

• we have $ Γ, Γ 1 rx Ð bs;

• if Γ, x : σ, Γ 1 $ τ : κ, then Γ, Γ 1 rx Ð bs $ τ rx Ð bs : κrx Ð bs; • if Γ, x : σ, Γ 1 $ p a : τ ñ ∆, then Γ, Γ 1 rx Ð bs $ p arx Ð bs : τ rx Ð bs ñ ∆rx Ð bs; Moreover, consider u 1 , u 2 such that Γ $ u 1 : τ , Γ $ u 2 : τ and Γ $ u 1 : τ » u 2 : τ . Then, • if Γ, α : Typ, Γ 1 $ τ 1 : κ 1 » τ 2 : κ 2 , then Γ, Γ 1 rα Ð u 1 s $ τ 1 rα Ð u 1 s : κ 1 rα Ð u 1 s » τ 2 rα Ð u 2 s : κ 2 rα Ð u 2 s; • if Γ, α : Typ, Γ 1 $ u 1 1 : τ 1 » u 1 2 : τ 2 , then Γ, Γ 1 rα Ð u 1 s $ u 1 1 rα Ð u 1 s : τ 1 rα Ð u 1 s » u 1 2 rα Ð u 2 s : τ 2 rα Ð u 2 s; • if TermsEqualpΓ, α : Typ, Γ 1 $ p a 1 : τ 1 » a 2 : τ 2 q, then TermsEqualpΓ, Γ 1 rα Ð u 1 s $ p a 1 rα Ð u 1 s : τ 1 rα Ð u 1 s » a 2 rα Ð u 2 s : τ 2 rα Ð u 2 sq.
Lemma 6.8 (Substitution, equalities). Consider Γ, Γ 1 and u 1 , u 2 such that $ Γ, pu 1 : σ 1 q » pu 2 : σ 2 q, Γ 1 . Suppose Γ $ u 1 : σ 1 » u 2 : σ 2 . Then,

• we have $ Γ, Γ 1 ; • if Γ, pu 1 : σ 1 q » pu 2 : σ 2 q, Γ 1 $ τ : κ, then Γ, Γ 1 $ τ : κ; • if Γ, pu 1 : σ 1 q » pu 2 : σ 2 q, Γ 1 $ p a : τ ñ ∆, then Γ, Γ 1 $ p a : τ ñ ∆; • if Γ, pu 1 : σ 1 q » pu 2 : σ 2 q, Γ 1 $ τ 1 : κ 1 » τ 2 : κ 2 , then Γ, Γ 1 $ τ 1 : κ 1 » τ 2 : κ 2 ; • if Γ, pu 1 : σ 1 q » pu 2 : σ 2 q, Γ 1 $ u 1 1 : τ 1 » u 1 2 : τ 2 , then Γ, Γ 1 $ u 1 1 : τ 1 » u 1 2 : τ 2 ; • if TermsEqualpΓ, pu 1 : σ 1 q » pu 2 : σ 2 q, Γ 1 $ p a 1 : τ 1 » a 2 : τ 2 q, then TermsEqualpΓ, Γ 1 $ p a 1 : τ 1 » a 2 : τ 2 q.
Lemma 6.9 (Substitution, computed results). Consider Γ, Γ 1 and p, u and τ such that $ Γ, puq˚p : τ, Γ 1 . Suppose Γ, pu » Trueq : bool $ u 0 : τ . Then,

• we have $ Γ, Γ 1 r˚p Ð u 0 s;

• if Γ, puq˚p : τ, Γ 1 $ τ : κ, then Γ, Γ 1 r˚p Ð u 0 s $ τ r˚p Ð u 0 s : κr˚p Ð u 0 s; • if Γ, puq˚p : τ, Γ 1 $ q a : τ ñ ∆, then Γ, Γ 1 r˚p Ð u 0 s $ q : ar˚p Ð u 0 sτ r˚p Ð u 0 s∆r˚p Ð u 0 s. Moreover, consider u 1 , u 2 such that Γ, pu » Trueq : bool $ u 1 : τ , Γ, pu » Trueq : bool $ u 2 : τ and Γ $ u 1 : τ » u 2 : τ . Then, • if Γ, puq˚p : τ, Γ 1 $ τ 1 : κ 1 » τ 2 : κ 2 , then Γ, Γ 1 r˚p Ð u 1 s $ τ 1 r˚p Ð u 1 s : κ 1 r˚p Ð u 1 s » τ 2 r˚p Ð u 2 s : κ 2 r˚p Ð u 2 s; • if Γ, puq˚p : τ, Γ 1 $ u 1 1 : τ 1 » u 1 2 : τ 2 , then Γ, Γ 1 r˚p Ð u 1 s $ u 1 1 r˚p Ð u 1 s : τ 1 r˚p Ð u 1 s » u 1 2 r˚p Ð u 2 s : τ 2 r˚p Ð u 2 s; • if TermsEqualpΓ, puq˚p : τ, Γ 1 $ q a 1 : τ 1 » a 2 : τ 2 q, then TermsEqualpΓ, Γ 1 r˚p Ð u 1 s $ q a 1 r˚p Ð u 1 s : τ 1 r˚p Ð u 1 s » a 2 r˚p Ð u 2 s : τ 2 r˚p Ð u 2 sq.
Lemma 6.10 (Substitution, path variables). Consider Γ, Γ 1 and π such that $ Γ, π, Γ 1 . Suppose p K Γ, Γ 1 . Then,

• we have $ Γ, Γ 1 rπ Ð ps;

• if Γ, π, Γ 1 $ τ : κ, then Γ, Γ 1 rπ Ð ps $ τ rπ Ð ps : κrπ Ð ps; • if Γ, π, Γ 1 $ q a : τ ñ ∆, then Γ, Γ 1 rπ Ð ps $ qrπÐps arπ Ð ps : τ rπ Ð ps ñ ∆rπ Ð ps. • if Γ, π, Γ 1 $ τ 1 : κ 1 » τ 2 : κ 2 , then Γ, Γ 1 rπ Ð ps $ τ 1 rπ Ð ps : κ 1 rπ Ð ps » τ 2 rπ Ð ps : κ 2 rπ Ð ps; • if Γ, π, Γ 1 $ u 1 1 : τ 1 » u 1 2 : τ 2 , then Γ, Γ 1 rπ Ð ps $ u 1 1 rπ Ð ps : τ 1 rπ Ð ps » u 1 2 rπ Ð ps : τ 2 rπ Ð ps; • if TermsEqualpΓ, π, Γ 1 $ q a 1 : τ 1 » a 2 : τ 2 q, then TermsEqualpΓ, Γ 1 rπ Ð ps $ qrπÐps a 1 rπ Ð ps : τ 1 rπ Ð ps » a 2 rπ Ð ps : τ 2 rπ Ð psq.
Proof. By induction on the derivations. When extending the environment, use weakening on the thing we are substituting. When reaching a variable rule for the substituted variable (e.g. Var), replace the rule by the typing derivation.

For the corresponding equality rule (e.g. Eq-Var), use reflexivity and replace the rule by the derivation obtained.

For computed results, use substitution with the equality in Rule Reuse-Present after weakening.

Extraction

We can now prove a useful result: the environments and types appearing in type well-formedness and typing derivations are well-formed and the types given in equality judgments are correct. Lemma 6.11 (Extraction for environment well-formedness). The following all imply $ Γ:

• Γ $ τ : κ • Γ $ π a : τ ñ ∆ (this additionally implies $ Γ, ∆) • Γ $ τ 1 : κ 1 » τ 2 : κ 2 • Γ $ u 1 : τ 1 » u 2 : τ 2 • TermsEqualpΓ $ p a 1 : τ 1 » a 2 : τ 2 q
Proof. By induction on the derivation. There is always an hypothesis that implies $ Γ, Γ 1 with Γ 1 some (optional) extra bindings. From this we can derive $ Γ by inverting the derivation.

The following two lemmas need to be proved by mutual induction: Lemma 6.12 (Extraction for type well-formedness). Suppose Γ $ π a : τ ñ ∆. Then, there exists κ such that Γ $ τ : κ. Suppose Γ $ τ 1 :

κ 1 » τ 2 : κ 2 . Then, Γ $ τ 1 : κ 1 and Γ $ τ 2 : κ 2 . Suppose Γ $ u 1 : τ 1 » u 2 : τ 2 .
Then, there exist κ 1 and κ 2 such that Γ $ τ 1 : κ 1 and Γ $ τ 2 : κ 2 . Lemma 6.13 (Extraction for well-typing). Suppose Γ $ u 1 :

τ 1 » u 2 : τ 2 . Then, Γ $ u 1 : τ 1 and Γ $ u 2 : τ 2 .
Proof. By mutual induction, using substitution when needed.

Subject reduction

We can now proceed to proving subject reduction for eML. Compared to subject reduction for ML, we need to handle both labels and equalities. Compared to subject reduction for labeled ML, we need to ensure that results are substituted with terms of the right type and that the reuse conditions stay true.

The main difficulty is to prove that the coercions we distribute in the subterms when reducing actually correspond to valid equalities. For example, we need to prove that when

Γ $ τ 1 Ñ τ 2 : κ » τ 1 1 Ñ τ 1 2 : κ 1 , then Γ $ τ 1 : Typ » τ 2 : Typ and Γ $ τ 1 1 : Typ » τ 1 2 : Typ.
Lemma 6.14 (Projection). Consider an environment Γ and types pτ i q i and pτ

1 i q i . • If Γ $ τ 1 Ñ τ 2 : κ » τ 1 1 Ñ τ 1 2 : κ 1 , then Γ $ τ 1 : Typ » τ 1 1 : Typ and Γ $ τ 2 : Typ » τ 1 2 : Typ. • If Γ $ @pα : Typq τ : κ » @pα : Typq τ 1 : κ 1 , then Γ, α : Typ $ τ : Sch » τ 1 : Sch. • If Γ $ ζ pτ i q i : κ » ζ pτ 1 i q i : κ 1 , then pΓ $ τ i : Typ » τ 1 i : Typq i .
Proof. The three cases are similar. We give the proof for universal quantification.

Let us define a function tail as follows:

tailp@pα : Typq τ q " τ tailpmatch a with pP i Ñ τ i q i q " match a with pP i Ñ tailpτ i qq i tailpτ q " Any Here, Any stands for some well-formed typed. For example, we may take @pα : Typq α for Any. The function tail returns the type below the universal quantifier, but it is also able to look under pattern matching, as if the quantifier were lifted out of the pattern matching. Then, we show by induction on type equality derivations that whenever Γ $ τ : κ » τ 1 : κ 1 , then Γ $ tailpτ q : Sch » tailpτ 1 q : Sch (or Typ for the case of type constructors and function types). This implies the result.

• For TEq-Trans, apply transitivity on the tails.

• For TEq-Split, split on the same term to prove the equality of the tails.

• For TEq-Sym, apply symmetry on the tails.

• For TEq-Match, apply the induction hypothesis on the branches. The tails will start with a pattern matching on the same two equal terms. Then, we can use TEq-Match to prove that the tails are equal.

• For TEq-ReduceMatch, note that the pattern matching in the left-hand tail will reduce in the same way as the pattern matching in the original term.

• TEq-All has equality of the tails as a premise.

• For the other congruence rules, the tails of the two terms are Any, which is equal to itself by reflexivity.

• For TEq-SubTyp, apply induction to the subderivation.

We are now able to prove that two equal terms have equal types: Lemma 6.15 (Equal terms have equal types). Suppose Γ $ u 1 :

τ 1 » u 2 : τ 2 .
Then, there exists κ 1 and κ 2 such that Γ $ τ 1 : κ 1 » τ 2 : κ 2 .

Proof. By induction on the derivation. This is immediate for most rules by applying the lemma inductively on the hypotheses. For Eq-Coerce and Eq-Trans, use transitivity. For Eq-Split and Eq-Match, split on the same term using TEq-Split. For Eq-TApp, use Lemma 6.14 to deduce equality of σ 1 and σ 2 from the equality of @pα : Typq σ 1 and @pα : Typq σ 1 , then apply substitution. Now we'll prove subject reduction. To pass to context, we need to prove that the equalities introduced using one term are preserved when the term reduces. For non-expansive reductions, we will show that reduction preserves equality of the reusable versions of the terms. For expansive reductions, they are represented in other terms by their label: we can then use substitution on the label.

The typing derivation are syntax-directed, except for the rule Coerce. Thus, we will often resort to the following pattern of reasoning: Lemma 6.16 (Extracting a coercion). Suppose we have a derivation Γ $ a : τ . Then, it has a subderivation Γ $ a : τ 1 whose first rule is not Coerce (so, is syntax-directed), and Γ $ τ : κ » τ 1 : κ 1 .

Proof. By induction:

• Suppose the derivation does not start with Coerce. Then, we can take τ 1 " τ . Since Γ $ a : τ , there exists a kind κ such that Γ $ τ : κ. Then, by reflexivity (Lemma 6.4), τ is equal to itself: Γ $ τ : κ » τ : κ.

• Otherwise, the derivation is an application of Coerce to a derivation of Γ $ a : τ 1 , and we have Γ $ τ : κ » τ 1 : κ 1 . By induction hypothesis on the subderivation, there exists τ 2 and a subderivation of Γ $ a : τ 2 starting with a syntax-directed rule. Then, it is a subderivation of the initial derivation too, and we have Γ $ τ 1 : κ 1 » τ 2 : κ 2 . We obtain Γ $ τ : κ » τ 2 : κ 2 by transitivity.

When reducing a term typed Γ $ π a : τ ñ ∆, the reduction might change the conditions in the output ∆, the types, and some labels may disappear. For instance, reducing match True with True Ñ f p1 x | False Ñ g p2 y to f p1 x removes the label p 2 and changes the condition for label p 1 from match True with True Ñ True | False Ñ False to True. We ensure that the outputs are still equivalent: notably, we need to ensure that the type for non-eliminated labels stay consistent (i.e. are equivalent for type equality), and that, for eliminated labels, their conditions were already equivalent to False. This ensures that the Reuse-Present and Reuse-Absurd typing rules still apply in the context where the reduced subterm appears. Definition 6.3 (Reduced outputs). Let ∆ 1 and ∆ 2 be outputs. We say that

∆ 2 is a reduced output of ∆ 1 in context Γ, noted Γ $ ∆ 1 Ě ∆ 2 , if
for all p P ∆ 2 , p P ∆ 1 and for all p P ∆ 1 such that pu 1 q˚p : τ 1 P ∆ 1 , either p R ∆ 2 and Γ $ u : bool » False : bool or pu 2 q˚p : τ 2 P ∆ 2 and we have both Γ $ u 1 : bool » u 2 : bool and Γ, pu 1 » Trueq : bool $ τ 1 : Sch » τ 2 : Sch. ♦ Lemma 6.17 (Substitution of outputs). Suppose Γ $ ∆ 1 Ě ∆ 2 . Then,

• $ Γ, ∆ 1 , Γ 1 implies $ Γ, ∆ 2 , Γ 1 ; • Γ, ∆ 1 , Γ 1 $ p a : τ ñ ∆ 1 implies Γ, ∆ 2 , Γ 1 $ p a : τ ñ ∆ 1 ;
• and similarly for other judgments.

Proof. By induction on the derivations. If something is independent of ∆ 1 , it is also independent of ∆ 2 . When the results are read (in Reuse-Present, Reuse-Absurd and their equivalent in the equality judgment), in the "present" case, the conditions are both true, so the types are equal and we can use coercion; in the "absent" case, the result stays absent.

Lemma 6.18 (Subject reduction). Let Γ be an environment, a a term such that Γ $ π a :

τ ñ ∆. Suppose a l Þ Ý Ñ b.
We can interpret l as a substitution. Then there exists ∆ 1 such that Γ $ π b : τ rls ñ ∆ 1 and:

• If l " 0, we have Γ $ ∆ Ě ∆ 1 . • If l " q Þ Ñ u, we have ∆ 1 " p∆´qqr˚q Ð usYS,
where S is an environment of labels with all labels prefixed by q.

Moreover, Γ, ∆ 1 $ reusepaqrls : τ » reusepbq : τ .

Proof. First, let us prove this for head reductions: we need to use projection (Lemma 6.14). Take for example reduction of a type-level application: we have Γ $ pΛpα : Typq. vq τ 0 : σ. Invert the derivation rules until we reach a rule that is not Coerce. Then, the last rule is necessarily TApp. By inverting the type derivation, we obtain Γ $ τ 0 : Typ, σ " τ rα Ð τ 0 s and Γ $ Λpα : Typq. v : @pα : Typq τ . After extracting a coercion, and inverting the last syntax directed rule, we obtain that there exists τ 1 such that Γ, α : Typ $ v : τ 1 and Γ $ @pα : Typq τ : κ » @pα : Typq τ : κ 1 . Then we apply projection on this equality: we obtain Γ, α : Typ $ τ : Sch » τ 1 : Sch. Thus, applying Coerce, we get Γ, α : Typ $ v : τ . Then we conclude by substitution: Γ $ vrα Ð τ 0 s : τ rα Ð τ 0 s. The equality of the reusable versions of the terms is guaranteed by

Eq-ReduceTApp.
Let us also examine the reduction of a pattern matching, as it removes labels: if it reduces, the conditions for the output labels reduce too, and they reduce to False in the branches that are not selected, so the new outputs ∆ 1 with the results in.discarded branches removed are reduced outputs of ∆.

For context: by induction on the context. The subterm that is reduced does not appear in the resulting type, but its reusable version may appear in an equality for typing another subterm that is not reduced. But we know by induction hypothesis that the reusable versions stay equal. The output changes, but stays equivalent, so any well-typed term with the old output is also well-typed with the new output. We need to show equality of the reused versions. This is immediate by congruence (for Eq-Fix, we require the equality on expansive terms to embed the equality on non-expansive terms). Finally, we need to show equivalence of the computed result sets. This is immediate by substituion/congruence (for Eq-Let and Eq-Match), and the fact that we combine equivalent computed result sets.

Soudness via a logical relation for equality

In order to prove soundness, we need to show that, in evaluation contexts, there will never be an equality between, e.g., an arrow type and a datatype, or between True and False. This is not an obvious result because it depends on the equalities in the environment: for example, if we have True " False in the environment we can prove any equality.

We prove that these equalities cannot be proved in inhabited environments, i.e. typing environments for which we can provide an instanciation of the type and term variables with types and terms that satisfies the equality in the context. For this, we explain the meaning of equality in the empty environment.

We define a terminating subset of the reduction ÝÑ ι on non-expansive terms that only does non-expansive reduction. It is defined in Figure 6.11 and does not emit labels.

The reduction ÝÑ ι does not involve labels, since applications are not reduced. It is confluent. It also preserves types, since its head reduction is a subset of ÝÑ β .

We need to prove that ÝÑ ι terminates. Then, this gives a meaning to a , the normal form of a for ÝÑ ι .

Lemma 6.19. The reduction ÝÑ ι is strongly normalizing: there is no infinite reduction path for ÝÑ ι starting from a term or type (even ill-typed). pΛpα : Typq. uq τ ÝÑ ι urα Ð τ s let x " u in a ÝÑ ι arx Ð us match d j pτ 2 k q k pu i q i with pd j pτ k q k px ji q i Ñ a j q j ÝÑ ι a j rx ji Ð u i s i match d j pτ 2 k q k pu i q i with pd j pτ k q k px ji q i Ñ σ j q j ÝÑ ι σ j rx ji Ð u i s i Proof. Note that this result is not restricted to well-typed terms and types. Implicitly, every reduction mentioned in this proof will be ÝÑ ι .

We define the set S τ of strongly normalizing types: we will show that every type belongs in S τ . We also define the set S a as the largest set of terms such that:

• if a P S a , a is strongly normalizing;

• if a P S a reduces to Λpα : Typq. u, then for all types τ P S τ , urα Ð τ s P S a ;

• if a P S a reduces to dpτ j q j pa i q i , then for all i, a i in S a .

These two sets are stable by reduction because the restrictions apply to all reductions of terms or types that are in the sets. Finally, let γ associate type variables to types and term variables to terms. We say that γ P S γ if for all α P dompγq, γpαq P S τ and for all x P dompαq, γpxq P S a .

We prove, by mututal induction on the structure of types and terms, the following results:

• for all types τ , if γ P S γ , γpτ q P S τ ;

• for all terms a, if γ P S γ , γpaq P S a .

For types τ :

• If τ " α, if α P dompγq, then γpτ q " γpαq P S τ , because γ P S γ . Otherwise, τ does not reduce.

• If τ " τ 1 Ñ τ 2 (similarly for τ " @pα : Typq σ, and τ " ζ pτ i q i ), the reduction sequences from τ 1 and τ 2 are finite, thus the reductions from τ " τ 1 Ñ τ 2 are finite (the arrow will never reduce).

• If τ " match a with pd i pτ j q j px ik q k Ñ τ i q i , then we have γpτ q " match γpaq with pd i pτ j q j px ik q k Ñ γpτ i qq i

By induction hypothesis, the subterm γpaq and the subtypes γpτ i q do not have an infinite reduction sequence. Thus any infinite reduction sequence includes a head reduction. Suppose the reduction is from τ 1 " match b with pd i pτ j q j px ik q k Ñ τ 1 i q i . Then, b " d i pτ 1 j q j pu k q k . The head reduction then reduces τ 1 to τ 1 i rx ik Ð u k s k . Let γ 1 " γrx ik Ð u k s k . We have γ 1 P S γ , because for all k, u k P S a . Thus, by induction hypothesis, γ 1 pτ i q P S τ . But

τ 1 i rx ik Ð u k s k is a possible reduction of γ 1 pτ i q, thus τ 1 i rx ik Ð u k s k P S τ . EnvT-Empty γ $ H EnvT-Var γ $ Γ x # Γ $ γpxq : γpτ q γpxq is nonexpansive γ $ Γ, x : τ EnvT-TVar γ $ Γ α # Γ $ γpαq : γpκq γ $ Γ, α : κ EnvT-Eq γ $ Γ $ γpu 1 q : γpτ q » γpu 2 q : γpτ q γ $ Γ, pu 1 » u 2 q : τ Env-Path-Var γ $ Γ γpπq K Γ γ $ Γ, π Env-Result γ $ Γ p$ γpuq : bool » True : boolq ùñ p$ γppq : γpτ qq γ $ Γ, puq˚p : τ Figure 6
.12: Environment typing

For terms a:

• The cases of variables and pattern matching are similar to their type equivalents.

• Labels stay labels and are never substituted.

• For function definition and application, the subterms are strongly normalizing by induction hypothesis, and they never reduce to a type abstraction or a type constructor.

• For constructors, by induction hypothesis on the fields, they are all in S a .

A constructor never reduces to a type abstraction.

• If a " Λpα : Typq. u, then, by induction hypothesis, γpuq has no infinite reduction sequence. Moreover, for every type τ , if γ 1 " γrα Ð τ s, then γ 1 puq has no infinite reduction sequence. Thus, urα Ð τ s P S a . Then a P S a .

• If a " a 1 τ , there are no infinite reduction sequences from a 1 and τ by induction hypothesis, thus an infinite reduction sequence from a must include a head reduction, and so must be a reduction sequence that yields a constructor or a type abstraction. Suppose the head reduction is from b " pΛpα : Typq. uq τ 1 . Then b reduces to urα Ð τ 1 s. Let γ 1 " γrα Ð τ 1 s.

We have γ 1 P S γ because τ 1 P S τ by induction hypothesis. Thus by induction hypothesis, we have γ 1 pσq P S τ and γ 1 puq P S a .

For an environment Γ and a mapping from term variables to non-expansive terms, type variables to types, path variables to paths, and paths to nonexpansive terms γ, we define a judgment γ $ Γ that indicates that the types and terms in γ are closed and well-formed and define a valid instance of Γ. The rules defining this judgment are given in Figure 6.12.

We will prove that every well-typed closed non-expansive term reduces for ÝÑ ι to a value of the correct syntactic shape for its type. We will also prove that equal non-expansive terms normalize to values, and that these values are semantically equal according to some relation. Although tempting, we cannot take this relation to only relate identical terms (up to renaming). Indeed, in function definitions λpx : τ q.a, a is not closed anymore, and does not necessarily reduce to a value (for example, a " match x with Unit Ñ Unit is equal to Unit, but reduction does not prove the equality). Since the terms inside function definitions are never taken out of the definition by the reduction ÝÑ ι , we can simply ignore them (as long as they are syntactically equal). We do not actually define a (unary) set of terms with the correct syntactic shape: instead, we use reflexivity and say that for any closed well-typed term a of type τ , the pair pa, aq is in Erτ s. The set Erτ s of comparable coerced terms is defined in terms of Vrτ s, the set of comparable values at type τ . Two equal coerced terms may have different, but equal, types. This is not a problem, as we prove that, for two closed equal types τ 1 and τ 2 , Vrτ 1 s " Vrτ 2 s.

The definition implementing these ideas is given in Figure 6.13. We limit our definitions, for Erτ s, to closed well-typed non-expansive terms equal in the empty environment, and for Vrτ s to values of types equal to τ . To keep the definitions readable, we implicitly limit the sets we define to only contain pairs of terms verifying these conditions, i.e. we allow ourselves to omit the typing conditions. The sets Erτ s and Vrτ s are defined as the least fixed point of the equations given here (it exists, because we never use the interpretation in a contravariant position). For the needs of the proof, we also define a relation on environments γ 1 , γ 2 : we say pγ 1 , γ 2 q P GrΓs if the terms and types in the two environments are syntactically equal, related and of the appropriate type. In the same way, we require the environments to be well-typed.

To start with, we need the following technical lemma on the interpretations. Proving that an environment is related to itself is important to build environments to apply transitivity in. Lemma 6.20 (Left slicing).

• If pu 1 , u 2 q P Erτ s, pu 1 , u 1 q P Erτ s.

• If pv 1 , v 2 q P Vrτ s, pv 1 , v 1 q P Vrτ s.

• If pγ 1 , γ 2 q P GrΓs, pγ 1 , γ 1 q P GrΓs.

Proof. For the second item, by induction of the derivation of pv 1 , v 2 q P Vrτ s. The syntactic typing/equality conditions are immediately true (by reflexivity of equality, Lemma 6.4).

• For pv 1 , v 2 q P Vrτ 1 Ñ τ 2 s: v 1 has the right syntactic form, and there are no other conditions.

• For pv 1 , v 2 q P Vr@pα : Typq σs: we have v 1 " Λpα : Typq. w 1 and v 2 " Λpα : Typq. w 2 . Consider $ τ : Typ. We have pw 1 rα Ð τ s, w 2 rα Ð τ sq P Vrσrα Ð τ 1 ss: by induction hypothesis we conclude that pv 1 rα Ð τ s, v 1 rα Ð τ sq P Vrσrα Ð τ 1 ss.

• For pv 1 , v 2 q P Vrζ pτ j q j s, we similarly apply the induction hypothesis on all fields.

• For a pattern matching: the selection of the branch is only decided by the type, then we can apply the induction hypothesis on the branch.

Erτ s Ď tpu 1 , u 2 q |$ u 1 : τ » u 2 : τ u Erτ s " tpu 1 , u 2 q | p u 1 , u 2 q P Vrτ squ Vrτ s Ď tpv 1 , v 2 q |$ v 1 : τ » v 2 : τ u Vrτ 1 Ñ τ 2 s " tpfix π x py : τ 1 1 q : τ 1 2 . a 1 , fix π x py : τ 2 1 q : τ 2 2 . a 2 qu Vr@pα : Typq σs " "ˆΛ pα : Typq. u 1 Λpα : Typq. u 2 ˙ˇˇˇ@ pτ 1 , τ 2 q p$ τ 1 : Typ » τ 2 : Typ ^Vrτ 1 s " Vrτ 2 sq ùñ pu 1 rα Ð τ 1 s, u 2 rα Ð τ 2 sq P Vrσrα Ð τ 1 ss * Vrζ pτ j q j s " "ˆd pτ 1j q j pv 1i q i dpτ 2j q j pv 2i q i ˙ˇˇˇp $ d : @pα j : Typq j pτ i q i Ñ ζ pα j q j q ^ppv 1i , v 2i q P Vrτ i rα j Ð τ j s j sq i * Vrmatch a with pd i pτ k q k px ij q j Ñ σ i q i s " $ & % Vrσ i rx ij Ð v j s j s if " ^ a " d i pτ 1 k q k pv j q j $ d i : @pα k : Typq k pτ j q i Ñ ζ pα k q k H otherwise GrΓs Ď tpγ 1 , γ 2 q | γ 1 $ Γ ^γ2 $ Γu GrHs " H GrΓ, α : Typs " tpγ 1 rα Ð τ 1 s, γ 2 rα Ð τ 2 sq | pγ 1 , γ 2 q P GrΓs ^Vrτ 1 s " Vrτ 2 s^$ τ 1 : Typ » τ 2 : Typu GrΓ, x : τ s " tpγ 1 rα Ð u 1 s, γ 2 rα Ð u 2 sq |
pγ 1 , γ 2 q P GrΓs ^pu 1 , u 2 q P Vrγ 1 pτ qsu GrΓ, pu 1 » u 2 q : τ s " tpγ 1 , γ 2 q | pγ 1 , γ 2 q P GrΓs ^pγ 1 pu 1 q, γ 2 pu 2 qq P Erγ 1 pτ qsu The proof of the result on environments similarly follows the structure of GrΓs.

We also need to prove that the interpretations are transitive: Lemma 6.21 (Transitivity).

• If pv 1 , v 2 q P Vrτ s and pv 2 , v 3 q P Vrτ s, then pv 1 , v 3 q P Vrτ s.

• If pu 1 , u 2 q P Erτ s and pu 2 , u 3 q P Erτ s, then pu 1 , u 3 q P Erτ s.

Proof. Transitivity of Erτ s is immediately implied by transitivity of Vrτ s. The typing conditions are immediately satisfied by transitivity. The rest of the proof is done by mutual induction.

For transitivity of Vrτ s, consider the different cases. Similarly to the previous lemma (6.20), it suffices to follow the structure of the derivation. Lemma 6.22 (Correcteness of the intepretation).

• If Γ $ u : τ , then for all pγ 1 , γ 2 q P GrΓs, pγ 1 puq, γ 2 puqq P Erγ 1 pτ qs.

• If Γ $ u 1 : τ 1 » u 2 : τ 2 then for all pγ 1 , γ 2 q P GrΓs, pγ 1 pu 1 q, γ 2 pu 2 qq P Erγ 1 pτ 1 qs.

• If Γ $ τ 1 : κ 1 » τ 2 : κ 2
, then for all pγ 1 , γ 2 q P GrΓs, Vrγ 1 pτ 1 qs " Vrγ 2 pτ 2 qs. Moreover, if γ $ Γ, then pγ, γq P GrΓs.

Proof. We prove the three first results by mutual induction on the derivations. The first result is essentially a special case of the second: we could indeed obtain it by first applying reflexivity to deduce that u is equal to itself, although that changes the derivation so that we cannot proceed by induction. We will focus on the second result on term equality instead.

For term equality: suppose Γ $ u 1 : τ 1 » u 2 : τ 2 , and pγ 1 , γ 2 q P GrΓs. Let us consider some of the different rules.

• For Eq-Trans, we have premises Γ $ u 1 : τ 1 » u 3 : τ 3 and Γ $ u 3 : τ 3 » u 2 : τ 2 . By Lemma 6.20, we have pγ 1 , γ 1 q P GrΓs. Thus, by induction hypothesis on the first premise, pγ 1 pu 1 q, γ 1 pu 3 qq P Erγ 1 pτ 1 qs. By induction hypothesis on the second premise, pγ 1 pu 3 q, γ 2 pu 2 qq P Erγ 1 pτ 3 qs. We also have Γ $ τ 1 : κ 1 » τ 3 : κ 3 (Lemma 6.15), thus Erγ 1 pτ 1 qs " Erγ 1 pτ 3 qs.

Then, by transitivity of Erγ 1 pτ 1 qs (Lemma 6.21), pγ 1 pu 1 q, γ 2 pu 3 qq P Erγ 1 pτ 1 qs.

• For Eq-Split, consider the premise Γ $ u : ζ pτ k q k . By induction hypothesis, pγ 1 puq, γ 2 puqq P Erγ 1 pζ pτ k q k qs. Thus, p γ 1 puq , γ 2 puq q P Vrγ 1 pζ pτ k q k qs.

Then there exists a constructor $ d : @pα k : Typq k pτ i q i Ñ ζ pα k q k such that γ 1 puq " dpτ 1k q k pv 1i q i , γ 2 puq " dpτ 2k q k pv 2i q i , and for all i, pv 1i , v 2i q P Erτ i rα j Ð τ 1j s j s. Suppose the premise corresponding to this branch is

Γ, px i : τ i rα k Ð τ k s k q i , pdpτ k q k px i q i » uq : ζ pτ k q k $ u 1 : τ 1 » u 2 : τ 2 Consider the environments γ 1 1 " γ 1 rx i Ð v 1i s i and γ 1 2 " γ 2 rx i Ð v 2i s i . We have: pγ 1 1 , γ 1 2 q P GrΓ, px i : τ i rα k Ð τ k s k q i ,
pdpτ k q k px i q i : uq » pζ pτ k q k :sq Thus, pγ 1 1 pu 1 q, γ 1 1 pu 2 qq P Erγ 1 1 pτ 1 qs. Since γ 1 i pu i q " γpu i q for i P t1, 2u, we have pγ 1 pu 1 q, γ 2 pu 2 qq P Erγ 1 pτ 1 qs.

• For Eq-Subst, this is true by the hypothesis pγ 1 , γ 2 q P GrΓs.

• For Eq-Coerce, use (by induction hypothesis) the equality of the interpretation of equal types.

• For Eq-Var on x, by hypothesis pγ 1 pxq, γ 2 pxqq P Erγ 1 pτ qs. Then we have p γ 1 pxq , γ 2 pxq q P Vrγ 1 pτ qs.

• For congruence rules, let us consider for example Eq-Let. We have u 1 " let x " u 01 in u 11 and u 2 " let x " u 02 in u 12 , with premises Γ $ u 01 :

σ 1 » u 02 : σ 2 and Γ, x 1 : τ 1 , px » u 01 q : σ 1 $ u 11 : τ 1 » u 12 : τ 2 .
Apply the induction hypothesis on the first premise: we have p γ 1 pu 01 q , γ 2 pu 02 q q P Vrγ 1 pτ 1 qs. Consider γ 1 1 " γ 1 rx Ð γ 1 pu 01 q s and γ 1 2 " γ 2 rx Ð γ 2 pu 02 q s. We have both γ 1 1 $ Γ, x : σ 1 and γ 1 2 $ Γ, x : σ 1 , since Γ $ γ 2 pσ 1 q : κ » γ 2 pσ 1 1 q : κ 1 . Then, pγ 1 1 , γ 1 2 q P GrΓ, x : σ 1 , px » σ 1 q : a 1 s, and by induction hypothesis, pγ 1 1 pu 11 q, γ 1 2 pu 12 qq P Erγ 1 1 pτ 1 qs. Finally, γ 1 1 pu 11 q " γ 1 pu 11 qrx Ð u 01 s " γ 1 plet x 1 " u 01 in u 11 q and similarly for u 2 . Thus, pγ 1 p let x 1 " u 01 in u 11 q, γ 2 p let x 2 " u 02 in u 12 q P Erγ 1 pτ 1 qs.

• For reduction rules, the two terms normalize to the same thing and have the same type. We conclude by applying the first result on the typing derivation of one of the sides of the equality.

For equality on types, consider the last rule in the derivation:

• For TEq-Trans, proceed as for Eq-Trans: suppose we have Γ $ τ 1 : κ 1 » τ 2 : κ 2 and Γ $ τ 2 : κ 2 » τ 3 : κ 3 and consider pγ 1 , γ 3 q P GrΓs. By Lemma 6.20, pγ 1 , γ 1 q P GrΓs, thus (applying the induction hypothesis on the first premise), Vrγ 1 pτ 1 qs " Vrγ 1 pτ 2 qs. From the second premise, we obtain Vrγ 1 pτ 2 qs " Vrγ 3 pτ 3 qs. Thus, Vrγ 1 pτ 1 qs " Vrγ 3 pτ 3 qs.

• For TEq-Split, select a branch and build an environment as for Eq-Split, then use the induction hypothesis on this branch.

• For congruence rules, take for instance TEq-All. We have Γ, α : Typ $ σ 1 : Sch » σ 2 : Sch. We want to prove that, for a term u and a closed type τ such that $ τ : Typ, urα Ð τ s P Vrγ 1 pσ 1 qrα Ð τ ss if and only if urα Ð τ s P Vrγ 2 pσ 2 qrα Ð τ ss. Consider, for i P t1, 2u, γ 1 i " γ i rα Ð τ s. Since Vrτ s " Vrτ s, pγ 1 1 , γ 1 2 q P GrΓ, α : Typs. By induction hypothesis, Vrγ 1

1 pσ 1 qs " Vrγ 1 2 pσ 2 qs, and γ 1 i pσ i q " γ i pσ i qrα Ð τ s. • For TEq-Match, consider the premise on the term that is matched on:

Γ $ a 1 : τ 1 » a 2 : τ 2 . Then, γ 1 pa 1 q and γ 2 pa 2 q both normalize to the same constructor. Then the correct branch can be selected as in TEq-Split.

• For TEq-ReduceMatch: compute the intepretations on both side, they are actually the same.

From the fact that the Vrτ s are distinct for different shapes of τ , we can conclude that, in the empty environment, it is impossible to prove an equality between, e.g., arrow types and universally quantified types. This suffices to prove progress. Lemma 6.23 (Inversion). Consider a value v such that pα k : Typq k $ v : τ .

• If τ " τ 1 Ñ τ 2 , there exists a, τ 1 1 , τ 1 2 such that v " fix π x py : τ 1 1 q : τ 1 2 . a. • If τ " @pα : Typq τ 1 , there exists w such that v " Λpα : Typq. w.

• If τ " ζ pτ i q i , there exists a constructor $ d : @pα i : Typq i pτ j q j Ñ ζ pα i q i , types pτ 1 i q i and terms pa j q j such that a " dpτ 1 i q i pa j q j . Proof. We will only look at the last case, the other cases are similar. Consider the different cases for v:

• If v " fix π x py : τ 1 q : τ 2 . a, then we have pα k : Typq k $ v : τ 1 Ñ τ 2 , and pα k : Typq k $ ζ pτ i q i : κ » τ 1 Ñ τ 2 : κ 1 .
We can instantiate the α k with, e.g. unit:

we get $ ζ pτ i rα k Ð units k q i : κ » τ 1 rα k Ð units k Ñ τ 2 rα k Ð units k : κ 1 But this would imply Vrτ 1 rα k Ð units k Ñ τ 2 rα k Ð units k s "
Vrζ pτ i rα k Ð units k q i s, which is false (function definitions are present in the first set but not the second).

• Similarly for v " Λpα : Typq. u, and for v " dpτ j q j pv k q k where d is a constructor of another type.

• There remains only the case v " dpτ 1 i q i pv k q k with d a constructor of ζ.

Lemma 6.24 (Progress). Suppose $ a : τ . Then, either a ÝÑ β b for some term b, or a is a value.

Proof. We proceed by induction on the base term, as in the proof of Theorem 4.2 for ML, strengthening the induction to accept environments of the form pα i : Typq i . Instead of inversion for ML, we use Lemma 6.23.

For the (new) case of Reuse-Present and Reuse-Absurd: if a " ˚p, a is not typeable in an environment composed only of type variables: the only possibility is that pα i q i $ True : bool » False : bool, which is impossible as pTrue, Falseq is not included in the interpretation of bool.

Full term equality and reduction

We'd like to prove that full term equality is stable by reduction. We have two cases to consider for an equality between a and b: the first one is performing a non-expansive reduction (ÝÑ ι ) on one of the terms (e.g. a reduces to a 1 q. Then, a 1 stays equal to the same terms. The second is performing an expansive reduction on one term. Then, we can perform some number of non-expansive reductions then an expansive reduction on the other term and recover equal terms: essentially, we are performing the same reduction on the two sides up to non-expansive reduction. Lemma 6.25 (Stability by non-expansive reduction). Suppose TermsEqualpΓ $ p a : τ a » b : τ b q, and a ÝÑ ι a 1 . Then, TermsEqualpΓ $ p a 1 : τ a » b : τ b q.

Proof. The atoms of a 1 are obtained by reducing one subterm of the decomposition of a, and removing some atoms. The removed atoms must have their condition equivalent to False by subject reduction for ÝÑ ι (subject reduction tells us the returned results from a 1 are reduced outputs of those of a, as defined in Definition 6.3). Proof. Reduce b until reaching either a value or an expansive reduction. If we reach a value b 1 , we must have TermsEqualpΓ $ p a : τ a » b 1 : τ b q. The decomposition of b 1 has no expansive atoms, thus the condition for all expansive atoms in a must be equivalent to False, thus there is no expansive reduction from a (expansive reductions in evaluation position have a constraint equal to True, by induction on evaluation context).

Otherwise, we reach an expansive reduction. It must be a reduction with equivalent function and argument. Then, by substitution, the bodies with argument substituted are equal terms.

Chapter 7

Staging with mML

In this chapter, we introduce another component of our encoding of ornaments, as an extension of eML called mML. This extension has two purposes. First, it allows separating some meta-abstractions and meta-applications than can be reduced in a separate phase from the abstractions and applications already present in user code. The language is designed so that all mML code can be reduced without touching the eML code. Building on this phase distinction, we can introduce richer abstractions facilities to mML: since we guarantee that they can be eliminated, we can add things that are not available in eML, such as dependent types, abstraction on equalities, and type-level functions.

Overview of the design

We want the extensions in the language mML to be able to reduce in a separate phase from the eML reduction. This imposes several constraints.

We write mML application with a # to distinguish it from ML application. Similarly, all mML abstraction are marked with #.

First, we must ensure that ML constructs (functions, pattern matching, etc) do not return meta abstractions, because then reduction of some ML code could make new mML redexes appear. We ensure this by introducing a superkind Met of Sch that classifies the types of meta abstractions.

Since term meta-abstraction can reduce at any moment, even when the argument is not fully evaluated, it could substitute expansive terms for variables. But this would break stability of non-expansivity by evaluation. Thus we limit meta term application to non-expansive terms.

In an environment with an incoherent equality (such as pTrue » Falseq : bool), any two eML types are equal. We prefer to avoid this for mML: since mML code will be evaluated under arbitrary contexts, we need, e.g., that type abstractions are not confused with term abstractions under any context. This is solved by disallowing mML types in type-level pattern matching, and limiting case splitting (TEq-Split) to only operate on types of kinds Typ and Sch.

Finally, we have to decide whether mML abstractions and applications are expansive. To allow reducing mML redexes in equalities, we consider most abstractions and applications non-expansive, and we require the body of abstractions to be non-expansive terms. However, to allow transporting expansive 105 computations in mML, for example for patches, we introduce thunks, noted rπ.as: thunks can contain an expansive term, whose labels start with π. A thunk is applied, noted puq p , by choosing a label p for the result of the evaluation of the body of the thunk. For example consider,

ppλ # px : boolq. rπ. f π¨1 xsq # Trueq p
This reduces to:

prπ. f π¨1 Truesq p

This reduces to the following term, emitting a label ˚p Ð ˚p ¨1:

f p¨1 True
Thus, thunks allows us to transport expansive computations inside mML abstractions, as long as the place where they are used is ready to unthunk them. This is similar to labeled ML abstractions, but we can eliminate the thunking and unthunking at mML reduction time, and we allow the thunk/unthunk redexes to be reduced in the full term equality for mML.

Definition of mML

Syntax and typing

The syntax of mML builds on the syntax of eML. One thing we need to add is type-level functions, taking types, terms, or equalities as arguments. This requires a richer language of kinds to denote these abstractions. In the same way, we need a richer language of types to represent the term-level meta-abstractions on types, terms, and equalities. The syntax of kinds and types is given in Figure 7.1. Compared to the syntax of kinds and types of eML (Figure 6.1), the kinds are enriched with a kind of meta types Met that will serve to separate terms having a meta type from terms having an eML type, and kinds for the type-level dependent metaabstractions on types, terms and equalities. Equalities stay unnamed in metaabstractions. The syntax of types is similarly enriched with types for term-level meta-abstractions on types, terms and equalities. These types have kind Met.

We also add type-level meta abstractions and applications on types, terms and equalities. The meta abstractions and applications are marked with # to distinguish them from normal abstractions and applications. As discussed previously, we limit meta term application to non-expansive terms. When applying an equality, we explicitly mark the equality, using the syntax pu » uq : τ (this is the syntax used to mark equalities in eML typing environments). This makes typing easier. Finally, the syntax of typing environments is modified to allow type variables at any kind instead of only the kind Typ. The syntax of terms (Figure 7.2) is similarly enriched with meta-abstractions and applications. We add meta-abstraction to non-expansive terms, but not meta-application as its reduction can yield an expansive term.

We now describe the typing rules of mML. Datatypes stay the same (in particular, they cannot contain values of a meta-type). The rules for the wellformedness of environments are staightforward and given on Figure 7.3. In EnvVar, the type of the variable can now be of kind Met. In EnvTVar, we | λ # ppuq˚p : τ q. u Result abstraction (meta) The well-formedness rules for types are given in Figure 7.4. We introduce new rules for the new constructions. The types of term-level abstractions are classified with kind Met. Type-level meta-abstractions are dependently typed using the new kinds. Type-level pattern matching and universal types are still limited to types of kind Typ or Sch: this enforces that the types of term-level meta-abstractions cannot appear inside a ML type. This is important for correctly reducing from mML to eML. We add a subtyping rule K-SubSch from Sch to Met: thus, the base kinds form a hierarchy, with Met containing Sch containaing Typ.

| u # u Result application (meta) P ::" Patterns | dpτ q i pxq i u ::" x | dpτ q i puq i | fix π x px : τ q : τ . a | u τ | Λpα : κq. u | let x " u in u | match u with pP Ñ u | .. P Ñ uq | ˚p | λ # pα : κq. u | λ # px : τ q. u | λ # pu » uq : τ. u | u # τ | u # u | u # pa » aq : τ | rπ. as | λ # ppuq˚p : τ q. u | u # ˚u Figure 7.2: Syntax of mML EnvEmpty $ H EnvPathVar $ Γ π # Γ $ Γ, π EnvVar $ Γ Γ $ τ : Met x # Γ $ Γ, x : τ EnvTVar x # Γ Γ $ τ : Met Γ, x : τ $ κ wf Γ $ Πpx : τ q κ wf
The typing rules are similar to the typing rules for eML, except that we add rules for the new constructs, similar to those for types. In rule Let, we check that the type of the term in the binding and of the returned type is of kind Sch and not Met. This was already done for Match.

The meta reduction

In mML, two reductions coexist: the normal eML reduction ÝÑ β and a reduction ÝÑ # that only reduces meta applications. The reduction ÝÑ # is nondeterministic and can occur under any context, including applications. Its definition is given in Figure 7.12. As in ÝÑ β , meta-reduction emits results that can

Var $ Γ x : σ P Γ Γ $ p x : σ ñ H TAbs Γ, α : Typ $ p u : σ ñ H Γ $ p Λpα : Typq. u : @pα : Typq σ ñ H TApp Γ $ τ : Typ Γ $ p a : @pα : Typq σ ñ ∆ Γ $ p a τ : σrα Ð τ s ñ ∆ Fix Γ, π, x : τ 1 Ñ τ 2 , y : τ 1 $ π a : τ 2 ñ ∆ Γ $ p fix π x py : τ 1 q : τ 2 . a : τ 1 Ñ τ 2 ñ H q K Γ Γ $ False : bool » True : bool Γ $ τ : Typ Γ $ p ˚q : τ ñ H
KEq-Trans Γ $ κ 1 » κ 2 Γ $ κ 2 » κ 3 Γ $ κ 1 » κ 3 KEq-Base $ Γ κ P tTyp, Sch, Metu Γ $ κ » κ KEq-Type-Fun Γ $ κ 1 » κ 2 Γ, α : κ 1 $ κ 1 1 » κ 1 2 Γ $ Πpα : κ 1 q κ 1 1 » Πpα : κ 2 q κ 1 2 KEq-Term-Fun Γ $ τ 1 : κ 1 » τ 2 : κ 2 Γ, x : τ 1 $ κ 1 1 » κ 1 2 Γ $ Πpx : τ 1 q κ 1 1 » Πpx : τ 2 q κ 1 2 Figure 7
.7: Kind equality for mML be reused. This only happens when evaluating thunks. The label translation rules are extended for the new abstractions and applications (see Figure 7.13): thunk abtraction hides the labels emitted inside, all applications are transparent to labels. We do not provide a label translation for the other meta abstractions as they only expect non-expansive terms.

Equality

The equality of mML is similar to the equality of eML. There are three major changes: we include congruence rules corresponding to the new constructs on types and terms; we include reduction rules corresponding to the head reduction of ÝÑ # (the non-head reduction are included because non-expansive term equality is a congruence). We limit case-splitting to proving equalities between terms whose type is of kind Sch, and between types whose kind is Sch: this ensures that the mML part of type equality always holds, even in contexts that are absurd, and thus unreachable for eML reduction: we need to guarantee progress for the full mML reduction.

The new and changed rules are given on Figure 7.8 for the congruence rules for types, Figure 7.9 for the congruence rules for terms. As in eML, the congruence rules follow the structure of the typing rules. The reduction rules, the new split rule and the subkinding rules are given in Figure 7.10 and Figure 7.11.

Since types can appear in kinds, we also have a kind equality judgment, that only includes congruence rules (defined on Figure 7.7).

We also extend term equality to take thunk application into account. There is a new atom of the form puq p . We can either chose to keep these atoms as-is, in which case they are equal to atoms pu 1 q p when u and u 1 are equal, or to expand them: we must provide a such that u is equal to rπ. as. Then, the atom is replaced by the decomposition of a before evaluating the equality. This makes such atoms transparent for term equality: we can reduce them as needed, thus meta-reduction preserves term equality.

Then, the definition of equality is in two steps: first we allow expanding as much as desired on each side, then we compare the terms for equality.

Definition 7.1 (Expansion). Consider Γ $ p a : τ ñ ∆. Let S " labelspaq and suppose atomspaq " p˚p i Ð pT i , a i qq piPlabelspaq , with for all i,

TEq-TyAbs Γ $ κ 1 1 » κ 1 2 Γ, α : κ 1 1 $ τ 1 : κ 1 » τ 2 : κ 2 Γ $ λ # pα : κ 1 1 q. τ 1 : Πpα : κ 1 1 q κ 1 » λ # pα : κ 1 2 q. τ 2 : Πpα : κ 1 2 q κ 2 TEq-TermAbs Γ $ σ 1 : κ 1 1 » σ 2 : κ 1 2 Γ, x : σ 1 $ τ 1 : κ 1 » τ 2 : κ 2 Γ $ λ # px : σ 1 q. τ 1 : Πpx : σ 1 q κ 1 » λ # px : σ 2 q. τ 2 : Πpx : σ 2 q κ 2 TEq-TyApp Γ $ σ 1 : Πpα : κ 1 Γ $ u 1 : Πpα : κ 1 q σ 1 » u 2 : Πpα : κ 2 q σ 2 Γ $ τ 1 : κ 1 » τ 2 : κ Γ $ u 1 # τ 1 : σ 1 rα Ð τ 1 s » u 2 # τ 2 : σ 2 rα Ð τ 2 s Eq-TermMetaApp Γ $ u 1 : Πpx : τ 1 1 q τ 1 » u 2 : Πpx : τ 1 2 q τ 2 Γ $ u 1 1 : τ 1 1 » u 1 2 : τ Γ, pu 1 » u 2 q : τ $ u : σ Γ $ u 1 : τ » u 2 : τ Γ $ pλ # ppu 1 » u 2 q : τ q. uq # ppu 1 » u 2 q : τ q : σ » u : σ Eq-Reduce-MetaPtrApp p K Γ Γ, pu 0 q˚p : τ $ u : σ Γ, pu 0 » Trueq : bool $ u 1 : τ Γ $ pλ # ppu 0 q˚p : τ q. uq # ˚u1 : σr˚p Ð u 1 s » ur˚p Ð u 1 s : σr˚p Ð u 1 s
pλ # pα : κq. σq # τ 0 Ý Ñ # σrα Ð τ s pλ # px : τ q. σq # u 0 Ý Ñ # σrx Ð us pλ # pu 1 » u 2 q : τ. σq # pu 1 » u 2 q : τ 1 0 Ý Ñ # σ pλ # pα : κq. uq # τ 0 Ý Ñ # urα Ð τ s pλ # px : τ q. uq # u 0 0 Ý Ñ # urx Ð u 0 s pλ # pu 1 » u 2 q : τ. uq # pu 1 1 » u 1 2 q : τ 1 0 Ý Ñ # u pλ # ppu 1 q˚p : τ q. uq # ˚u0 0 Ý Ñ # ur˚p Ð u 0 s prπ. asq p ˚pÐreuseparπÐpsq Ý ÝÝÝÝÝÝÝÝÝÝÝ Ñ # arπ Ð ps Red-NoLabel a 0 Ý Ñ # b Cras 0 Ý Ñ # Crbs Red-Label a ˚pÐu Ý ÝÝÝ Ñ # b Cras p˚pÐuqÒC ÝÝÝÝÝÝÑ # pCr˚p Ð usqrbs Figure 7.12: Definition of ÝÑ # p˚p Ð uq Ò rπ. rss " 0 p˚p Ð uq Ò rs # τ " ˚p Ð u p˚p Ð uq Ò rs # u 1 " ˚p Ð u p˚p Ð uq Ò rs # pu 1 1 » u 1 2 q : τ " ˚p Ð u p˚p Ð uq Ò rs # ˚u1 " ˚p Ð u p˚p Ð uq Ò prsq q " ˚p Ð u Figure 7
.13: Label translation for mML

• either a i " u i u 1 i , and then Γ, ∆ Y T i $ u i : τ i Ñ σ i and Γ, ∆ Y T i $ u 1 i : τ i ;
• or a i " pu i q pi and then Γ, ∆ Y T i $ u i : rσ i s

. Then, consider a set of non-expansive term expand i for all i for which a i is a thunk application, and a set of terms expanded i , such that:

• For all i, Γ, ∆ Y T i $ expand i : bool, i.e. the expand i are boolean nonexpansive expressions.

• For all i, Γ, ∆ Y T i , pexpand i » Trueq : bool $ u i : σ i » rp. expanded i s : σ i , i.e. the expression inside the thunk application is equivalent to rp.expanded i s whenever expand i is True.

Then, consider a 1 the term obtained by replacing all thunk application atoms in a with match expand i with False Ñ pu i q pi | True Ñ expanded i rπ Ð p i s. We say that a 1 is a one-step expansion of a.

We way that a 1 is an expansion of a if it can be obtained from a by a finite number of expansions. ♦ Definition 7.2 (Term equality for mML). Consider an environment Γ, two terms a u , b u , and two types τ a , τ b . Consider expansions a and b of these terms, and suppose there exists p, ∆ a , ∆ b such that Γ $ p a : τ a ñ ∆ a and Γ $ p b :

τ b ñ ∆ b .
Let S a " labelspaq, S b " labelspbq Suppose atomspaq " p˚p i Ð pT a,i , a i qq piPlabelspaq and atomspbq " p˚q j Ð pT b,j , b j qq qj Plabelspbq , with for all i,

• either a i " u i u 1 i , and then Γ, ∆ a Y T a,i $ u a,i : τ a,i Ñ σ a,i and Γ, ∆ a Y T a,i $ u 1 a,i : τ a,i ;

• or a i " pu i q pi and then Γ, ∆ a Y T a,i $ u i : rσ a,i s and similarly for Moreover, suppose that for all i, and similarly for all j, Γ, ∆ b Y T b,j $ u b,j : τ b,j Ñ σ b,j and Γ, ∆ b Y T b,j $ u 1 b,j : τ b,j . Finally, suppose that ∆ a " ppu c a,i q˚p i : σ a,i q i and ∆ b " ppu c b,j q˚q j : σ b,j q j . We define a type unthunk τ with one constructor Unthunk : τ Ñ unthunk τ to represent thunk-valued atoms. Then, for each i, we define atom a,i " Apppu i , u 1 i q and atomty a,i " app pτ i , σ i q if the expression defining p i is of the form u i u 1 i , and atom a,i " Unthunk u, atomty a,i " unthunk σ a,i if the expression defining p i is of the form pp i q _ , and similarly for each j

Then, we say that that a and b are equal, noted TermsEqualpΓ $ p a u : τ a » b u : τ b q if and only if:

• For all k, Γ, ∆ a , ∆ b , ppIndex pu c a,i Ñ p i q i » Index pu c b,j Ñ q j q j q : Index pu c a,i Ñ τ i q i q ăk $ Index k pu c a,i Ñ atom a,i q i : Index k pu c a,i Ñ atomty a,i q i » Index k pu c b,i Ñ atom b,i q i : Index k pu c b,i Ñ atomty b,i q i i.e. the k-th atom on the left-hand side is equivalent to the k-th atom on the right-hand side.

• The final expressions are equal:

Γ, ∆ a , ∆ b , ppIndex pu c a,i Ñ p i q i » Index pu c b,j Ñ q j q j q : Index pu c a,i Ñ τ i q i q ăpn,mq $ reusepaq : τ a » reusepbq : τ b where n and m are the number of labels appearing in a and b respectively.

♦

This equality has the same properties as the eML equality. In particular, for transitivity, we can perform expansion on all terms and then apply transitivity as for eML.

Then, reduction preserves equality:

Lemma 7.1 (Meta reduction preserves equality). Suppose Γ $ p a : τ ñ ∆ and a ÝÑ # a 1 . Then, TermsEqualpΓ $ p a : τ » a 1 : τ q.

Proof. A meta-reduction is either a non-expansive reduction, that preserves equality as in Lemma 6.25, or a reduction of a thunk, in which case we need to mark the expanded thunk as to-be-expanded and then recover identical terms.

Metatheory of mML

Confluence

First, we prove that the mML reduction ÝÑ # is confluent. This is not immediate because of labels: we need to show that the same labels are substituted whatever the order thunks are reduced in, and independently of where mML reduction moves them. As explained when presenting labeled ML, this is only true for well-typed terms and well-formed types and kinds.

Well-labeling and subject reduction

We have not yet proved subject reduction for ÝÑ # , and we intend to use confluence in the proof. Fortunately, the reduction ÝÑ # does not drop expansive expressions and labels are preserved: the obstacles to proving confluence using only the well-labeling of §5 are absent here. Our first step is thus to extend the well-labeling defined in Figure 5.8 to mML. The new rules, given in Figure 7.14 for terms, and Figure 7.16 for types, are essentially a simplification of the typing rules for mML, where only the label information is kept: the judgment Σ; Γ $ p l a ñ ∆ reads as with path variables Σ and labels Γ in context, and with current label p, the term a is well-labeled and emits labels in ∆. We also give a well-labeling judgment for kinds and terms. Since they do not emit labels, the judgments are simpler: Σ; Γ $ l τ (resp. Σ; Γ $ l κ) states that the type τ (resp. the kind κ) is well-labeled in the environment Σ, Γ.

The well-labeling judgment for mML is more lenient than the typing judgment:

L-Var orthogonalpΓq Σ; Γ $ p l x ñ H L-TAbs Σ; Γ $ p l u ñ H Σ; Γ $ p l Λpα : Typq. u ñ H L-TApp Σ; Γ $ p l a ñ ∆ Σ; Γ $ l τ Σ; Γ $ p l a τ ñ ∆ L-Fix π # Σ Σ, π; Γ $ π l a ñ ∆ Σ; Γ $ l τ 1 Σ; Γ $ l τ 2 Σ; Γ $ p l fix π x py : τ 1 q : τ 2 . a ñ H L-App Σ; Γ $ p l a ñ ∆ 1 Σ; Γ, ∆ 1 $ p l b ñ ∆ 2 p ď q q K Γ, ∆ 1 , ∆ 2 Σ; Γ $ q l a q b ñ ∆ 1 , ∆ 2 , q L-Let Σ; Γ $ p l a ñ ∆ 1 Σ; Γ, ∆ 1 $ p l b ñ ∆ 2 Σ; Γ $ p l let x " a in b ñ ∆ 1 , ∆ 2 L-Con orthogonalpΓq pΣ; Γ $ l τ i q i pΣ; Γ, p∆ k q kąj $ p l a j ñ ∆ j q j Σ; Γ $ p l dpτ i q i pa j q j ñ p∆ j q j L-Match Σ; Γ $ p l a ñ ∆ pΣ; Γ $ l τ k q k pΣ; Γ, ∆ $ p l a i ñ ∆ i q i orthogonalpp∆ i q i q Σ; Γ $ p l match a with pd i pτ k q k px ij q j Ñ b i q i ñ ∆, p∆ i q i L-Reuse orthogonalpΓq p P Γ _ p K Γ Σ; Γ $ p l ˚p ñ H L-TyMetaAbs Σ; Γ $ l κ Σ; Γ $ p l u ñ H Σ; Γ $ p l λ # pα : κq. u ñ H L-TyMetaApp Σ; Γ $ p l a ñ ∆ Σ; Γ $ l τ 0 Σ; Γ $ p l a # τ 0 ñ ∆ L-TermMetaAbs Σ; Γ $ l τ 0 Σ; Γ $ p l u ñ H Σ; Γ $ p l λ # px : τ 0 q. u ñ H L-TermMetaApp Σ; Γ $ p l a ñ ∆ Σ; Γ $ p l u ñ H Σ; Γ $ p l a # u ñ ∆ L-EqMetaAbs Σ; Γ $ l σ Σ; Γ $ p l u 1 ñ H Σ; Γ $ p l u 2 ñ H Σ; Γ $ p l u ñ H Σ; Γ $ p l λ # ppu 1 » u 2 q : σq. u ñ H L-EqMetaApp Σ; Γ $ p l a ñ ∆ Σ; Γ $ l σ Σ; Γ $ p l u 1 ñ H Σ; Γ $ p l u 2 ñ H Σ; Γ $ p l a # pu 1 » u 2 q : σ ñ ∆ Figure 7
.14: Well-labeling for types

L-PtrMetaAbs q K Γ Σ; Γ $ p l u 0 ñ H Σ; Γ $ l τ Σ; Γ, q $ p l u ñ H Σ; Γ $ p l λ # ppu 0 q˚q : τ q. u ñ H L-PtrMetaApp Σ; Γ $ p l a ñ ∆ Σ; Γ $ p l u ñ H Σ; Γ $ p l a # ˚u ñ ∆ L-Thunk π # Σ Σ, π; Γ $ π l a ñ ∆ Σ; Γ $ p l rπ. as ñ H L-Unthunk p ď q q K Γ, ∆ Σ; Γ $ p l a ñ ∆ Σ; Γ $ p l paq q ñ ∆, q Figure 7
.15: Well-labeling for types (cont.)

LT-Var orthogonalpΓq Σ; Γ $ l α LK-Base orthogonalpΓq κ P tTyp, Sch, Metu Σ; Γ $ l κ LK-TyFun Σ; Γ $ l κ Σ; Γ $ l κ 1 Σ; Γ $ l Πpα : κq κ 1 LK-TermFun Σ; Γ $ l τ Σ; Γ $ l κ Σ; Γ $ l Πpx : τ q κ Figure 7
.17: Well-labeling for kinds Lemma 7.2 (Well-typed expressions are well-labeled). Consider a typing environment Γ. We can obtain a labeling environment Σ; Γ 1 from it by removing everything except path variables and the names of labels. Similarly, from a list of computed results for typing ∆ with their types and conditions, we can obtain a list of computed results for labeling ∆ 1 . Then,

• if Γ $ κ wf, then Σ; Γ 1 $ l κ; • if Γ $ τ : κ, then Σ; Γ 1 $ l τ ; • if Γ $ p : aτ ∆, then Σ; Γ 1 $ p l a ñ ∆ 1 . Proof.
By induction on the derivation. Some hypotheses requires in the labeling derivation but absent from the mML derivation can be extracted from the already-present typing hypotheses (Lemma 6.12).

We need weakening and substitution for this judgment: Lemma 7.3 (Weakening). Suppose Σ; Γ $ p l a ñ ∆. Then: • Suppose q ď p, and q independent of Γ, ∆. Then, Σ; Γ $ q l a ñ ∆. • Suppose π R Σ. Then, Σ, π; Γ $ p l a ñ ∆. • Suppose q K p, Γ, ∆. Then, Σ; Γ, q $ p l a ñ ∆. We have the same results for types and kinds.

Proof. By induction on the derivation: these changes translate to weakening in the premises. The independence side-conditions stay true in the derivations.

Lemma 7.4 (Substitution). Suppose Σ; Γ $ p l a ñ ∆.

• Consider π P Σ, and q K Γ, ∆. Then, Σ ´π; Γrπ Ð qs $ prπÐqs l arπ Ð qs ñ ∆rπ Ð qs.

• Consider x and a non-expansive term u such that Σ; Γ $ p l u ñ H. Then, Σ; Γ $ p l arx Ð us ñ ∆. We have the same results for types and kinds.

Proof. By induction on the derivation.

We then prove subject reduction for the well-labeling. This lemma is similar to Lemma 5.11, except that we do not need a case for labels that disappear. It is also extended to handle types and kinds.

Lemma 7.5 (Subject reduction for well-labeling and ÝÑ # ).

• Suppose Σ; Γ $ l κ. If κ ÝÑ # κ 1 , then Σ; Γ $ l κ 1 . • Suppose Σ; Γ $ l τ . If τ ÝÑ # τ 1 , then Σ; Γ $ l τ 1 . • Suppose Σ; Γ $ p l a ñ ∆. Moreover, suppose a l Ý Ñ # b. Then: -If l " 0, we have Σ; Γ $ p l b ñ ∆. -If l " ˚q Ð u, we have Σ; Γ $ p l b ñ ∆ 1
where ∆ 1 " ∆ ´tqu Z S where S is an orthogonal set of labels prefixed by q, and q P ∆.

Proof. The proof is similar to Lemma 5.11, except that we do not have to handle the case of reduction of a pattern matching, thus labels never disappear.

The parallel reduction

In order to prove confluence, we follow [START_REF] Takahashi | Parallel reductions in λ-calculus[END_REF]. We define a parallel reduction for ÝÑ # . For types, it is noted a σ a 1 , where σ is a substitution of labels, corresponding to the labels emitted by the one-step reductions represented by this parallel reduction. When σ is empty, we will also write a a 1 . It also applies to types and kinds. Since all terms appearing in types and kinds are nonexpansive, σ will always be empty and we write τ τ 1 and κ κ 1 . The reduction has two parts: it has congruence rules, presented in Figure 7.18 for terms and Figure 7.19 for types and kinds, and reduction rules, presented in Figure 7.20. The congruence rules (for example P-App) reduce each subexpression. If labels are generated, the labels are substituted in all the subexpressions, as well as in the substitutions that were generated while reducing these expressions (until there is nothing to substitute). The rules for let binding (P-Let) and pattern matching (P-Match) also ensure that the substitutions stay well-scoped, as is already done by label translation.

We will need a few substitution and reflexivity results on :

Lemma 7.6 (Reflexivity of ). The parallel reduction is reflexive:

• For all a, a H a.

• For all τ , τ τ .

• For all κ, κ κ.

Proof. By mutual induction on terms, types, and kinds: apply the lemma for each subexpression, and always choose the congruence rules.

Lemma 7.7 (Substitution for ). Let σ be a substitution (of term, type or label variables, or of labels). Consider σ a reduced version of this substitution ( i.e.

where some terms and types have been replaced by their reductions by ). Then,

• If a l a 1 , then arσs lrσ s a 1 rσ s.

• If τ τ 1 , then τ rσs τ 1 rσ s.

• If κ κ 1 , then κrσs κ 1 rσ s. • If a l a 1 , for all ˚p Ð u P l, p P ∆.

P-Var x H x P-Let a la a 1 b l b b 1 let x " a in b la,l b rla,xÐreusepa 1 qs let x " a 1 in b 1 rl a s P-Fix a l a 1 τ 1 τ 1 1 τ 2 τ 1 2 fix π x py : τ 1 2 q : τ 1 . a H fix π x py : τ 1 2 q : τ 1 1 . a 1 P-App a la a 1 b l b b 1 a p b la,l b rlas a 1p b 1 rl a s P-TAbs u H u 1 Λpα : Typq. u H Λpα : Typq. u 1 P-TApp a l a 1 a τ l a 1 τ P-Match a l a 1 pτ k τ 1 k q k pb i li b 1 i q i match a with pd i pτ k q k px ij q j Ñ b i q i l,pmatchreusepa 1 q with dipτ k q k pxij q j Ñlirlsq i match a 1 with pd i pτ 1 k q k px ij q j Ñ b 1 i rlsq i P-Reuse ˚p H ˚p P-TyMetaAbs κ κ 1 u H u 1 λ # pα : κq. u H λ # pα : κ 1 q. u 1 P-TyMetaApp u H u 1 τ τ 1 u # τ H u 1 # τ 1 P-TermMetaAbs τ τ 1 u H u 1 λ # px : τ q. u H λ # px : τ 1 q. u 1 P-TermMetaApp u 1 H u 1 1 u 2 H u 1 2 u 1 # u 2 H u 1 1 # u 1 2 P-EqMetaAbs u 0 H u 1 0 u 1 H u 1 1 u 2 H u 1 2 τ τ 1 λ # pu 1 » u 2 q : τ. u 0 H λ # pu 1 1 » u 1 2 q : τ 1 . u 1 0 P-EqMetaApp u 0 H u 1 0 u 1 H u 1 1 u 2 H u 1 2 τ τ 1 u 0 # pu 1 » u 2 q : τ H u 1 0 # pu 1 1 » u 1 2 q : τ 1 P-PtrMetaAbs u 0 H u 1 0 u H u 1 τ τ 1 λ # ppu 0 q˚p : τ q. u λ # ppu 1 0 q˚p : τ 1 q. u 1 P-PtrMetaApp u 1 H u 1 1 u 2 H u 1 2 u 1 # u 2 H u 1 1 # u 1 2 P-Thunk a l a 1 rπ. as H rπ. a 1 s P-Unthunk u H u 1 puq p H pu 1 q p
κ 1 κ 1 1 κ 2 κ 1 2 Πpα : κ 1 q κ 2 Πpα : κ 1 1 q κ 1 2 P-KTermFun τ τ 1 κ κ 1 Πpx : τ q κ Πpx : τ 1 q κ 1 P-TyVar α α P-TyFun τ 1 τ 1 1 τ 2 τ 1 2 τ 1 Ñ τ 2 τ 1 1 Ñ τ 1 2 P-TyDatatype pτ i τ 1 i q i ζ pτ i q i ζ pτ 1 i q i P-TyAll τ τ 1 @pα : Typq τ @pα : Typq τ 1 P-TyMatch a l a 1 pτ k τ 1 k q k pσ i σ 1 i q i match u with pd i pτ k q k px ij q j Ñ σ i q i match u 1 with pd i pτ 1 k q k px ij q j Ñ σ 1 i q i P-TyTyAbs κ κ 1 τ τ 1 λ # pα : κq. τ λ # pα : κ 1 q. τ 1 P-TyTyApp σ σ 1 τ τ 1 σ # τ σ 1 # τ 1 P-TyTermAbs τ τ 1 σ σ 1 λ # px : τ q. σ λ # px : τ 1 q. σ 1 P-TyTermApp τ τ 1 u u 1 τ # u τ 1 # u 1 P-TyMetaTyFun κ κ 1 τ τ 1 Πpα : κq τ Πpα : κ 1 q τ 1 P-TyMetaTermFun τ τ 1 σ σ 1 Πpx : τ q σ Πpx : τ 1 q σ 1 P-TyMetaEqFun u 1 u 1 1 u 2 u 1 2 τ τ 1 σ σ 1 Πpu 1 » u 2 q : τ σ Πpu 1 1 » u 1 2 q : τ 1 σ 1 P-TyMetaPtrFun u u 1 τ τ 1 σ σ 1 Πppuq˚p : τ q σ Πppu 1 q˚p : τ 1 q σ 1 P-TyThunk
Proof. By induction on the derivation of the reduction.

The usual reduction and the parallel reductions do not perform the same substitutions of labels: in a b, if the reduction of b emits a substitution, it will be substituted in a by the usual reduction but not by the parallel reduction. We need to prove that this has no consequences on the result: this is the case because all labels that could be emitted by b are out of scope for a.

Lemma 7.11.

• If Σ; Γ $ q l a ñ ∆ and p R Γ, ∆, then ar˚p Ð us " a.

• If Σ; Γ $ l τ and p K Γ, then τ r˚p Ð us " τ .

• If Σ; Γ $ l κ and p K Γ, then κr˚p Ð us " κ.

Proof. By induction on the derivation.

We also need the same result for the emitted substitutions. Here, we need a stronger hypothesis because emitted substitutions may reference labels that are suffixes of already existing labels.

Lemma 7.12. Suppose Σ; Γ $ q l a ñ ∆. Let ˚p Ð u be a substitution with q ď p and p K Γ, ∆. Suppose a l b. Then, lr˚p Ð us " l.

Proof. By induction on the reduction, we prove that all labels appearing in the terms in l are suffixes of the labels in Γ, ∆.

We prove that the parallel reduction embeds the usual reduction. This relies on the well-labeling to be true: when propagating reduction labels, the parallel reduction only substitutes in the part of the context that are after the evaluation of the label, while ÝÑ # substitutes in the whole context. The welllabeling guarantees that such labels cannot appear in the parts that are before the evaluation. Lemma 7.13 (ÝÑ # is included in ).

• Suppose Σ; Γ $ p l a ñ ∆. Then if a l Ý Ñ # a 1 , a l a 1 . • Suppose Σ; Γ $ l τ . Then, if τ ÝÑ # τ 1 , τ τ 1 . • Suppose Σ; Γ $ l κ. Then, if κ ÝÑ # κ 1 , κ κ 1
Proof. By induction on the reduction, inverting the typing derivation along the way.

Head reduction map directly to reduction rules of the parallel reduction. The subexpressions of the reduction rules are not reduced: we map them to themselves using reflexivity for parallel reduction (Lemma 7.6).

For context rules, we will take the reduction in context C " let x " a in rs as an example, as it has the most complicated features, and we will suppose that the term in the context reduces with an attached substitution. Suppose b ˚pÐu Ý ÝÝÝ Ñ # a 1 . Then, Crbs ˚pÐurxÐreusepaqs Ý ÝÝÝÝÝÝÝÝÝÝÝ Ñ # let x " ar˚p Ð us in br˚p Ð urx Ð reusepaqss. Consider the labeling derivation of let x " a in b. The last rule must be L-Let. Inverting the rule Let, we obtain Σ; Γ $ q l a ñ ∆ and Σ; Γ, ∆ $ q l b ñ ∆ 1 . By Lemma 7.10, we know that p P ∆ 1 . Thus, p K Γ, ∆. Then, we can apply Lemma 7.11: we have ar˚p Ð us " a.

We conclude by applying P-Let: we have a H a (by reflexivity, Lemma 7.6) and b ˚pÐu b 1 by induction hypothesis, thus let x " a in b ˚pÐurxÐreusepaqs let x " a in b 1 .

We also prove that the parallel reduction is a subset of the (iterated) usual reduction:

Lemma 7.14 ( included in ÝÑ # ).

• Suppose Σ; Γ $ l κ and κ κ 1 . Then, κ ÝÑ # κ 1 .

• Suppose Σ; Γ $ l τ and τ τ 1 . Then, τ ÝÑ # τ 1 .

• Suppose Σ; Γ $ a l ∆ ñ , and a l a 1 . Then,

a l Ý Ñ # a 1 .
Proof. By mutual induction on the parallel reduction derivations. We describe the reasoning for two representative rules:

• If the last rule is a congruence rule such as P-Let:

P-Let a la a 1 b l b b 1 let x " a in b la,l b rla,xÐreusepa 1 qs let x " a 1 in b 1 rl a s
The last rule of the well-labeling derivation must be L-Let:

L-Let Σ; Γ $ p l a ñ ∆ 1 Σ; Γ, ∆ 1 $ p l b ñ ∆ 2 Σ; Γ $ p l let x " a in b ñ ∆ 1 , ∆ 2
By induction hypothesis on the well-labeled term b, we have b l b Ý Ñ # b 1 . All the labels q P l b are in ∆ 2 by Lemma 7.10. Thus, l 2 K Γ, ∆ 1 , and for any subset l 1 2 of l 2 , arl 1 2 s " a. Thus, (by applying the context rule for C " let x " a in rs, we have let x " a in b

l b rxÐreusepaqs Ý ÝÝÝÝÝÝÝÝ Ñ # let x " a in b 1 .
By induction hypothesis on the well-labeled term a, we have a la Ý Ñ # a 1 . Thus, by applying the context rule for C " let x " rs in b 1 , we obtain

let x " a in b 1 la Ý Ñ # let x " a in b 1 rl a s.
By composing these two reductions we obtain:

let x " a in b la,l b rla,xÐreusepa 1 qs Ý ÝÝÝÝÝÝÝÝÝÝÝÝ Ñ # let x " a 1 in b 1 rl a s.
• If the last rule is a reduction rule such as P-TermThunkRed: P-TermThunkRed a l a 1 prπ. asq p ˚pÐreusepa 1 qrπÐps a 1 rπ Ð ps By inverting the well-labeling derivation (L-Unthunk then L-Thunk), we obtain that a is well-typed. Thus, by induction hypothesis,

a l Ý Ñ # a 1 .
Then, prπ.asq p ÝÑ # prπ.a 1 sq p (the rπ.rss removes the substitution emitted by the reduction of a). By head-reduction, we have prπ. a 1 sq p ˚pÐreusepa 1 qrπÐps Ý ÝÝÝÝÝÝÝÝÝÝÝ Ñ # a 1 rπ Ð ps

We conclude by composition.

Confluence for

We now define the maximal reduction for : a l a 1 is a maximal reduction of a if we always use the reduction rules whenever possible. Then, we write this a l a 1 . We can similarly define a maximal reduction for types and kinds. The core of the confluence proof is the following lemmas, expressing that if we start by doing a step of non-maximal reduction, we can always obtain the maximal reduction by performing another step of reduction. The term version is more complex to express because it also needs to state how the substitutions labelling these reductions are related: intuitively, performing a first reduction might make some redexes that were hidden under a lambda exposed. Reducing these lambdas in the second reduction step will emit labels that are not visible when doing the maximal reduction in one step. The labels of these now-revealed redexes are suffixes of labels emitted in the first reduction.

Lemma 7.15.

• Suppose Σ; Γ $ l κ 0 . Consider a maximal reduction κ 0 κ 2 . Suppose we also have κ 0 κ 1 . Then, κ 1 κ 2 .

• Suppose Σ; Γ $ l τ 0 . Consider a maximal reduction τ 0 τ 2 . Suppose we also have τ 0 τ 1 . Then, τ 1 τ 2 .

• Suppose Σ; Γ $ p l a 0 ñ ∆. Consider a maximal reduction a 0 l12 a 2 . Suppose we also have a 0 l1 a 1 . Then, there exists l 2 , l 1 2 and l 1 such that:

a 1 l2,l 1 2 a 2 . l 1 rl 2 , l 1 2 s l 1 , i.e. l 1 associates labels to reduced versions of their corresponding terms in l 1 .

-The labels in l 1 2 are suffixes of the labels in l 1 , l 12 " l 1 rl 2 , l 1 2 s, l 2 .

Proof. By mutual induction on terms, types and kinds. We consider a few representative cases:

• If the last rule of the maximal reduction is P-Thunk, the last rule of the non-maximal reduction is also P-Thunk. Inverting the well-labeling derivation, we obtain that a is well-labeled.

Then by induction hypothesis, there exists l a,2 , l 1 a,2 such that a 1 la,2,l 1 a,2 a 2 . Then, applying P-Thunk, rπ. a 1 s H rπ. a 2 s. We conclude with l 1 " l 1 " l 2 " l 1 2 " l 12 " H.

• If the last rule of the maximal reduction is P-Unthunk, then the last rule of the non-maximal reduction is also P-Unthunk (the last rule cannot be P-TermThunkRed because if it was possible to apply it it would be applied in the maximal reduction).

u 0 H u 2 pu 0 q p H pu 2 q p u 0 H u 1 pu 0 q p H pu 1 q p
Inverting the well-labeling derivation, we obtain that u is well-labeled.

Then by induction hypothesis, we have u 1 H u 2 . Thus, applying the rule P-Unthunk, we obtain pu 1 q p H pu 2 q p .

• If the last rule of the maximal reduction is P-TermThunkRed and the last rule of the non-maximal reduction is P-Unthunk: then, the second-to-last rule of the non-maximal reduction is P-Thunk. By inverting the well-labeling derivation, we obtain that a 0 is well-labeled. By induction hypothesis, there exists l a,2 , l 1 a,2 such that a 1 la,2,l 1 a,2 a 2 Then, by P-TermThunkRed, we obtain prπ.a 1 sq p ˚pÐreusepa2qrπÐps a 2 rπ Ð ps. We conclude, with l 12 " l 2 " ˚p Ð reusepa 2 qrπ Ð ps, and l 1 " l 1 " l 1 2 " H.

• If the last rule of the maximal reduction is P-TermThunkRed and the last rule of the non-maximal reduction is not P-Unthunk, it must be P-TermThunkRed too.

a 0 la,12 a 2 prπ. a 0 sq p ˚pÐreusepa2qrπÐps a 2 rπ Ð ps a 0 la,1 a 1 prπ. a 0 sq p ˚pÐreusepa1qrπÐps a 1 rπ Ð ps

Similarly to the previous case, we have a 0 la,12 a 2 , a 0 la,1 a 1 , a 1 la,2,l 1 a,2 a 2 . By substitution, we have a 1 rπ Ð ps pla,2,l 1 a,2 qrπÐps a 2 rπ Ð ps. We have l 1 " ˚p Ð reusepa 1 qrπ Ð ps. By substitution (Lemma 7.7), we have a 1 rπ Ð ps pl2,l 1 2 qrπÐps a 2 rπ Ð ps. Then, by Lemma 7.8, there exists u such that reusepa 1 q H u and ˚a2 rπ Ð ps " urpl 2 , l 1 2 qrπ Ð pss. Let l 2 " H, l 1 2 " pl a,2 , l 1 a,2 qrπ Ð ps, Then, let l 1 " ˚p Ð u. We have url 2 , l 1 2 s " ˚a2 rπ Ð ps. Thus l 1 rl 2 , l 1 2 s " ˚p Ð reusepa 2 qrπ Ð ps By subject reduction for well-labeling (Lemma 7.5), the labels emitted by the reduction a 1 rπ Ð ps pla,2,l 1 a,2 qrπÐps a 2 rπ Ð ps must be prefixed by p (the output label set for prπ. a 0 sq p only contains p, thus the new labels appearing may only start with p and parallel reduction only emits exposed labels by Lemma 7.10).

Then, l 12 " l 1 , l 2 and we conclude.

• If the last rule of the maximal reduction is P-Let, the last rule of the other reduction is also P-Let:

a 0 la,12 a 2 b 0 l b,12 b 2 let x " a 0 in b 0 la,12,l b,12 rla,12,xÐreusepa2qs let x " a 2 in b 2 rl a,12 s a 0 la,1 a 1 b 0 l b,1 b 1 let x " a 0 in b 0 la,1,l b,1 rla,1,xÐreusepa1qs let x " a 1 in b 1 rl a,1 s
By inverting the well-labeling derivation, we obtain that a 0 and b 0 are well-labeled. Thus, by induction hypothesis, there exists l a,1 , l a,2 , l 1 a,2 such that a 1 la,2,l 1 a,2 a 2 and l a,12 " l a,1 rl a,2 , l 1 a,2 s, l a,2 , and l b,1 , l b,2 , l 1 b,2 such that b 1 l b,2 ,l 1 b,2 b 2 and l a,12 " l b,1 rl b,2 , l 1 b,2 s, l b,2 .

By substitution (Lemma 7.7), we have b 1 rl a,1 s l b,2 rl a,1 s,l 1 b,2 rl a,1 s b 2 rl a,1 s.

Thus, applying P-Let, we get:

let x " a 1 in b 1 rl a,1 s la,2,l 1 a,2 ,pl b,2 ,l b,2 qrl a,1 srxÐa2,la,2,l 1 a,2 s let x " a 2 in b 2 rl a,1 srl a,2 , l 1 a,2 s
Let us first show that the reduced expression is the one we want: we have b 2 rl a,1 srl a,2 , l 1 a,2 s " b 2 rl a,1 rl a,2 , l 1 a,2 s, l a,2 , l 1 a,2 s " b 2 rl a,1 rl a,2 , l 1 a,2 s, l a,2 s " b 2 rl a,12 s. The second-to-last equality is true because the labels in l 1 a,2 do not appear in b 2 because they are strict suffixes of labels that may be emitted by the reduction of a 0 (by induction hypothesis).

By a similar argument, we have: pl b,2 , l 1 b,2 qrl a,1 srx Ð reusepa 2 q, l a,2 , l 1 a,2 s " pl b,2 , l 1 b,2 qrx Ð reusepa 2 q, l a,1 rl a,2 , l 1 a,2 s, l a,2 , l 1 a,2 s " pl b,2 , l 1 b,2 qrx Ð reusepa 2 q, l a,1 rl a,2 , l 1 a,2 s, l a,2 s " pl b,2 , l 1 b,2 qrx Ð reusepa 2 q, l a,12 s

We take l 1 " l a,1 , l b,1 rx Ð reusepa 1 q, l a,1 s, l 1 " l a,1 , l b,1 rx Ð reusepa e q, l a,2 s, l 2 " l a,2 , l b,2 rx Ð reusepa 2 q, l a,12 s, l 1 2 " l 1 a,2 , l 1 b,2 rx Ð reusepa 2 q, l a,12 s. Then, we have l 12 " l 1 rl 2 , l 1 2 s, l 2 .

From this, we deduce the diamond property for the parallel reduction. We'll allow ourselves to write without label for l for some substitution l.

Lemma 7.16 (Diamond property for ). Consider a well-labeled term a 0 Suppose a 0 a 1 and a 0 a 2 . Then, there exists a 12 such that: a 1 a 12 and a 2 a 12 .

We have the same results on types and kinds.

Proof. Take a 12 to be the maximal reduction of a 0 .

Lemma 7.17 (Confluence for ). Suppose a 0 ˚a1 and a 0 ˚a2 . Then, there exists a 12 such that a 1 ˚a12 and a 2 ˚a12 .

We have the same result for types and kinds.

Proof. We will write the proof for types. Suppose τ 0,0 τ 1,0 . . . τ n,0 and τ 0,0 τ 0,1 . . . τ 0,m . By subject reduction, the τ i,0 and τ 0,j are well-labeled.

For each 0 ă i ď n, 0 ă j ď m, suppose τ i´1,j´1 is well-labeled and let τ i,j be the type such that τ i,j´1 τ i,j and τ i´1,j τ i,j . It exists by the diamond property (Lemma 7.16). Moreover, it is well-labeled by subject reduction.

Then τ n,m is such that τ n,0 τ n,1 . . . τ n,m and τ 0,m τ 1,m . . . τ n,m , ie. τ n,0 ˚τn,m and τ 0,m ˚τn,m .

As a consequence, we have confluence for ÝÑ # : Theorem 7.1 (Confluence for ÝÑ # ). The reduction ÝÑ # is confluent: consider a well-typed term a 0 , and suppose a 0

l1 Ý Ñ # a 1 , a 0 l2 Ý Ñ # a 2 .
Then, there exists a 3 and l 1 1 , l 1 2 such that a 1

l 1 1 Ý Ñ # a 3 and a 2 l 1 2 Ý Ñ # a 3 .
The same result is true for types and kinds.

Proof. Well-typed terms, types, and kinds are well-labeled (Lemma 7.2) is confluent on well-typed terms, types and kinds, and ˚and ÝÑ # coincide.

Basic properties of the typing derivation

We need weakening, reflexivity and substitution lemmas as for eML (see §6.3.1), as well as symmetry of the equality. Neither the proofs nor the statements change significantly, and we will not repeat them here.

Strong normalization

Our goal in this section is to prove that meta-reduction and type reduction are strongly normalizing. The notations used in this proof are only used here, and will be re-used for other purposes later in this article.

Theorem 7.2 (Normalization for meta-reduction). The meta-reduction ÝÑ # is strongly normalizing.

As usual, the proof uses reducibility sets [START_REF] Girard | Proofs and Types[END_REF]. We need some unusual properties to deal with labels: terms must stay strongly normalizing, even when labels are substituted by arbitrary terms of the right types. Since the labels are always substituted by expressions whose types are eML types, and thus substitution of labels does not interact with the mML reduction, we actually allow substitution of labels by safe term: Definition 7.3 (Safe terms). The set of safe terms B a is defined as the maximal set of terms such that • All terms in B a are strongly normalizing.

• If a P B a , then a does not begin with a meta-abstraction or a meta thunk. The set of safe terms is stable by reusep_q: reuse distributes over reduction, and does not create meta abstractions or thunks.

• Suppose a P B a . If a 0 Ý Ñ # a 1 , a 1 P B a . If a ˚pÐu Ý ÝÝÝ Ñ # a 1 , then both a 1 P B a and u P B a . ♦ ⟪Typ⟫ " tB a u ⟪Sch⟫ " tB a u ⟪Met⟫ " C a ⟪Πpα : κ 1 q κ 2 ⟫ " ⟪κ 1 ⟫ Ñ ⟪κ 2 ⟫ ⟪Πpx : τ q κ⟫ " 1 Ñ ⟪κ⟫
Lemma 7.18 (Stability by label substitution). Suppose a P B a , and consider a label p and u P B a . Then, ar˚p Ð us P B a , and we have the same property for partial substitution (where only some labels are substituted).

Proof. All reductions of ar˚p Ð us are either reductions of a or of u: because u can never begin with a constructor for ÝÑ # , there can be no redex spanning the substitution boundary.

We now define reducibility sets. The unusual property here is CR4, which asserts that labels can be arbitrarily substituted. CR2 needs to check that generated labels are still safe.

Definition 7.4 (Reducibility set). A set S of terms is called a reducibility set if it respects the properties CR1-4 below. We write C a the set of reducibility sets of terms.

CR1 Every term a P S is strongly normalizing. CR2 If a P S and a 0 Ý Ñ # a 1 then a 1 P S; if a ˚pÐu Ý ÝÝÝ Ñ # a 1 then a 1 P S and u P B a . CR3 Suppose a is not a meta-abstraction ( i.e. it is a neutral term for metareduction), and for all a 1 such that a l Ý Ñ # a 1 we have a 1 P S and moreover if l " ˚p Ð u then u P B a . Then a P S.

CR4 If a P S and u P B a , then ar˚p Ð us P S Similarly, replacing terms with types and kinds, we obtain a version of the properties CR1-4 for sets of types and sets of kinds. A set of types or kinds is called a reducibility set if it respects those properties, and we write C t the set of reducibility sets of types, and C k the set of reducibility sets of kinds. ♦ Lemma 7.19. B a is a reducibility set.

Proof. The properties CR1-3 are immediate from the definition. CR4 is exactly Lemma 7.18.

Let us all N k , N t , and N a the maximal reducibility sets of kinds, types and terms.

Definition 7.5 (Interpretation of types and kinds). We define an interpretation ⟪κ⟫ of kinds as sets of possible interpretations of types, with 1 the set with one element '. Type-level abstractions and applications are interpreted as functions in set theory. The interpretation is given on Figure 7.21. On Figure 7.22, we also define an interpretation rrκss ρ of a kind κ as a set of types and an interpretation rrτ ss ρ of a type τ as a set of terms, both under rrTypss ρ " rrSchss ρ " rrMetss ρ " N t rrΠpα : κ 1 q κ 2 ss ρ " " τ P N t ˇˇˇ@ τ 1 P rrκ 1 ss ρ , rrτ 1 ss ρ defined ùñ τ # τ 1 P rrκ 2 ss ρrαÐrrτ 1 ssρs * rrΠpx : τ q κss ρ " tτ P N t | @u P rrτ ss ρ , τ # u P rrκss ρ u rrαss ρ " ρpαq rrτ 1 Ñ τ 2 ss ρ " rrζ τ ss ρ " rrmatch a with . . .ss ρ " rr@pα : Typq . . .ss ρ " B a rrΠpx : τ 1 q τ 2 ss ρ " ta P N a | @u P rrτ 1 ss ρ , a # u P rrτ 2 ss ρ u rrΠpα : κq τ ss ρ " " a P N a ˇˇˇ@ τ 1 P rrκss ρ , rrτ 1 ss ρ defined ùñ a # τ 1 P rrτ ss ρrαÐrrτ 1 ssρs * rrΠpu 1 » u 2 q : τ τ 1 ss ρ " ta P N a | a # pu 1 » u 2 q : τ P rrτ 1 ss ρ u rrΠppuq˚p : τ q σss ρ " ta P N a | @u P rrτ ss ρ , a # ˚u P rrσss ρ u rrrτ sss ρ " ta P N a | @p.paq p P rrτ ss ρ u rrλ # px : τ 1 q. τ ss ρ " λ ' . rrτ ss ρ rrλ # pα : κq. τ ss ρ " λpS α P ⟪κ⟫q. rrτ ss ρrαÐSαs rrτ 1 # τ 2 ss ρ " rrτ 1 ss ρ rrτ 2 ss ρ rrτ # uss ρ " rrτ ss ρ ' Proof. By induction on the derivation of the judgment Γ $ κ 1 » κ 2 .

• This is immediately true for KEq-Base.

• For KEq-Trans, apply the induction hypothesis and use transitivity of equality.

• For KEq-Type-Fun and KEq-Term-Fun: the subkinds have equal interpretations by induction hypothesis, so the interpretations are equal.

Lemma 7.21 (Interpretation of kinds and types). Assume ρ ( Γ. Then:

• If Γ $ κ wf, then ⟪κ⟫ and rrκss ρ are well-defined, and rrκss ρ P C t .

• If Γ $ τ : κ, then rrτ ss ρ is well-defined, and we have rrτ ss ρ P ⟪κ⟫.

Proof. By simultaneaous induction on the well-formedness derivations for types and kinds.

• For K-Var: if pα : κq P Γ, since ρ ( Γ, then ρpαq P ⟪κ⟫.

• The types in the conclusion of rules K-Datatype, K-Arr, K-All, K-Match, K-SubTyp and K-SubSch are all interpreted as N a , which is in the intepretation of the kinds (Typ, Sch and Met) that appear as conclusions of these rules.

• For rule Wf-Base, the interpretations of Typ, Sch and Met is N t , which is in C t .

• For the type-level meta abstractions (K-TyAbs and K-TermAbs), by induction. The extended type environment ρ 1 matches the extended type environment Γ 1 : we still have ρ 1 ( Γ 1 . The interpretation is a function, which is in the interpretation of function kinds as sets of interpretations.

• Similarly for the type-level applications (K-TyApp and K-TermApp): we provide an argument of the right type, and the interpretation of the kind of the function guarantees that the application will be in the interpretation of the result kind.

• The rules Wf-TyFun, Wf-TermFun, K-TyMetaArr, K-TermMetaArr, K-EqMetaArr, K-PtrMetaArr and K-Thunk are similar. We only give the proof for K-TermMetaArr: take τ " Πpx : τ 1 q τ 2 . Define S 1 " rrτ 1 ss ρ and S 2 " rrτ 2 ss ρ . By induction hypothesis, S 1 and S 2 are reducibility sets. We will prove CR1-4 for S " rrτ ss ρ " ta P N a | @u P S 1 , a # u P S 2 u.

CR1 S is a subset of N a .

CR2 Consider a P S and a 1 such that a σ Ý Ñ # a 1 . For a given u P S 1 , a # u P S 2 σ Ý Ñ # a 1 # urσs. Thus, a 1 # urσs P S 2 by CR2 for S 2 . Then, a 1 P S. Moreover, we know that σ only substitutes a safe term. CR3 Consider a, not an abstraction, such that if a σ Ý Ñ # a 1 , a 1 P S. For u P S 1 , we'll prove a # u P S 2 . Since a is not an abstraction, a # u reduces either to a 1 # urσs with a σ Ý Ñ # a 1 , or a # u 1 with u 0 Ý Ñ # u 1 . In the first case, a 1 P S by hypothesis and urσs P S 1 , so a 1 # urσs P S 2 . In the second case, u 1 P S 1 by CR2, so a # u 1 P S 2 . By CR3 for S 2 , because a # u is not an abstraction, a # u P S 2 . CR4 Consider a P S, and a substitution ˚p Ð u with u P B a . For u 1 P S 1 , we have to prove ar˚p Ð us # u 1 P S 2 . This is a partial substitution of a # u 1 P S 2 thus is in S 2 too,

We need the following substitution lemma:

Lemma 7.22 (Substitution). For all τ , κ, τ 1 , α, a, u, x, p and ρ, we have:

• rrτ ss ρrαÐrrτ 1 ssρs " rrτ rα Ð τ 1 sss ρ

• rrκss ρrαÐrrτ 1 ssρs " rrκrα Ð τ 1 sss ρ

• rrτ ss ρ " rrτ rx Ð asss ρ " rrτ r˚p Ð usss ρ

• rrκss ρ " rrκrx Ð asss ρ " rrκr˚p Ð usss ρ

Proof. By induction on types and kinds. This comes from the fact that the interpretation of type variables is obtained by looking them up in the context, and that the interpretation never considers the terms inside types and kinds.

• If the last rule is a conversion, use soundness of conversion.

• If the last rule is a reuse: γp˚pq P B a , and the type in conclusion of the typing derivation has kind Sch so its interpretation is B a .

• If the last rule is App: suppose a " a 1 a 2 , with Γ $ a 1 : τ 1 Ñ τ 2 and Γ $ a 2 : τ 1 . Assume ρ, γ ( Γ. We have γpa 1 q P rrτ 1 ss ρ and γpa 2 q P rrτ 2 ss ρ . We need to show: γpa 1 a 2 q " γpa 1 q γpa 2 q P rrτ 2 ss ρ " B a (because τ 2 is necessarily of kind Typ). Meta-reduction does not reduce ML application: then, any reduction is either a reduction of γpa 1 q or γpa 2 q. By hypothesis, these two terms are strongly normalizing, thus γpa 1 a 2 q P B a .

• If the last rule is a meta-application TermMetaApp Γ $ u : Πpx :

τ 1 q τ 2 Γ $ u 1 : τ 1 Γ $ u # u 1 : τ 2 rx Ð u 1 s
Consider ρ, γ ( Γ. Then, by induction hypothesis, we have: γpuq P rrΠpx : τ 1 q τ 2 ss ρ , and γpu 1 q P rrτ 1 ss ρ . We thus have: γpu # u 1 q " γpuq # γpu 1 q P rrτ 2 ss ρ . By Lemma 7.22 rrτ 2 ss ρ " rrτ 2 rx Ð u 1 sss ρ . It follows that γpu # u 1 q P rrτ 2 rx Ð u 1 sss ρ .

• If the last rule is a meta-abstraction TermMetaAbs:

Γ, x : τ 1 $ u : τ 2 Γ $ λ # px : τ 1 q. u : Πpx : τ 1 q τ 2
Consider ρ, γ ( Γ. Consider u 1 P rrτ 1 ss ρ . We need to prove that pλ # px : γpτ 1 qq. γpuqq # u 1 P rrτ 2 ss ρ . Let us write u 2 " γpuq, τ 1 1 " γpτ 1 q. Then we will proceed by induction on the sum of the longest derivation starting τ 1 1 , u 1 , and u 1 . Let us apply CR3 to pλ # px : τ 1 1 q. u 2 q # u 1 , and consider all possible reductions:

-If the reduction happens in τ 1 1 , u 2 , or u 1 , we obtain a term of the same shape with the number of possible reductions strictly decreased. Then, we apply the induction hypothesis.

-Otherwise, we reduce the head redex: by hypothesis, u 2 rx Ð u 1 s P rrτ 2 ss ρ .

• If the last rule is K-TyAbs:

Γ, α : κ 1 $ τ : κ 2 Γ $ λ # pα : κ 1 q. τ : @pα : κ 1 q κ 2
As previously, we need to prove that for all τ 1 P rrκ 1 ss ρ , pλ # pα : γpκ 1 qq.γpτ qq # τ 1 P rrκ 2 ss ρ . We will only consider the case of the head redex:

if rrτ 1 ss ρ is not defined, there is nothing to prove;

otherwise, we need to show that γpτ qrα Ð τ 1 s P rrκ 2 ss ρrαÐrrτ 1 ssρs . Define γ 1 " γrα Ð τ 1 s and ρ 1 " ρrα Ð rrτ 1 ss ρ s. Then, we have ρ 1 , γ 1 ( Γ, α : κ 1 . We conclude by the induction hypothesis.

-If the last rule is Unthunk: Unthunk p ď q q K Γ, ∆ Γ $ p u : rτ s ñ ∆ Γ $ p puq q : τ ñ ∆, pTrueq˚q : τ

We examine the possible reductions as for TermMetaApp. When reducing the thunk, we emit ˚γpaq where a is the term currently inside the thunk. We have γpaq P B a , thus ˚γpaq P B a .

We can now prove the main result of this section:

Proof. [Proof of Theorem 7.2] Consider a kind, type, or term X that is welltyped in a context Γ. We can take the identity substitution γpxq " x for all x P Γ and apply the fundamental lemma. All interpretations are subsets of N a , thus X P N a .

Subject reduction and soundness

In order to prove subject reduction and soundness, we need to understand better the equalities on mML types. We prove a decomposition result: if we have an equality between two mML types that start with a type constructor, then they must start with the safe constructor, and the arguments to the constructor are also equal. This is a stronger result than the same for eML: we assert that, even in absurd contexts, we cannot derive an absurd equality between meta types. This makes the strong reduction sound.

The proof is by normalizing equality derivations, i.e. maximally reducing (for ÝÑ # ) the terms appearing in the derivation. Then such derivations do not have any type-level mML reduction. Once we have such a derivation between two terms with a given mML head constructor, we can show by case analysis that the head constructor is preserved throughout the equality derivation. The definition of normalized equality derivations, noted Γ $ norm τ 1 : κ 1 » τ 2 : κ 2 is given in Figure 7.23 for non-congruence rule and Figure 7.24 for congruence rules. The rules are a subset of the rules for Γ $ τ 1 : κ 1 » τ 2 : κ 2 . For mML, the congruence rules (equivalent to the rules presented in Figure 7.8 for the full equality) and the transitivity rule (TEqN-Trans) are preserved, while the meta-reduction rules (that were presented in Figure 7.10) are removed. Once the derivation reaches an eML type or a term, it proceeds using the usual equality rules (TEqN-eML). We also need to preserve the sub-kinding rules (TEqN-SubSch-R).

Normal equalities are a subset of the usual equality, and are compatible with substitution.

Lemma 7.26 (Normal equalities are equalities). Suppose Γ $ norm τ 1 :

κ 1 » τ 2 : κ 2 . Then, Γ $ τ 1 : κ 1 » τ 2 : κ 2
Proof. By induction on the derivation: each rule of the normal equality can be translated to the corresponding rule on the usual equality, except TEqN-eML which directly embeds an usual equality.

Lemma 7.27 (Substitutions for normal equalities). Suppose Γ, x : σ,

Γ 1 $ norm τ 1 : κ 1 » τ 2 : κ 2 . Then, if Γ $ u 1 : σ » u 2 : σ, we have Γ, Γ 1 rx Ð u 1 s $ norm τ 1 rx Ð u 1 s : κ 1 rx Ð u 1 s » τ 2 rx Ð u 2 s : κ 2 rx Ð u 2 s. Γ $ norm τ : Typ » τ 1 : κ Γ $ norm τ : Sch » τ 1 : κ TEqN-SubTyp-R Γ $ norm τ : κ » τ 1 : Typ Γ $ norm τ : κ » τ 1 : Sch Figure 7.23: Normal equalities (except congruence rules) Similarly, if Γ, α : κ, Γ 1 $ norm τ 1 : κ 1 » τ 2 : κ 2 . Then, if Γ $ norm σ 1 : κ » σ 2 : κ, we have Γ, Γ 1 rα Ð σ 1 s $ norm τ 1 rα Ð σ 1 s : κ 1 rα Ð σ 1 s » τ 2 rα Ð σ 2 s : κ 2 rα Ð σ 2 s.
Proof. By induction on equalities, similarly to substitution for usual equalities.

We prove that every equality can be turned into a normal equality. This requires some care around function kinds: we not only want to prove that the equality between the two type-level functions can be normalized, but also that for any pair of arguments with a normal equality between them, there is a normal equality between the application of the the left function to the left argument and the right function to the right argument. What we want is a logical relation: we aim to prove that if Γ $ τ 1 : κ 1 » τ 2 : κ 2 , then pτ 1 , τ 2 q P rrΓ $ κ 1 ss, and if pτ 1 , τ 2 q P rrΓ $ κss, then Γ $ norm τ 1 : κ » τ 2 : κ. The relation rrΓ $ κss is defined by induction on the kind-depth of Γ. Its definition is given on Figure 7.26. For the base kinds Typ, Sch and Met, we simply require that the equality derivation between them be normalizable. For arrow kinds, we require that the equality be normalizable, and that, for any pair of equal arguments (according to the relation), the applications of the (equal) types to equal arguments have a normal equality.

It is not immediate that this relation is well-defined: the substitutions in the arrow rules may grow the size of the kind. To make the definition precise, we define the kind-depth of a kind KindDepthpκq inductively as the depth of the kind expression, stopping at types and terms (Figure 7.25 Kind-depth ignores the types and terms present in a kind: it is thus invariant by substitution of type and term variables. This is enough to prove that the logical relation is well-defined.

Lemma 7.28 (Substitution preserves kind-depth). Consider a kind κ, type and term variables x and α, a non-expansive term u and a type τ . Then, KindDepthpκq " KindDepthpκrx Ð usq " KindDepthpκrα Ð τ sq.

KindDepthpTypq " KindDepthpMetq " KindDepthpSchq " 0 KindDepthpΠpα : κ 1 q κ 2 q " 1 `maxpKindDepthpκ 1 q, KindDepthpκ 2 qq KindDepthpΠpx : τ q κq " 1 `KindDepthpκq

, σ 2 q | Γ $ norm σ 1 : κ » σ 2 : κu rrΓ $ Πpx : τ q κss " $ & % pσ 1 , σ 2 q ˇˇˇˇˇΓ $ norm σ 1 : Πpx : τ q κ » σ 2 : Πpx : τ q κ ^@pu 1 , u 2 q, Γ $ u 1 : τ » u 2 : τ ùñ pσ 1 # u 1 , σ 2 # u 2 q P rrΓ $ κrx Ð u 1 sss , .
-

rrΓ $ Πpα : κ 1 q κss " $ & % pσ 1 , σ 2 q ˇˇˇˇˇΓ $ norm σ 1 : Πpα : κ 1 q κ » σ 2 : Πpα : κ 1 q κ ^@pτ 1 , τ 2 q P rrΓ $ κ 1 ss, pσ 1 # τ 1 , σ 2 # τ 2 q P rrΓ $ κrα Ð τ 1 sss , .
- This definition is invariant by substitution of equal things:

Lemma 7.29 (Substitution of terms and types).

• Consider Γ, x : τ $ κ wf. Suppose Γ $ u 1 : τ » u 2 : τ . Then, rrΓ $ κrx Ð u 1 sss " rrΓ $ κrx Ð u 2 sss.

• Consider Γ, α : κ $ κ 1 wf. Suppose Γ $ norm σ 1 : κ » σ 2 : κ. Then, rrΓ $ κ 1 rα Ð σ 1 sss " rrΓ $ κ 1 rα Ð σ 2 sss.

Proof. Immediate by induction on the definition of the relation, and using the same results on the normal equality derivations.

We need symmetry and transitivity for the relation:

Lemma 7.30 (Symmetry for logical normalizability). Suppose pτ 1 , τ 2 q P rrΓ $ κss. Then pτ 2 , τ 1 q P rrΓ $ κss.

Proof. By induction on kind-depth.

• For base kinds, we need to prove Γ $ norm τ 2 : κ » τ 1 : κ. By hypothesis, Γ $ norm τ 1 : κ » τ 2 : κ. By symmetry of normal equality, we have the result.

• For arrow kinds: we'll examine the case κ " Πpα : κ 1 q κ 2 . For the base normalized equality, proceed as for base kinds. Consider pσ 1 , σ 2 q P rrΓ $ κ 1 ss. We need to prove pτ 2 # σ 1 , τ 1 # σ 2 q P rrΓ $ κ 2 rα Ð σ 1 sss. We have pσ 2 , σ 1 q P rrΓ $ κ 1 ss because rrΓ $ κ 1 ss is symmetric by induction hypothesis. Thus, pτ 1 # σ 2 , τ 2 # σ 1 q P rrΓ $ κ 2 rα Ð σ 2 sss. By invariance by substitution of equal things (Lemma 7.29), rrΓ $ κ 2 rα Ð σ 2 sss " rrΓ $ κ 2 rα Ð σ 1 sss Moreover, by induction hypothesis, rrΓ $ κ 2 rα Ð σ 1 sss is symmetric (it has the same kind-depth as κ 2 which is lower than the kinddepth of κ). Thus, pτ 2 # σ 1 , τ 1 # σ 2 q P rrΓ $ κ 2 rα Ð σ 1 sss Lemma 7.31 (Logical normalizability is transitive). Suppose pτ 1 , τ 2 q P rrΓ $ κss and pτ 2 , τ 3 q P rrΓ $ κss, then pτ 1 , τ 3 q P rrΓ $ κss

Proof. By induction on kind-depth:

• For base kinds, we have Γ $ norm τ 1 : κ » τ 2 : κ and Γ $ norm τ 1 : κ » τ 2 : κ. By TEqN-Trans, Γ $ norm τ 1 : κ » τ 3 : κ.

• For arrow kinds: the base normalized equality is obtained as for base kinds. We'll examine the case κ " Πpα : κ 1 q κ 2 . Consider pσ 1 , σ 3 q P rrΓ $ κ 1 ss. We need to prove pτ 1 # σ 1 , τ 3 # σ 3 q P rrΓ $ κ 2 rα Ð σ 1 sss.

We have pσ 1 , σ 1 q P rrΓ $ κ 1 ss: from pσ 1 , σ 3 q P rrΓ $ κ 1 ss, by symmetry (Lemma 7.31, we have pσ 3 , σ 1 q P rrΓ $ κ 1 ss, and we conclude by transitivity (since κ 1 has lower kind-depth than κ). From pτ 1 , τ 2 q P rrΓ $ κss, we obtain pτ 1 # σ 1 , τ 2 # σ 1 q P rrΓ $ κ 2 rα Ð σ 1 sss. We also have pτ 2 # σ 1 , τ 3 # σ 3 q P rrΓ $ κ 2 rα Ð σ 1 sss. By transitivity of rrΓ $ κ 2 rα Ð σ 1 sss (induction hypothesis, since κ 2 rα Ð σ 1 s has lower kind-depth than κ), pτ 1 # σ 1 , τ 3 # σ 3 q P rrΓ $ κ 2 rα Ð σ 1 sss.

We know want to prove, by induction on equality derivations, that pairs of equal types are included in the relation. We'll need to strengthen our inductive hypothesis to allow some substitutions without changing the derivation we are doing the induction on. We need to introduce a notion of environments mapping one typing environment to another. Definition 7.8 (Environment mapping). We say that a pair of environments pγ 1 , γ 2 q map Γ to Γ 1 , noted Γ 1 $ pγ 1 , γ 2 q : Γ, if it has the same domain as Γ and:

• For all px : τ q P Γ, Γ 1 $ γ 1 pxq : γ 1 pτ q » γ 2 pxq : γ 2 pτ q.

• For all pα : κq P Γ, pγ 1 pαq, γ 2 pαqq P rrΓ 1 $ γ 1 pκqss.

• For all π P Γ, π P Γ 1 .

• For all puq˚p : τ P Γ, pγ 1 puqq˚p : γ 1 pτ q P Γ 1 ♦ Then a pair of identity environments, mapping variables to themselves, satisfies this definition. Then we can state a lemma that can be proved by induction on the derivations: Lemma 7.32 (Equalities are logically normalizable). Suppose Γ $ τ 1 : κ 1 » τ 2 : κ 2 . Moreover, suppose Γ 1 $ pγ 1 , γ 2 q : Γ. Then, pγ 1 pτ 1 q, γ 2 pτ 2 qq P rrΓ 1 $ γ 1 pκ 1 qss.

Proof. We must (simultaneously) prove a reflexivity result, although it's the same process because any well-formedness derivation for a type can be expanded into an equality derivation between this type and itself. We need a separate result for the induction to be structural on derivations, but the arguments are identical and we omit it. The result is the following: suppose Γ $ τ : κ, and suppose Γ 1 $ pγ 1 , γ 2 q : Γ. Then, pγ 1 pτ q, γ 2 pτ qq P rrΓ 1 $ γ 1 pκqss.

Let us consider the proof of the main result. By induction on the equality derivation:

• Suppose the last rule is an eML congruence or reduction rule, or TEq-Split.

Then, the conclusion of the rule has kind Typ or Sch and we can directly apply TEqN-eML.

• Suppose the last rule is TEq-Thunk. Then, the subderivation inside TEq-Thunk has kind Sch, and is immediately normal after applying the rule TEqN-eML.

• Suppose the last rule is TEq-Trans.

TEq-Trans

Γ $ τ 1 : κ 1 » τ 2 : κ 2 Γ $ τ 2 : κ 2 » τ 3 : κ 3 Γ $ τ 1 : κ 1 » τ 3 : κ 3
Consider the two sub-derivations Γ $ τ 1 : κ 1 » τ 2 : κ 2 and Γ $ τ 2 : κ 2 » τ 3 : κ 3 . By induction hypothesis, pγ 1 pτ 1 q, γ 1 pτ 2 qq P rrΓ $ γ 1 pκ 1 qss and pγ 1 pτ 2 q, γ 2 pτ 3 qq P rrΓ $ γ 1 pκ 2 qss. Then rrΓ $ γ 1 pκ 1 qss " rrΓ $ γ 1 pκ 2 qss. We conclude by Lemma 7.31.

• Suppose the last rule is TEq-Var: TEq-Var $ Γ α : Typ P Γ Γ $ α : Typ » α : Typ Then, by hypothesis on pγ 1 , γ 2 q, pγ 1 pαq, γ 2 pαqq P rrΓ 1 $ γ 1 pκ 1 qss.

• Suppose the last rule is an mML reduction (rules TEq-Red-Meta-*).

Then, the two ends of the equality normalize to the same well-formed type. We conclude by the reflexivity result.

• For conversion rules (TEq-SubSch,TEq-SubTyp), observe that Typ, Sch and Met have the same interpretation up to subkinding: we apply the corresponding normal rule for normal derivations.

• Suppose the last rule is a congruence for an mML type constructor (ie. one of the rules TEq-TyMetaArr, TEq-TermMetaArr, TEq-EqMetaArr, TEq-PtrMetaArr, TEq-Thunk). Take for example TEq-TyMetaArr:

TEq-TyMetaArr Γ $ κ 1 » κ 2 Γ, α : κ 1 $ τ 1 : Met » τ 2 : Met Γ $ Πpα : κ 1 q τ 1 : Met » Πpα : κ 2 q τ 2 : Met
Then we have Γ $ κ 1 » κ 2 and Γ, α : κ 1 $ τ 1 : Met » τ 2 : Met. We need to prove, that pγpΠpα : κ 1 q τ 1 q, γpΠpα : κ 2 q τ 2 qq P rrΓ 1 $ γpMetqss " rrΓ 1 $

• If Γ $ Πpα : κ 1 q σ 1 : Met » Πpα : κ 2 q σ 2 : Met, then Γ $ κ 1 » κ 2 Met and Γ, α : κ 1 $ σ 1 : Met » σ 2 : Met. • If Γ $ Πppu 1 » u 1 1 q : τ 1 q σ 1 : Met » Πppu 2 » u 1 2 q : τ 2 q σ 2 : Met, then Γ $ τ 1 : Sch » τ 2 : Sch, Γ $ u 1 : τ 1 » u 2 : τ 2 , Γ $ u 1 1 : τ 1 » u 1 2 : τ 2 , and Γ, pu 1 » u 2 q : τ 1 $ σ 1 : Met » σ 2 : Met. • If Γ $ Πppu 1 q˚p : τ 1 q σ 1 : Met » Πppu 2 q˚p : τ 2 q σ 2 : Met, then Γ $ u 1 : bool » u 2 : bool, Γ, pu 1 » Trueq : bool $ τ 1 : Sch » τ 2 : Sch, and Γ, pu 1 q˚p : τ 1 $ σ 1 : Met » σ 2 : Met Proof.
All cases are similar. Let us consider the first one: suppose we have Γ $ rτ 1 s : Met » rτ 2 s : Met. Let γ be the identity environment for Γ; we have Γ $ pγ, γq : Γ, thus by Lemma 7.32, we have p rτ 1 s , rτ 2 s q P rrΓ $ Metss. We have rτ s " rτ s. Then, by definition of rrΓ $ Metss, we have Γ $ norm r τ 1 s : Met » r τ 2 s : Met.

We will then show that such an equality implies Γ $ τ 1 : Sch » τ 2 : Sch. This is done by induction on the equality derivation, generalizing to have any kinds instead of Met in the equality, and anything on the right-hand side: suppose Γ $ norm rτ 1 s : κ 1 » σ 2 : κ 2 . Then, σ 2 " rτ 2 s for some τ 2 , and Γ $ τ 1 : Sch » τ 2 : Sch.

• If the last rule is a congruence rule, it must be TEqN-Thunk. Then, the result we need is an hypothesis of the rule.

• If the last rule is a subkinding rule, apply the induction hypothesis to the premise.

• The last rule cannot be TEqN-eML: this would imply Γ $ r τ 1 s : Sch which is impossible.

• If the last rule is TEqN-Trans, TEqN-Trans

Γ $ norm rτ 1 s : κ 1 » σ 2 : κ 2 Γ $ norm σ 2 : κ 2 » σ 3 : κ 3 Γ $ norm rτ 1 s : κ 1 » σ 3 : κ 3
apply the induction hypothesis to the first premise: we obtain σ 2 " rτ 2 s, with Γ $ τ 1 : Sch » τ 2 : Sch. Then, the induction hypothesis can also be applied to the second premise: we obtain σ 3 " rτ 3 s, with Γ $ τ 2 : Sch » τ 3 : Sch. Finally, by transitivity (TEq-Trans), we conclude that Γ $ τ 1 : Sch » τ 3 : Sch. This is sufficient to prove subject reduction for eML: Lemma 7.34 (Subject reduction, mML). Let Γ be an environment, a a term such that Γ $ π a : τ ñ ∆. Suppose a l Ý Ñ # b. Then there exists ∆ 1 such that Γ $ π b : τ rls ñ ∆ 1 and:

• If l " 0, we have Γ $ ∆ Ě ∆ 1 . • If l " q Þ Ñ u, we have ∆ 1 " ∆r˚q Ð us ´q Y S,
where S is a environment of labels with all labels prefixed by q.

Moreover, Γ, ∆ 1 $ arls : τ » b : τ .

Proof. Identical to the proof for eML, using the projection result.

mML elimination

The last result we need to prove about mML is that any mML term that can be typed in an environment without any meta construct normalizes by ÝÑ # to an eML term of the same type. It does not suffice to normalize the term, check that it does not contain any mML syntactic construct and conclude by subject reduction: we have to show the existence of an eML typing derivation of the term.

To distinguish mML derivations from eML derivations, we will write eML derivations with a subscript, for example Γ $ eM L u 1 : τ 1 » u 2 : τ 2 for typing derivations. In this section, we take _ to perform every possible metareduction in a term or type.

The proof is similar to the subject reduction proof: we construct a logical relation for terms and types stating that (under the right typing conditions) they reduce to terms that have an eML typing derivation. The logical relation is defined by mutual induction on the syntax of types and kinds.

The interpretation of types as binary relations is given in Figure 7.27. It is written rrΓ 1 $ pτ q γ:Γ ss, where Γ 1 is the eML environment in which the reduction is performed, τ the type we interpret and γ an environment mapping variables in a mML environment Γ to terms and types scoped in Γ 1 . γ is useful because, as we descend inside mML abstractions, we accumulate some mML-typed variables in the environment that we need to keep separated (as they must be handled by reduction). For eML types, rrΓ 1 $ pτ q γ:Γ ss is simply the set of pairs of nonexpansive terms of the correct type that can be proved to be equal in eML. For mML constructs, the interpretation is still a set of pairs of non-expansive terms, but since we need to evaluate them, we check that they can be properly applied. Finally, we interpret type-level abstractions and applications as settheoretic abstractions and applications.

We define in Figure 7.29, given a type τ of kind κ, the set ⟪Γ 1 $ pτ : κq γ:Γ ⟫ of acceptable interpretations of τ . This is useful because, in type abstractions, it breaks a circular dependency: we cannot abstract on a type and then compute the interpretation of this type, as the type we are given is not a subtype of the type abstraction. Instead, we ask for an acceptable interpretation only. To interpret transitivity, we require the binary relations R to have the zig-zag property, noted zigzagpRq:

for all a, b, c, d, if a R b R ´1 c R d, then a R d.
This is a variant of transitivity for heterogenous relations where the left and right-hand side are taken from different sets. For Typ and Sch, we only allow one possible interpretation. We check (Lemma 7.35) that this interpretation has the zig-zag property too.

Similarly, we define in Figure 7.28 an interpretation of kinds as sets of pairs of equal types, noted rrΓ 1 $ pκq γ:Γ ss. For the kinds Typ and Sch, we require that the types are equal in eML. For Met, we simply require that they be equal in mML, and functional kinds are interpreted as pairs of type-level functions that map valid pairs of terms or types to valid pairs of types. We also define the set of possible interpretations of kinds ⟪Γ 1 $ pκq γ:Γ ⟫ in Figure 7.30. As for sets of interpretations of types, we require all relations to be between types of the correct kind, and to have the zig-zag property.

Finally, we define in Figure 7.31 the set rrΓ 1 $ Γss of acceptable environments γ representing an mML typing environment Γ in the eML environment Γ 1 .

-By (e), we have p γ 1 pτ 1 q , γ 2 pτ 2 q q P rrΓ 1 $ pκq γ:Γ ss, i.e. Γ 1 $ eM L γ 1 pτ 1 q : κ » γ 2 pτ 2 q : κ.

-By(f), we have Γ 1 $ eM L γ 1 pτ 2 q : κ » γ 2 pτ 2 q : κ.

Thus by symmetry and transitivity, Γ $ eM L γ 1 pτ 1 q : κ » γ 1 pτ 2 q : κ, and we conclude by conversion.

• Consider a congruence for an mML type constructor: the interpretations of the subexpressions are equal.

• Similarly, congruences for type-level abstraction and reduction are treated simply by using the induction hypothesis to verify that the interpretations of subexpressions are equal.

• Consider a type-level reduction, for example:

TEq-Reduce-MetaApp Γ, x : τ $ σ : κ Γ $ u : τ Γ $ pλ # px : τ q. σq # u : κrx Ð us » σrx Ð us : κrx Ð us
The left-hand side is interpreted as pλpu 1 , u 2 q P rrΓ 1 $ pτ q .:γ ss rrΓ 1 $ pσq γ,xÐpu1,u2q:Γ,x:τ ssq p γ 1 puq , γ 2 puq q " rrΓ 1 $ pσq γ,xÐp γ1puq , γ2puq q:Γ,x:τ ss while the right-hand side is interpreted as rrΓ 1 $ pσrx Ð usq γ:Γ ss, and these two interpretations are equal by substitution.

We deduce the main theorem of this section:

Theorem 7.3 (mML elimination). Let Γ be an eML environment, τ an eML type. Then, if in mML Γ $ p a : τ ñ ∆, there exists ∆ 1 such that we have Γ $ p eM L a : τ ; ∆ 1 . Proof. Consider Γ 1 " Γ, and γ the environment such that:

• γpxq " px, xq • γpαq " pα, α, tpu 1 , u 2 q | Γ 1 $ eM L u 1 : α » u 2 : αuq • γpπq " π • γp˚pq " ˚p
We then have γ P rrΓ $ Γss and TermsEqualpΓ $ p a : τ » a : τ q By the previous lemma, TermsEqualpΓ $ p eML a : τ » γ : τ q. This implies that there exists ∆ 1 such that Γ $ p eM L a : τ ; ∆ 1 .

Chapter 8

A logical relation for reasoning on mML

We now define a logical relation for reasoning parametrically on mML. We want this relation to be compatible with term equality, so that we can reduce the left and right-hand side. The relation needs to handle non-strictly positive types and non-termination. We do this by defining a step-indexed logical relation [START_REF] Appel | An indexed model of recursive types for foundational proof-carrying code[END_REF]McAllester, 2001, Ahmed, 2006], indexed by the number of available execution step (here, we count only expansive steps).

A deterministic reduction

In this section we introduce another view of mML: instead of having two stages of reduction, first ÝÑ # then ÝÑ β , we can define a single reduction ÝÑ d that extends ÝÑ β and normalizes every term to a value. This interleaved view of mML and eML evaluation helps reasoning about mML: we simply have two different abstractions and applications that work independently, but at the same time. This will help set up the logical relation.

We never need to evaluate types for reduction to proceed to a value. Thus, our reduction will ignore the types appearing in terms (and the terms appearing in these types, etc.). The reduction is defined in Figure 8.1. The evaluation contexts E are the evaluation contexts of eML, extended with mML applications, and the redexes are the ML redexes plus the mML redexes, restricted to value arguments. For a term meta-application u 1 # u 2 , we require the term u 2 to be fully evaluated to a value v 2 , then u 1 to be fully evaluated to v 1 . On the other hand, for a result application u 1 # ˚u2 , u 2 may be typed in an absurd context, and its reduction might block. For this reason, we do not require (and, indeed, do not allow) reducing the right-hand side of # ˚. We instead substitute it as a non-expansive term. The values v are also defined in Figure 8.1.

As for the labeled ML reduction, this reduction is deterministic, and values are irreducible for it.

This reduction coincides with the eML reduction on eML terms: the contexts and redexes can only match eML terms and redexes.

We define an indexed version of this reduction as follows: the beta-reduction and the expansion of fixed points in ML take one step each, and all other reduc-155 tions take 0 steps. Then, ÝÑ i d is the reduction of cost i, i.e. the composition of i one-step reductions and an arbitrary number of zero-step reductions. Since ÝÑ d 0 is a subset of the union of ÝÑ ι and ÝÑ # , it terminates.

E ::" let x " rs in a | a p rs | rs p v | d τ pa, .. a, rs, v, .. vq | Λpα : Typq. rs | rs τ | match rs with pP Ñ a | .. P Ñ aq | u # rs | rs # v | rs # τ | rs # ppu » uq : τ q | rs # ˚u | prsq p v ::" x | d τ v | fix π x px : τ q : τ . a | Λpα : κq. v | λ # pα : κq. u | λ # px : τ q. u | λ # pu » uq : τ. u | λ # ppuq˚p : τ q. u | rπ. as pfix π x py : τ 1 1 q : τ 1 2 . aq p v ˚pÐreuseparπÐp,xÐfix π x py:τ 1 1 q:τ 1 2 . a,yÐτ 1 1 sq Ý ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ Ñ d arπ Ð p, x Ð fix π x py : τ 1 1 q : τ 1 2 . a, y Ð τ 1 1 s pΛpα : Typq. vq τ 0 Ý Ñ d vrα Ð τ s let x " v in a 0 Ý Ñ d arx Ð vs match d j τ 1 pv i q i with pd j τ px ji q i Ñ a j q j 0 Ý Ñ d a j rx ji Ð v i s i pλ # pα : κq. aq # τ 0 Ý Ñ d arα Ð τ s pλ # px : τ q. aq # v 0 Ý Ñ d arx Ð vs pλ # pu 1 » u 2 q : τ. aq # pu 1 1 » u 1 2 q : τ 1 0 Ý Ñ d a pλ # ppu 1 q˚p : τ q. aq # ˚u 0 Ý Ñ d ar˚p Ð us prπ. asq p ˚pÐreuseparπÐpsq Ý ÝÝÝÝÝÝÝÝÝÝÝ Ñ d arπ Ð ps Red-NoLabel a 0 Ý Ñ d b Eras 0 Ý Ñ d Erbs Red-Label a ˚pÐu Ý ÝÝÝ Ñ d b Eras ˚pÐu Ý ÝÝÝ Ñ d pEr˚p Ð usqrbs
We have the following lemma describing how the counting reduction interacts with term equality: Lemma 8.1 (Equal terms stay equal after i reductions). Suppose TermsEqualppτ j : κ j q j $ p a : τ a » b : τ b q, and suppose a ÝÑ i d a 1 . Then, there exists b 1 such that b ÝÑ i d b 1 and TermsEqualppτ j : κ j q j $ p a 1 : τ a » b 1 : τ b q.

Proof. By induction on the reduction: if the first reduction is a non-expansive reduction or a thunk reduction, it preserves term equality. If it is the reduction of a function application, by Lemma 6.26, there exists b 1 such that we can go from b to b 1 by some non-expansive reductions, then one expansive reduction, preserving equality.

Also, we have a progress result for ÝÑ 0 d :

Lemma 8.2 (ÝÑ 0 d reduces non-expansive terms). Let $ u : τ be a well-typed non-expansive term in the empty environment. Then there exists v such that u ÝÑ 0 d v

Proof. ÝÑ 0 d terminates. Consider the non-value term in reduction position in u (if there is no such term, u is already a value). It is either a mML application or a ML destructor that operates on a value. If it is an mML application, we can apply ÝÑ # on it (otherwise the term would be stuck for ÝÑ # ) and similarly for an ML destructor.

Interpretation of kinds

We want to define a typed, binary, step-indexed logical relation. We first define the shape of the interpretation of types depending on their kinds on Figure 8.2 by induction on the kinds. The interpretation is defined in a pair of environments γ 1 , γ 2 associating term, type and label variables appearing in κ to closed values and types, and label variables to label variables. For a kind κ, K j rκs γ1,γ2 is a set of triples of the form pσ 1 , pS k q kďj , σ 2 q, where σ 1 and σ 2 are the possible left and right-projections of a type of kind κ and pS k q kďj is a possible sequence of interpretations of the type up to rank j. The left and right projections have kind respectively γ 1 pκq and γ 2 pκq in the empty environment.

For types of terms (i.e. of kinds Typ, Sch and Met), the interpretation of a type will be a left and a right projection of a type and a relation between values of this type. This relation is step-indexed, i.e. it is defined as a sequence of refinements of the largest relation between these types. We also require it to be stable by equality: if two values are equal, they are related to the same values.

We interpret the types of higher-order kinds as sequences of functions. For an abstraction on terms Πpx : τ qκ, the k-th function in the sequence takes a pair of values of the left and right-hand side projection of the type of the argument γ 1 pτ q and γ 2 pτ q and returns the interpretation of the application at rank k. We require the interpretation to be stable when replacing the arguments by equal values. The interpretation of an abstractions on type Πpα : κq κ 1 is similar: the k-th function in the sequence takes a pair of types of kinds γ 1 pκq and γ 2 pκq and

The logical relation

We define a typed binary step-indexed logical relation on mML equipped with ÝÑ d . We define an interpretation of types of terms as a relation on values V k rτ s γ stable by equality.

The environment γ in this interpretation maps term variables to pairs of terms related at the given type, labels to pairs of expressions representing a value for this label if the expression is true, nothing otherwise, label variables to labels, and type variables α to a triple pσ 1 , pS k q kďj , σ 2 q where σ 1 and σ 2 are the left and right-projections of the type and the pS j q kďj are the interpretations of the a relation between σ 1 and σ 2 at rank k. We note γ 1 (resp. γ 2 ) the left (resp. right) projection of γ, i.e. the environment mapping variables to their left (resp. right) projection in γ. Thus, γ 1 , γ 2 is a pair of environments we could use with the interpretation of kinds. If γpαq is pσ 1 , pS k q kďj , σ 2 q, we also write γ R pαq for the sequence of interpretations pS k q kďj . The constraints of environments are given in Figure 8.3: an environment γ is in G j rΓs if it respects these conditions at step-index j. For type variables α : κ, we require the triple pσ 1 , pS k q kďj , σ 2 q to be in the interpretation of the corresponding kind κ. For term variables x : τ , we require the pair of left and right projections v 1 , v 2 to be related by the relation at type τ . For equalities, we check that the left and right projections of the terms respect the equality in the empty environment. For results puq˚p : τ , either we require the condition u to reduce to false in the left projection γ 1 , or we require that γ maps ˚p to pairs of related non-expansive terms.

The projection T rσs γ of a relational type σ in γ maps σ to a pair of types pσ 1 , σ 2 q. We define it here as pγ 1 pσq, γ 2 pσqq, but we will extend relational types to embed ornaments as a first-class concept in Chapter 10. It does not depend on the index.

The interpretation V j rσs γ of σ in γ at step-index j, is given in Figure 8.4. Types of terms σ are interpreted as sets of values of types σ 1 , σ 2 if T rσs γ " pσ 1 , σ 2 q (the typing condition is left implicit to make the definitions lighter), while type-level functions are interpreted as functions transforming interpretations into interpretations. Type-level abstraction maps to abstraction and type-level application to application. When a type variable appears, its interpretations is looked up in the context γ. Related values at function types map related arguments to related results. When the body of the function is nonexpansive (in mML functions and ML type abstractions), we can simply reduce it to a value in zero steps by ÝÑ 0 d . For thunks and ML functions, we need to check that terms are equal. We delegate this to an interpretation of terms E k rγs σ built on the interpretation of types. We test this at an index k ă j: this is because we performed one expensive step of reduction already by substituting the argument into the body. Finally, for type-level pattern matching, we reduce the term matched upon in zero steps, look at the head-constructor to select the branch, and use the interpretation of this branch with the variables representing the constructor arguments added to the environment.

The interpretation of types as set of terms E j rγs σ is defined in Figure 8.4. Two terms pa 1 , a 2 q are in relation at rank j if they are well-typed and when we can reduce a 2 in k ď j steps to a value, a 1 also reduces in an unspecified number of steps to a value and the values are related at index j ´k: we use some of the step-index to "pay" for the reduction. This definition requires that G j rHs " tHu G j rΓ, x : τ s " tγ, x Ð pv 1 , v 2 q | γ P G j rΓs ^pv 1 , v 2 q P V j rγs τ u G j rΓ, α : κs " tγ, α Ð S | γ P G j rΓs ^S P K j rκs γ1,γ2 u G j rΓ, pu a » u b q : τ s " tγ P G k rΓs | p$ γ i pu a q : γ i pτ q » γ i pu n q : γ i pτ qq iPt1,2u u G j rΓ, puq˚p :

τ s " tγ | γ P G j rΓs ^γ1 puq ÝÑ 0 d Falseu Y tγ, ˚p Ð pu 1 1 , u 1 2 q | γ P G j rΓs ^γ1 puq ÝÑ 0 d True ^pu 1 1 , u 1 2 q P E j rτ s γ u G j rΓ, πs " tγ, π Ð p | γ P G j rΓs ^p K γu Figure 8
.3: Interpretation of environments a 1 terminates whenever a 2 terminates, i.e. that a 1 terminates more often. In particular, every program of the correct type is related to the never-terminating program. This is not a problem: if we need to consider termination, we can use the reverse relation, where the left and right side are exchanged. This is what we will do on ornaments: we will first show that, for arbitrary patches, the ornamented program is equivalent but terminates less, and then, assuming the patches terminate, we show that the base program and the lifted program are linked by both the normal and the reverse relation.

We need to ensure that this is well-defined. The interpretation is first defined by induction on the index k. For a given k, the interpretation is defined by induction on the type τ , except in the case of datatypes, where we define the relation by induction on the term: the terms inside data constructors are smaller, and their types are either data constructors or function types, and functions types strictly decrease the index. This justification is sufficient to handle ML datatypes, but it would not work if we had (ML) quantified types or mML constructs inside datatypes.

We now prove that, in a well-formed context, the interpretation of a wellkinded type is included in the set of valid interpretations at its kind.

Lemma 8.5 (Type interpretation (as values) is well-defined). Suppose Γ $ σ : κ, and γ P G j rΓs. If pσ 1 , σ 2 q " T rσs γ , then pσ 1 , pV k rσs γ q kďj , σ 2 q P K j rκs γ1,γ2 .

Simultaneously, we prove that term interpretation is monotonic and stable by equality (this is sufficient because the types of terms necessarily have kinds Typ, Sch or Met): Lemma 8.6 (Type interpretation (as terms) is well-defined). Suppose κ P tTyp, Sch, Metu, Γ $ σ : κ and γ P G j rΓs. Suppose pσ 1 , σ 2 q " T rσs γ . Suppose pa 1 , a 2 q P E j rσs γ . Consider a 1 1 , a 1 2 such that TermsEqualpH $ p a 1 : σ 1 » a 1 1 : σ 1 q and TermsEqualpH $ p a 2 : σ 2 » a 1 2 : σ 2 q. Then, for all k ď j, pa 1 1 , a 1 2 q P E k rσs γ

Proof. By induction on the well-kindedness judgment.

For the lemma on interpretation as values, the typing constraints are always (implicitly) implied by the definition of V j rσs γ . We need to prove monotonicity and stability by equality. Consider the last rule:

• If it is K-Var: by hypothesis on γ, γpαq " pσ 1 , pS k q kďj , σ 2 q P K j rκs γ1,γ2 .

• For K-SubTyp and K-SubSch: apply the inductive hypothesis, and the same rule on the kinding constraints.

• For K-Datatype: monotonicity derives from the monotonicity of the interpretations we use for the subvalues. For stability by equality: suppose pv 1 , v 2 q P V j rζ pτ i q i s γ . Then, we have v 1 " dpτ 1,i q i pw 1,k q k and v 2 " dpτ 1,i q i pw 2,k q k . Suppose $ v 1 : ζ pτ 1,i q i » v 1 1 : ζ pτ 1,i q i . and $ v 2 : ζ pτ 2,i q i » v 1 2 : ζ pτ 2,i q i . By mML elimination (Theorem 7.3), we have

$ eM L v 1 : ζ pτ 1,i q i » v 1 1 : ζ pτ 1,i q i .
We have v 1 " dp τ 1,i q i p w 1,k q k , and v 1 1 is a value. By the logical relation for eML (Lemma 6.22),

v 2 1 " v 1 1 must be of the form v 2 1 " dpτ 2 1,i q i pw 2 1,k q k , with $ eM L w 1,k : σ 1,k » w 2 1,k : σ 1,k for all k. Since v 1
1 is a value, it starts with a constructor, so we must have v 1

1 " dpτ 1 1,i q i pw 1 1,k q k , with w 2 1,k " w 1 1,k . Normalization preserves equality. Thus, for all k, $ w 1 : σ 1,k » w 1 1 : σ 1,k , and similarly for v 2 , and we use the stability by equality of their interpretations.

• The other rules for function types follow identical patterns.

• For K-Match, the conditions for the interpretation not to be empty are stronger if the index j is larger, and ensure that γ stays valid. We then use monotonicity and stability by equality of the interpretation of the branch.

• For higher-order constructs: consider K-TyAbs (K-TermAbs is similar).

When the function is applied to a valid interpretation, it gives back a valid interpretation by induction hypothesis. Moreover, it is stable by type equality: equal types as inputs translate to equal environments.

• Consider K-TyApp (K-TermApp is similar): by definition of the interpretation of function kinds, the result of the application is valid.

For the lemma on type interpretation as terms, monotonicity comes from monotonicity of the interpretation of values, and stability by equality is implied by Lemma 8.1 and stability of the interpretation of values.

Lemma 8.7 (Substitution commutes with interpretation). For all environments γ and indices j, we have:

V j rτ rα Ð τ 1 ss γ " V j rτ s γrαÐpγ1pτ 1 q,pV k rτ 1 sγ q kďj ,γ2pτ 1 qqs V j rτ rx Ð uss γ " V j rτ s γrxÐpγ1puq,γ2puqqs

Proof. By induction on the structure of the interpretation.

We want to prove that terms are related to themselves by the relation. For the induction to work properly, we need a finer version of E j rτ s γ that also checks emitted labels: while the current version works to interpret the expansive bodies of functions and thunks, it ignores the emitted labels because they are inaccessible to the surrounding terms. We thus define a set E j rτ ñ ∆s γ that takes emitted labels into account: we require

• the emitted labels one each side to be present in ∆ or to be suffixes of labels presents in ∆;

• the label in ∆ to be emitted on both sides whenever their condition in True, and not emitted otherwise;

• for emitted labels in ∆, the emitted values on both sides to be related at the type given in ∆.

Definition 8.1 (Equivalence, including results). Consider an index j, a type σ such that Γ $ σ : κ with κ P tTyp, Sch, Metu, and γ P G j rΓs, and let pσ 1 , σ 2 q " T rσs γ .

Consider pa 1 , a 2 q such that Γ $ p a 1 : σ 1 ñ ∆ and Γ $ p a 2 : σ 2 ñ ∆. We say that pa 1 , a 2 q P E j rτ ñ ∆s γ if the reduction of a 2 by ÝÑ d does not terminate, or:

• There exists i such that a 2 p˚p 2,k Ðu 2,k q k ÝÝÝÝÝÝÝÝÝÑ i d v 2 .
• We have a 1

p˚p 1,k Ðu 1,k q k ÝÝÝÝÝÝÝÝÝÑ d v 1 .
• The labels in pp 1,k q k and pp 2,k q k are either in ∆ or suffixes of labels in ∆.

• The labels in pp 1,k q k present in ∆ are also the labels in pp 2,k q k . Define pp 1 l q the subsequence formed from the labels in ∆, associated on the left with the pu 1 1, q and on the right with the pu 1 2, q .

• We define γ 1 " γ, p˚p 1 Ð pu 1 1, , u 1 2, qq . Then, we must have γ 1 P G j´i rΓ, ∆s. This implies that every label is present if its condition evaluates to true, and that the non-expansive terms associated to labels are related at the type given in ∆.

• Finally, we must have pv 1 , v 2 q P V j´i rσs γ 1

♦

We simultaneously need to prove that equal terms have equal interpretations in equivalent environments, as defined here: Lemma 8.8 (Interpretation is compatible with equality). Suppose Γ $ τ : κ » τ 1 : κ 1 and that γ and γ 1 are equivalent, i.e. $ γ 1 » γ 1 1 : Γ and $ γ 2 » γ 1 2 : Γ, and that for all α : κ P Γ, γ R pαq " γ 1 R pαq. Then, for all j, if γ 1 P G j rΓs, then V j rτ s γ " V j rτ 1 s γ 1

We thus prove the following two lemmas by mutual induction: Theorem 8.1 (Terms are related to themselves). Suppose Γ $ p a : τ ñ ∆.

Consider k and γ P G k rΓs. Then, pγ 1 paq, γ 2 paqq P E k rτ ñ ∆s γ .

Proof. By induction on j then on the typing derivation.

For equality:

By induction, we have pγ 1 puq, γ 2 puqq P E j rζ pτ k q k s γ . γ 2 puq is non-expansive and well-typed in the empty environment, thus it reduces in 0 steps to some value v 2 . Then, γ 1 puq ÝÑ 0 d v 1 for some v 1 , and pv 1 , v 2 q P E j rζ pτ k q k s γ . γ 2 puq: there exists a constructor $ d i : @pα k : Typq k pτ i q i Ñ ζ pα k q k such that v 1 " d i pτ 1,k q k pw 1,i q i , v 2 " d i pτ 2,k q k pw 2,i q i , and for all i, pw 1,i , w 2,i q P V j rσ i s γ where σ i is the type of the i-th parameter.

We have H $ γ i puq : ζ γppτ k q k q » γ 1 i puq : ζ γ 1 ppτ k q k q for i P t1, 2u. Thus (applying the same reasoning as in the previous lemma), γ 1 1 puq reduces to a term d 1 pτ 1 1,k q k pw 1 1,i q i and similarly for γ 1 2 puq, with pw 1,i , w 2i q P V j rσ i s γ 1 because V j rσ i s γ is stable by equality and equal to V j rσ i s γ 1 .

Then consider the branch for d i , with environments γ 2 " γ, px i Ð pw 1,i , w 2i qq i and γ 3 " γ 1 , px i Ð pv 1 1,i , w 1 2,i qq i : these environments are valid and compatible and satisfy the newly introduced equality pd i pτ k q k px ij q j » uq : ζ pτ k q k , so we apply the induction hypothesis in that branch.

• The sub-kinding rules do not change the interpretations.

• If the last rule is TEq-Var, the interpretations are the same.

• If the last rule is congruence for an ML or mML type constructor (i.e.

one of the rules TEq-Datatype, TEq-Arr, etc.), the subtypes and subkinds appearing are equal so their interpretations are equal by induction hypothesis, and the interpretation only depends on the interpretations of the subtypes.

• The type-level abstractions and applications respect equality: for congruence, abstractions with equal bodies have equal interpretations, as do applications with equal function and argument. For reduction, this is implied by substitution inside the interpretation.

• For TEq-Match: as for TEq-Split, equal terms will reduce to terms starting with the same constructor and equal parameters, so the new environments stay equal.

• For TEq-ReduceMatch: like the previous case, then the interpretation of the expanded and reduced term are equal by substitution.

For typing, consider the last rule. We will examine a few representative cases:

• If it is Coerce: coercion preserves the interpretations (by induction hypothesis).

• If it is Var: from γ P G k rΓs, we get pγ 1 pxq, γ 2 pxqq P V k rτ s γ .

• If it is Reuse:

Reuse ppuq˚q : τ P Γ ^Γ $ u : bool » True : boolq _pq K Γ ^Γ $ False : bool » True : boolq Γ $ p ˚q : τ ñ H
We apply the induction hypothesis on u: we have pγ 1 puq, γ 2 puqq P E j rbool ñ Hs γ . Since γ 2 puq is well-typed in the environment, it reduces in 0 steps to a value. This value must be True, because the other case implies we have $ γ 1 pTrueq : bool » γ 1 pFalseq : bool, which is impossible. Thus, by hypothesis on γ, γp˚pq " pu 1 , u 2 q P E j rbools γ . Since they are non-expansive, their reductions do not emit labels, and we have pu 1 , u 2 q P E j rbool ñ Hs γ .

• Consider the Fix rule:

Fix Γ $ τ : Typ Γ $ σ : Typ Γ, π, x : τ Ñ σ, y : τ $ q a : σ ñ ∆ Γ $ p fix π x py : τ q : σ . a : τ Ñ σ ñ H
Consider γ P G j rΓs. We want to prove pfix π xpy : γ 1 pτ qq : γ 1 pσq .γ 1 paq, fix π xpy : γ 2 pτ qq : γ 2 pσq . γ 2 paqq P V j rτ Ñ σs γ .

Consider k ă j, and pv 1 , v 2 q P V k rτ s γ . We need to show: pγ 1 paqrx Ð fix π x py : γ 1 pτ qq : γ 1 pσq . γ 1 paq, y Ð v 1 , π Ð p 1 s, γ 2 paqrx Ð fix π x py : γ 2 pτ qq : γ 2 pσq . γ 2 paq, y Ð v 2 , π Ð p 2 sq P V k rσs γ Note that by weakening, γ P G k rΓs. Moreover, by induction hypothesis at rank k ă j, pfix π x py : γ 1 pτ qq : γ 1 pσq . γ 1 paq, fix π x py : γ 2 pτ qq : γ 2 pσq . γ 2 paqq P V k rτ Ñ σs γ . Consider γ 1 " γrx Ð pfix π x py : γ 1 pτ qq : γ 1 pσq . γ 1 paq, fix π x py : γ 2 pτ qq : γ 2 pσq . γ 2 paqq, y Ð pv 1 , v 2 q, , π Ð pp 1 , p 2 qs. Then, γ 1 P G k rΓ, x : τ Ñ σ, y : τ s. Thus, by induction hypothesis on a, pγ 1 1 paq, γ 1 2 paqq " pγ 1 paqrx Ð fix π x py : γ 1 pτ qq :

γ 1 pσq . γ 1 paq, y Ð v 1 , π Ð p 1 s , γ 2 paqrx Ð fix π x py : γ 2 pτ qq : γ 2 pσq . γ 2 paq, y Ð v 2 , π Ð p 2 sq P E k rσ ñ ∆s γ 1 Ď E k rσs γ 1 " E k rσs γ .
• Consider the App rule:

App p ď q q K Γ, ∆ a , ∆ b Γ $ p a : τ Ñ σ ñ ∆ a Γ, ∆ a $ p b : τ ñ ∆ b Γ $ p a q b : σ ñ ∆ a , ∆ b , pTrueq˚q : σ Let γ P G j rΓs. Suppose γ 2 paq γ 2 pbq ÝÑ k d v 2 . Then, there must exist k a ă k such that: γ 2 paq la,2 Ý Ý Ñ ka d v a,2
where l a,2 is a sequence of labels. By induction hypothesis on a, we have γ 1 paq la,1

Ý Ý Ñ d v a,1 .
The labels in l a,1 and l a,2 are either in ∆ a or strict suffixes of labels in ∆ a . By the typing conditions, only the labels in ∆ a can appear in b: the other labels are neither in ∆ a not orthogonal to it. Consider γ a P G k´ka rΓ, ∆ a s the environment obtained by adding these labels to

γ. Then, γ 2 paq γ 2 pbq la,2 Ý Ý Ñ k d v a,2 γ 2 pbqrl a,2 s " v a,2 γ a2 pbq, and similarly γ 1 paq γ 1 pbq la,1 Ý Ý Ñ d v a,1 γ a1 pbq.
There also exists k b ă k ´ka such that:

γ a2 pbq l b,2 Ý Ý Ñ k b d v b,2 .
Similarly, by induction hypothesis, we have γ 1 paq l b,1 Ý Ý Ñ d v b,1 , and there exists γ b P G k´ka´k b rΓ, ∆ a , ∆ b s.

We have: pv a,1 , v a,2 q P V k´ka´k b rΓs γ b : there exists a 1 , a 2 such that v a,1 " fix π x px : τ 1 q : σ 1 . a 1 and v a,2 " fix π x px : τ 2 q : σ 2 . a 2 . Then, we have

v a,2 v b,2 ˚pÐreusepa2qrπÐp,xÐfix π x px:τ2q:σ2 . a2,yÐv b,2 s Ý ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ Ñ 1 d a 1 rπ Ð p, x Ð, y Ð v b,2 s
and similarly for v a,1 v b,1 . These two terms are related by E k´ka´k b ´1rσs γ 1 , and all labels they emit are prefixed by p. Then, when they reduce to values v 1 and v 2 in k c ď k ´ka ´kb ´1 steps, these values are in V k´ka´k b ´1´kc rσs γ 1 . Then, their non-expansive versions are related too. Finally,

γ 1 " γ b , ˚p Ð preusepa 1 qrπ Ð p, x Ð, y Ð v b,1 s, reusepa 2 qrπ Ð p, x Ð, y Ð v b,2 sq P G k´ka´k b ´kc´1 rΓ, ∆ a , ∆ b , pTrueq˚p : σs Chapter 9
From eML to ML

In this chapter, we'll prove that any eML term well-typed in an ML environment can be transformed into an equivalent ML term, such that the original term and the final terms are equal for the eML equality.

There are three features of eML we need to simplify. First, eML has pattern matching on types, and such types cannot exist in ML. We remove these types by moving the pattern matching to the term level: for example, the term We also need to get rid of reused results. This is done by lifting the evaluation of the function application producing this result into a separate let binding so we can give it a name. For example, the term match f p x with True Ñ ˚p | False Ñ True can be rewritten as let y " f p x in match y with True Ñ y | False Ñ True. Some cases are more complex: consider

let x " match y with True Ñ True | False Ñ f 1 False in match y with True Ñ x | False Ñ ˚1
There, the result is only present conditional on y. We again solve this by matching on y first, and having two branches:

match y with True Ñ let x " True in x False Ñ let z " f 1 False in let x " z in z
Finally, we have conversions in typing derivations: if a type is equal to another for eML, all values of this type are values of the other type. These type equalities can be proved using value equalities deduced from let bindings and pattern matching. We can eliminate the equalities from the context: we make sure that pattern matching is always on a variable. Then, equalities of the form px » dpτ i q i px j q j q : τ can be eliminated from the environment by replacing all instances of x by dpτ i q i px j q j . Then, all equalities are provable in an environment without equalities. We prove that in this case an equality between ML types is either trivial (the two types are syntactically equal), or there are variables of some un-inhabited types in the contexts.

For technical reasons, we restrict ourselves to environments where all polymorphic definition are definitions of functions. This guarantees that pattern matching only occurs on monomorphic values, which allows us to substitute the variables that are matched on by their values in the branches.

Expanded terms

The simplification we present here is a maximal version of the transformations described above: pattern matchings and bindings are extruded even if they actually would not need to be. In practice, the implementation performs the maximal simplification then tries to move let bindings and pattern matchings back to their original position.

Our goal is to end up with a term where there is no type-level pattern matching, all function applications are given a name, and all pattern matching is extruded such that we never match on the result of a match of a let. We might match on a variable or a constructor (the latter case would reduce).

Thus we define in Figure 9.1 the syntax of expanded terms e. An expanded term is formed by a series of bindings of the results of function applications, pattern matchings, and finally a simple term. The function and argument in application, the things we are matching on, and the terms at the end are required to be simple terms s, which are a subset of non-expansive terms: a simple term may be a variable applied to some type arguments, a reused result, a type abstraction whose body is simple, a function definition whose body is expanded or a constructor. Finally all types must be ML types, i.e. types that do not feature type-level pattern matching, We note these types ν.

After terms are expanded, we will need to perform a second pass on them to actually eliminate coercions.

Simplification

The simplification is then described as a small-step reduction on terms. The reduction context, defined in Figure 9.2, is the composition of a binding context

F ::" rs | let x " F in a | Λpα : Typq. F | F τ | s F t | fix p x px : τ q : F t . a | fix p x px : F t q : ν . a | s p F | F p a | d pν, F t , τ q a | d ν ps, F, aq | match F with pP Ñ a | .. P Ñ aq F t ::" rs | @pα : Typq F t | F t Ñ τ | ν Ñ F t | ζ pν, F t , τ q | match F with pP Ñ τ | .. P Ñ τ q B ::" rs | let x " s p s in B | match x with P Ñ B | P Ñ a | F rfix p x px : νq : ν . Bs Figure 9.2: Binding contexts, expansion contexts BrF rlet x " s in ass BrF rarx Ð ssss F ‰ let _ " rs in _ BrF rs 1 p s 2 ss Brlet x " s 1 p s 2 in F rxss F ‰ rs
BrF rmatch s with pd i pν j q j px ik q k Ñ a i q i ss Brmatch s with pd i pν j q j px ik q k Ñ relabelpF ra i sqq i s BrF rmatch x with pd i pν j q j px ik q k Ñ σ i q i ss Brmatch x with pd i pν j q j px ik q k Ñ relabelpF rσ i sqq i s Figure 9.3: Simplification rules B that binds variables, and is composed of bindings of results of applications and pattern matching, and an expansion context F that does not bind variables and is similar to the evaluation contexts E of the ML reduction, with values replaced by simple terms s. The expansion contexts F can also have their hole in the type part of the terms. Contexts that create a type are written F t .

The simplification rules are given in Figure 9.3. For a let binding let x " a in b, once a has been simplified to a simple value s, we substitute it inside the term (as it is non-expansive). When we encounter a function application, we lift it at the end of the binding context. We ask for the expansion context to not be just a let binding to avoid endlessly lifting the same application. When we encounter a pattern matching on a simple term, the pattern matching is similarly added to the end of the binding environment B. This duplicates the term that enclosed the pattern matching. To keep the labeling consistent, we relabel all labels produced in F with distinct labels in each branch. This is done by a function relabelpaq whose definition is given next. This rule can be applied both for type-level and term-level pattern matching. Definition 9.1 (Relabeling). Consider a term a introducing labels pp i q i (not counting the labels under abstractions, similarly to the decomposition atomspaq given in Figure 6.10). Then, consider a substitution σ from labels in pp i q i to fresh labels. We write σpaq for the term obtained by replacing all pp i q i and their uses by the corresponding labels in σ. Then, we note relabelpaq any such relabeled term. ♦ Lemma 9.1 (Relabeling preserves typing). Consider a such that Γ $ p a : τ ñ ∆. Suppose b " relabelpaq with label substitution σ. Then, Γ $ p b : σpτ q ñ σp∆q.

Proof. By induction on the typing derivation of the term.

We first prove that we can ignore the binding environment when proving equalities. This is true because the binding environment is always before the hole for the order of evaluation, and thus of propagation of results.

Lemma 9.2 (Equality in a binding context). Consider a binding context B and a term a, with Γ $ p Bras : σ ñ ∆. Suppose the typing derivation uses a typing Γ, Γ 1 $ p 1 a : τ ñ ∆ 1 of a, and moreover suppose TermsEqualpΓ, Γ 1 $ p 1 a : τ » a 1 : τ q. Then, TermsEqualpΓ $ p Bras : σ » Bra 1 s : σq.

Proof. By induction on B:

• Suppose B " F rfix π x py : τ 1 q : τ 2 . B 1 ras. We have Γ, π, x : τ 1 Ñ τ 2 , y :

τ 1 $ π B 1 ras : τ 2 ñ ∆ 1
. By induction hypothesis, we have TermsEqualpΓ, π, x :

τ 1 Ñ τ 2 , y : τ 1 $ π B 1 ras : τ 2 » B 1 ra 1 s : τ 2 q.
Thus, by congruence for function definition, TermsEqualpΓ $ p fix π x py : τ 1 q : τ 2 . B 1 ras :

τ 1 Ñ τ 2 » fix π x py : τ 1 q : τ 2 . B 1 ra 1 s : τ 1 Ñ τ 2 q
We conclude by congruence in F : we obtain a non-expansive equality that implies the term equality.

• Suppose B " let x " s 1 q s 2 in B 1 ras. We have Γ, pTrueq˚q : τ x , x : τ x , px » ˚qq : τ x $ p B 1 ras : σ ñ ∆ 2 . By induction hypothesis, we have TermsEqualpΓ, pTrueq˚q : τ x , x : τ x , px » ˚qq : τ x $ p B 1 ras : σ » B 1 ra 1 s : σq. This means the decompositions ( §6.2.5) of B 1 ras and B 1 ra 1 s match. Then the decompositions of Bras and Bra 1 s match (since they are the same with the indices shifted by one).

• The same reasoning is used when the binding context is a pattern matching.

We prove that simplification preserves term equality:

Lemma 9.3 (Expansion preserves term equality). Consider a well-typed term a with Γ $ p a : τ ñ ∆ and suppose a a 1 . Then, TermsEqualpΓ $ p a : τ » a 1 : τ q.

This implies Γ $ p a 1 : τ ñ ∆ 1 for some ∆ 1 , i.e. that expansion preserves types (but not results).

Proof. The simplification of let bindings is a non-expansive reduction. It preserves term equality by Lemma 6.25.

By Lemma 9.2, we only have to consider reductions with an empty binding context B.

We have three rules to consider. Let us start with lifting of a labeled application into a let binding:

F rs 1 p s 2 s let x " s 1 p s 2 in F rxs
Consider the decomposition of F rs 1 p s 2 s: the first atom in the decomposition is ˚p Ð s 1 s 2 with condition True (simple terms are non-expansive so they are equal to their reusable version). The subsequent atoms are some p˚p i Ð u i u 1 i q i with conditions u c,i . The reusable version of the term is u " reusepF r˚psq.

Then, the decomposition of let x " s 1 p s 2 in F rxs has first atom ˚p Ð s 1 s 2 with condition True, the subsequent atoms are p˚p Ð pu i u 1 i qrx Ð ˚psq i , with conditions u c,i rx Ð ˚ps. The reusable version of the term is let x " p in reusepF rxsq.

Then, all atoms of both terms have equal expressions and conditions: the first atom is the same; for subsequent atoms, we have pu i u 1 i qrx Ð ˚ps " u i u 1 i , because x does not occur in u i , and the same for the condition u c,i .

Moreover, the reusable versions of the tests are equal by reduction. Then, the terms are equal.

Consider now the lifting of a term-level pattern matching. We will only look at the lifting of terms, the lifting of types is similar. We can consider only the case B " rs as well. The rule to consider is then: F rmatch s with pd i pν j q j px ik q k Ñ a i q i s match s with pd i pν j q j px ik q k Ñ relabelpF ra i sqq i

We only need to show that F rmatch s with pd i pν j q j px ik q k Ñ a i q i s is equal to match s with pd i pν j q j px ik q k Ñ relabelpF rmatch x with pd i pν j q j px ik q k Ñ a i q i sqq i : the latter term is equal to match s with pd i pν j q j px ik q k Ñ relabelpF rmatch d i pν j q j px ik q k with pd i pν j q j px ik q k Ñ a i q i sqq i by substitution using the equalities in each branch of the outer match, and this term reduces (preserving equality) to the term on the right-hand side of the reduction.

We suppose the relabeling transforms labels pp j q j into labels pp ij q j in the branch of the constructor i. Consider the decomposition of the left-hand side: it is p˚p j Ð u j q j , with conditions u c,j and types τ j . Consider the decomposition of the right-hand side. It is p˚p ij Ð match s with d i pν j q j px ik q k Ñ u j match s with d i pν j q j px ik q k Ñ u 1 j q ij , with conditions match s with d i pν j q j px ik q k Ñ u c,j | pd pν j q j px k q k Ñ Falseq ‰i and types match s with d i pν j q j px ik q k Ñ τ j .

We want to show that the indexings of the atoms of these two terms match: consider an index m. We want to prove: Γ $ Index m pu c,j Ñ Apppu j , u 1 j qq j : Index m pu c,j Ñ app pτ j , τ 1 j qq j » Index m ppmatch x with d i pν j q j px ik q k Ñ u c,j | _ Ñ Falseq Ñ Apppmatch s with d i pν j q j px ik q k Ñ u j , match s with d i pν j q j px ik q k Ñ u 1 j qq j : Index m ppmatch s with d i pν j q j px ik q k Ñ u c,j | _ Ñ Falseq Ñ app pτ j , τ 1 j qq j . Let us start by splitting on s: we need to prove this equality in Γ, px ik : τ ik q ik , ps » d i pν j q j px ik q k q : ζ pν j q j for each i. We apply this substitution everywhere and reduce: the items on the right-hand side become:

• For " i, the conditions are u c,j , the terms are Apppu j , u 1 j q and the types are app pτ j , τ 1 j q

• For ‰ i, the conditions are False.

Then, the conditions for p j on the right-hand side are False for ‰ i. We can reduce the corresponding matches in Index m p. . .q: this yield exactly an Index m p. . .q where these options have been removed. We thus obtain the equality.

We also have to prove that the reusable versions of the terms are equal. Again, we first split on x and substitute and reduce on the right-hand side:

we have to prove Γ, ∆, ∆ 1 , ppIndex m pu c,j Ñ p j q j » Index m pu c,j Ñ p ij q j q : Index pu c,j Ñ τ j q j q m , px ik : τ ik q k $ F ra i s : τ » F ra i sr˚p j Ð ˚pij s j : τ . This is true as long as for all j Γ, ∆, ∆ 1 , ppIndex m pu c,j Ñ p j q j » Index m pu c,j Ñ p ij q j q : Index pu c,j Ñ τ j q j q m , pu c,j » Trueq : bool $ ˚pij : τ 1 j » ˚pj : τ 1 j , i.e. the labels match between the left and right-hand side. We proceed by splitting on all the u c,j : then, there exists at least one index m such that the m-th index matches p j . It also matches p ij since the conditions are equal. Otherwise, u c,j is false and we derive the equality from this contradiction.

Then the two terms are equal since their decompositions are equal.

We now have to prove that the simplification terminates and yields and expanded term: Lemma 9.4 (Simplification terminates). There is not infinite sequence of terms pa i q i such that a i a i`1

Proof. Consider a reduction in a bind context B. Then, there is no rule that allows reduction in a prefix of this bind context, thus bind contexts always grow. We define the weight of a term a as the number of let bindings, function applications, and pattern matchings it contains (not counting inside functions), and the set of weights of a term as the multiset of weights of residuals, i.e. terms that are in the holes of maximal B contexts.

All reductions take a residual of weight n and transform it into multiple residuals of weight n ´1. Then consider the sequence pw n q nPN counting the terms of weight n. Each transformation leads to a lower value of this sequence for the lexical ordering. Since the lexical ordering of sequence of natural numbers is a well-order, there cannot be infinite sequences of simplifications.

Lemma 9.5 (Un-simplifiable terms are expanded terms). Suppose that there is no a 1 such that a a 1 . Then, a is an expanded term.

Proof. We are proving three results by simultaneous induction, proving that subterms of a are either expanded terms or simple terms depending on their contexts, and that subtypes of a are ML types. Consider a term a in B such that Bras is irreducible. Then a is an expanded term e. By case analysis:

• If the term starts with a let binding let x " a in b: by induction hypothesis in the context Brlet x " rs in bs, a must be a simple term s or of the form s 1 p s 2 . If it were a simple term s, we could reduce the let, so it must be an application. Then, by induction hypothesis in Brlet x " s 1 p s 2 in rss, the term b must be an expanded term, thus let x " s 1 p s 2 in b is an expanded term.

• If the term starts with a pattern matching, the term we are matching on must be a simple term (by induction hypothesis, since match rs with . . . is a valid F context). Then, we can apply the induction hypothesis on each branch (since each branch forms a valid context B 1 ): all branches are expanded terms, thus the pattern matching is an expanded term.

• Otherwise, B is of the form BrF rss with F " rs, and by induction hypothesis, the term must be a simple tern.

Consider a in BrF rss such that BrF rass is irreducible. Then:

• either a is a simple term s

• or F is let x " rs in b and a is s 1 p s 2
• or F is rs and a is match s with . . . By looking at the different cases for a:

• If a is x or ˚p, it is a simple term.
• If a is Λpα : Typq. u, apply the induction hypothesis to u in BrF rΛpα : Typq. rsss. Only the first case is possible, thus u is simple and a is simple.

• If a is b τ : by induction hypothesis applied to a in BrF rrs τ ss, b must be a simple term. Then, by induction hypothesis applied to τ in BrF rb rsss, τ must be an ML type, thus a is simple.

• If a is fix p x py : τ q : σ . b, we first apply the induction hypothesis to τ in BrF rfix p x py : rsq : σ . bs to find out it is an ML type, then similarly for σ.

Finally, we apply the induction hypothesis to b in the context B 1 equal to BrF rfix p x py : τ q : σ . rss and conclude it is an expanded term. Thus a is simple.

• If a is b 1 p b 2 : by induction hypothesis, both b 1 and b 2 are simple terms. Then, F must be let x " rs in b for some b, otherwise BrF ras would reduce.

• If a is a constructor, we similarly show that all types and terms appearing in the constructor must be simple.

• If a is match b with . . ., b must be a simple term by induction hypothesis. Then, if F ‰ rs, we could move the pattern matching around F . Thus F " rs.

Finally consider τ in BrF rss such that BrF rτ ss is irreducible. Then τ is a simple type τ , by a similar case analysis.

Removing equalities

Simplification removes all apparent result reuse and term-level pattern matching. But we also need the typing derivation of the final term to be a valid ML typing derivation. This is ensured by performing a final rewriting step on the term that also rewrites its typing derivation to be in ML.

We need to take care of equalities. We can prove that in an environment containing only type variables, two equal ML types are syntactically equal. We can extend this result to equalities in inhabited environments, i.e. environments for which we can provide an instantiation of each type and term variable.

First, we prove a stronger version of inversion (Lemma 6.23):

Lemma 9.6 (Equalities in almost empty environments). Suppose that pα i : Typ, x i :

α i q i $ ν 1 : Sch » ν 2 : Sch. Then, ν 1 " ν 2 .
Proof. We already know (Lemma 6.14) that if the two types have the same head (i.e. arrow, type constructor, or quantification), their tails are equal, thus are syntactically equal by induction.

We therefore only to prove that the heads are equal.

• If the heads are both type variables α 1 and α 2 : if they are identical, the types are equal. Otherwise, take γpα 1 q " unit (and γpxq " Unit for the corresponding term); γpα 2 q " bool (and γpxq " True). Then we would have $ unit : Sch » bool : Sch, which is impossible (for the same reasons as in Lemma 6.23: their interpretations are distinct).

• If one head is a type variable (let's say ν 1 ) and the other not a type variable, instantiate the type variable with unit or bool, whichever is different from ν 2 .

• Otherwise proceed as in Lemma 6.23.

We now consider more closely the environments. We prove that an environment Γ is either inhabited, i.e. we can provide an instance of this environment, or that we can prove in eML that it is absurd, by exhibiting a non-expansive term returning void (or any type). For example, the environment Γ 1 equal to x : @pα : Typq α Ñ α, y : nat is inhabited by γ 1 such that γ 1 pxq is the identity function and γ 1 pyq is S Z, while Γ 2 equal to x : @pα : Typq α is not, since x void has type void. This is made slightly more complicated by free type variables, so we instead consider instances of an environment that type in an almost empty environment pα i : Typ, x i : α i q i . Lemma 9.7 (Environment inhabitant). Consider an ML environment Γ with type variables pα i q i . Then, either there exists γ such that pα i : Typ, x i : α i q i $ γ : Γ mapping each type variable to itself and we say the environment is inhabited, or there exists a non-expansive term u such that Γ $ u : void.

Proof. Construct γ as follows: map type variables to themselves. For a term variable of type @pβ j : Typq j τ with τ of kind Typ, construct a value as follows by induction on the type τ :

• If the type is α i with α i in Γ, take x i .

• If the type is β j for some j, we cannot construct a term.

• If the type is τ 1 Ñ τ 2 , take the term fix π x py : τ 1 q : τ 2 . x y.

• If the type is ζ pτ j q j , choose a constructor d i such that its arguments are constructible with the same process. Now consider the case where we do not succeed in building γ: it means that there is some variable x : @pβ j : Typq j τ for which we were not able to construct a value. Then, we construct a term that matches on u " x pvoidq j of type τ rβ j Ð voids j and that is of type void. By induction on τ :

• If the type is α i with α i P Γ we were able to construct a value.

• If the type is β j for some j, it is substituted by void. Then we return u.

• If the type is τ 1 Ñ τ 2 , we were able to construct a value.

• If the type is ζ pτ j q j : the constructors are d i taking arguments of type pτ ik q k . For each constructor there must be at least one argument k for which we cannot construct a term: we then have a term u k of type σ matching on x ik of type τ ik . Then, we construct match u with pd i pτ j q j px ik q k Ñ u k q i . Lemma 9.8 (Equalities are almost trivial). Consider an environment Γ without equalities or results and two ML types τ 1 and τ 2 . Suppose Γ $ τ 1 : Sch » τ 2 : Sch. Then either Γ is inhabited τ 1 " τ 2 or there exists a non-expansive ML term u such that for any type σ, we have Γ $ u : σ, and for any a such that Γ $ p a : σ ñ ∆, we haveTermsEqualpΓ $ p u : σ » a : σq.

Proof. We either construct an environment γ that gives a value all bindings of Γ, or a term u of type void by Lemma 9.7. If we have a non-expansive term of type void, it is equal to any other term (as each equality required for term equality can be proved by splitting on void).

Otherwise, we use Lemma 9.6.

Then we can proceed with simplification:

Lemma 9.9 (Expanded terms type without equalities and with ML types only). Suppose Γ is an ML environment and τ an ML type. Consider an expanded term e such that Γ $ p e : τ ñ ∆. Then there exists an ML term a such that TermsEqualpΓ $ p e : τ » a : τ q and Γ $ a : τ in ML.

Proof. During simplification, we accumulate a substitution γ describing how variables and results must be replaced by simple terms to obtain a term that types in an ML environment. We write Γ $ ML γ : Γ 1 if:

• for all px : τ q P Γ 1 , γpxq is a simple term and Γ $ ML γpxq : τ ;

• for all pTrueq˚p : τ P Γ 1 , Γ $ ML γpαq : τ ;

• and for all equalities pu 1 » u 2 q : τ in Γ 1 , Γ $ γpu 1 q : τ » γpu 2 q : τ .

The proof is by simultaneous induction on e and s. For simple terms s, we prove that if Γ 1 $ s : τ and Γ is an inhabited ML environment such that Γ $ ML γ : Γ 1 , then there exists s 1 and ν such that Γ $ ML s 1 : ν and Γ $ γpsq : τ » s 1 : ν We can always assume that the type derivation for the term does not end with a conversion (as we can always remove all conversions and reapply the equalities as conversion in the equality proof afterwards).

• If the term is x, with Γ 1 $ x : τ : we have px : τ q P Γ 1 . Then, γpxq is an ML type with Γ $ ML γpxq : τ .

• If the term is s ν, with Γ 1 $ s : @pα : Typq τ : we have Γ 1 $ s ν : τ rα Ð νs.

There exists a term s 1 and a type σ such that Γ $ γpsq : @pα : Typq τ » s 1 : σ, with σ an ML type. By extraction, Γ $ @pα : Typq τ : Sch » σ : Sch. Since Γ is inhabited, σ must be of the form @pα : Typq τ 1 . Then, we have, in ML (because ν is an ML type), Γ $ s 1 ν : τ 1 rα Ð νs, and Γ $ γps νq : τ rα Ð νs » s 1 ν : τ 1 rα Ð νs

• We reason similarly for constructor applications, universal quantification and function definitions.

For expanded term, we prove that if Γ 1 $ p e : ν ñ ∆ and Γ is an inhabited ML environment such that Γ $ ML γ : Γ 1 , then there exists a such that Γ $ ML s : ν and TermsEqualpΓ $ p γpeq : ν » a : νq. First, we check if Γ is inhabited. Otherwise, we replace the term by the equal, non-expansive term proving that Γ is not inhabited (Lemma 9.7). Then by case analysis:

• If we return a simple term s at the ML type ν: there exists an equivalent term s 1 at ML type ν 1 that types in ML. Since Γ is inhabited, by Lemma 9.8, τ " τ 1 .

• For let bindings let x " s 1 p s 2 in e: there exists τ 1 and τ 2 such that Γ $ s 1 : τ 1 Ñ τ 2 and Γ $ s 2 : τ 1 .

By induction hypothesis, there exists s 1 1 and s 1 2 , σ 1 and τ 1 2 such that Γ $ γps 1 q : τ 1 Ñ τ 2 » s 1 1 : σ 1 , and Γ $ γps 2 q : τ 1 » s 1 2 : τ 1 1 . Since Γ is inhabited, by Lemma 9.8, there exists τ 2 1 and τ 1 2 such that σ

1 " τ 2 1 Ñ τ 1 2 . We thus have Γ $ τ 1 1 : Sch » τ 2 1 : Sch, thus we have τ 1 1 " τ 2 1 . Then we have, in ML, Γ $ s 1 1 s 1 2 : τ 1 2 . Then, define γ 1 " γ, ˚p Ð x. We have Γ, x : τ 1 2 $ ML γ 1 : Γ, x : τ 2 , pTrueq˚p : τ 2 , px » ˚pq : τ 2 .
Thus, by induction hypothesis, there exists a such that Γ, x : τ 1 2 $ ML a : ν and TermsEqualpΓ, x : τ 1 2 $ γpeq ν :» a : νq. Then, we have Γ $ ML let x " s 1 1 s 1 2 in a : ν, and TermsEqualpΓ $ p γplet x " s 1 p s 2 in eq : ν » let x " s 1 1 s 1 2 in a : νq. • For pattern matching match s with pd i pν j q j px ik q k Ñ e i q i : By induction hypothesis, there exists s 1 and an ML type τ such that Γ $ ML s 1 : τ and Γ $ γpsq : ζ pν j q j » s 1 : τ . Then, τ " ζ pν j q j by Lemma 9.8 since Γ is inhabited. We can reduce s 1 so that there is no type abstraction/application redex, preserving the equality. Then, consider the different cases for s 1 : it can only be a variable, a constructor, or a type application. If it is a type application s 1 " s 2 σ, consider again s 2 : it can only be a variable or a type application (it cannot be a type abstraction as we removed these redexes, and it cannot be a constructor because it would be ill-typed). But then, that would mean that we have a variable in context of type @α ζ pν j q j , which is forbidden.

If s 1 is a variable x, take, for all i, γ i " γ, x Ð d i pν j q j px ik q k . We then have Γ, px ik : σ ik q k $ ML γ i : Γ 1 , px ik : σ ik q k , px » d i pν j q j px ik q k q : ζ pν j q j . Then, we can apply the induction hypothesis in each branch and build an ML term.

Otherwise, s 1 " d i pν j q j ps k q k for some i. Then, we take γ 1 " γ, px ik Ðq k s k and apply the induction hypothesis in the branch to obtain a term a. By congruence and reduction, the original term reduces to γpe i qrx ik Ð s k s k " γ 1 pe i q, thus we get the required equality.

Theorem 9.1 (Simplification). Let Γ be an ML environment whose polymorphic bindings are all functions. Suppose Γ $ p a : τ ñ ∆ with τ an ML type. Then, there exists an ML term a 1 such that Γ $ ML a 1 : τ , and TermsEqualpΓ $ p a : τ » a 1 : τ q.

Part III

Encoding ornaments

Chapter 10

Encoding ornaments in mML

We now consider how ornaments are described and represented in the lifting process. This section bridges the gap between mML, a language for metaprogramming that does not have any built-in notion of ornamentation, and the interface presented to the user for ornamentation. We define both the datatype ornaments, i.e. the base ornaments specified by the user, and the higher-order functional ornaments that can be built from them.

As a running example, we use the ornament natlist α from natural numbers to lists: type ornament natlist α : nat Ñ list α with | Z Ñ Nil | S w Ñ Cons p_, wq when w : natlist α

The ornament natlist α defines, for all types α, a relation between values of its base type nat, which we write pnatlist αq ´, and its lifted type list α, written pnatlist αq `: the first clause says that Z is related to Nil; the second clause says that if w ´is related to w `, then S w ´is related to Cons pv, w `q for any value v.

As a notation shortcut, the variables w ´and w `are identified in the definition above.

A higher-order ornament type natlist α Ñ natlist α relates two functions f óf type nat Ñ nat and f `of type list τ Ñ list τ when for related inputs v ´and v `, the outputs f ´v´a nd f `v`a re related.

The ornament list pnatlist αq relates a list of natural numbers to lists of lists whose lengths are given by the corresponding element in the base list.

Ornamentation as a logical relation

We formalize this idea by defining a family of ornament types corresponding to the ornamentation definitions given by the user and giving them an interpretation in the logical relation. Then, we say that one term is a lifting of another if they are related at the desired ornament type.

The syntax of ornament types, given on Figure 10.1, mirrors the syntax of types. An ornament type, written ω, may be an ornament variable ϕ, a datatype ornament χ ω, a higher-order ornament ω 1 Ñ ω 2 , or an identity ornament ζ pωq i , which is automatically defined for any datatype of the same name (ω i indicates χ ::" Base ornaments

| natlist | . . . ω ::" Ornament types | ϕ Ornament variables | χ pωq i Datatype ornament | ζ pωq i Identity ornament | ω Ñ ω Function Figure 10.1: Ornament types α " α pω 1 Ñ ω 2 q " ω 1 Ñ ω 2 pζ pω i q i q " ζ pω i q i χ pα i q i : τ ñ σ pχ pω i q i q ´" τ rα i Ð ω í s i χ pα i q i : τ ñ σ pχ pω i q i q `" σrα i Ð ω ì s i Figure 10
.2: Projection of ornament types how the i-th type argument of the datatype is ornamented). An ornament type ω is interpreted as a relation between terms of type ω ´and ω `. The projection operation, defined on Figure 10.2, depends on the projections of the datatype ornaments: they are given by the global judgment χ α : τ ñ τ . We also define a well-formedness judgment pα i q i $ ω, for ornaments given an environment of type variables in Figure 10.3. For example, the ornament list pnatlist natq describes the relation between lists whose elements have been ornamented using the ornament natlist nat. Thus, its projections are plist pnatlist natqq ´equal to list nat and plist pnatlist natqq `equal to list plist natq.

The projection is defined and well-kinded for any well-formed ornament type:

Lemma 10.1 (Projection is a type). If α $ ω holds, then we have α $ pωq : Typ.

Proof. By induction on the derivation of α $ ω.

We define in the next section how to interpret the base ornaments χ, and focus here on the interpretation of higher-order ornaments ω 1 Ñ ω 2 and identity

pα i q i $ α i α $ ω 1 α $ ω 2 α $ ω 1 Ñ ω 2 ζ : pTypq j Ñ Typ p α $ ω j q j α $ ζ pω j q j
χ pα j q j : . . . ñ . . . p α $ ω j q j α $ χ pω j q j . The interpretation we want for higher-order ornaments is as functions sending arguments related by ornamentation to results related by ornamentation. But this is exactly what the interpretation of the arrow type τ 1 Ñ τ 2 gives us, if we replace the types τ 1 and τ 2 by ornament types ω 1 Ñ ω 2 . Thus, we do not have to define a new interpretation for higher-order ornaments, it is already included in the logical relation. For this reason, we use the function arrow and the ornament arrow interchangeably (when talking about the logical relation).

We have the same phenomenon for the identity ornament: constructors are related at the identity ornament if their arguments are related. Once more, we can simply take the interpretation of a datatype ζ pτ i q i and, by replacing the type parameters pτ i q i by ornament parameters pω i q i , reinterpret it as an interpretation of the identity ornament.

Finally, ornament variables must be interpreted by getting the corresponding relation in the relational environment. This is exactly the interpretation of a type variable.

Thus, the common subset between types and ornament specifications can be identified, because their interpretations are the same. This property plays a key role in the instantiation: from a relation at a type, we deduce, by proving the correct instantiation, a relation at an ornament.

Deep pattern matching in eML

Ornaments are defined through deep pattern matching, and our presentation of eML only allows for shallow pattern matching. In this section, we present an encoding of deep pattern matching in eML, based on eML features. An alternative way of handling pattern matching would be to compile it down to a tree of simple pattern matching [START_REF] Maranget | Compiling pattern matching to good decision trees[END_REF], but this would introduce deeper changes to the term. Instead, the encoding given here maintains a structure very close to the original deep pattern matching. The syntax of patterns we support is defined in Figure 10.4. A pattern may be a variable x, a wildcard pattern _, the void pattern K that matches nothing, an alternative pattern P | Q that matches if either P or Q matches, or a constructor pattern d pτ i q i pP j q j matching a constructor d whose arguments match the pattern P j . We do not support pattern synonyms P as Q as they cannot be used in ornament definitions.

Patterns are checked by the judgment $ P : σ ù Σ, asserting that the pattern P matches values of type σ and returns variables in Σ. The definition of the judgment is given in Figure 10.5. Apart from checking typing, the judgment

P-Var $ x : σ ù x : σ P-Wild $ _ : σ ù H P-Empty $ K : σ ù Σ P-Alternative $ P 1 : σ ù Σ $ P 2 : σ ù Σ $ P 1 | P 2 : σ ù Σ P-Con $ d : @pα i : Typq i pτ j q j Ñ ζ pα i q i $ P j : τ j rα i Ð σ i s i ù Σ j @j, k, Σ j # Σ k
$ dpτ i q i pP j q j : ζ pσ i q i ù pΣ j q j Figure 10.5: Typing for patterns also checks that each variable is defined only once (we write Σ 1 # Σ 2 if the variables in Σ 1 and Σ 2 are distinct), and that alternatives define the same variables with the same types.

We provide an encoding of patterns into eML. This is interesting, because it allows us to add deep patterns to eML without changing the core of the language and adding reasoning and reduction rules for these patterns. For each pattern P , we define a non-expansive term Patpu, P q that is equal to None when the pattern does not match, and Some ppv i q i q when it matches, where the v i are the values matched by the pattern. This definition is given in Figure 10.6. For matching on constructors, we use an operation Combinepu i q i on the result of matching on each argument: it returns Some with a tuple of all the variables of each result concatenated, or None if any of the matches fail. For example, CombinepSome 1, Noneq is equal to None and CombinepSome 1, Some pTrue, 2qq is equal to Some p1, True, 2q. Its definition is also given in Figure 10.6.

The expression Patpu, P q is well-typed:

Lemma 10.2 (The match term is well-typed). Suppose Γ $ u : σ and $ P : σ ù px i : τ i q i . Then, Γ $ Patpu, P q : option pτ i q i . Proof. By induction on the derivation of the pattern typing, using as a lemma the fact that if pΓ $ u i : option pτ ij q j q i , then Γ $ Combinepu i q i : option

pτ ij q ij .
From a non-expansive term u, a set of patterns pP i q i , associated expressions (terms, types, or non-expansive terms) pX i q i and a default value Y , we define in Figure 10.6 the pattern matching with default value Matchpu, pP i Ñ X i q i , Y q: it returns the X i of the first clause that matches a pattern, or Y if nothing matches.

We say that a set of patterns pP i q 1ďiďn is complete for σ in an environment Γ if one pattern in Γ always matches, i.e. if we have:

Γ, x : σ $ True : bool » Matchpx, pP i Ñ Trueq i , Falseq : bool Patpu, xq
" Some u Patpu, _q " Some pq Patpu, Kq " None Patpu, P | Qq " match Patpu, P q with Some x Ñ Some x None Ñ Patpu, Qq Patpu, d i pτ j q j pP k q k q " match u with d i pτ j q j px k q k Ñ CombinepPatpx k , P k qq k pd pτ j q j px k q k Ñ Noneq ‰i Combinepu i q i " Combine'ppu i q i ; Hq Combine'pH; px j q j q " Some px j q j Combine'ppu 0 , pu i q i‰0 q; px j q j q " match u 0 with None Ñ None Some y Ñ match y with py k q k Ñ Combine'ppu i q i‰0 ; ppx j q j , py k q k qq Matchpu, pP i Ñ X i q iPt1,...,nu , Y q " match Patpu, P 1 q with Some px 1j q j Ñ X 1 None Ñ . . . match Patpu, X n q with Some px nj q j Ñ b n None Ñ Y From this, we can define the deep pattern matching:

Definition 10.1 (Deep pattern matching). We define:

match a with pP i Ñ b i q i " let x " a in Matchpx, pP i Ñ b i q i , Unitq
where the px ij q j are the variables matched by P i .

Similarly, for types, we define:

match u with pP i Ñ τ i q i " Matchpu, pP i Ñ τ i q i , unitq ♦
Deep pattern matching verifies the following (derived) typing rule:

Match-Deep
Γ $ u : σ pP i q i complete for Γ $ σ p$ P i : σ ù px ik : τ ik q ik q i ˆΓ, ppPatpu, P j q » Noneq : option pτ jk q k q jăi , px ik : τ ik q ik , pPatpu, P i q » Some px ik q k q : option pτ ik q k $ a i : τ ˙i Γ $ match u with pP i Ñ a i q i : τ Proof. This follows from applying the (syntax directed) pattern matching rule. The last (absurd) branch of the pattern matching is unreachable: it can only be reached if all matches return None, but then by the completeness condition, we obtain True equal to False.

Defining datatype ornaments

In general, an ornament definition is a mutually recursive group of definitions, each of the form: type ornament χ pα j q jPJ : ζ pτ k q kPK ñ σ `with pP i ñ Q i when px i : ω i q PLi q iPI This defines a datatype ornament χ, parametrized by a set of types pα j q jPJ . The base type is a datatype σ ´" ζ pτ k q kPK and the ornamented type is σ `. The ornamented type is most often a datatype but it needs not be. For example, we can define an ornament unwrap α : option α ñ α that maps Some x to x: type ornament unwrap α : option α ñ α with Some x ñ x when x : α

The ornament is defined by a series of clauses P i ñ Q i indexed by a set I and mapping values of the base type to values of the ornamented type. The variables Values γ px : τ q " tγpxqu Values γ p_ : τ q " tv | $ v : τ u Values γ pK : τ q " H Values γ pP | Q : τ q " Values γ pP : τ q Y Values γ pQ : τ q Values γ pd τ k pP i q i : ζ pτ k q k q " " dpτ k q k pv i q i ˇˇˇp d : @pα k q k pσ i q i Ñ ζ pα k q k q ^@i, v i P Values γ pP i :

σ i rα k Ð τ k s k q * Figure 10
.7: Values matched by a pattern present in the patterns are exactly the px i q PLi . On the left-hand side, their types are the left-projections of the ω i , while on the right-hand side their types are the right-projections. The ornamentation process ensures that the value of this variable on the left and right-hand side are related at the ornament ω i .

The patterns P i should be both expressions and patterns, i.e. they can only match variables or constructors. This ensures that from a P i and the values of the variables we can recover the unique value that may have been matched. The typing condition, for each P i , is: $ P i : ζ pτ k q k ù px i : pω i q ´q . We require for convenience that the pP i q i do not overlap. We also require that they form a complete pattern matching: for ornament definitions, an incomplete pattern matching can be made complete by adding some clauses mapping the unmatched values to K (our surface language accepts specifying a clause _ ñ K to request the generation of all such patterns).

The patterns pQ i q i on the right-hand side can be any patterns matching on the ornamented type. They must obey the typing condition $ Q i : σ `ù px i : pω i q `q PLi . Moreover, we require that they are complete and do not overlap: this allows any term of the ornamented type to be non-ambiguously projected to the base type (as long as we can project the subcomponents).

We give meaning to these definitions by adding them to the logical relation. The interpretation of a datatype ornament is the union of the relations defined by each clause of the ornament. For each clause, the left and right hand-side values of the variables must be related at ornament type given by the user. Since the pattern on the left is also an expression, the value on the left is uniquely defined once values have been chosen for the variables. The pattern on the right can still represent a set of different values (none, one, or many, depending on whether the empty pattern, an or-pattern or a wildcard is used). We define a function Values γ pP : τ q that returns the set of values of types τ matching P where the values of the free variables in P are taken from γ. Its definition is given in Figure 10.7.

Then, the interpretation is:

T rχ pω j q j s γ " pσ ´rα j Ð τ j ´sj , σ `rα j Ð τ j `sj q where @j, T rω j s γ " pτ j ´, τ j `q V p rχ pω j q j s γ "

$ & % pP i rx i Ð v ´s , v `q ˇˇˇˇˇi P I @ P L i , pv ´, v `q P V p rω i rα j Ð ω j s j s γ v `P Values px i Ðv `q pQ i q

, .

-It is in fact quite similar to the interpretation of datatypes: the recursive conditions are the same, but instead of merely applying a constructor, we build the left and right-hand side values using the patterns of the ornament definition.

For example, on natlist , we get the following definition (omitting the typing conditions):

V k rnatlist τ s γ " tpZ, Nilqu Y t pSpv ´q, Consp_, v `q | pv ´, v `q P V k rnatlist τ s γ u
As expected, we have, e.g. pS pS Zq, Cons pv 1 , Cons pv 2 , Nilqqq P V k rnatlist bools for any boolean values v 1 and v 2 .

Shallow ornaments

This definition of ornamentation is convenient for the surface language, but it unfortunately does not exactly match the encoding. In this section, we'll give a slightly lower-level definition of datatype ornaments that allows us to bridge the gap between the original user-facing definition and the lower-level workings of lifting.

The issue appears when defining ornaments with deep pattern matching on the left-hand side. Suppose we have a type t with one constructor T: nat Ñ t. We may define the following ornament broken: Unfortunately this breaks down when trying to write the construction function inj: λ # px : ???q. λ # py : boolq. match x with Some pT pz : list boolqq Ñ Cons py, zq This function does not type, as T can only contain a natural number, but at this stage of lifting, we expect the value inside the Some pT rsq context to be already lifted to list bool.

We can still write this ornament by instead proceeding in two steps: we need to ensure that when we are lifting the Some constructor, the type inside the constructor has already been lifted to a type t 1 that can hold a list bool (thus we take T 1 : list bool Ñ t 1 ). We start by defining an ornament aux : t ñ t 1 as follows:

type ornament aux : t ñ t 1 with | T x ñ T 1 x when x : natlist bool Then, we require that first the argument of Some is ornamented with aux, and instead of simply forwarding it, we match on it to remove the T 0 constructor. This is a form of shallow ornamentation, where each ornament only reads one layer of constructor from the base term. This is easy to express as a construction function, but the surface syntax does not allow for this. We thus offer an extended syntax supporting this: when specifying an ornament of a datatype, one requests a specific ornamentation for each parameter of each constructor, then one matches on the transformed arguments of the constructors.

With this extended syntax, the broken ornament definition can be fixed as follows:

type ornament fixed : option t ñ list bool rSome aux | Nones with | Some pT 1 xq ñ Cons p_, xq | None ñ Nil These definitions do not use when clauses: instead, we specify which ornament must be used for which argument to each constructor. This is a restriction compared with the previous definition, because it prevents ornaments such as the following from being translated: This cannot be transformed into a valid shallow ornament because we would need to specify two different ornament types for the second argument of Pair. This is in fact a limitation of our encoding of ornaments: to decide how the parameters should be ornamented, we can only look at one level of constructor. Thus, we will reject such ornament definitions when converting to the lower-level representation ( §10.5). Instead of using the aux ornament, we prefer to use a generic ornament that allows to transform the type inside T into any type we want. The target type for this can be the skeleton of t (we first introduced the skeleton when informally discussing the ornamentation process in Section 3.1).

Consider a datatype ζ pα i q iPI defined by a family of constructors pd k q kPK each taking arguments of types pτ kj q jPJ k : `dk : @pα i : Typq iPI pτ kj q jPJ k Ñ ζ pα i q iPI ˘kPK We define the skeleton by abstracting out the concrete types from the constructors and replacing them by type parameters: the skeleton of ζ, written ζ, is parametrized by types pα kj q kPK,jPJ k and has constructors: `d k : @pβ j : Typq PK,jPJ pβ kj q jPJ k Ñ ζ pβ j q PK,jPJ ˘kPK Let us write A ζ pτ i q iPI for pτ kj rα i Ð τ i s i q kPK,jPJ k , i.e. the function that expands arguments of the datatype into arguments of its skeleton. The types ζ pτ i q i and ζ pA ζ pτ i q i q are in bijection by construction (the bijection is obtained by adding hats on the constructors, or removing them when going the other way).

For example, the skeleton of t is the type t α with a single constructor T : α Ñ t α, and there is a bijection between t and t nat.

We would like to define, for each datatype ζ, an ornament r ζ mapping its values to values of its skeleton with the argument suitably ornamented. For t, we would have, written as a shallow ornament: type ornament r t α : t ñ t α with rT αs | T x ñ T x However, this does not quite work, because we cannot accept any ornament for α, but only ornaments whose base type is nat. Thus, we need constrained type parameters for ornament definitions: we write α nat (or, in code, <:) to abstract over ornaments whose base type is nat. Then our definition becomes: type ornament r t pα natq : t ñ t α with rT αs | T x ñ T x For a datatype ζ pα i q i defined by a family of constructors pd k q kPK each taking arguments of types pτ kj q jPJ k , the ornament r ζ is defined as: type ornament r ζ pα i q i pβ kj τ kj q kPK,jPJ k : ζ pα i q i ñ ζ pβ kj q kPK,jPJ k with rd k pτ kj q jPJ k s kPK pd k px kj q jPJ k ñ x d k px kj q jPJ k q kPK

Then, we can define the ornament fixed, mechanically, as follows: type ornament χ pα j q j pβ k τ k q k : ζ pσ q PL ñ σ `with rd m pω mn q nPNm s mPM pP i ñ Q i q iPI

We first state the conditions for the types appearing in the definition:

• The constraints on the base types are formed with well-defined types: for all k, pα j : Typq j $ τ k : Typ.

• For all P L, pα j : Typq j $ σ : Typ. The β k are not in scope in the σ because their projections are already known.

• σ `is a well-defined type: pα j : Typq j , pα k : Typq k $ σ `: Typ.

• The types for each constructor argument are valid ornament types: for all m P M and n P N m , pα j : Typq j , pα k : Typq k $ ω mn .

• The left-projection of the types for each constructor argument matches the original (base) type of the arguments:

ppω ḿn qrβ k Ð τ k s k q mPM,nPNm " A ζ pσ q PL
Then, we require the following for the patterns pP i q i and pQ i q i . We assume that all patterns pP i q i start by a constructor of ζ. Let us define P i the pattern obtained by replacing the head constructor by its skeleton version in P i . We require:

• The patterns p P i q i are both expressions and patterns, and are complete and non-overlapping for ζ pω mn q mPM,nPNm , the type obtained by projecting all the arguments to the skeleton to their ornamented type.

• The patterns pQ i q i on the right-hand side are complete and non-overlapping for σ `, (but not necessarily expressions).

• For each i P I there exists Σ i such that $ P i : ζ pω mn q mPM,nPNm ù Σ i and

$ Q i : σ `ù Σ i
Our goal is to find the ornament arguments that must be passed to the skeleton and transform the left-hand side patterns into patterns that match alreadyornamented values.

We first require that every pattern in pP i q i starts with a constructor of ζ, i.e. for all i P I, there exists d i and pP in q nPNi such that P i " d i pP in q nPNi . This can always be ensured by splitting the pattern: if the only pattern is x ñ dpxq, we can instead match on every constructor of ζ.

Then, we need to find ornament types pω mn q mPM,nPNm for the different arguments of the skeleton. We suppose these types given, and we give a procedure to check them. The implementation instead performs unification to build these types. The idea is to transform P i into a pattern Pi 1 where all constructors have been replaced by their skeleton, and check the ornament type at the same type. We define a function SkelPatpP : ωq Σ , where Σ is px i : ω i q i and associates variables in the pattern to ornaments, as follows:

SkelPatpx : ωq Σ " x if px : ωq P Σ SkelPatpd i τ pP k q k : r ω pω ik q ik q Σ " di ppω ik q `qik pSkelPatpP k : ω ik q Σ q k
This function satisfies the following properties:

Lemma 10.3. Suppose Q " SkelPatpP : ωq Σ , with P a pattern matching a subset px i q i of Σ. Then:

• We have $ pωq `: Q ù px i : pΣpx i qq `qi .

• Suppose we have pv i´q i and pv i`q i , with pv i´, v i`q P V q rΣpx i qs γ . Then, pP rx i Ð v i´s i , Qrx i Ð v i`s i q P V q rωs γ .

• Consider v ´and pv i`q i such that pv ´, Qrx i Ð v i`s i q P V q rωs γ . Then there exists pv i´q i such that pv i´, v i`q P V q rΣpx i qs γ and v ´" P rx i Ð v i´s i .

Proof. By induction on the pattern.

• If the pattern is P " x, then Q " x and Σpx i q " ω. Then we have $ pωq `: x ù x : pΣpx i qq `. The second and third item are immediate.

• If the pattern is a constructor, looking at the definition of r ζ, the relation only matches constructors to matching constructors, and we use the induction hypothesis on each argument. We define P 1 i " di pP 1 in q nPNi with P 1 in " SkelPatpP in : ω in q px il :ω il q PL i . Then we define the shallow ornament χ 1 as follows:

type ornament χ 1 pα j q j : ζ pτ k q k ñ σ `with rd m pω mn q nPMn s mPM pP 1

i ñ Q i q iPI
The first point of Lemma 10.3 ensures this is a well-formed shallow ornament. We prove that they have the same interpretation:

Lemma 10.4 (The translation from deep to shallow preserves the relation). Suppose the pω j q j are valid ornaments. Then, V q rχ pω j q j s γ " V q rχ 1 pω j q j s γ Proof. Suppose pv ´, v `q P V q rχ pω j q j s γ . Suppose we match pattern i. Then, by definition, there exists pv ´, v `q P V q rω i rα j Ð ω j s j s γ such that v ´" d i pP im rx i Ð v ´s q m , and v `P Values px i Ðv `q pQ i q. Then, consider v m´" P im rx i Ð v ´s and v m`" P 1 im rx i Ð v `s . We need to show that pv m´, v m`q P V q rω im rα j Ð ω j s j s γ : this suffices to have pv ´, v `q P V q rχ 1 pα j q j s γ . This is true by Lemma 10.3

Conversely, suppose we have pv ´, v `q P V q rχ 1 pα j q j s γ . Then, there exists i such that v ´" d i pv m´q m , for all m, pv m´, v m`q P V q rω im rα j Ð ω j s j s γ , and there exists pv p q p such that v m`" P 1 im rx ip Ð v p s p , and v `P Values pxipÐvpq pQ i q. Then, it suffices to show that pv m´, P 1 im rx ip Ð v p s p q P V q rω im rα j Ð ω j s j s γ implies that there exists pv p ´qp such that v m´" P im rx ip Ð v p ´sp and for all p, pv p ´, v p q P V q rω ip rα j Ð ω j s j s γ . This is also true by Lemma 10.3

Encoding ornaments in mML

We now describe the encoding of datatype ornaments in mML. Consider a valid ornament definition: type ornament χ pα j q j pβ k τ k q k : ζ pσ q ñ σ `with rd m pω mn q nPMn s mPM pP i ñ Q i q iPI All terms given in this section are actually parametric in the input types pα j q j and pβ k q k . We call τ `the type ζ pω mn q mPM,nPMn , i.e. the type of a subterm as it is given to the construction function, after its components have been ornamented according to the specification given in the ornament definition.

The ornament is encoded as a quadruple pσ, δ, proj, injq where σ : Typ is the lifted type; δ is the extension, a type-level function describing the information that needs to be added to create a value of the lifted type from a value of τ `; and proj and inj are the projection and injection functions introduced in §3.1. More precisely, the projection function proj from the lifted type to the skeleton has type Πpx : σq τ `and, conversely, the injection inj has type Πpx : τ `q Πpy : δ # xq σ, where the argument y is the additional information necessary to build a value of the lifted type. The type of y is given by the extension type function δ of kind τ `Ñ Typ, which takes the skeleton and gives the type of the missing information. This dependence allows us to add different pieces of information for different shapes of the skeleton, e.g. in the case of natlist α, we need no additional information when the skeleton is Ẑ, but a value of type α when the skeleton starts with Ŝ. The encoding works incrementally: all functions manipulate the type τ `, with all subterms already ornamented.

The projection proj χ pωj q j from the lifted type to the skeleton is given by reading the clauses of the ornament definition from right to left: proj χ pωj q j : σ χ pωj q j Ñ τ ` " λ # px : σ χ pωj q j q. match x with pQ i Ñ P i q i

The extension δ χ pωj q j is determined by computing, for each clause P i ñ Q i of the ornament, the type of the information missing to reconstruct a value. There are many isomorphic representations of this information. The representation we Missingpp_ : τ qq " τ Missingpxq " unit MissingpP | Qq " either pMissingpP q, MissingpQqq MissingpKq " void MissingpdpP 1 , .. P n qq " MissingpP 1 q ˆ.. MissingpP n q PatchpdpP i q i , uq " match u with px i q i Ñ dpPatchpP i , x i qq i Figure 10.9: Patching a pattern use is given by the function MissingpQ i q mapping a pattern to a type, defined in Figure 10.8. There is no missing information in the case of variables, since they correspond to variables on the left-hand side. In the case of constructors, we expect the missing information corresponding to each subpattern, given as a tuple. For wildcards, we expect a value of the type matched by the wildcard. The empty pattern matches nothing: we cannot add any information to get a term matching the pattern, so the missing information has the void type. Finally, for an alternative pattern, we require to choose between the two sides of the alternative and give the corresponding information, representing this as a sum type either pτ 1 , τ 2 q.

From the value of the variables and the missing parts, we can patch the holes in the pattern and reconstruct the value that was matched: we define an expression PatchpP, uq that does this in Figure 10.9. This expresion matches on u to extract the information. In the case of K, we can return anything, because u must be a value of type void, which means that this branch is unreachable. The correctness of the combination of MissingpP q and PatchpP, uq is stated by the following lemma: Lemma 10.5. Suppose Γ $ σ : Typ and $ P : σ ù px i : τ i q i . Then, Γ $ MissingpP q : Typ: the missing type is a valid type. Moreover, if Γ $ u : MissingpP q, then we have Γ, px i : τ i q i $ PatchpP, uq : σ: patching creates a well-typed non-expansive term of the correct type. Finally, patching then matching gives back the same values for the variables: Γ, px i : τ i q i $ PatpP, PatchpP, uqq : option pτ i q i » Some px i q i : option pτ i q i Proof. By induction on the pattern. At each step, split on the non-expansive value u, apply the lemma recursively and then reduce the matches.

We could use any pair of functions that satisfies these properties: in our implementation, we generate simpler type by avoiding empty types in sums, units in products, flattening products, etc.

Then, the extension δ χ pωj q j matches on the p P i q i to determine which clause of the ornament definition can handle the given skeleton, and returns the cor-responding extension type: δ χ pωj q j : Πpx : σq τ ` " λ # px : τ `q. match x with p P i Ñ MissingpQ i qq i

The injection inj χ pωj q j then examines the skeleton to determine which clause of the ornament to apply, and calls the corresponding reconstruction code (writing just δ for δ χ pωj q j ): inj χ pωj q j : Πpx : τ `q Πpy : δ # xq T " λ # px : τ `q. λ # py : δ # xq. match x with p P i Ñ PatchpQ i , yqq i

In the case of natlist , we recover the definitions given in §3.1.2, with a slightly more complex (but isomorphic) encoding of the extra information:

σ natlist τ " list τ δ natlist τ " λ # px : x natplist τ qq. match x with Ẑ Ñ unit | Ŝ x Ñ τ ˆunit proj natlist τ " λ # px : list τ q. match x with Nil Ñ Ẑ | Cons py, _q Ñ Ŝ y inj natlist τ " λ # px : x natplist τ qq. λ # py : δ natlist τ # xq. match y with Ẑ Ñ pmatch y with pq Ñ Nilq | Ŝ x 1 Ñ pmatch y with py 1 , pqq Ñ Cons py 1 , x 1 qq
We also need to be able to instantiate ornamentation points with the identity ornament, so we need to define the same functions for them: the identity ornament corresponding to a datatype ζ defined as pd i : @pα j : Typq j pτ ik q k Ñ ζ pα j q j q i is automatically generated and is described by the following code: type ornament ζ pα j q j : ζ pα j q j Ñ ζ pα j q j with rpd i pτ ik q k q i s pd i px k q k Ñ d i px k q k q i

The generated definition is then: σ " ζ pτ j q j δ " λ # px : ζ pτ ik q ik q. match x with p di px ik q k Ñ unitq i proj " λ # px : ζ pα j q j q. match x with pd i px ik q k Ñ di px ik q k q i inj " λ # px : ζ pτ ik q ik q. match x with p di px ik q k Ñ d i px ik q k q i 10.7 Correctness of the encoding

In this section, we show that the terms defined in the previous section do correspond to the ornament as interpreted by the logical relation. This will be used to prove correctness of the lifting, i.e. that the base term and the ornamented term are related at some ornament type.

The base term will be proved equal to the ornamented term instantiated with the identity ornament. Thus, what we need to do here is to prove that the identity ornament and an ornament that does something are related at the ornament type.

Consider an ornament definition:

type ornament χ pα j q j pβ k τ k q k : ζ pσ q ñ σ `with rd m pω mn q nPNm s mPM pP

i ñ Q i q i
The ornament is encoded in mML by pσ, δ, proj, injq. Consider the identity ornament for ζ pσ q : it is encoded as pσ id , δ id , proj id , inj id q, with σ id " ζ pσ q . Consider the ornamented skeleton type τ " ζpσ q , and an environment γ P G k rpα j : Typq j , pβ k : Typq j s. We define r δ " λpv 1 , v 2 q. tpUnit, w 2 q | H $ w 2 : γ 2 pδq # v 2 u the relational version of δ: for any pair of base and ornamented skeletons, it returns the relation that relates Unit, the extension type of the identity ornament, to any value of the extension type of the ornament.

Definition 10.2 (Valid ornament). A valid ornament is an ornament that verifies the following properties:

• pγ 1 pζ pσ q q, γ 2 pσqq " T rγs τ • r δ P V q rΠpx : τ q Typs γ • pγ 1 pproj id q, γ 2 pprojqq P V q rΠpx : χ pα j q j pβ k q k q τ s γ .

• pγ 1 pinj id q, γ 2 pinjqq P V q rΠpx : τ q Πy : α # x χ pα j q j pβ k q k s γ,αÐ r δ ♦ These properties are simply relational versions of the typing rules for proj and inj: they ensure that we can relate two instances of the same term, one instantiated with the identity ornament and the other with the actual ornament.

Theorem 10.1. The construction given in this chapter produces a valid ornament.

Proof. The first item is by definition.

For the second one, note that tpUnit, w 2 q | H $ w 2 : γ 2 pδq # v 2 u is stable by equality and does not vary with the index.

For the third and fourth point: we'll examine only the third one, the fourth one is similar. γ 1 pproj id q and γ 2 pprojq are values. Consider an index q and pv 1 , v 2 q P V q rχ pα j q j pβ k q k s γ . Then pv 1 , v 2 q matches some clause i of the ornament whose head constructor is d i , and there exists pv m´, x m`q m such that pv m´, x m`q P V q rω im s γ and v 1 " d i pv m´q m . Then, γ 1 pproj id q # v 1 reduces to di pv m´q m . There also exists pv p q p such that v `P Values pxipÐvpq p pQ i q. Then, γ 2 pprojq # v `reduces to P i rx ip Ð v p s p (this matches the i-th pattern, and the i-th pattern is the only one that matches, because the patterns do not overlap). This rewrites to di pP im rx ip Ð v p s p q m Thus, we need to prove p di pv m´q m , di pP im rx ip Ð v p s p q m q P V q r ζpω im q im s γ , i.e. for all m, pv m´, P im rx ip Ð v p s p q P V q rω im s γ . From the definition of the relation for χ, we have P im rx ip Ð v p s p " v m`, and we have pv m´, x m`q P V q rω im s γ .

Once processed, all well-formed ornament definitions are added to a global ornament definition: we will write $ χ α β τ Þ Ñ pδ χ α β , inj χ α β , proj χ α β q ω1 i : σ 1 i ñ T to indicate that a definition of ornament χ has been processed with the given parameters, base type, and skeleton. We also write δ χ ωj , inj χ ωj and proj χ ωj to stand for instantiated versions of the extension types, construction, and projection functions defining χ.

Chapter 11

Elaborating to the generic term

We now consider the problem of ornamenting terms. The ornamentation is done in two main steps: first the base term is elaborated to a generic term, which is then specialized using user-specified ornaments to generate ML code.

Preparing an ML term for lifting

When quantifying over ornaments, one expects to receive some pieces of mML code that need to be applied, patched and reduced to produce a valid ML term. Thus, we cannot simplify code that is polymorphic in ornaments back to eML: the lifted code cannot be polymorphic in ornaments.

Consider a polymorphic definition, for example head : @pα : Typq .list α Ñ α. We do not know the exact types of the ornaments we may use until the type variable α has been instantiated. We could specify some ornaments depending on the values of α: for example, we could apply the ornament listoption α : list α ñ option α. However, this prevents us from applying some other interesting ornaments, such as the ornament that transforms Cons pTrue, xq to Cons A pxq and Cons pFalse, xq to Cons B pxq (in OCaml, applying such a transformation saves memory, as the latter type only needs two words instead of three). Thus our approach is to instantiate the type variables, then choose some appropriate ornaments, then generalize to produce a lifted definition. Then, we have produced a lifting compact_head of head bool, but not a general lifting of head.

At the point where head is used, we need to look at its type argument to decide whether compact_head is an appropriate lifting. This treatment requires some restrictions on when instantiation and generalization are performed. We choose to restrict ML polymorphism to top-level bindings and to require all uses of polymorphic values to immediately instantiate them fully. For local polymorphic bindings, we know the set of instantiations of the term: we can thus simply duplicate the term to create one instance per use with different type arguments. This does not affect usability much, as polymorphic let bindings are rarely used [START_REF] Vytiniotis | Let should not be generalized[END_REF].

To encode the restriction to toplevel polymorphism, we need to make a distinction between (generalizable) toplevel bindings and monomorphic local bindings. The environment Γ can then be split into G, pα i : Typq i , Θ where G is an environment of polymorphic variable bindings, α the list of type variables of kind Typ parametrizing the current binding, and Θ a local environment binding only monomorphic term variables. The syntax of these environments is given in Figure 11.1. The definitions in G are of the form x β : τ " a. Such a definition means that x expects type parameters β and then is of (monomorphic) type τ with value a. We store the value in the environment because it will be convenient to prove that the lifting is correct. To save notation, we just write α instead of α : Typ in typing contexts or polymorphic types, assuming that type variables have the Typ kind by default. The well-formedness judgment for G, noted $ G, is defined in Figure 11.2.

We give the typing rules for this restriction of ML in Figure 11.3. The typing judgment is now of the form G; α ; Θ $ a : τ (the input type is in ML, and its typing features neither labels nor equalities). The modified rules are in black, the rules that were only changed to pass a split environment are in grey. Types are only checked in the environment α , since they can only contain toplevel type variables. The rule Var-Local looks up a variable in the monomorphic environment, and the rule Var-Global looks up a toplevel definition in the polymorphic environment. We removed rules for type abstraction and application.

Generalization is handled through a separate judgment: we consider a program as a sequence s of top-level definitions let x α " a. Such a sequence is checked by a judgment G $ s ñ G 1 : after typing s in the top-level environment G, the top-level environment is now G 1 . The rules of this judgment are given in Figure 11.4. Then, the rule Top-Let quantifies over the type variables pα i q i before typechecking the body a.

Elaboration environments

The elaboration process is run in parallel with the typing process: each toplevel definition is elaborated in the order it appears in the program, right after being typechecked. As for typechecking, the information gathered when processing previous definitions is used to elaborate the next definition.

For each toplevel definition "let x " Λα. a", we elaborate a using the term elaboration judgment of the form Γ $ p a A : ω ñ ∆ (described in Figure 11.9), which implies both Γ ´$ML a : ω Γ and Γ `$p A : ω Γ ñ ∆ (Lemma 11.1). We use capital letters (A for terms, T for types) to denote terms and types from the generic side.

Similarly to ML with restricted polymorphism, the elaboration environment Γ, described in Figure 11.5, is composed of multiple environments G, α, S, R, Θ, As in the ML typing rules, G stores the global definitions with some information derived from elaboration we will describe later. α is the list of type variables the term was originally quantified over, and Θ contains the local bindings accumulated when typing the term. It binds the variables appearing in a to ornament types describing how the values of these variables are related in a and A. It also contains bindings that are only available in the ornamented term: these are equalities, noted pu » u 1 : τ q # to highlight the fact that they are not available in a, as well as results ppuq˚p : τ q # and path variables pπq # . Similarly, the output ∆ contains the list of results produced by the evaluation of the term, and is only available on the ornamented side. S and R, explained below, contain the ornaments and patches that are used by the generic term. Finally, ω describes the ornament relation between a and A once all parts of the environment have been instantiated.

A definition is typed (Elab-Decl in Figure 11.10) in the current G environment, quantified over its type variables α, in an initially empty local environment Θ " H, and with S and R chosen by the lifting procedure (we will describe how they are chosen later). The result of the elaboration of a definition is then folded into the global environment G as a sequence of declarations of the form xxα, S, Ry : ω " a A. The environments S and R are new and used to describe abstract ornaments and patches, respectively. The generic term A is usually more polymorphic than a, since we abstract over ornaments where we originally had a fixed type. It is thus parametrized by a number of ornaments, described by the ornament specification environment S which is a set of mutually recursive bindings, each of the form ϕ Þ Ñ pδ, proj, injq ζ pω k q k : ζ pτ i q i ñ β. This binds an ornament variable ϕ that can be instantiated by an ornament of base type ζ pτ i q i with skeleton ζ pω k q k ; it also binds the target type β and the ornament type extension, projection, and injection functions to the variables δ, proj, and inj. The skeleton is important here because it determines how the arguments of constructors must be ornamented.

The ornament variables ϕ can then be used in ornament types ω. They are considered distinct from the α because they represent datatype ornaments, and because the environment S specifies what their base type is. Ornament types ω with ornament variables are projected under a given environment S: ϕ is replaced on the left with the base type given in S, and on the right with the given type variable. The definitions of the left and right projections pωq

G-Empty $ H G-Def $ G G, α $ S G, α, S $ ω orn pG, αq ´$ a : ω Ś G, α, S $ R pG, α, S, Rq `$ A : ω S $ G, xxα, S, Ry : ω " a A Wf-S @pϕ Þ Ñ _ ζ pω k q k : ζ pτ j q j ñ _q P S, pα $ τ j : Typq j ^pG, α, S $ ω k ornq k ^ppω k q Ś q k " A ζ pτ j q j G, α $ S Wf-R-Empty G, α, S $ H Wf-R-Patch G, α, S $ R pϕ Þ Ñ pδ, . . .q ω : _ ñ _q P S pG, α, S, Rq `, Θ S $ A : ωS G, α, S $ R, y : # ΠpΘ S q. rδ # As Wf-R-Inst
G, α, S $ R pxxpβ j q j , S 1 , Ry : ωq P G pG, α, S $ ω j ornq j G, α, S $ s : S 1 rβ j Ð ω j s j G, α, S $ R, pxxpω j q j , sy y : ωrpβ j Ð ω j q j , ssq Note that these environments do not contain concrete ornaments or identity ornaments: the generic term is made as generic as possible, and each concrete ornament can be replaced with an ornament variable with the same base type instead. The environment S is not ordered: each binding defines an ornament variable ϕ and a type variable β that can be used in the skeleton of any other ornament request. This is necessary to ornament recursive functions, and this is why its projection pSq `(Figure 11.6) first projects all type variables representing ornamented types before projecting the other parts of the environment.

Wf-inst @pϕ Þ Ñ _ ω : τ ñ _q P S 1 , pspϕq Þ Ñ _ spωq : τ ñ _q P S G, α, S $ s : S 1 Wf-Orn-Arrow G, α, S $ ω 1 orn G, α, S $ ω 2 orn G, α, S $ ω 1 Ñ ω 2 orn Wf-Orn-TVar α P α G, α, S $ α orn Wf-Orn-Var ϕ P S G, α, S $ ϕ orn Wf-s S 1 rss Ď Γ Γ $ s : S 1
A generic term also abstracts over patches and the liftings used to lift references to previously elaborated bindings. Since these bindings do not influence the final ornament type and are not mutually recursive, they are stored in a separate patch environment R. Together, S and R specify all the parts that have to be user-provided at specialization time (see Chapter 12).

The environment R contains lifting requests accumulated when processing the term. During elaboration, it is built as an output to the judgment: when a rule requires that something be in R, we simply add it to the output.

When the elaboration process encounters a variable x that corresponds to a global definition (Rule E-VarGlobal in Figure 11.9), we look up the signature of the elaboration of this definition pxxα, S 1 , R 1 y : ωq P G. We choose an instantiation ω of the type parameters α by ornament types, an instantiation s 1 of the ornament variables in S 1 with ornament variables of S (checked by the judgment Γ $ s : S 1 rα Ð ωs, defined by Wf-s in Figure 11.8) , and request a value y corresponding to an instantiation of the function with the chosen type and ornament parameters (we do not ask for a specific instantiation of the patches and liftings in R 1 as they do not contribute to the lifting specification) We record this instantiation R in the form pxx ω , sy y : ωrα Ð ω i , ssq P Γ. The environment R also contains patches, i.e. mML terms of the appropriate type, written in R as y : # σ. Well-formedness rules (Wf-R-Patch) require that the type σ corresponds to meta functions of multiple arguments returning a value of type rδ # us, i.e. a thunk whose evaluation gives a result of type δ # u, where δ is the extension function of some ornament in S.

The elaboration judgment Γ $ p a A : ω ñ ∆ implies two typing judgments, one for the base term a and one for the elaborated term A (this will be stated and prove in Lemma 11.1). This requires being able to project the environments for the base and ornamented terms from the elaboration environment: these projections are defined in Figure 11.7.

The projection of an environment Γ of the form G, pα i q i , S, R, Θ, noted pΓq is built from the projection of its components. On the base side, S and R are ignored, since they correspond to abstraction added to create the generic term. For the local environment, variable definitions x : ω are translated by projecting ω. Since the projection of ornament types is parametrized by S, the projection of Θ is too. The generic-only constructs (pu » u 1 : τ q # , ppuq˚p : τ q # and pπq # ) are translated to themselves on the elaborated side, and ignored on the base side.

Similarly, the patch environment R is only translated on the elaborated side. A patch request y : # A makes y : A available on the elaborated side. An instance request xxω, sy y : ω makes y available on the elaborated side, with type the projection of ω.

For the ornament environment, a type variable representing the destination type, a type variable for the extension function, and two variables for the injection and projection functions are put in scope for each ornament request. To break up the arbitrary recursion in S, we build S `as the concatenation of two environments: first we quantify over type variables representing the ornamented types, then we quantify over the components of the ornament. The type for the components of the ornament only depend on the type variables previously defined.

Finally, the global environment of elaborated definitions G projects on the left to a polymorphic environment G `and a substitution from global definitions to their non-elaborated values.

The well-formedness rules for all these constructions are given on Figure 11.8.

Proof. By induction on the well-formedness judgments of S and R. The identity ornament is well-formed, thus the functions that define it have the correct types.

For any ornament in scope, the extension δ is λ_. unit. Thus, the patches are well-typed. For the liftings, notice that each ornament is the identity ornament: thus, we ask for a function of the same type as the original function.

Lemma 11.4 (Identity instantiation and types). Suppose ω is well formed in S.

Then for all R, we have:

pωq Ś " pωq S rIdInst S,R s
Proof. By induction over ω. If pϕ Þ Ñ _ _ : τ ñ βq P S, the ornament variable ϕ is replaced by τ on the left-hand side by left-projection. On the right-hand side it is replaced by β by right-projection, then by τ again when substituting with the identity instantiation.

We define a variant of equality that passes more easily to context: a label on the left-hand side is always matched with the same label on the right-hand side. This allows substituting them into the a context that may use the results to obtain equal terms again. Definition 11.2 (Exact equality). Consider two terms a and a 1 . Suppose atomspaq is p˚p i Ð a i q iPI with conditions u i and types τ i , and atomspa 1 q is p˚p 1 j Ð a 1 j q jPJ with conditions u 1 j and types τ 1 j . Then suppose there exists a permutation σ mapping the indices in I to the indices in J such that:

• Results with the same name are equivalent: for all i, Γ, ppp k q˚u k : τ k q kăi_σpkqăσpiq $ u i : bool » u 1 σpiq : bool and Γ, ppp k q˚u k : τ k q kăi_σpkqăσpiq $ atom i : atomty i » atom 1 σpiq : atomty 1 σpiq • The results are executed in the same order: for all i, Γ, ppp k q˚u k : τ k q kăi_σpkqăσpiq $ countpu k q kăi : nat » countpu 1 k q kăσpiq : nat where countpu i q i counts the number of expressions evaluating to True: countpHq " Z and countpu, pu i q i q " match u with False Ñ countpu i q i | True Ñ S pcountpu i q i q.

• The reusable versions of a and a 1 are equal: Γ, ppu i q˚p i : τ i q i $ reusepaq : τ » reusepa 1 q : τ .

Then we say that they are exactly equal, and we write this equality ExactlyEqualpΓ $ p a : τ » a 1 : τ 1 q. ♦ Lemma 11.5. Exact equality is:

• reflexive: if Γ $ p a : τ ñ ∆, then ExactlyEqualpΓ $ p a : τ » a : τ q;

• symmetric: if ExactlyEqualpΓ $ p a 1 : τ 1 » a 2 : τ 2 q, then ExactlyEqualpΓ $ p a 2 : τ 2 » a 1 : τ 1 q;

• transitive: if ExactlyEqualpΓ $ p a 1 : τ 1 » a 2 : τ 2 q and ExactlyEqualpΓ $ p a 2 : τ 2 » a 3 : τ 3 q, then ExactlyEqualpΓ $ p a 1 : τ 1 » a 3 : τ 3 q.

Proof. For reflexivity, use the identity permutation. Then everything matches by reflexivity. For symmetry, invert the permutation and the equalities For transitivity, compose the permutation and the equalities.

Lemma 11.6 (Exact equality is a congruence). Suppose ExactlyEqualpΓ $ p a : τ » a 1 : τ 1 q. Then, if Γ 1 $ p 1 Cras : σ ñ ∆ 1 , we also have ExactlyEqualpΓ 1 $ p 1 Cras : σ » Cra 1 s : σq.

Proof. Looking at the decomposition: the reusable versions are equal, since nonexpansive equality is a congruence. Moreover, the terms match, by taking the substitution that maps every label in C to itself in the same position, and the substitution for a and a 1 for the labels present in a and a 1 .

Lemma 11.7 (Exact equality implies term equality). Suppose ExactlyEqualpΓ $ p a : τ » a 1 : τ 1 q. Then TermsEqualpΓ $ p a : τ » a 1 : τ 1 q.

Proof. The main difficulty is in matching the indexing: from the count matching we can prove that the indexings also match (the count is intuitively the inverse operation of indexing).

Theorem 11.1. Suppose G, α, S, R $ p a A : ω ñ ∆. Then, TermsEqualppGq ´, α $ p a : pωq Ś » ArIdInst S,R s : pωq Ś q, Proof. We first consider A 1 the term obtained by reducing all patches to Unit in ArIdInst S,R s (this preserves equality because it is an mML reduction).

We then prove by induction on a a stronger result that allows for a non-empty local binding environment Θ, and using exact equality to use congruence: if G, α, S, R, Θ $ p a A : ω ñ ∆, then ExactlyEqualppGq ´, α, pΘq S rIdInst S,R s $ p a : pωq Ś » A 1 : pωq Ś q.

Let us examine the rules:

• For Var-Local, we conclude by reflexivity.

• For Var-Global: this is true by our choice of instantiation.

• Other rules except E-Match and E-Con: this is true by congruence.

• For E-Con: first, apply congruence to all subexpressions. We then have to prove that dpτ i q i pa j q j is equal to pA 1 j q j ; Unit; inj ζ pτiq i # dpreusepA 1 j qq j # Unit. Both terms do the same computation in the same order, we only have to prove that the reusable versions are equal. By hypothesis, for all j, reusepa j q and reusepA 1 j q are equal. Then the right-hand side reduces to dpreusepA 1 j qq j so we get the equality.

• For E-Match: proceed similarly by applying congruence to all expressions.

To prove the final equality of the reusable terms, split on reusepaq.

Chapter 12

Lifting by instantiation

Once the user has defined some ornaments and the base terms have been elaborated, the user specifies a set of liftings of the base definitions. We describe here how these liftings are processed.

A lifting of x to y is declared as: let y β " lifting x pω j q j with s, r

The lifting y is polymorphic over a set of type variables β. It is a lifting of a toplevel definition x of type @pα j q j τ , with its type arguments instantiated with pω j q j . The declaration of x has been generalized: there is a generalized definition xxα, S, Ry : ω " a A. To obtain the lifting, the user provides an instantiation s of the ornaments of S and an instantiation r of R. These instantiations are then used to instantiate the generic term and obtain the lifting.

In this chapter, we describe how such a definition is checked, what ornament specification is derived for y, and we prove that the term we obtain indeed verifies this ornament specification.

Specifying liftings

Consider an elaborated term xxα, S, Ry : ω " a A from the global elaboration environment G. To instantiate it, we need to choose first a set of types to instantiate the α, then a sequence of ornaments for S and finally a sequence of patches and liftings for R. If the sets of types, ornaments, patches, and liftings given match the requirement, we obtain a lifting at some specification ω 1 obtained by specializing ω. We then register these liftings in a lifting environment.

The ornament instantiation s is a substitution from ornament variables to concrete datatype ornaments. We need to check that it conforms to the ornament specification S. This is checked by the judgment β $ s : S given in Figure 12.1: for every ornament request ϕ i Þ Ñ _ ωi : σ i ñ _ in S, we check that there is a binding spϕ i q " χ i pω ij q j pω 1 ik q k in s such that χ i is a valid datatype ornament (checked in a global environment left implicit), that the unconstrained arguments pω ij q j are valid ornament types, and the constrained arguments types pω 1 ik q k have the right base types, and that the skeleton of χ i pω ij q j pω 1 ik q k matches the skeleton given in the request, after substitution of s in the request.

209

Wf-OrnInst H `" H pI, @α pxxpω i q i , sy y α : ω " Aqq `" I `, y α : ω `" A

pspϕ i q " χ i pω ij q j pω 1 ik q k q i p$ χ i pα ij q j pβ ik τ ik q k Þ Ñ _ ω1 i : σ 1 i ñ _q i pα $ ω ij q ij pα $ ω 1 ik q ik ppω 1 ik q ´" τ ik rα ij Ð pω ij rssq ´sj q ik pω i rss " ω1 i rpα ij Ð ω ij q j , pβ ik Ð ω 1 ik q k sq i α $ s : pϕ i Þ Ñ _ ωi : σ i ñ _q i psq H " H psq S,ϕÞ Ñpδϕ,proj ϕ ,inj ϕ q _:_ñβ " psq S , β Ð pspϕqq `, δ ϕ Ð δ spϕq , inj ϕ Ð inj spϕq , proj ϕ Ð proj spϕq

LiftEnv-Empty

G $ H

LiftEnv-Cons G $ I pxxpβ j q j , S, _y : ω 1 q P G pα $ ω j q j α $ s : S I `; α; H $ A : ω `ω " ω 1 rpβ j Ð ω j q j , ss G $ I, @α pxxpω j q j , sy y α : ω " Aq Figure 12.2: Lifting environment When β $ s : S holds, we may take the right-projection s S of s defined in Figure 12.1: it binds all the variables bound associated to the ornament ϕ on the right-hand side to the value associated to the concrete ornament spϕq. For example, if S binds a projection function proj ϕ for ornament ϕ, and S substitutes ϕ with natlist bool, then s S substitutes proj ϕ with proj natlistbool . Lemma 12.1. Suppose β $ s : S. Then, β $ s S : pSq Proof.

This derives from the checking judgment and the types of the components of valid ornaments (Definition 10.2). From a valid s, we can deduce the specification of the lifting: it will be ωrss. We store the result A of the instantiations (we will describe how to compute it later) in a lifting environment I whose syntax is given in Figure 12.2. It is composed of bindings of the form @αpxxω, sy y α : ω " Aq indicating that the base definition x instantiated with ω has been lifted with ornament instantiation s to y with ornament specification ω. A lifting environment projects to the ornamented side as a global definition environment, as defined in Figure 12.2: each lifting is projected to its definition. We define a judgment G $ I that checks that a lifting environment is valid, i.e. that all the liftings provided have the right type and ornament specification. I; α $ r : R rpyq " z pω i q i p@pβ i q i xxpω 1 j q j , s 1 y z pβ i q i : ω 1 " _q P I pω j " ω 1 j rβ i Ð ω i s i q j s " s 1 rβ i Ð ω i s i ω " ω 1 rβ i Ð ω i s i I; α $ r : R, pxxpω j q j , sy y : ωq Proof. This is implied by the typing condition for well-formed lifting environments.

We now have to check the patch environment r, which is a substitution from patch names e to patches u (i.e. fragments of mML code) and of names of requested liftings y to names of actual liftings applied to ornament arguments z pω i q i , where z is a previously defined lifting in I. This is checked by a judgment I; β $ r : R defined in Figure 12.3. For a patch request e : # T , the judgment requires that rpeq is a non-expansive term u of type T (with the substitution prq `applied, so that information learned from previous patches can be reused). For a lifting request xxpω j q j , sy y : ω, we check that it maps to an instance z pω i q i of a lifting of x and that the instances of ornaments in the request and in the lifting match. Before checking the types, we apply the substitution s to R, so that we do not need the judgment to be parametrized by s.

We also define a projection prq `of r in Figure 12.3.

Lemma 12.3. Suppose α $ s : S, G $ I and I; α $ r : Rrs, psq S s. Then, I `, α $ prq `: pRq S .

Proof. This is implied by the typing conditions for patches and liftings.

The processing of an instantiation is described by the rule Lifting given in Figure 12.4. To process an instantiation, we first find in G the binding pxx α , S, Ry : ω " a Aq for the variable x. We then check the validity of s, then r. Finally, we construct the instantiated term Arα j Ð pω j q `, psq S , prq `s. This is an mML term: we can meta-reduce it back to eML (Theorem 7.3) then eliminate the eML constructs to obtain an ML term (Theorem 9.1). For a term B, we note simplifypBq the result of applying these two operations. We then insert the instantiated and simplified term in the lifting environment along with its lifting specification.

Lifting pxxpα i q i , S, Ry : ω " a Aq P G pβ $ ω i q j β $ s : Srα i Ð ω i s i I; β $ r : Rrpα i Ð ω i q i , s, psq SrαiÐωis i s G; I $ let y β " lifting x pω j q j with s, r ñ I, p@β xxpω j q j , sy y β : ωrpα i Ð ω i q i , ss " simplifypArpα i Ð pω i q `qi , psq RrpαiÐωiq i s , r `sqq Proof. By hypothesis on G, we have xxα, S, Ry : ω " a A. By Lemma 12.1, β $ s S : pSq `. By Lemma 12.3, I `, α $ prq `: pRq S . Thus,

I `, α $ Arpα i Ð pω i q `qi , psq RrαiÐωis i , r `s : pωq S rpα i Ð pω i q `qi , psq RrαiÐωis i , r `s
The final type is pωrpα i Ð ω i q i , ssq `because the patches and liftings do not appear in the ornament type, and projection commutes with substitution. Then, the term is ML-typed and can be simplified to an ML term by simplifyp_q.

These judgments check that the lifting is valid. In our prototype, they are also used to generate constraints that are used to infer the ornaments and liftings that have not been specified by the user. We give more details of this process in Section 13.2.

Correctness of the lifting

We use the logical relation from Chapter 8 to prove that the lifted term is related to the base term by ornamentation. We prove that any valid instantiation is related to the identity instantiation, thus by parametricity of the generic term, the identity instantiation and the user-specified instantiation are related at the ornament specification.

Suppose given an elaboration environment G generated as described in Chapter 11. Every binding in G has its base term equal to its identity instantiation. Definition 12.1. We say that a lifting environment I is correct relative to an elaboration environment G if, for every lifting @αpxxω, sy y α : pω i q i " Aq P I there is a matching binding xxpβ i q i , _, _y : _ " a _ P G, and for all indices p and γ P G p rαs, we have pγ 1 parβ i Ð pω i q ´si q, γ 2 pAqq P V p rωs γ .

♦

Then, we have the following correctness result for instantiation, stating that liftings are indeed lifted at the advertised ornament type: Theorem 12.1 (Instantiation is correct). Consider $ G, and suppose I is correct relative to G. If G; I $ let y β " lifting x pω j q j with s, r ñ I 1 , then I 1 is also correct relative to G.

Proof. We use here the notations from Lifting in Figure 12.4.

Consider an index p and an environment γ P G p rαs. We prove the correctness of the ornamentation by constructing a relational instantiation γ 1 P G p rppβ i q i , S, Rq `s. as follows:

In the case of strictly positive datatypes and first-order functions, this result can be translated to the coherence property of ornaments [START_REF] Dagand | Transporting functions across ornaments[END_REF]. We can define a projection function that projects the whole datatype at once (rather than incrementally as with the proj function), e.g. the length function for natlist α. Then, the relation expressed by natlist α between a and A is simply a " length A (up to termination). Consider the statement that append is a lifting of add at natlist α Ñ natlist α Ñ natlist α. Following the definition of the relation, it is equivalent (again, up to termination) to the fact that for all a 1 and A 1 related by natlist, and all a 2 and A 2 also related, the terms add a 1 a 2 and append A 1 A 2 are related. Since a 1 " length A 1 and a 2 " length A 2 , this translates to the fact that for all A 1 , A 2 , length pappend A 1 A 2 q " add plength A 1 q plength A 2 q.

In order to prove that, when the patches terminate, the lifted term terminates whenever the base term terminates, we need to use the relation the other way around, with the base term on the right-hand side and the lifted type on the left-hand side: for each ornament, we define a relation V q rχ ´1 pω i q i s γ using the same definition with the sides reversed. Then, a patch is in the interpretation of its type if it always terminates, and the final relation then guarantees that the lifted term terminates more often than the base term. Since the base term also terminates more often than the lifted term, they terminate on exactly the same inputs.

Chapter 13

Implementation

Our implementation works on a small subset of OCaml containing only the constructs of core ML with datatypes, but without objects, GADTs, modules, etc. (we explore possible extensions to the language in Section 15.4). It follows the structure outlined in Chapter 3. In this chapter, we examine some interesting parts of the implementation: how inference is used to perform generalization ( §13.1); how we process the lifting directives given by the user and infer the missing parts ( §13.2), and how we annotate terms to recover more readable terms after eML simplification ( §13.3).

Generalization by inference

The first step for lifting a term is to find a generalized term and the constraints on its instantiations. The rules for generalization we presented in Chapter 11 are presented as checking rules: they assume given a set of datatype ornaments and check that to each datatype constructor and pattern matching we assign an ornament variable of the right specification. In practice, we do not want the user to have to specify the generalization themself: instead, we should compute the most generic term that can be obtained from the base declaration.

For instance, consider again the example of addition of natural numbers:

let rec add = fun m n Ñ match m with | Z Ñ n | S m' Ñ S (add m' n)
As we explained previously, it is possible to use two distinct ornaments of natural numbers, one transforming the first input, and the other transforming the second input and the output. Thus, the most generic lifting has the following signature, using the notation established in Chapter 11:

addxpϕ Þ Ñ _ x nat ϕ : nat ñ _q, pψ Þ Ñ _ x nat ψ : nat ñ _q, _y : ϕ Ñ ψ Ñ ψ Reusing ML inference
We implement this by building upon ML type inference [START_REF] Milner | A theory of type polymorphism in programming[END_REF] to also extract information about ornaments. The intuition behind this process is that when two variables have the same type, it can be because their types have actually been unified during inference, or simply because we constructed the same 217 type expression twice, but unrelatedly. We can observe both in the example of add: while the branch Z Ñ n actually unifies the type of n and the return type, the type of m and the return type are only accidentally the same: we match on n with constructors of nat, thus m must have type nat, and we construct the return value using the constructor S, which also requires the return type to be nat.

This can be observed by adding a phantom type variable to the type nat: the type 'a nat_with_tag is the same as nat, but the extra type variable ensures that two unrelated instances of nat_with_tag are labeled by different variables:

type 'a nat_with_tag = Z_with_tag | S_with_tag of 'a nat let rec add_with_tag = fun m n Ñ match m with | Z_with_tag Ñ n | S_with_tag m' Ñ S_with_tag (add_with_tag m' n) val add_with_tag : 'a nat_with_tag Ñ 'b nat_with_tag Ñ 'b nat_with_tag
Here, we took the arbitrary choice of using the same tag for a natural number and its recursive argument. This is not necessary: indeed, we have seen some examples of ornaments (e.g. expr_value in Section 2.3) where the recursive structure of type does not match the original type. During ornamentation, we use the skeleton to express the fact that arguments of constructors may change types. We can similarly use the skeleton for ornament inference. This requires extending the inference to support recursive types. In OCaml, this can be enabled by passing the option ´rectypes [START_REF] Leroy | The OCaml system release 4.11: Documentation and user's manual[END_REF]. The type ('s1 , 'tag) nat_skel_tag represents the skeleton of nat, where 's1 is the type of the argument of the constructor S, and 'tag the tag distinguishing separate ornamentations. We name the constructors Z_skel_tag and S_skel_tag in the code. In mathematical notation, we will name the type | nat and its constructors q Z and q S. The type signature at the bottom can be read in the following way: let ϕ be an ornament with destination type α and skeleton x nat α, and ψ an ornament with destination type β and skeleton x nat β. Then, we can give add the ornament type ϕ Ñ ψ Ñ ψ.

Translating to ornamentation constraints

We want to prove that this reinterpretation of the ornamentation constraints translates exactly the constraints in the generalization judgment.

Consider first the case of pattern matching match x with pd i pτ j q j py ik q kPKi Ñ b i q iPI on a type ζ pτ j q j (we assume for simplicity that we are matching on a variable). Let us examine the corresponding elaboration rule, simplified to only handle matching on local variables: E-Match px : ϕq P Γ pϕ Þ Ñ pδ, inj, projq ζ pω ik q iPI,kPKi : ζ pτ j q j ñ _q P Γ ¨Γ, px ik : ω ik q kPI k , px » di ppω k q S q PI,kPK py ik q kPKi : ζ ppω k q S q PI,kPK q # $ p b i B i : ω ñ ∆ i 'i Γ $ p match x with pd i pτ j q j py ik q kPKi Ñ b i q iPI match x with p di ppω ik q S q PI, PK py ik q kPKi Ñ B i q iPI : ω ñpmatch x with di ppω k q S q PI,kPK px ik q kPKi Ñ ∆ i q i

We suppose that the datatype ζ has constructors pd i : @pα j q j pσ ik q kPI k Ñ ζ pα j q j q iPI . Its skeleton with tags is the type q ζ with parameters ppβ ik q iPI,kPKi , ϕq and constructors p q d i : @ppβ ik q iPI,kPKi , ϕq pβ ik q kPI k Ñ q ζ ppβ ik q iPI,kPKi , ϕqq iPI . We write q b i the terms obtained by applying the transformation to use the skeleton with tags to the pb i q i . Then, for the whole term the transformation gives: match x with p q d i ppq τ k q PI,kPK , ϕqpx ik q kPKi Ñ q b i q i

where ϕ is the inferred ornament for x (it will always be a variable because it cannot be unified with anything else than a variable). This expression only generates a constraint that x has type q ζ ppq τ k q PI,kPK , ϕq where ϕ is some ornament variable and the q τ ik are the types expected by the q b i , and a constraint that all the q b i return the same type, which are exactly the constraints expressed by E-Match.

Similarly, construction in the skeleton with tags expresses the constraints required by the rule E-Con used for elaborating data constructors.

We also want to show that the term rewritten to use the skeleton with tags always admits a typing: this is enough to show that elaboration is always possible. Inference will then find the most generic term. We can first apply an extension operation to a term: we replace all types by their skeleton and all constructors by the corresponding constructor in the skeleton. For example, any instance of nat becomes the cyclic type µα. x nat α (where the notation µα. F pαq denotes the recursive type that is the fixed point of F ). Similarly, any instance of S a becomes Ŝ pµα. x nat αq a. This preserves the typing constraints, since the transformation transforms datatypes in a uniform way, and all constructors are transformed in a compatible way. We then switch to the skeleton with tags by adding type variables to all skeleton types such that two types have the same variable if and only if they have exactly the same parameters. This transformation preserves all equalities between types, and preserves the property that one ornament variable is always linked to exactly one skeleton. Thus, the resulting term is well-typed.

Implementation

The implementation is not based on this transformation: instead, we directly generate the constraints that would be generated with this transformation. We use the Inferno library [Pottier, 2014a,b] to express the constraints in applicative style and solve them.

To reconstruct the final constraints in S, we keep a mapping from ornament variables ϕ, i.e. the variables used to tag skeleton types, to the corresponding skeleton type. When interpreting the solution of the constraints as an ornament type, we ignore the skeleton and only keep the ornament variable.

When generalizing a term, we obtain two kinds of free variables:

• We may get usual type variables α. These variables are copied in the environment α containing the type variables in scope of the generalized type.

• We may also quantify over ornament type variables ϕ. In this case, we look up the corresponding skeleton in the mapping from ornament variables to skeleton, and add it in S with the constraints that its skeleton be the one found in the mapping.

We also need to handle liftings and patches. This is done by keeping a global list R of patches that are required by the type. For each location needing a patch, we take the expected type from the ornament specification, we collect the type of local variables and add a patch taking the local variables as arguments and returning something of the expected type to R. For each location where a global definition is used, we need to choose the ornaments that will be used to instantiate the ornaments in its environment S 1 : we create a fresh ornament variable for each ornament in S 1 and let them unify with the other ornament variables in the term. Once inference is done, we recover their value and add to the patch environment for the current term R a request for a lifting of the global definition at the ornament specification determined during inference.

We thus obtain a generic term and an ornament specification that we add to the global environment. We immediately add the identity instantiation of this generic term as an already-done lifting and proceed to the next definition.

Strategies for instantiation

When describing the instantiation of a generic to obtain a lifting (Chapter 12), we assumed that a value was given for all the required ornaments, liftings and patches. In practice, we allow the user to give less information and try to infer the missing information using various strategies. Our strategies consider ornaments and liftings on the one hand, and patches on the other hand, in two separate phases.

The instantiation of ornaments and lifting uses unification (again, based on the type inference engine) to ensure that the provided ornaments and liftings are compatible with the requirements of the generic term and with each other. When lifting a definition of x, we first look up the generic term for x and encode the constraints in the ornament requirements S and the liftings requirements of R into type inference constraints. We then consider some information given by the user:

• The user may specify an ornament specification for the term. This ornament specification may be partial (i.e. contain wildcards _ to indicate unconstrained parts). We unify this specification with the specification of the generic term to infer the values of some variables.

• The user may specify the ornaments to be used at some construction and pattern matching locations. We add constraints specifying that the ornament at these locations must be instantiated with the specified ornament.

• The user may specify some liftings to be used at some program points. The choice of the lifting gives us additional constraints on the ornament variables in the generic term.

Once these explicit indications are processed, we apply multiple strategies:

• The user may similarly specify a list of ornaments to be used: for each program point where we still need a datatype ornament, we try each of the specified ornaments in order. This is useful for a refactoring: the user may specify that the ornament describing the refactoring is always to be used. This is expressed with a declaration of the form: ornament * Ð orn1, orn2, orn3.

• The user may specify a list of liftings to be used in priority order, but not attached to a particular location in the program. Each of these liftings is a lifting of some term y: for each occurrence of y still to be lifted, we try each of these liftings in order and commit to the first matching lifting. This in turn may instantiate some ornament variables. This can be written lifting * Ð f1, f2 , f3.

The order of application of these strategies is important: one of them might decide on an ornament and prevent the other from applying. For this reason, these clauses are always applied in the order given by the user: they may choose to prioritize one strategy over the other. We do not warn the user if one of these strategies does not apply because some other strategy already instantiated the term (this is in contrast with the hints applied to specific program locations, where we interpret as requirements for the lifted term). Finally, we propose two other optional mechanisms. The first one exploits unique liftings: after learning of some ornaments, we may end up in a situation where only one known lifting can be used in some location. In this case, the user may elect to have the unique remaining lifting automatically used. This avoids specifying some liftings, assuming that the user already defined all the liftings they may want to use.

The other mechanism allows for auto-lifting: if no lifting is available for a location (i.e. applying any existing lifting leads to a set of unsatisfiable constraints), the user may ask us to automatically generate a new lifting to fill the spot. This is useful when no patches are needed, for example in the case of refactorings: this way, a user can ask for a refactoring of one function and all functions it depends on will have refactorings automatically generated.

We have much fewer possibilities for patches, because we are not treating patches as typed: instead, we assume that they are well-typed and check the types after reduction to eML and simplification to an ML term. We still perform an approximation of type-directed patch inference: during simplification, if we are matching on an unspecified patch with a pattern matching having a single branch, we assume that the patch must start with this constructor.

Finally, when simplifying the term obtained after lifting and instantiation, some program locations may disappear, for example if we simply remove a constructor and the associated branches: for this reason, we proceed with instantiation even if some ornaments, liftings, or patches are missing. If simplification eliminates the missing program locations, we accept the lifting. Otherwise, we pretty-print the term with markers indicating where a lifting is missing, what is the name of the location and what kind of object is expected to instantiate this location. For example, the fully generalized version of add is printed as:

let rec add_gen m n = match (orn´match #4) m with | Z_skel Ñ n | S_skel m' Ñ (orn´cons #1) (S_skel (add_gen m' n)) #2
The user can deduce that #1 should be instantiated with an ornament of the type nat (since it should transform S_skel the skeleton of S), that the same should be true for #4, and that #2 should be a patch of the type required by the ornament given for #1.

Refolding terms after the transformation

The transformation described in Chapter 9 to convert eML terms to ML is rather heavy-handed: notably, it separates out possibly effectful computations and removes other let bindings. Moreover, before generalizing the term, we had to transform deep pattern matching into shallow pattern matching. The simplified term might end up rather unreadable. For this reason, after simplifying, we apply a resugaring transformation to generate a term closer to the original term.

For re-sharing let declarations, we insert markers in the term, one at the site of the original declaration and corresponding markers at every place where the definition has been expanded. When resugaring the term, we look for the markers of declarations: under the declaration, we look up all markers of uses of this declaration. If there are no uses left, we do not attempt to restore the definition. Otherwise, we check that the usages would still be well-scoped at the declaration site, compare them for syntactic equality, and re-insert a declaration for each family of equal expressions at use site. Along with the declaration marker, we store the original name of the declaration, so that we can restore it (management of names is detailed later in this section).

For pattern matching, we look at chains of pattern matching in the final term and try, as much as possible, to gather them in one pattern matching. We then compare branches: if some branches have the same code, we use an alternative pattern to regroup them. We do not add back wildcard patterns to match all remaining cases, even if they were present in the original term. We also do not preserve the order of the patterns: this could be done by adding a mark on the branches indicating which appeared first in the source term. For example, consider the input term: If we ask for its identity lifting, we obtain the following output term. The order of the branches has been lost and the wildcard pattern has been replaced by a pattern listing all alternatives, but the branches that were merged are still merged: Finally, we insert a specific mark on let bindings introduced to lift effectful computations. When we encounter such a binding, we try to insert the computation as close to its use-site in the term without reordering function applications. For example, if f1 and f2 are two functions, consider the following term and its identity lifting: let h t = (f1 t, f2 t) let h' = lifting h with ornament * Ð @id Since constructor arguments are evaluated from right to left, during its elaboration, it is transformed to:

let h' t = let x = f2 t in let y = f1 t in (x, y)
The resugaring transform will then fold the two function calls back into the construction:

let h' t = (f1 t, f2 t)
Suppose now that we apply an ornament that reverses the members of a tuple: We cannot refold both applications into the tuple construction, because they would run in the reverse order. Instead, we obtain the following term: the second applications could be folded into the construction, then the first one is blocked because if it were lifted in its position it would execute before the second one.

let h'' t = let x = f2 t in (x, f1 t)

All these transformations operate on abstract names, represented by unique integers. To generate readable code at the end, we store alongside these names the name they had in the original program. This might be a set of names, as some variables can end up identified during the transformation (for example if we match twice on the same value). Names can come both from the base term and from the pattern in the ornament definition. We then look at the names that must be available in each scope to select a name formed by one of the original names followed by a numeric prefix. If possible, we prefer shadowing variables to using the same variable with a prefix.

Taken together, these transformations generate reasonable-looking codes on our (admittedly simple) examples. To use ornamentation to transform codebases and continue working on the transformed codebase, we would have to also be able to preserve comments. This is usually done by attaching them to nodes of the abstract syntax tree. We do output pretty-printed term, but we expect that the user would prefer running a code formatter configured with the recommended style for their project as a post-processing phase before committing the code to source control.

Chapter 14

Unfolding of definitions

The presentation of lifting given before has one major restriction: we cannot change the recursive structure of a function. This is because recursive calls refer to the function being defined as a local variable, so they can only refer to the function being currently lifted.

Unfolding the recursive structure

This sometimes prevents us from writing interesting liftings of functions. For example, consider the map function on lists: We can define a type of chunked lists, where each constructor contains two elements. We define the ornament using the low-level syntax for ornaments, and use an auxiliary ornament to transform lists of odd length into an element and a list of even length. The syntax (x2, xs) : 'a odd_list is used to require this argument to be lifted with the ornament 'a odd_list and then matching on the result of the lifting. This ornament relates, e.g., the list Cons p1, Cons p2, Nilqq to Cons2 p1, 2, Nil2q.

Given such an ornament, we cannot lift the function map: we quickly realize that the type of the recursive call must be the same as the type of map because it is defined as a fixed point, while the ornament requires the recursive call to be ornamented with odd_list.

Our solution is to optionally consider recursive calls as calling global variables: then, a recursive call can be ornamented by any lifting of the function, not Similarly, if we ask for a lifting to trees, we obtain the following code after inlining:

let rec fold_tree z f x = match x with | Leaf Ñ z | Node(x, l, r) Ñ f x (f (fold_tree z f l) (fold_tree z f r))

Chapter 15

Extensions and future work

In this manuscript, we presented a theoretical framework for ornamentation, and we illustrated its usefulness with a proof of concept implementation of ornamentation. This presentation is purposefully restricted to focus on the core ideas behind the transformation. The results obtained on this restricted field are very encouraging and invite us to consider how this refactoring technique could be scaled to a wider family of cases. The theoretical framework has been explored in a core subset of ML, and on a restricted class of transformations: there is some work remaining to adapt it to handle more language features. The implementation we propose is only a proof of concept, with only the minimal features needed to demonstrate ornamentation. It only operates on a restricted subset of OCaml. Operating on this subset is already useful, but there is a lot to do to scale ornamentation to larger examples using more language features. Although they work remarkably well, our strategies to output readable code are also an interesting area for further improvements. This remaining work is extensive, and involve both interesting research topics and extensive design and engineering work, but our results indicate that scaling up ornamentation should be very rewarding. We detail some of these challenges in this chapter.

Handling effects

OCaml programs very often feature effects, in the form of non-termination, exceptions, references, and interaction with external systems. Our presentation of ornamentation only handles non-termination. In practice, programmers will want to ornament effectful programs, and thus require an ornamentation procedure that preserves a wider range of effects.

In fact, the ornamentation procedure has been carefully designed so as to preserve effects, assuming only function calls can carry side effects. This can be intuitively understood by the following reasoning: first, two instantiations of a generic term perform the same side effects (when called with related arguments) up to the side effects performed in patches: all functions are called in the same order in the same branches and with related arguments. The side effects performed by patches are interleaved between the side effects performed by the base term. Then, the term is transformed both on the left and the right-hand sides, preserving the full term equality. But full term equality also preserves effects: it precisely keeps the order of function calls and their arguments stay equal. Thus, effects should be preserved throughout the ornamentation process.

Our implementation does respect the ordering imposed by full term equality, and thus does preserve the existence and the ordering of side-effects. We are still missing a presentation of effects in mML and results asserting that they are preserved by both the logical relation and the program transformations. We would also like to explicitly handle control effects such as exceptions and continuations.

Generalizing the ornamentation relations

We limited the relations we consider on datatypes to only adding and reorganizing information. This is obviously not the only kind of transformation on datatypes that a programmer might want to perform. [START_REF] Baudin | Disornamentation. In ML 2018 -ML Family Workshop[END_REF] extend ornaments to also allow for disornamentation, i.e. removing information from a datatype. They build on the theory described in this manuscript to allow writing relations such as rev_add_loc below, removing location information from an abstract syntax tree, and lifting functions along these relations. This relation is not an ornament, since it removes information that cannot be recovered: indeed, it is a disornament as its inverse transformation would be an ornament. Their system actually generalizes ornamentation: it allows writing both ornaments, disornaments, and compositions of ornaments and disornaments in a uniform syntax. Disornamentation can be used to remove data that is no longer useful, or to provide a simplified view into a program manipulating different kinds of data at once to focus on only understanding and editing one aspect of the program. For example, the disornament above can be used to erase location information in a compiler manipulating a toy language: the programmer would then be able to see and edit code that does not manipulate the locations. After performing the desired changes, the programmer may want to port their change back to the original version of the compiler. One way to do this is to generate during the disornamentation a set of patches explaining how to reornament the program to manipulate locations again: these patches can then be applied when possible, leaving the programmer with only a few locations to fill in after reornamentation.

The example of reornamentaion is very interesting in itself, since it may offer a model to abstract away some irrelevant details when manipulating complex programs. It also shows that our framework is not exclusively limited to ornamentation and can handle at least some other transformations: we can handle disornamentation and mixed ornamentation solely by adding an argument to the function defining projection of a type before pattern matching, and propagating the corresponding requests for patches. Ornamentation and disornamentation can be freely mixed, and all the theory we developed then immediately extends to this case. Further exploration is needed to determine what other interesting transformations could be encoded, or what obstacles exist to encoding them.

Improving the patching language

The patching language we propose is very limited. We identify two main issues with it. The first one is that patches are tied to program locations expressed as integers. These locations are not at all robust to modifications of the source term, even modifications that should not change the meaning of the patches. To avoid this issue, [START_REF] Baudin | Disornamentation. In ML 2018 -ML Family Workshop[END_REF] propose to match on the syntax of the term to identify where patches should be inserted. For example, consider the incomplete version of append obtained from the addition function on natural numbers: There is a single hole #3, which may be selected with any of the following patterns:

• #[...]

• Cons(#[...], _)

• match _ with | Cons(_, _) Ñ Cons(#[...], _)

The code pattern can be used to capture the variables used in the patch, instead of relying on the names in the original term. Here, the hole should be filled with the first argument of the constructor Cons that comes from the destruction of m.

Then, the patch could be expressed as follows, with the patch inserted inside the square brackets appearing in the pattern:

patch match _ with | Cons(a, _) Ñ Cons(#[a], _)

The other issue is that most patches need to be written manually. It would be interesting to explore some strategies to generate patches, for example by exploiting typing information to deduce that only one value of the desired type could be constructed in the context [START_REF] Scherer | Which simple types have a unique inhabitant[END_REF], or by exploiting strategies such as copying the latest value of the appropriate type introduced in the context. Such a strategy could be enough to propagate source locations in an abstract syntax tree.

Scaling up the prototype

Our small prototype only works on small subset of OCaml and on small examples. Porting it to work on the full OCaml language would be a large amount of work, and would come with significant challenges. Ornament inference is based on type inference: the simplest way to implement ornament inference for OCaml might be to base it on type inference. Most alterations to the type-checker should be local to code handling data types and type constructors. Then, lifting would be based on a suitably-annotated version of the typed abstract syntax tree. Some language constructions would require special care:

Modularity Large programs tend to be split into different modules: some of these modules might be created by the programmer, others might be part of a library. In both cases, the lifting should be done following the structure of the existing modules: one module can be lifted to its lifted version, producing both the lifted code and a lifting interface similar to the module interface, but describing the relation between two versions of the module. This lifting interface could then be used as an input to the lifting process for modules depending on the first one. One can imagine that library maintainers wanting to update the interface of their library could provide such a file, allowing all clients of the library to semi-automatically lift their programs to use the newest version of the library. The OCaml module system has rich abstraction constructs (such as functors and first-class modules). These would need special care. Module used as arguments of functors often provide an abstract datatype and operations on this datatype: we can replace them with a module providing an ornament of the original datatype and implementations of these operations related to the implementations on the base type.

GADTs Programming with generalized algebraic datatypes (GADT) requires writing multiple definitions of the same type holding different invariants. GADT definitions that only add constraints could be considered ornaments of regular types, which was one of the main motivations for introducing ornaments in the first place [START_REF] Dagand | Transporting functions across ornaments[END_REF]. It would then be useful to automatically derive, whenever possible, copies of the functions on the original type that preserve the new invariants. Extending our results to the case of GADTs is certainly useful but still challenging future work. GADTs integrate both existential types and type equalities: we would have to add both into eML and mML. On the practical side, we would have to consider how a definition of an ornament from a GADT might be expressed, and ensure that the procedure for simplifying from eML terms to terms that type in ML is compatible with GADTs. It might also be necessary to add type annotations inside the lifted term to make it type: we would have to provide a mechanism to insert them.

Extensible variants, objects, polymorphic variants, and exceptions

OCaml provides some other datatype-like constructs, including objects, extensible variants and polymorphic variants. It would be interesting to accept them as both source and destination types for ornaments. For polymorphic and extensible variant, this could be expressed with a default case that transforms all constructors that were not mentioned using the identity ornament. Exceptions are represented by a global extensible variant. Ornamenting the exception type means, in essence, changing the global exception type used by some functions: then, functions using this new exception type would be incompatible with functions using the normal exception type. This is acceptable for full program refactoring, but it might be possible to find a finer strategy (for example, terms with different ornaments of the exception type become compatible again once all ornamented exception constructors are captured).

Part V

Conclusion

235

Chapter 16

Related works

Ornaments

The notion of ornament has been introduced by [START_REF] Mcbride | Ornamental algebras, algebraic ornaments[END_REF] in context of dependently-typed programming language. Here, ornaments are described in a framework where a universe of datatypes [START_REF] Chapman | The gentle art of levitation[END_REF] is encoded in the Agda programming language, allowing descriptions of indexed datatypes to be manipulated as first-class objects. Building on this description, ornaments can be described as patches over existing datatypes, adding fields and enriching their indexing. Because they respect the indexing structure of the base datatypes, ornaments describe an algebra allowing for example to forget the elements of a list to get a natural number. This ornamental algebra can be used to index lists, building vectors as an algebraic ornaments of lists.

Working in a dependently-typed programming language and over a universe of datatypes allows the flexibility to describe ornaments as first-class objects: this allows the programmer to re-use the concept of ornaments, adapting it to their specific use. On the other hand, the encoding induces a lot of syntactic overhead and makes it impossible to work on programs that operate on the native datatypes. We instead chose to have ornaments operate as a second-class construct in a tool external to the language and to the compiler: this allows ornamentation on practical programs within the constraints of ML. We lose the ability to describe ornaments as diffs: instead, we define ornaments as relations between two pre-existing types. We could recover this ability by adding a facility to generate an ornamented type and a relation by describing what data should be added on what constructors.

Finally, the presentation of ornaments in this article, and in subsequent work, is very much rooted in the presentation of datatypes as fixed points of functors: ornaments must respect the recursive structure of datatypes. In ML, the recursive structure of a datatype is less obvious: for example, when considering two mutually recursive datatypes, the recursion steps could be inserted only when coming back to the first type, or between each of the types. Using the notion of skeleton and recursive types during ornament inference, we do not have to decide on a recursive structure for each type; the way the type is to be interpreted is instead implicitly described by the user when giving the recursive structure of the ornamentation relation.

The idea of lifting functions across ornaments was introduced by [START_REF] Dagand | Transporting functions across ornaments[END_REF], along with the coherence property explaining the meaning of lifting. Again, this is done by defining a universe of functions, and a notion of functional ornament following the original signature. A notion of patch is then defined, using algebraic ornaments to have a convenient structure isomorphic to a function along with its coherence proof. By writing a term of this type, the programmer builds a correct by construction lifting. The authors then propose following the structure of the base term to build the patch: a user can build a patch reproducing the recursive structure of the base term, and then choose to lift the constructors already present. They propose an interactive mechanism to define such liftings. This idea formed the base of our exploration of semiautomatic ornamentation in ML.

In this context, [START_REF] Ko | Programming with ornaments[END_REF] explore the use of ornaments, still using universes of datatypes, to define data structures (e.g. binomial trees) as liftings of representations of binary numbers. They also define a notion of ornamentation for higher-order functions by considering an ornamentation relation between functions that is not based on projection. [START_REF] Dagand | The essence of ornaments[END_REF] presents a more general model of what ornamentation means: datatypes are represented as many-sorted signature and ornaments as cartesian morphisms on these signatures. This fits somewhat better the types available in ML, although our treatment of ornaments allows ornamentation below function arrows, even in negative position. From this categorical presentation, the author describes how a number of categorical concepts translate to operations on ornaments. Notably, vertical composition creates an ornament from two ornaments applied in sequence, and a categorical pullback would combine the data and constraints added by two ornaments and thus allow building types from base types and multiple ornamentations. These forms of composition could be integrated to our prototype implementation, and would be especially useful for GADTs, where one would want to combine multiple invariants into a single type.

On the practical side, [START_REF] Ringer | Ornaments for proof reuse in coq[END_REF] propose Devoid, an implementation of ornamentation as a plugin for Coq to allow for proof reuse. The plugin approach works directly on the Coq language and does not require an embedding of datatypes to allow their manipulation. Their work is concerned only with algebraic ornaments. They propose a way to automatically search for an ornament between two types, limiting the search by requiring that the types have the same constructors in the same order, with additional arguments accounting for the indexing. These ornaments can then be used to lift Coq terms, generating along the way a proof that the lifted terms and the base terms behave in the same way up to indexing. An automatic search for ornaments would also be interesting in ML, particularly for GADTs: when only adding constraints, without adding or reorganizing data, constructors are simply replaced with the matching constructor of the ornamented type. It would be good to ensure the programmer does not have to explicitly write such definitions.

Refactoring

The notion of refactoring has mainly been considered in context of objectoriented programming languages [START_REF] Mens | A survey of software refactoring[END_REF].

HaRe, the Haskell Refactorer [START_REF] Li | The haskell refactorer, hare, and its api[END_REF], is a refactoring tool for Haskell that automates a variety of operations (adding arguments, renaming, moving definitions across modules, etc.). The tool also provides an API allowing the programmer to define their own transformations. More recently, the Rotor tool [START_REF] Reuben Ns Rowe | Characterising renaming within ocaml's module system: theory and implementation[END_REF] has been developed to automatically perform renaming of top-level declarations in OCaml. Renaming a top-level declaration can induce many other renamings: functors take module of a given signature, and renaming an identifier in a module given as argument to a functor requires renaming the same identifier in the signature, and in all modules used in the same position.

The transformation is based on a formal semantics of names in the module system. Cross-module lifting in OCaml would be affected by similar issues (indeed, lifting may already be used as a form of renaming), where we additionally would have to take ornament types into account. This shows that handling ornamentation across modules requires some pretty involved work, although one might be able to rely on the analysis underlying such a tool to propagate ornamentation constraints.

Robert [2018] considers the problem of refactoring proofs in dependentlytypes language, where the goal is to replace the original code by some code taking into account a modification. His approaches takes as input the original program and a partially-refactored program. From this partially-refactored program, a diff is inferred, representing the modifications applied by the programmer. This diff is then repaired by propagating changes from definitions to use-sites. The diff language considered in this work handles renaming of constants and variables, changing the number, order and type of function arguments, and changing the definition of inductive types, including addition and removal of constructors and arguments. The repair process can leave holes in the patches that should be filled by the programmer. This repair process is extended to richer languages by embedding them in the core language: the richer constructs are ignored during the transformation in the hope that they do not interfere with the repair that is in progress. This is unsafe, since there is no way to detect that an embedded construct should have been repaired, but still helps in automating part of a refactoring. The embedding from the surface language to the core language used in the transformation loses some information. To preserve as much as possible the surface syntax of the original term, the abstract syntax tree on which the transformation is performed is decorated with extra information indicating the original shape of the term. This information is attached to the abstract syntax tree and preserved in a systematic way during patching (following the "Trees that grow" technique, [START_REF] Najd | Trees that grow[END_REF]). This is similar to the mark we add in terms, although we do not take such a principled approach to attaching this information: we instead have a marking construct where the mark is taken from an extensible type. Finally, to preserve the layout of the code, the repaired code is pretty-printed by following simultaneously the original code and the new code.

Pumpkin patch [START_REF] Ringer | Adapting proof automation to adapt proofs[END_REF] proposes a solution to the problem of patching proof scripts instead of terms. The idea is to examine existing adaptations to a change in a definition, and infer corresponding patches by looking at the downstream modifications. The patches are found in a typedirected way, by looking for term fragments that have the type of the desired transformation. The user can then reuse these patches to fix subsequent proofs.

Porting operations to similar datatypes

Type Theory in Color [START_REF] Bernardy | Type-theory in color[END_REF] is another way to understand the link between a base type and a richer type. Some parts of a datatype can be tainted with a color modality: this allows tracing which parts of the result depend on the tainted values and which are independent from them. Terms operating on a colored type can then be erased to terms operating on the uncolored version, which would correspond to the base term. This is internalized in the type theory: in particular, equalities involving the erasure hold automatically. This is the inverse direction from ornaments, and thus more related to disornamentation ( §15.2). Once the operations on the ornamented datatype are defined, the base functions are automatically derived, as well as a coherence property between the two implementations. Moreover, the range of transformations supported by type theory in color is more limited: it only allows field erasure, but not, for example, to rearrange a product of sums as a sum of products. Interestingly, their definition supports a notion of composition as there can be multiple colors than can be separately projected out.

Programming with GADTs may require defining one base structure and several structures with some additional invariants, along with new functions for each invariant. Ghostbuster [McDonell et al., 2016] proposes a gradual approach to porting functions to GADTs with richer invariants, by allowing as a temporary measure to write a function against the base structure and dynamically checking that it respects the invariant of the richer structure, until the appropriately typed function is written. While the theory of ornaments supports adding invariants, we do not yet support GADTs. Moreover, we propose ornaments as a way to generate new code to be integrated into the program, rather than to quickly prototype on a new datatype. [START_REF] Dagand | Foundations of Dependent Interoperability[END_REF] also consider the problem of interacting between code written to operate on dependent types and code that operates on unrestricted simple types. They propose a solution based on inserting dynamic checks at appropriate boundaries. Notably, this allows the safe interaction of code extracted from a dependently-typed language and code that may generate invalid values because it operates on less-restricted types. Their framework is based on Galois connections between simple and dependent types, which offer a very flexible notion of connection. [START_REF] Najd | Trees that grow[END_REF] also observe that one often needs many variants of a given data structure (typically an abstract syntax tree), and corresponding functions for each variant. They propose a programming idiom to solve this problem: they create an extensible version of the type, and use type families to determine from an extension name what information must be added to each constructor. In this approach, the type of the additional information only depends on the constructor, while our type-level pattern matching allows depending on the information stored in the already-present fields. Their approach uses only existing features of GHC, avoiding a separate pre-processing step and allowing one to write generic functions that operate on all decorations of a tree. On the other hand, the programmer must pay the runtime and readability cost of the encoding even when using only the undecorated tree. The encoding of extensible trees scales naturally to GADTs. Interestingly, this idiom and ornaments are largely orthogonal features with some common use case (factoring operations working on several variants of the same datatype) and might hopefully benefit from one another.

Views, first proposed by [START_REF] Wadler | Views: A way for pattern matching to cohabit with data abstraction[END_REF] and later reformulated by [START_REF] Okasaki | Views for standard ml[END_REF] have some resemblance with isomorphic ornaments. They allow several interchangeable representations for the same data, using isomorphisms to switch between views, but, again, the isomorphisms persist at runtime, which gives views applications that are quite different from those of ornamentation.

Chapter 17

Conclusion

In this work, we propose the notion of ornamentation as an interesting kind of refactoring, allowing for many useful examples that could free programmers from tedious and error-prone hand-refactoring. We use ornament types as specifications for these refactorings. The ornament types are a binary counterpart to usual types: they relate two different versions of a program, allowing us to reason about program transformations.

To implement this transformation and prove its correctness, we define a richer language mML and follow a process where from a base term we compute a generic term that can be instantiated with any ornamentation. We then use parametricity of mML to relate two instantiations of the generic term: one with identity ornaments, giving back the base term, and one with the user-specified ornaments. The instantiation with user-specified ornaments is then simplified and printed to the user.

We demonstrate a prototype implementation based on this process: we use it to illustrate how ornaments are useful on a variety of examples. One, maybe surprising, result is that, even though the transformation does a lot of modifications on the term, we manage, with a bit of marking, to recover a term close to the original term.

Many of the ideas exposed here can be reused for other transformations, as illustrated by the example of disornamentation. To allow the writing of the generic term, we construct a stack of languages over core ML: we add labels, then equalities to form eML, and meta-abstractions to form mML. The equalities and reasoning features of eML are closely related to the fact that, for ornamentation, the types of the patches depend on the shape of the term we are constructing. Other transformations might require adding some features in eML, or might not require equalities at all (that would be the case if we were only interested in pure refactorings that do not add or remove information). Labels are a very convenient way to transport information about the result of evaluating some language features that would be tricky to reason about (or that we are simply not interested in), such as side-effects: this should be useful when building other transformations. Similarly, the abstractions offered by mML are necessary as soon as the abstractions needed for the generic term cannot be expressed in ML, and they moreover ensure that traces of the encoding are eliminated from the term.

The type-like specifications we use to express the relation between the orig-243 CHAPTER 17. CONCLUSION inal and the refactored terms can be extended to encode many other transformations, such as adding and removing arguments, or defunctionalization. The idea of inferring a most general transformed term that then needs to be instantiated allows incremental interaction with the transformation: a user can see a partial result and deduce from there what next steps they should take to obtain the desired result. On the other hand, it seems harder to scale this to offer a wide range of transformations at once: the term would quickly become too abstract and unintelligible. One may want instead to guide the generation of the abstract, generic term based on the (partial) specification provided by the user. The generic term plays another key role: by being an abstraction over both the base term and the ornamented term, it allows us to only prove that the basic building blocks of the ornamentation, i.e. the function describing datatype ornaments, are related at the correct specification, and to deduce by parametricity that the whole base term and ornamented terms are related. This reasoning principle should generalize to many transformations. Providing programmers with powerful transformations they can apply as needed allows for faster development of higher-quality programs, and give them the ability to easily experiment with restructuring their code. This manuscript describes one possible transformation that is already useful by itself, but its building blocks are also hopefully reusable to construct other refactoring tools.

  type expr = | Const of int | Add of expr * expr | Mul of expr * expr let rec eval a = match a with

  type ornament oexpr : expr ñ expr' with| Const i ñ Const' i | Add (u, v) ñ Binop' (Add', u, v) when u v : oexpr | Mul (u, v) ñ Binop' (Mul', u, v) when u v : oexprThis definition is to be understood as type ornament oexpr : expr ñ expr' with| Const i´ñ Const' i`when i´ñ i`in int | Add (u´, v´) ñ Binop' (Add', u`, v`)when u´ñ u`and v´ñ v`in oexpr | Mul (u´, v´) ñ Binop' (Mul', u`, v`)

  type value = | VAbs of id * expr | VTup of value type ornament expr_value : expr ñ value with | Abs(x, e) ñ VAbs(x, e) when e : expr | Tup(e) ñ VTup(e) when e : expr_value | _ Ñ "

  let eval' = lifting eval : (id * expr_value) list Ñ expr Ñ expr_value option ( * val eval' : (id * value) list ´> expr ´> value option * ) The lifting succeeds-and eliminates all occurrences of fail () in eval'. let rec eval' env e = match e with | Var x Ñ assoc x env | Abs(x, e) Ñ Some (VAbs(x, e)) | App(e1, e2) Ñ begin match eval' env e1 with | (None | Some (VTup _)) Ñ None | Some (VAbs(x, e)) Ñ begin match eval' env e2 with | None Ñ None | Some v Ñ eval' (Cons((x, v), env)) e end end | Tup e Ñ begin match eval' env e with | None Ñ None | Some e Ñ Some (VTup e) end | Proj e Ñ begin match eval' env e with | (None | Some (VAbs(_, _))) Ñ None | Some (VTup e) Ñ Some e end We may now refine the code to add a field for storing the environment in closures: type value' = | VClos' of id * (id * value') list * expr | VTup' of value' type ornament value_value' : value ñ value' with | VAbs(x, e) ñ VClos'(x, _, e) | VTup(v) ñ VTup'(v) when v : value_value'

  let rec eval'' env e = match e with | Var x Ñ assoc x env | Abs(x, e) Ñ Some (VClos'(x, env, e)) | App(e1, e2) Ñ begin match eval'' env e1 with | (None | Some (VTup' _)) Ñ None | Some (VClos'(x, closure_env, e)) Ñ begin match eval'' env e2 with 2.4. HIDING ADMINISTRATIVE DATA | None Ñ None | Some v Ñ eval'' (Cons((x, v), closure_env ( * was env * ) )) e end end | Tup e Ñ begin match eval'' env e with | None Ñ None | Some v Ñ Some (VTup' v) end | Proj e Ñ begin match eval'' env e with | (None | Some (VClos'(_, _, _))) Ñ None | Some (VTup' v) Ñ Some v end

  Figure 3.1: Overview of the lifting process

Figure||

  Figure 4.3: Well-formedness rules

Figure 4 . 5 :

 45 Figure 4.5: Typing rules for ML

v

  ::" d τ v | fix x px : τ q : τ . a | Λpα : Typq. v E ::" rs | E a | v E | d τ pa, .. a, E, v, .. vq | Λpα : Typq. E | E τ

Figure 4

 4 Figure 4.6: Reduction for ML

  Lemma 4.2 (ÝÑ β is deterministic). Suppose a ÝÑ β b and a ÝÑ β b 1 . Then b " b 1 .

•

  If a is a let binding let x " b in b 1 , apply the induction hypothesis on b, well-typed in Γ. If b reduces to b 2 , a reduces to let x " b 2 in b 1 . Otherwise, b is a value, and a reduces to b 1 rx Ð bs. • In the case of applications a " b b 1 , by inverting the last typing rule, b and b 1 are well-typed. If b 1 reduces, a reduces. Otherwise, it is a value. Then, if b reduces, a reduces. Let us assume b and b 1 are values.

|

  Figure 5.1: Syntax of labelled ML

Figure 5 . 2 :

 52 Figure 5.2: Reduction for labeled ML

Figure 5 . 3 :

 53 Figure 5.3: Making ML terms reusable

Figure 5 . 4 :

 54 Figure 5.4: Full head reduction for labeled ML

Figure

  Figure 5.6: Translation

Figure 5

 5 Figure 5.7: Full reduction

  α : Typquq τ reduces to urα Ð τ s with label 0. Inverting the last rule (L-TApp), we get Σ; Γ $ p l Λpα : Typq. u ñ H and ∆ " H. Inverting rule L-TAbs, we get Σ; Γ $ p l u ñ H. By substitution of the type variable (Lemma 5.10), Σ; Γ $ p l urα Ð τ s ñ H,

|

  Figure 6.1: Types and kinds for eML

C

  Figure 6.3: Additional contexts for eML reduction

Figure 6 . 5 :

 65 Figure 6.5: Typing rules for eML

a

  Figure 6.11: Non-expansive reduction

Figure 6 .

 6 Figure 6.13: Interpretation of types

  Lemma 6.26 (Stability by expansive reduction). Suppose TermsEqualppα i : Typq i $ a τ a : b » τ b :) , and a ÝÑ β a 1 where the reduction reduces a function application. Then, there exists b 1 , b 2 such that b ÝÑ β b 1 without performing an expansive reduction, then b 1 ÝÑ β b 2 , performing an expansive reduction, and TermsEqualpΓ $ p a 1 : τ a » b 2 : τ b q.

|

  Figure 7.1: Kinds and types of mML

Figure 7

 7 Figure 7.3: Well-formedness for environments and kind

Figure 7 . 5 :

 75 Figure 7.5: Typing rules for mML (eML rules)

Figure 7 . 11 :

 711 Figure 7.11: Term equality for mML: new reduction rules

Figure

  Figure 7.18: Parallel reduction: congruence for terms

Figure 7

 7 Figure 7.19: Parallel reductions: congruence for types and kinds

  0 s H rπ. a 1 s

  a 2 prπ. a 0 sq p ˚pÐreusepa2qrπÐps a 2 rπ Ð ps a 0 la,1 a 1 rπ. a 0 s H rπ. a 1 s prπ. a 0 sq p H prπ. a 1 sq p

Figure 7 .

 7 Figure 7.21: Interpretation of kinds as sets of interpretations

Figure 7 .

 7 Figure 7.22: Interpretation of kinds and types as sets of types and terms

Figure 7 .

 7 Figure 7.25: Kind depth rrΓ $ κ P tTyp, Sch, Metuss " tpσ 1 , σ 2 q | Γ $ norm σ 1 : κ » σ 2 : κu

Figure 7 .

 7 Figure 7.26: Logically normalizable equalities

Figure 8 . 1 :

 81 Figure 8.1: Deterministic reduction ÝÑ d for mML

  ¨match x with True Ñ λpy : unitq. True False Ñ λpy : boolq. y 'p ¨match x with True Ñ Unit False Ñ x ' contains a type-level pattern matching because the type of both the function and the argument depend on x, but we can move this pattern matching to the term level, around the application, and obtain the following simplified term that only requires ML types: match x with True Ñ pλpy : unitq. Trueq p Unit False Ñ pλpy : boolq. yq p x

  Figure 9.1: Expanded terms, simple terms and types

Figure 10

 10 Figure 10.3: Well-formedness of ornament types

Figure 10 . 6 :

 106 Figure 10.6: The matching function

  type ornament broken : option t ñ list bool with | Some pT xq ñ Cons p_, xq when x : natlist bool | None ñ NilFor example, it relates Some pT Zq to Cons pTrue, Nilq.

  type ornament illegal : pair pbool, natq ñ either pnat, list boolq with | Pair pFalse, xq ñ Left x when x : nat | Pair pTrue, xq ñ Right x when x : natlist bool

  type ornament fixed : option t ñ list bool with rSome p r t pnatlist boolqq | Nones | Some p T xq ñ Cons p_, xq | None ñ Nil Let us now define the constraints and the interpretation of shallow ornament definitions. Suppose the type ζ has type arguments indexed by L and data constructors indexed by M with arguments indexed by N m . Consider a shallow ornament definition:

Figure

  Figure 10.8: Missing part of a pattern

Figure 11 . 1 :

 111 Figure 11.1: Environments for ML restricted to top-level polymorphism

Ś

  and pωq S are given in Figure11.7. An ornament type ω is well-formed in an

Figure 11 .

 11 Figure 11.8: Well-formedness for elaboration

Figure 12 . 1 :

 121 Figure 12.1: Ornament instantiation: checking and projection

  Patch pHq `" H pr, y Ð z ωq `" prq `, y Ð z pωq `pr, e Ð uq `" prq `, e Ð u Wf-r-Empty I; α $ r : H Wf-r-Patch I; α $ r : R I `, α $ rpeq : T rprq `s I; α $ r : R, e : # T Wf-r-Lifting

Figure 12 . 3 :

 123 Figure 12.3: Patch instantiation: grammar, projection and well-formedness

Figure 12 .

 12 Figure 12.4: Lifting

  type ('s1, 'tag) nat_skel_tag = Z_skel_tag | S_skel_tag of 's1 let rec add_st = fun m n Ñ match m with | Z_skel_tag Ñ n | S_skel_tag m' Ñ S_skel_tag (add_st m' n) val add_st : (('a, 'phi) nat_skel_tag as 'a) Ñ (('b, 'psi) nat_skel_tag as 'b) Ñ 'b

  let rec eval e = match e with | App (u, v) Ñ begin match eval u with | Some (Abs f) Ñ eval (f v) | _ Ñ None end | _ Ñ Some(e)

  let rec eval_id e = match e with| (Abs _ | Const _) Ñ Some e | App(u, v) Ñ begin match eval_id u with | Some (Abs f) Ñ eval_id (f v) | ((Some (App(_, _)) | Some (Const _)) | None) Ñ None end

  type ornament ('a, 'b) rev : ('a * 'b) ñ ('b * 'a) with | (x,y) ñ (y,x) let h'' = lifting h with ornament * Ð @id

  type 'a list = Nil | Cons of 'a * 'a list let rec map f l = match l with | Nil Ñ Nil | Cons(x, xs) Ñ Cons(f x, map f xs)

  type 'a chunked_list = Nil2 | Cons2 of 'a * 'a * 'a chunked_list type ornament 'a chunk_list : 'a list ñ 'a chunked_list with | Nil ñ Nil2 | Cons(x1, (x2, xs) : 'a odd_list) ñ Cons2(x1, x2, xs) and 'a odd_list : 'a list ñ 'a * 'a chunked_list with | Nil ñ " ( * empty lists are not odd * ) | Cons(x1, xs) ñ (x1, xs) when xs : 'a chunk_list

|

  Cons(u, v) Ñ f (gen_fold_auto z f u) (fold_list z f v) and gen_fold_auto z f x = xThis can be simplified by inlining to:let rec fold_list z f x = match x with | Nil Ñ z | Cons(u, v) Ñ f u (fold_list z f v)

  type relation rev_add_loc : (expr' * location) ñ expr with | (Abs' f, _) ñ Abs f when f : (rev_add_loc Ñ rev_add_loc) | (App' (u, v), _) ñ App (u, v) when u v : rev_add_loc | (Const' i, _) ñ Const i

  let rec append_incomplete m n = match m with | Nil Ñ n | Cons(_, m') Ñ Cons(#3, append_incomplete m' n)

  . A typing environment Γ is well-formed

	unit	: Typ
	Unit EnvEmpty : unit
	bool	: Typ
	True	: bool
	False	: bool
	void	: Typ
	nat	: Typ
	Z	: nat
	S	: nat Ñ nat
	list	: Typ ñ Typ
	Nil	: @pα : Typq list α
	Cons	: @pα : Typq pα, list αq Ñ list α
	option : Typ ñ Typ
	None : @pα : Typq option α
	Some : @pα : Typq α Ñ option α
	either : pTyp, Typq ñ Typ
	Left	: @pα : Typ, β : Typq α Ñ either pα, βq
	Right : @pα : Typ, β : Typq β Ñ either pα, βq
	pair	: pTyp, Typq ñ Typ
	Pair	: @pα : Typ, β : Typq pα, βq Ñ pair pα, βq
	Figure 4.2: Definition of some datatypes

The prototype, available at url https://morphis.me/ornaments/, contains a library of detailed examples, including those presented here.

http://caml.inria.fr/ 27

Our naming convention is to use the suffix _nat_list for the functions related to the ornament from nat to list .

CHAPTER 4. CORE MLVar $ Γx : σ P Γ Γ $ x : σ TAbs Γ, α : Typ $ u : σ Γ $ Λpα : Typq. u : @pα : Typq σTApp Γ $ τ : Typ Γ $ a : @pα : Typq σ Γ $ a τ : σrα Ð τ s Fix Γ $ τ 1 : Typ Γ $ τ 2 : Typ Γ, x : τ 1 Ñ τ 2 , y : τ 1 $ a : τ 2 Γ $ fix x py : τ 1 q : τ 2 . a : τ 1 Ñ τ 2 App Γ $ b : τ 1 Γ $ a : τ 1 Ñ τ 2 Γ $ a b : τ 2 Let Γ $ a : τ 1 Γ, x : τ 1 $ b : τ Γ $ let x " a in b : τ Con $ Γ$ d : @pα j : Typq j pτ i q i Ñ ζ pα j q j pΓ $ τ j : Typq j pΓ $ a i : τ i rα j Ð τ j s j q i Γ $ dpτ j q j pa i q i : ζ pτ j q j Match Γ $ τ : Sch pd i : @pα k :Typq k pτ ij q j Ñ ζ pα k q k q i Γ $ a : ζ pτ k q k pΓ, px ij : τ ij rα k Ð τ k s k q j $ b i : τ q i$ pd i q i : ζ complete Γ $ match a with pd i pτ k q k px ij q j Ñ b i q i : τ

Var$ Γx : σ P Γ Γ $ p x : σ ñ H TAbs Γ, α : Typ $ p u : σ ñ H Γ $ p Λpα : Typq. u : @pα :Typq σ ñ H TApp Γ $ τ : Typ Γ $ p a : @pα : Typq σ ñ ∆ Γ $ p a τ : σrα Ð τ s ñ ∆ Fix Γ, π, x : τ 1 Ñ τ 2 , y : τ 1 $ π a : τ 2 ñ ∆ Γ $ p fix π x py : τ 1 q : τ 2 . a : τ 1 Ñ τ 2 ñ H App Γ $ p a : τ 1 Ñ τ 2 ñ ∆ 1 Γ, ∆ 1 $ p b : τ 1 ñ ∆ 2 p ď q q K Γ, ∆ 1 , ∆ 2 Γ $ p a q b : τ 2 ñ ∆ 1 , ∆ 2 , pTrueq˚q : τ 2 Let Γ $ p a : τ 1 ñ ∆ 1 Γ, ∆ 1 , x : τ 1 , px » reusepaqq : τ 1 $ p b : τ ñ ∆ 2 Γ $ p let x " a in b : τ ñ ∆ 1 , ∆ 2 rx Ð reusepaqs Con $ Γ$ d : @pα j : Typq j pτ i q i Ñ ζ pα j q j pΓ $ τ j : Typq j pΓ, p∆ k q kąi $ p a i : τ i rα j Ð τ j s j ñ ∆ i q i Γ $ p dpτ j q j pa i q i : ζ pτ j q j ñ p∆ i q i Match $ pd i q i : ζ complete Γ $ τ : Sch pd i : @pα k :Typq k pτ ij q j Ñ ζ pα k q k q i Γ $ p a : ζ pτ k q k ñ ∆ pΓ, ∆, px ij : τ ij rα k Ð τ k s k q j , pd i pτ k q k px ij q j » reusepaqq : ζ pτ k q k $ p b i : τ ñ ∆ i q i Γ $ p match a with pd i pτ k q k px ij q j Ñ b i q i : τ ñ ∆, pmatch reusepaq with d i pτ k q k px ij q j Ñ ∆ i q i Coerce Γ $ p a : τ 1 ñ ∆ Γ $ τ 1 : κ 1 » τ : κ Γ $ p a : τ ñ ∆Reuse-Present puq˚q : τ P Γ Γ $ u : bool » True : bool Γ $ p ˚q : τ ñ H Reuse-Absurd

EnvTVar $ Γ α # Γ $ Γ, α : κ EnvEq $ Γ Γ $ u 1 : τ Γ $ u 2 : τ $ Γ, pu 1 » u 2 q : τ EnvPtr $ Γ p K Γ pp " π ¨q ùñ π P Γq Γ $ u : bool Γ $ τ : Sch $ Γ, puq˚p : τ K-Var $ Γ α : Typ P Γ Γ $ α : Typ K-Datatype $ Γ $ ζ : pTypq i ñ Typ pΓ $ τ i : Typq i Γ $ ζ pτ i q i : Typ K-Arr Γ $ τ 1 : Typ Γ $ τ 2 : Typ Γ $ τ 1 Ñ τ 2 : Typ K-All Γ, α : κ $ τ : Sch Γ $ @pα : Typq τ : Sch K-SubTyp Γ $ τ : Typ Γ $ τ : Sch K-Match $ pd i q i : ζ complete pd i : @pα k : Typq k pτ ij q j Ñ ζ pα k q k q i Γ $ u : ζ pτ k q k pΓ, px ij : τ ij rα k Ð τ k s k q j , pd i pτ k q k px ij q j » uq : ζ pτ k q k $ σ i : κq iΓ $ match u with pd i pτ k q k px ij q j Ñ σ i q i : κ

TEq-TransΓ $ τ 1 : κ 1 » τ 2 : κ 2 Γ $ τ 2 : κ 2 » τ 3 : κ 3 Γ $ τ 1 : κ 1 » τ 3 : κ 3 TEq-Sym Γ $ τ 1 : κ 1 » τ 2 : κ 2 Γ $ τ 2 : κ 2 » τ 1 : κ 1 TEq-Split $ pd i q i : ζ complete p$ d i : @pα k : Typq k pτ ij q j Ñ ζ pα k q k q i Γ $ u : ζ pτ k q k Γ $ σ 1 : κ 1 Γ $ σ 2 : κ 2 pΓ, px ij : τ ij rα k Ð τ k s k q j , pd i pτ k q k px ij q j » uq : ζ pτ k q k $ σ 1 : κ 1 » σ 2 : κ 2 q i Γ $ σ 1 : κ 1 » σ 2 : κ 2 TEq-SubTyp Γ $ τ : Typ » τ 1 : κ Γ $ τ : Sch » τ 1 : κ TEq-Var $ Γ α : Typ P Γ Γ $ α : Typ » α : Typ TEq-Datatype $ Γ $ ζ : pTypq i ñ Typ pΓ $ τ i : Typ » τ 1 i : Typq i Γ $ ζ pτ i q i : Typ » ζ pτ 1 i q i : Typ TEq-Arr Γ $ τ 1 : Typ » τ 1 1 : Typ Γ $ τ 2 : Typ » τ 1 2 : Typ Γ $ τ 1 Ñ τ 2 : Typ » τ 1 1 Ñ τ 1 2 : Typ TEq-AllΓ, α : Typ $ τ : Sch » τ 1 : Sch Γ $ @pα : Typq τ : Sch » @pα : Typq τ 1 : SchTEq-Match $ pd i q i : ζ complete pd i : @pα k : Typq k pτ ij q j Ñ ζ pα k q k q i Γ $ u 1 : ζ pτ 1k q k » u 2 : ζ pτ 2k q k pΓ, px ij : τ ij rα k Ð τ 1k s k q j , pd i pτ 1k q k px ij q j » u 1 q : ζ pτ 1k q k $ σ 1i : κ 1 » σ 2i : κ 2 q i Γ $ match u 1 with pd i pτ 1k q k px ij q j Ñ σ 1i q i : κ 1 » match u 2 with pd i pτ 2k q k px 1 ij q j Ñ σ 2i q i : κ 2 TEq-ReduceMatch $ pd i q i : ζ complete pd i : @pα k : Typq k pτ ij q j Ñ ζ pα k q k q i pΓ $ u j : τ ij rα k Ð τ 1 k s k q j Γ, px ij : τ ij rα k Ð τ k s k q j , pd i pτ k q k px ij q j » d i pτ 1 k q k pu j q j q : ζ pτ k q k $ σ i : κ Γ $ match d i pτ 1k q k pu j q j with pd i pτ k q k px ij q j Ñ σ i q i : κ » σ i rx ij Ð u j s j : κ Figure 6.7: Type equality

CHAPTER 6. A LANGUAGE FOR EQUALITIESEq-TransΓ $ u 1 : τ 1 » u 2 : τ 2 Γ $ u 2 : τ 2 » u 3 : τ 3 Γ $ u 1 : τ 1 » u 3 : τ 3 Eq-Sym Γ $ u 1 : τ 1 » u 2 : τ 2 Γ $ u 2 : τ 2 » u 1 : τ 1 Eq-Split $ pd i q i : ζ complete pd i : @pα k : Typq k pτ ij q j Ñ ζ pα k q k q i Γ $ u : ζ pτ k q k Γ $ u 1 : τ 1 Γ $ u 2 : τ 2 pΓ, px ij : τ ij rα k Ð τ k s k q j , pd i pτ k q k px ij q j » uq : ζ pτ k q k $ u 1 : τ 1 » u 2 : τ 2 q i Γ $ u 1 : τ 1 » u 2 : τ 2 Eq-Subst $ Γ ppu 1 » u 2 q : τ q P Γ Γ $ u 1 : τ » u 2 : τ Eq-ReduceLet Γ $ u : τ 1 Γ, x : τ 1 , px » uq : τ 1 $ u 1 : τ 2 Γ $ let x " u in u 1 : τ 2 » u 1 rx Ð us : τ 2

» τ 2 : κ 2 Γ $ u 1 : τ 1 » u 2 : τ 2 Eq-Var $ Γ x : σ P Γ Γ $ x : σ » x : σ Eq-TAbs Γ, α : Typ $ u 1 : σ 1 » u 2 : σ 2 Γ $ Λpα : Typq. u 1 : @pα : Typq σ 1 » Λpα : Typq. u 2 : @pα : Typq σ 2 Eq-TApp Γ $ τ 1 : Typ » τ 2 : Typ Γ $ u 1 : @pα : Typq σ 1 » u 2 : @pα : Typq σ 2 Γ $ u 1 τ 1 : σ 1 rα Ð τ 1 s » u 2 τ 2 : σ 2 rα Ð τ 2 s Eq-Fix Γ $ τ 1 : Typ » τ 2 : Typ TermsEqualpΓ, x : τ 1 Ñ τ 1 1 , y : τ 1 $ π a 1 : τ 1 1 » a 2 : τ 1 2 q Γ $ fix π x py : τ 1 q : τ 1 1 . a 1 : τ 1 Ñ τ 1 1 » fix π x py : τ 2 q : τ 1 2 . a 2 : τ 2 Ñ τ 1 2 Eq-Let Γ $ u 1 : σ 1 » u 2 : σ 2 Γ, x : σ 1 $ u 1 1 : τ 1 » u 1 2 : τ 2 Γ $ let x " u 1 in u 1 1 : τ 1 » let x " u 2 in u 1 2 : τ 2Eq-Con $ Γ $ d : @pα j : Typq j pτ i q i Ñ ζ pα j q j pΓ $ τ 1j : Typ » τ 2j : Typq j pΓ $ u 1i : τ i rα j Ð τ 1j s j » u 2i : τ i rα j Ð τ 2j s j q i Γ $ dpτ 1j q j pu 1i q i : ζ pτ 1j q j » dpτ 2j q j pu 2i q i : ζ pτ 2j q j Eq-Match$ pd i q i : ζ complete pd i : @pα k : Typq k pτ ij q j Ñ ζ pα k q k q i Γ $ u 1 : ζ pτ 1k q k » u 2 : ζ pτ 2k q k pΓ, px ij : τ ij rα k Ð τ k s k q j , pd i pτ 1k q k px ij q j » u 1 q : ζ pτ 1k q k $ u 1 1i : σ 1 » u 1 2i : σ 2 q i Γ $ match u 1 with pd i pτ 1k q k px ij q j Ñ u 1 1i q i : σ 1 » match u 2 with pd i pτ 2k q k px 1 ij q j Ñ u 1 2i q i : σ 2Eq-Reuse-Present puq˚p : τ P Γ Γ $ u : bool » True : bool Γ $ ˚p : τ » ˚p : τ Eq-Reuse-Absurd

$ Γ Γ $ κ wf α # Γ $ Γ, α : κ EnvEq $ Γ Γ $ u 1 : τ Γ $ u 2 : τ Γ $ τ : Sch $ Γ, pu 1 » u 2 q : τ EnvPtr $ Γ p K Γ pp " π ¨q ùñ π P Γq Γ $ u : bool Γ $ τ : Sch $ Γ, puq˚p : τ Wf-Base $ Γ κ P tTyp, Sch, Metu Γ $ κ wf Wf-TyFun α # Γ Γ $ κ wf Γ, α : κ $ κ 1 wf Γ $ Πpα : κq κ 1 wf Wf-TermFun

CHAPTER 7. STAGING WITH MMLK-Var $ Γ α : κ P Γ Γ $ α : κ K-Datatype $ Γ $ ζ : pTypq i ñ Typ pΓ $ τ i : Typq i Γ $ ζ pτ i q i : Typ K-Arr Γ $ τ 1 : Typ Γ $ τ 2 : Typ Γ $ τ 1 Ñ τ 2 : Typ K-SubTyp Γ $ τ : Typ Γ $ τ : Sch K-SubSch Γ $ τ : Sch Γ $ τ : Met K-All Γ, α : κ $ τ : Sch Γ $ @pα : Typq τ : Sch K-Match κ P tTyp, Schu $ pd i q i : ζ complete pd i : @pα k : Typq k pτ ij q j Ñ ζ pα k q k q i Γ $ u : ζ pτ k q k pΓ, px ij : τ ij rα k Ð τ k s k q j , pd i pτ k q k px ij q j » uq : ζ pτ k q k $ σ i : κq i Γ $ match u with pd i pτ k q k px ij q j Ñ σ i q i : κ K-TyAbs Γ, α : κ 0 $ τ : κ Γ $ λ # pα : κ 0 q. τ : Πpα : κ 0 q κ K-TyApp Γ $ τ : Πpα : κ 0 q κ Γ $ τ 0 : κ 0 Γ $ τ # τ 0 : κrα Ð τ 0 s K-TermAbs Γ, x : τ 0 $ τ : κ Γ $ λ # px : τ 0 q. τ : Πpx : τ 0 q κ K-TermApp Γ $ τ : Πpx : τ 0 q κ Γ $ u : τ 0 Γ $ τ # u : κrx Ð us K-TyMetaArr Γ, α : κ $ τ : Met Γ $ Πpα : κq τ : Met K-TermMetaArr Γ, x : τ 0 $ τ : Met Γ $ Πpx : τ 0 q τ : Met K-EqMetaArr Γ, pu 1 » u 2 q : σ $ τ : Met Γ $ Πpu 1 » u 2 q : σ τ : Met K-PtrMetaArr p K Γ Γ $ u : bool Γ, pu » Trueq : bool $ τ : Sch Γ, puq˚p : τ $ σ : Met

AppΓ $ p a :τ 1 Ñ τ 2 ñ ∆ 1 Γ, ∆ 1 $ p b : τ 1 ñ ∆ 2 p ď q q K Γ, ∆ 1 , ∆ 2 Γ $ p a q b : τ 2 ñ ∆ 1 , ∆ 2 , pTrueq˚q : τ 2 Let Γ $ p a : τ 1 ñ ∆ 1 Γ, ∆ a , x : τ 1 , px » reusepaqq : τ 1 $ p b : τ ñ ∆ 2 Γ $ τ : Sch Γ $ τ 1 : Sch Γ $ p let x " a in b : τ ñ ∆ 1 , ∆ 2 rx Ð reusepaqs Con $ Γ$ d : @pα j : Typq j pτ i q i Ñ ζ pα j q j pΓ $ τ j : Typq j pΓ, p∆ k q kąi $ p a i : τ i rα j Ð τ j s j ñ ∆ i q i Γ $ p dpτ j q j pa i q i : ζ pτ j q j ñ p∆ i q i Match $ pd i q i : ζ complete Γ $ τ : Sch pd i : @pα k :Typq k pτ ij q j Ñ ζ pα k q k q i Γ $ p a : ζ pτ k q k ñ ∆ pΓ, ∆, px ij : τ ij rα k Ð τ k s k q j , pd i pτ k q k px ij q j » reusepaqq : ζ pτ k q k $ p b i : τ ñ ∆ i q i Γ $ p match a with pd i pτ k q k px ij q j Ñ b i q i : τ ñ ∆, pmatch reusepaq with d i pτ k q k px ij q j Ñ ∆ i q i Coerce Γ $ p a : τ 1 ñ ∆ Γ $ τ 1 : κ 1 » τ : κ Γ $ p a : τ ñ ∆ Reuse-Present puq˚q : τ P Γ Γ $ u : bool » True : bool Γ $ p ˚q : τ ñ H Reuse-Absurd

CHAPTER 7. STAGING WITH MML TyMetaAbs Γ, α : κ $ p u : τ ñ H Γ $ p λ # pα : κq. u : Πpα :κq τ ñ H TyMetaApp Γ $ p u : Πpα : κ 0 q τ ñ H Γ $ τ 0 : κ 0 Γ $ p u # τ 0 : τ rα Ð τ 0 s ñ H TermMetaAbs Γ, x : τ 0 $ p u : τ ñ H Γ $ p λ # px : τ 0 q. u : Πpx : τ 0 q τ ñ H TermMetaApp Γ $ p u : Πpx : τ 0 q τ ñ H Γ $ p u 0 : τ 0 ñ H Γ $ p u # u 0 : τ rx Ð u 0 s ñ H EqMetaAbs Γ, pu 1 » u 2 q : σ $ p u : τ ñ H Γ $ p λ # ppu 1 » u 2 q : σq. u : Πppu 1 » u 2 q : σq τ ñ H EqMetaApp Γ $ p u : Πpu 1 » u 2 q : σ τ ñ H Γ $ u 1 : σ » u 2 : σ Γ $ p u # pu 1 » u 2 q : σ : τ ñ H PtrMetaAbs Γ, pu 0 » Trueq : bool $ τ : Sch Γ, pu 0 q˚q : τ $ p u : σ ñ H Γ $ p λ # ppu 0 q˚q : τ q. u : Πppu 0 q˚q : τ q σ ñ H PtrMetaApp Γ $ p u : Πppu 0 q˚p : τ q σ ñ H Γ, pu 0 » Trueq : bool $ p u 1 : τ ñ H Γ $ p u # ˚u1 : σr˚p Ð u 1 s ñ H Thunk Γ, π $ π a : τ ñ ∆ Γ $ p rπ. as : rτ s ñ H Unthunk Γ $ p u : rτ s ñ Hp ď q q K Γ, ∆ Γ $ p puq q : τ ñ ∆, pTrueq˚q : τ Figure 7.6: Typing rules for mML (new rules)

q κ 1 » σ

: Πpα : κ 1 2 q κ 2 Γ $ τ 1 : κ 1 1 » τ 2 : κ 1 2 Γ $ σ 1 # τ 1 : κ 1 rα Ð τ 1 sσ 2 # τ 2 κ 2 rα Ð τ 2 s TEq-TermApp Γ $ σ 1 : Πpx : τ 1 q κ 1 » σ 2 : Πpx : τ 2 q κ 2 Γ $ u 1 : τ 1 » u 2 : τ 2 Γ $ σ 1 # u 1 : κ 1 rx Ð u 1 sσ 2 # u 2 κ 2 rx Ð u 2 s TEq-TyMetaArr Γ $ κ 1 » κ 2 Γ, α : κ 1 $ τ 1 : Met » τ 2 : Met Γ $ Πpα : κ 1 q τ 1 : Met » Πpα : κ 2 q τ 2 : Met TEq-TermMetaArr Γ $ τ 1 : κ 1 » τ 2 : κ 2 Γ, x : τ 1 $ σ 1 : Met » σ 2 : Met Γ $ Πpx : τ 1 q σ 1 : Met » Πpx : τ 2 q σ 2 : Met TEq-EqMetaArr Γ $ u 11 : σ 1 » u 21 : σ 2 Γ $ u 12 : σ 1 » u 22 : σ 2 Γ, pu 11 » u 12 q : σ 1 $ τ 1 : Met » τ 2 : Met Γ $ Πpu 11 » u 12 q : σ 1 τ 1 : Met » Πpu 21 » u 22 q : σ 2 τ 2 : Met TEq-PtrMetaArr p K Γ Γ $ u 1 : bool » u 2 : bool Γ, pu 1 » Trueq : bool $ τ 1 : Sch » τ 2 : Sch Γ, pu 1 q˚p : τ 1 $ σ 1 : Met » σ 2 : Met Γ $ Πppu 1 q˚p : τ 1 q σ 1 : Met » Πppu 2 q˚p : τ 2 q σ 2 : Met TEq-Thunk Γ $ τ 1 : Sch » τ 2 : Sch Γ $ rτ 1 s : Met » rτ 2 s : MetFigure 7.8: Type equality for mML: new congruence rules

: bool » u 1

: bool Γ, pu 1 1 » Trueq : bool $ τ 1 : Sch » τ 2 : Sch Γ, pu 1 1 q˚p : τ 1 $ u 1 : σ 1 » u 2 : σ 2 Γ $ λ # ppu 1 1 q˚p : τ 1 q. u 1 : Πppu 1 1 q˚p : τ 1 q σ 1Eq-ThunkTermsEqualpΓ $ π a 1 : τ 1 » a 2 : τ 2 q Γ $ rπ. a 1 s : rτ 1 s » rπ. a 2 s : rτ 2 sEq-TyMetaApp

Γ $ u 1 # u 1 1 : τ 1 rx Ð u 1 1 s » u 2 # u 1 2 : τ 2 rx Ð u 1 2 s Eq-EqMetaApp Γ $ u 1 : Πpu 11 » u 12 q : σ 1 τ 1 » u 2 : Πpu 21 » u 22 q : σ 2 τ 2 Γ $ u 11 : σ 1 » u 12 : σ 1

TEq-SubSch Γ $ τ : Sch » τ 1 : κ Γ $ τ : Met » τ 1 : κ TEq-Split p$ d i : @pα k : Typq k pτ ij q j Ñ ζ pα k q k q i Γ $ u : ζ pτ k q k Γ $ σ 1 : κ 1 Γ $ σ 2 : κ 2 κ 1 , κ 2 P tTyp, Schu pΓ, px ij : τ ij rα k Ð τ k s k q j , pd i pτ k q k px ij q j » uq : ζ pτ k q k $ σ 1 : κ 1 » σ 2 : κ 2 q i Γ $ σ 1 : κ 1 » σ 2 : κ 2 TEq-Reduce-MetaTApp Γ, α : κ 0 $ σ : κ Γ $ τ : κ 0 Γ $ pλ # pα : κ 0 q. σq # τ : κrα Ð τ s » σrα Ð τ s : κrα Ð τ s TEq-Reduce-MetaApp Γ, x : τ $ σ : κ Γ $ u : τ Γ $ pλ # px : τ q. σq # u : κrx Ð us » σrx Ð us : κrx Ð us TEq-Reduce-MetaEqApp Γ, pu 1 » u 2 q : τ $ σ : κ Γ $ u 1 : τ » u 2 : τ Γ $ pλ # ppu 1 » u 2 q : τ q. σq # ppu 1 » u 2 q : τ q : κ » σ : κ Figure 7.10: Type equality for mML: subkinding, reduction and splitEq-Reduce-MetaTApp Γ, α : κ $ u : σ Γ $ τ : κ Γ $ pλ # pα : κq. uq # τ : σrα Ð τ s » urα Ð τ s : σrα Ð τ s Eq-Reduce-MetaApp Γ, x : τ 0 $ u : τ Γ $ u 0 : τ 0 Γ $ pλ # px : τ q. uq # u 0 : τ rx Ð u 0 s » urx Ð u 0 s : τ rx Ð u 0 sEq-Reduce-MetaEqApp

LT-DatatypeorthogonalpΓq pΣ; Γ $ l τ i q i Σ; Γ $ l ζ pτ i q i LT-Arr Σ; Γ $ l τ 1 Σ; Γ $ l τ 2 Σ; Γ $ l τ 1 Ñ τ 2 LT-All Σ; Γ $ l τ Σ; Γ $ l @pα : Typq τ LT-Match Σ; Γ $ p l u ñ H pΣ; Γ $ l τ k q k pΣ; Γ $ l σ i q i Σ; Γ $ l match u with pd i pτ k q k px ij q j Ñ σ i q i LT-TyAbs Σ; Γ $ l κ Σ; Γ $ l τ Σ; Γ $ l λ # pα : κq. τ LT-TyApp Σ; Γ $ l σ Σ; Γ $ l τ Σ; Γ $ l σ # τ LT-TermAbs Σ; Γ $ l τ Σ; Γ $ l σ Σ; Γ $ l λ # px : τ q. σ LT-TermApp Σ; Γ $ l τ Σ; Γ $ p l u ñ H Σ; Γ $ l τ # u LT-TyMetaArr Σ; Γ $ l κ Σ; Γ $ l τ Σ; Γ $ l Πpα : κq τ LT-TermMetaArr Σ; Γ $ l τ Σ; Γ $ l σ Σ; Γ $ l Πpx : τ q σ LT-EqMetaArr Σ; Γ $ p l u 1 ñ H Σ; Γ $ p l u 2 ñ H Σ; Γ $ l τ Σ; Γ $ l σ Σ; Γ $ l Πpu 1 » u 2 q : τ σ LT-PtrMetaArr p K Γ Σ; Γ $ p l u ñ H Σ; Γ $ l τ Σ; Γ, p $ l σ Σ; Γ $ l Πppuq˚p : τ q σ LT-Thunk

TEqN-eMLΓ $ τ 1 : κ 1 » τ 2 : κ 2 κ 1 , κ 2 P tTyp, Schu Γ $ norm τ 1 : κ 1 » τ 2 : κ 2 TEqN-Trans Γ $ norm τ 1 : κ 1 » τ 2 : κ 2 Γ $ norm τ 2 : κ 2 » τ 3 : κ 3 Γ $ norm τ 1 : κ 1 » τ 3 : κ 3 TEqN-SubSch-L Γ $ norm τ : Sch » τ 1 : κ Γ $ norm τ : Met » τ 1 : κ TEqN-SubSch-R Γ $ norm τ : κ » τ 1 : Sch Γ $ norm τ : κ » τ 1 : Met TEqN-SubTyp-L

q κ 1 » σ

: Πpα : κ 1 2 q κ 2 Γ $ norm τ 1 : κ 1 1 » τ 2 : κ 1 2 Γ $ σ 1 # τ 1 : κ 1 rα Ð τ 1 sσ 2 # τ 2 κ 2 rα Ð τ 2 s TEqN-TermApp Γ $ norm σ 1 : Πpx : τ 1 q κ 1 » σ 2 : Πpx : τ 2 q κ 2 Γ $ u 1 : τ 1 » u 2 : τ 2 Γ $ σ 1 # u 1 : κ 1 rx Ð u 1 sσ 2 # u 2 κ 2 rx Ð u 2 s TEqN-TyMetaArr Γ $ κ 1 » κ 2 Γ, α : κ 1 $ norm τ 1 : Met » τ 2 : Met Γ $ norm Πpα : κ 1 q τ 1 : Met » Πpα : κ 2 q τ 2 : Met TEqN-TermMetaArr Γ $ norm τ 1 : κ 1 » τ 2 : κ 2 Γ, x : τ 1 $ norm σ 1 : Met » σ 2 : Met Γ $ norm Πpx : τ 1 q σ 1 : Met » Πpx : τ 2 q σ 2 : Met TEqN-EqMetaArr Γ $ u 11 : σ 1 » u 21 : σ 2 Γ $ u 12 : σ 1 » u 22 : σ 2 Γ, pu 11 » u 12 q : σ 1 $ norm τ 1 : Met » τ 2 : Met Γ $ norm Πpu 11 » u 12 q : σ 1 τ 1 : Met » Πpu 21 » u 22 q : σ 2 τ 2 : Met TEqN-PtrMetaArr p K Γ Γ $ u 1 : bool » u 2 : bool Γ, pu 1 » Trueq : bool $ norm τ 1 : Sch » τ 2 : Sch

• If the last rule is TEq-Trans: apply induction hypothesis on the left with environments γ and γ, on the right with environments γ and γ 1 , and conclude by transitivity.• For TEq-Split:TEq-Split p$ d i : @pα k : Typq k pτ ij q j Ñ ζ pα k q k q i Γ $ u : ζ pτ k q k Γ $ σ 1 : Sch Γ $ σ 2 : Sch pΓ, px ij : τ ij rα k Ð τ k s k q j , pd i pτ k q k px ij q j » uq : ζ pτ k q k $ σ 1 : κ 1 » σ 2 : κ 2 q i Γ $ σ 1 : κ 1 » σ 2 : κ 2

Remerciements

Part IV Implementing lifting

Cette oeuvre est mise à disposition sous la

Γ $ Πppuq˚p : τ q σ : Met K-Thunk Γ $ τ : Sch Γ $ rτ s : Met Γ, α : κ 1 $ u 1 : τ » u 2 : τ 2 Γ $ λ # pα : κ 1 q. u 1 : Πpα : κ 1 q τ 1 » λ # pα : κ 2 q. u 2 : Πpα : κ 2 q τ

Eq-TermMetaAbs Γ $ τ 1 : Met » τ 2 : Met Γ, x : τ 1 $ a 1 : σ 1 » a 2 : σ 2 Γ $ λ # px : τ 1 q. a 1 : Πpx : τ 1 q σ 1 » λ # px : τ 2 q. a 2 : Πpx : τ 2 q σ 2 Eq-EqMetaAbs Γ $ u 11 : σ 1 » u 21 : σ 2 Γ $ u 12 : σ 2 » u 22 : σ 2 Γ, pu 11 » u 12 q : σ 1 $ u 1 : τ 1 » u 2 : τ 2 Γ $λ # ppu 11 » u 12 q : σ 1 q. u 1 : Πppu 11 » u 12 q : σ 1 q τ 1 »λ # ppu 21 » u 22 q : σ 2 q. u 2 : Πppu 21 » u 22 q : σ 2 q τ 2 Eq-PtrMetaAbs

.9: Term equality for mML: new congruence rules P-TyTermRed σ σ 1 u u 1 pλ # px : τ q. σq # u σ 1 rx Ð u 1 s P-TyTyRed σ σ 1 τ τ 1 pλ # pα : κq. σq # τ σ 1 rα Ð τ 1 s P-TermTermRed

pλ # pα : κq. uq # τ u 1 rα Ð τ 1 s P-TermEqRed u u 1 pλ # pu 1 » u 2 q : τ. uq # pu 1 » u 2 q : τ 1 u 1 P-TermPtrRed

prπ. asq p ˚pÐreusepa 1 qrπÐps a 1 rπ Ð ps Proof. By induction on the derivation of the reduction. When reaching a variable substituted by σ, use the reduction from its value for σ to its value for σ .

We also need to prove that the reduction is compatible with making terms reusable:

Lemma 7.8 (Reusability for ). Suppose a l a 1 . Then, there exists u such that reusepaq l u and reusepa 2 q " urls.

Proof. By induction on the derivation.

Embedding of one reduction into the other

We then need to prove that ÝÑ # is a subset of , and that is a subset of ÝÑ #. From this, we will deduce subject reduction for , and that ÝÑ # is confluent if is confluent.

We need a few lemmas analogous to lemmas from §5. The following lemma is the equivalent for mML of Lemma 5.7: Lemma 7.9 (Disjoint labels). Suppose Σ; Γ $ p l a ñ ∆. Then, Γ and ∆ are orthogonal and all labels in ∆ are prefixed by p.

Proof. Similar to Lemma 5.7.

The two next lemmas state that the typing describes what labels may be emitted by reducing a term. We need one for the usual reduction and one for the parallel reduction: Lemma 7.10 (Emitted labels). Suppose Σ; Γ $ q l a ñ ∆.

We then need to prove that conversion is sound with respect to the relation. We start by proving soundness of reduction: Lemma 7.23 (Soundness of meta-reduction). Assume that ρ ( Γ, and τ , τ 1 , κ, κ 1 are well-kinded (or well-formed) in Γ. Then rrτ ss ρ " rrτ 1 ss ρ whenever τ ÝÑ h # τ 1 and rrκss ρ " rrκ 1 ss ρ whenever κ ÝÑ # κ 1 . Proof. By structural induction on the context in which head reduction occurs. The only interesting context is the hole rs. Consider the different kinds of head-reduction on types (the induction hypothesis is not concerned with terms, and there is no head-reduction on kinds). The cases of all meta-reductions are similar. Consider for example pλ # pα : κq. τ q # τ 1 ÝÑ h # τ rα Ð τ 1 s. The interpretation of the left-hand side is pλS α P ⟪κ⟫.rrτ ss ρrαÐSαs q rrτ 1 ss ρ " rrτ ss ρrαÐrrτ 1 ssρs and the interpretation of the right-hand side is rrτ rα Ð τ 1 sss ρ " rrτ ss ρrαÐrrτ 1 ssρs by substitution (Lemma 7.22).

Lemma 7.24 (Soundness of conversion). If ρ ( Γ and Γ $ τ 1 :

Proof. By induction on the equality judgment.

• This is obviously true for TEq-Trans and KEq-Trans.

• By induction hypothesis, this is true for subtyping rules (TEq-SubTyp, TEq-SubSch).

• For all eML congruence rules (TEq-Datatype, TEq-Arr, TEq-All, TEq-Match), the result holds because the interpretation of rrτ 1 ss ρ " rrτ 2 ss ρ " B a .

• For all mML congruence rules, the result holds: by induction hypothesis, the interpretation of the subtypes/kinds appearing as premises is the same, so the interpretation of the types/kinds is the same.

• For the mML reduction rules, by soundness of meta-reduction (Lemma 7.23).

• For TEq-Split and the eML reduction rules (TEq-ReduceMatch), the types τ 1 and τ 2 have kind Typ or Sch. Their interpretations are in rrTypss ρ " rrSchss ρ " tN t u, thus are both equal to N t . Now we can prove the fundamental lemma. We consider environments γ associating term variables to terms and type variables to types. Definition 7.7. We say ρ, γ ( Γ if ρ ( Γ, for all px : τ q P Γ, γpxq P rrτ ss ρ , for all ˚p P Γ, γp˚pq P B a , and for all pα : κq P Γ, rrγpαqss ρ " ρpαq. ♦ Lemma 7.25 (Fundamental lemma). Suppose ρ, γ ( Γ. Then:

• If Γ $ τ : κ, then γpτ q P rrκss ρ .

• If Γ $ a : τ , then γpaq P rrτ ss ρ .

Proof. By mutual induction on typing, kinding, and well-formedness derivations. We will examine a few representative rules:

.24: Normal equalities: congruence rules Metss, i.e. Γ 1 $ norm Πpα : γ 1 pκ 1 qq γ 1 pτ 1 q : Met » Πpα : γ 2 pκ 2 qq γ 2 pτ 2 q : Met. We intend to apply TEqN-TyMetaArr: we need to prove that Γ 1 $ γ 1 pκ 1 q » γ 2 pκ 2 q (this is true by substitution), and that Γ 1 $ norm γ 1 pτ 1 q : Met » γ 1 pτ 2 q : Met-Consider γ 1

1 " γ 1 rα Ð α 1 s, γ 1 2 " γ 2 rα Ð α 1 s. Then, we have Γ 1 , α 1 : γ 1 pκ 1 q $ pγ 1 1 , γ 1 2 q : Γ, α : κ 1 . By induction hypothesis, pγ 1

1 pτ 1 q, γ 1 2 pτ 2 qq P rrΓ 1 $ γ 1 1 pMetqss " rrΓ 1 $ Metss. From this we obtain the desired result.

• Suppose the last rule is a congruence for an application. Consider for example TEq-TyApp:

Consider Γ 1 $ pγ 1 , γ 2 q : Γ: by induction hypothesis, pγ 1 pσ 1 q, γ 2 pσ 2 qq P rrΓ 1 $ Πpα : γ 1 pκ 1 1 qq γ 1 pκ 1 qss, and pγ 1 pτ 1 q, γ 2 pτ 2 qq P rrΓ 1 $ γ 1 pκ 1 1 qss. Then, by definition of rrΓ 1 $ Πpα : γ 1 pκ 1 1 qq γ 1 pκ 1 qss, pγ 1 pσ 1 q # γ 1 pτ 1 q, γ 2 pσ 2 q # γ 2 pτ 2 qq P rrΓ 1 $ γ 1 pκ 1 qrα Ð γ 1 pτ 1 qsss.

• Suppose the last rule is a congruence for an abstraction. Consider for example TEq-TyAbs:

Consider γ such that Γ 1 $ pγ 1 , γ 2 q : Γ. We first need to prove that Γ 1 $ norm p γ 1 pλ # pα : κ 1 1 q. τ 1 qq : γ 1 pΠpα : κ 1 1 q κ 1 q » γ 2 pλ # pα : κ 1 2 q. τ 2 q : γ 2 pΠpα : κ 1 2 q κ 2 q. This is very similar to the case of congruence for constructors treated above. Now consider pσ 1 , σ 2 q P rrΓ 1 $ γ 1 pκ 1 1 qss. We want to show pγ 1 pλ # pα : κ 1 1 q. τ 1 q # σ 1 , γ 2 pλ # pα : κ 1 2 q. τ 1 q # σ 2 q P rrΓ 1 $ γ 1 pκ 1 rα Ð σ 1 sqss, This is equivalent to showing that: pγ 1 pτ 1 rα Ð σ 1 sq, γ 2 pτ 2 rα Ð σ 2 sqq P rrΓ 1 $ γ 1 pκ 1 rα Ð σ 1 sqss. Let γ 1 1 " γ 1 rα Ð σ 1 s, γ 1 2 " γ 2 rα Ð σ 2 s be the extension of γ 1 , γ 2 with values for α. Then, Γ 1 $ pγ 1 1 , γ 1 2 q : Γ, α : κ 1 1 , and the previous inclusion can be rewritten as: pγ 1 1 pτ 1 q, γ 1 2 pτ 2 qq P rrΓ 1 $ γ 1 1 pκ 1 qss, true by induction hypothesis.

As an immediate corollary, if two terms are equal, there is a normal equality derivation between their normal forms.

We can now prove a projection result very similar to the one for eML (Lemma 6.14).

Lemma 7.33 (Projection). Consider an evironment Γ. and types pτ i q i and pτ

σ " match u with pd j pτ k q k px ji q i Ñ σ j q j rrΓ $ pΠpx : τ q σq γ:Γ ss "

^pΓ 1 $ u i a : τ i » γ i pu a q : τ i q iPt1,2u ^pΓ 1 $ u i b : τ i » γ i pu b q : τ i q iPt1,2u ^pu 1 , u 2 q P rrΓ 1 , p γ 1 pu a q » γ 1 pu b q q : γ 1 pτ q $ pσq γ:Γ,pua»u b q:τ ss

* rrΓ $ pλ # px : τ q. σq γ:Γ ss " λpu 1 , u 2 q P rrΓ 1 $ pτ q .:γ ss rrΓ 1 $ pσq γ,xÐpu1,u2q:Γ,x:τ ss rrΓ $ pτ # uq γ:Γ ss " rrΓ 1 $ pτ q γ:Γ ss p γ 1 puq , γ 2 puq q rrΓ $ pλ # pα : κq. σq γ:Γ ss " λpτ 1 , τ 2 q P rrΓ 1 $ pκq γ:Γ ss. λR P ⟪Γ 1 $ pτ 1 : κq γ:Γ ⟫. rrΓ 1 $ pσq γ,αÐpτ1,τ2,Rq:Γ,α:κ ss rrΓ $ pσ # τ q γ:Γ ss " rrΓ 1 $ pσq γ:Γ ss p γ 1 pτ q , γ 2 pτ q q rrΓ 1 $ pτ q γ:Γ ss

.30: Logical relation for mML elimination: constraints on kind interpretation Consider κ P tTyp, Schu, and suppose S P ⟪Γ 1 $ pτ : κq γ:Γ ⟫. Then, zigzagpSq.

Proof. We necessarily have:

Suppose pu 0 , u 1 q P S, pu 2 , u 1 q P S and pu 2 , u 3 q P S. Then, we have

By symmetry and transitivity, Γ $ eM L u 0 : γ 1 pτ q » u 3 : γ 2 pτ q .

We first need to prove substitution properties for our interpretations:

Lemma 7.36 (Substitution). Suppose γ P rrΓ 1 $ Γss and consider Γ $ u : τ . Let γ 1 " γ, x Ð pγ 1 puq, γ 2 puqq. Then,

• γ 1 P rrΓ 1 $ Γ, x : τ ss

• rrΓ 1 $ pτ q γ 1 :Γ,x:τ ss " rrΓ 1 $ pτ rx Ð usq γ:Γ ss

We have the same result with type substitutions, with γ 1 " α Ð pγ 1 pτ q, γ 2 pτ q, rrΓ 1 $ pτ q γ:Γ ssq.

Proof. By induction on the definitions.

We can then prove all the following by mutual induction:

Lemma 7.37 (Well-typed things are in relation). Suppose γ P rrΓ 1 $ Γss. Then,

Then, p γ 1 pu 1 q , γ 2 pu 2 q q P rrΓ 1 $ pτ 1 q γ:Γ ss.

(d) Suppose Γ $ u : τ (or Γ $ u : τ » u 1 : τ 1 q. Then, p γ 1 puq , γ 2 puq q P rrΓ 1 $ pτ q γ:Γ ss.

(e) Suppose Γ $ τ 1 : κ 1 » τ 2 : κ 2 . Then, p γ 1 pτ 1 q , γ 2 pτ 2 q q P rrΓ 1 $ pκ 1 q γ:Γ ss.

(f ) Suppose Γ $ τ : κ. Then, p γ 1 pτ q , γ 2 pτ q q P rrΓ 1 $ pκq γ:Γ ss.

(g) Suppose Γ $ τ 1 : κ 1 » τ 2 : κ 2 . Then, rrΓ 1 $ pτ 1 q γ:Γ ss " rrΓ 1 $ pτ 2 q γ:Γ ss, and ⟪Γ 1 $ pτ 1 : κ 1 q γ:Γ ⟫ " ⟪Γ 1 $ pτ 2 : κ 1 q γ:Γ ⟫.

(h) Suppose Γ $ κ 1 » κ 2 . Then, rrΓ 1 $ pκ 1 q γ:Γ ss " rrΓ 1 $ pκ 2 q γ:Γ ss, and ⟪Γ 1 $ pτ : κ 1 q γ:Γ ⟫ " ⟪Γ 1 $ pτ : κ 2 q γ:Γ ⟫.

(i) Suppose TermsEqualpΓ $ p a 1 : τ 1 » a 2 : τ 2 q, with Γ $ τ 1 : Sch and Γ $ τ 2 : Sch. Then TermsEqualpΓ $ p eML γ 1 pa 1 q : γ 1 pτ 1 q » γ 2 pa 2 q : γ 2 pτ 2 q q.

Proof. By induction on the typing/kinding/equality derivations of the judgment after "Suppose". Consider part (a). We'll only consider the kinding derivation as a premise. We can derive equivalent properties from the equalities (because they imply that their left-hand side has the right kind). Let us consider some representative kinding rules:

• If the last rule is the type variable rule, with τ " α, and pα : κq P Γ, then by hypothesis, γ R pαq P ⟪Γ 1 $ pγ 1 pαq : κq γ 1 :Γ 1 ⟫ where Γ 2 , γ 1 is a subset of Γ, γ. By weakening and substitution, ⟪Γ 1 $ pγ 1 pαq : κq γ 1 :Γ 2 ⟫ " ⟪Γ 1 $ pα : κq γ:Γ ⟫.

• If the last rule is a conversion: we have ⟪Γ $ pτ : κq γ:Γ ⟫ " ⟪Γ $ pτ :

• If the last rule is an eML type formation rule, then the type is of the form τ 1 Ñ τ 2 , @pα : Typq τ , ζ pτ i q i , or a pattern matching. Thus it has kind Typ or Sch, and the interpretation matches the single allowed interpretation.

• If the last rule is the formation of an mML arrow type, for example the rule K-TermMetaArr:

The interpretation of this kind is:

The equality condition is satisfied by using the two equality conditions and by transitivity. Let us prove this satisfies the zig-zag property: suppose pλ # px : τ 0 q. u 0 , λ # px : τ 1 q. u 1 q P S, λ # px : τ 2 q. u 2 , λ # px : τ 1 q. u 1 P S and λ # px : τ 2 q.u 2 , λ # px : τ 3 q.u 3 P S, and consider pu 1 0 , u 1 3 q P rrΓ 1 $ pτ q γ:Γ ss. Let T " rrΓ 1 $ pσq γ,xÐpu 1 1 ,u 1 2 q:Γ,x:τ ss. By induction hypothesis, T has the zigzag property, and

3 s q P T .

• If the last rule is a type-level abstraction, such as:

The type is interpreted as:

F " λpu 1 , u 2 q P rrΓ 1 $ pτ q .:γ ss rrΓ 1 $ pσq γ,xÐpu1,u2q:Γ,x:τ ss

The interpretation of this kind is:

⟪Γ 1 $ pτ : Πpx : σq κq γ:Γ ⟫ " " F ˇˇˇ@ pu 1 , u 2 q P rrΓ 1 $ pσq γ:Γ ss F pu 1 , u 2 q P ⟪Γ 1 $ pτ # x : κq γ,xÐpu1,u2q:Γ,x:σ ⟫ * Consider pu 1 , u 2 q P rrΓ 1 $ pσq γ:Γ ss. Then, γ 1 " γ, x Ð pu 1 , u 2 q P rrΓ 1 $ Γ, x : σss. Thus, by induction hypothesis, F pu 1 , u 2 q " rrΓ 1 $ pσq γ,xÐpu1,u2q:Γ,x:τ ss P ⟪Γ 1 $ pτ # x : κq γ,xÐpu1,u2q:Γ,x:σ ⟫

• If the last rule is a type-level application, such as:

By induction hypothesis (d), p γ 1 puq , γ 2 puq q P rrΓ 1 $ pσq γ:Γ ss, and by induction hypothesis (a), rrΓ 1 $ pτ q γ:Γ ss P ⟪Γ 1 $ pτ : Πpx : σq κq γ:Γ ⟫. Then, rrΓ 1 $ pτ # uq γ:Γ ss P ⟪Γ 1 $ pτ # x : κq γ,xÐp γ1puq , γ2puq q:Γ,x:σ ⟫ " ⟪Γ 1 $ pτ # u : κrx Ð usq Γ:γ ⟫ by substitution.

For part (d), let us consider some representative rules. We will omit part (d), (e) and (f) as they are very similar.

• If the last rule is variable rule, this is immediate by hypothesis on γ.

• If the last rule is a conversion rule: by part (g) the interpretation of the original type and the converted type are equal.

• If the last rule is the transitivity rule:

By induction hypothesis (g), we have rrΓ 1 $ pτ 1 q γ:Γ ss " rrΓ 1 $ pτ 2 q γ:Γ ss. We also have, by (c) and (d):

p γ 1 pu 1 q , γ 2 pu 2 q q P rrΓ 1 $ pτ 1 q γ:Γ ss p γ 1 pu 2 q , γ 2 pu 2 q q P rrΓ 1 $ pτ 2 q γ:Γ ss p γ 1 pu 2 q , γ 2 pu 3 q q P rrΓ 1 $ pτ 2 q γ:Γ ss Thus, by the zig-zag property, p γ 1 pu 1 q , γ 2 pu 3 q q P rrΓ 1 $ pτ 1 q γ:Γ ss.

• If the last rule is an eML congruence or reduction rule, or the split rule (ie. any eML rule that has Sch-kinded output types): we will consider Eq-Let for example.

Eq-Let

By induction hypothesis, p γ 1 pu 1 q , γ 2 pu 2 q q P rrΓ $ pσ 1 q γ:Γ ss P ⟪Γ $ pσ 1 : Schq γ:Γ ⟫. Thus, we have Γ 1 $ eM L γ 1 pu 1 q : γ 1 pσ 1 q » γ 2 pu 2 q : γ 2 pσ 2 q and similarly Γ 1 , x : γ 1 pσ 1 q $ eM L γ 1 pu 1 1 q : γ 1 pτ 1 q » γ 2 pu 1 2 q : γ 2 pτ 2 q . Then, by Eq-Let, we have Γ 1 $ eM L let x " γ 1 pu 1 q in γ 1 pu 1 1 q : γ 1 pτ 1 q » let x " γ 2 pu 2 q in γ 2 pu 1 2 q : γ 2 pτ 2 q . Finally, γ i plet x " u i in u 1 i q " let x " γ i pu i q in γ i pu 1 i q .

• If the last rule is congruence for an mML abstraction, for example:

The interpretation of the type is:

We have γ i pλ # px : τ i q. a 1 q " λ # px : γ i pτ i q q. u i . The typing conditions are satisfied because normalization preserves equality.

Consider pu 1 1 , u 1 2 q P rrΓ 1 $ pτ 1 q γ:Γ ss. We have γ 1 " γ, x Ð pu 1 1 , u 1 2 q P rrΓ 1 $ Γ, x : τ 1 ss. By induction hypothesis, p γ 1 1 pa 1 q , γ 1 2 pa 2 q q P rrΓ 1 $ pσq γ,xÐpu 1 1 ,u 1 2 q:Γ,x:τ1 ss. We conclude because γ 1 i pu i q " γ i pu i q rx Ð u 1 i s " u i rx Ð u 1 i s .

• If the last rule is congruence for an mML application, for example:

By induction hypothesis, and unpacking the definition, we learn that p γ 1 pu 1 q , γ 2 pu 2 q q is a pair of abstractions. Then, reducing, we obtain a term that is guaranteed to be in the correct interpretation.

For part (i), notice that normalization distributes around term equality: we can normalize all subterms, then remove all thunks using the fact that thunktyped terms reduce to thunkings, and normalize what was inside the thunks independently.

For part (g), let us consider some representative rules. We will omit part (h) as it is very similar.

• If the last rule is transitivity, we use transitivity of the equality.

• If the last rule is a conversion, use the induction hypothesis directly.

• Consider the case of an equality between eML types (ie. of kind κ P tTyp, Schu): The interpretations of τ 1 are the sets of pairs of terms pu 1 , u 2 q such that Γ 1 $ eM L u 1 : γ 1 pτ 1 q » u 2 : γ 2 pτ 1 q , and we wish to substitute τ 2 for τ 1 there. Consider the first type (the second is similar):

^@k ď j, @pv 1 , v 2 q P R k , p$ v i :

^@k ď j, @pτ 1 , pS q ďk , τ 2 q P Krκs γ1,γ2 , pσ 1 # τ 1 , pF pτ 1 , pS h q hď , τ 2 qq ďk , σ 2 # τ 2 q P K k rκ 1 s pγ1,αÐτ1q,pγ2,αÐτ2q ^@k ď j, @pτ 1 , pS q ďk , τ 2 q P K k rκs γ1,γ2 , @pτ 1 1 , τ 1 2 q,p$ τ i :

^@k ď j, @pv 1 , v 2 q, p$ v i : a sequence of interpretation at levels l ď k, and returns the interpretation at rank k. We require the triple formed by the types and the interpretation to be in K k rκs γ1,γ2 . We say that two environments γ 1 and γ 2 are equal, noted $ γ 1 » γ 2 : Γ, if they map type, term, and result variables to equal type, terms and results. Then, equal kinds have equal interpretations in equal environments: Lemma 8.3 (Equal kinds have equal interpretations in equal environments).

Proof. By induction on equality derivations. The kind equality rules preserve the head constructor. The types and terms in the environment are only used in typing judgments which are stable by substitution.

Lemma 8.4 (The interpretation of kinds is well-indexed). Consider a kind κ, and environments γ 1 , γ 2 . Let k ď j. Then, if pσ 1 , pS q ďj , σ 2 q P K j rκs γ1,γ2 , then pσ 1 , pS q ďk , σ 2 q P K k rκs γ1,γ2

Proof. By induction on kinds.

where pγ i puq ÝÑ 0 d v i q iPt1,2u V j rλ # pα : κq. τ s γ " λpR P K j rκs γ1,γ2 q. V j rτ s γ,αÐR V j rλ # px : κq. τ s γ " λpv 1 , v 2 q. V j rτ s γ,xÐpv1,v2q

-V j r@pα : Typq σs γ " "ˆΛ pα : Typq. u 1 , Λpα : Typq. u 2 ˙ˇˇˇ@ k ď j, @pτ 1 , S, τ 2 q P K k rTyps γ1,γ2 ,

˙ˇˇˇp H $ γ i pu i q : γ i pτ q » γ i pu 1 i q : γ i pτ qq iPt1,2u ùñ pu 2 1 , u 2 2 q P E j rσs γ * V j rΠpα : κq σs γ " "ˆλ # pα : κ 1 q. u 1 , λ # pα : κ 2 q. u 2 ˙ˇˇˇ@ k ď j, @pτ 1 , S, τ 2 q P K k rκs γ1,γ2 , pu 1 rα Ð τ 1 s, u 2 rα Ð τ 2 sq P E k rσs γ,αÐpτ1,S,τ2q

The definition of r ζ we provided satisfies these criteria. For such a definition, we can define its interpretation in the logical relation. For a clause i P I, we note P i " d i pP in q nPNi , binding variables px ip q pPPi . Two values are related if:

• we can choose a clause i P I with head constructor d i such that the lefthand side is d i pv n´q nPNi ;

• for each n P N i we have a lifting v n`o f v n´a t the ornament type ω in specified in the skeleton;

• for all n P N i , the left-hand side patterns P in match the lifted values v n`, binding the variables px ip q pPPi appearing in the pattern to values pw ip q pPPi ;

• the right-hand side matches Q i given the values of the variables pw ip q pPPi More formally, the interpretation of the ornament is the following:

Our example becomes (after simplification):

V q r r t ωs γ " ! pT w ´, T v ´q ˇˇpw´, w `q P V q rωs γ )

V q rfixeds γ " tpNone, NilquY $ & % pSome w ´, v `q ˇˇˇˇˇp w ´, w `q P V q r r t pnatlist boolqs γ ^w`" T w 1 ^v`P Values xÐw 1 pCons p_, xqq

, .

-Inlining the first definition into the second we obtain:

V q rfixeds γ " tpNone, NilquY " pSome pT w ´q, v `q ˇˇˇp w ´, w `q P V q rnatlist bools γ ^v`P Values xÐw`p Cons p_, xqq *

From high-level definition to low-level definition

We build the encoding of ornaments from shallow definitions but we allow the user to specify ornaments using the higher-level deep ornamentation syntax. In this section, we will describe the transformation from deep to shallow ornaments and prove that a high-level definition and its low-level translation have the same interpretation: this is enough to show that they are equivalent.

The transformation operates on every ornament definition independently, and never generates constraints on the base type of ornament parameters. Consider an ornament definition of the form: type ornament χ pα j q j : ζ pτ k q kPK ñ σ `with pP i ñ Q i when px i : ω i q PI q iPI Var-Local px : τ q P Θ G; α; Θ $ x : τ Var-Global px pβ j q j : σq P G pα $ τ j : Typq j G; α; Θ $ x pτ j q j : σrβ

$ pd i q i : ζ complete G; α; Θ $ match a with pd i pτ k q k px ij q j Ñ b i q i : τ α S " α pω 1 Ñ ω 2 q S " pω 1 q S Ñ pω 2 q S pϕ Þ Ñ _ _ : τ ñ αq P S ϕ Ś " τ ϕ S " α

Elaboration

The main elaboration judgment Γ $ p a A : ω ñ ∆ is described in Figure 11.9. It follows the structure of the original term. We need to expand Γ as G, α, S, R, Θ to describe the flow of information during elaboration: G, α, and Θ are inputs, while S and R are outputs, and added to on demand (some equality constraints may force two ornament variables in S to be unified). The term a is an input while A and ω are outputs. Applications, abstractions, letbindings, and local variables are translated to themselves. We also add labels, label variables, equalities, and compute the output results.

We have already explained the elaboration of global variables.

The key rules are pattern matching and construction of datatypes. For E-Match, consider a pattern matching match a with pd i pτ j q j px ik q kPKi Ñ b i q iPI . We first elaborate the term a that we are matching on to a term A. We expect the ornament relation to be some ornament variable ϕ: it must be a datatype ornament, and it cannot be a concrete ornament). We check the ornament environment for ϕ: we find an ornament specification pϕ Þ Ñ pδ, inj, projq ζ pω ik q iPI,kPKi : ζ pτ j q j ñ _q P Γ. We check that the base type is the one specified for the ornament. The type of the skeleton is ζ pω ik q iPI,kPKi , given by the ornamentation specification. Then, in the elaborated term, we bind A to a variable x and match on x of type ζ ppω ik q Γ q iPI,kPKi . We then elaborate each branch independently at a common ornament type ω in an environment that holds the equality between reusepAq and the pattern of the branch. The ornamented versions are the pB i q i . The rule for constructors E-Con works similarly: we lookup the returned ornament type ϕ, obtain the ornaments to be used for each argument from the skeleton, then elaborate each argument at this type (adding the results computed from previous elaborated arguments). Finally, we request a patch e that will have access to all local definitions as well as the results computed when evaluating the elaborated version of the arguments. In the elaborated term we first evaluate the elaborated versions pA j q j of each argument and bind them to variables px j q j , evaluate the result of applying the patch and bind it to y, then call the construction function inj with these arguments.

ELABORATION

205

Γ " _, _, S, _, Θ p ď q p K Θ, p∆ j q j $ d : @pα i q i pτ j q j Ñ ζ pα i q i pϕ Þ Ñ pδ, inj, projq ζ pω k q k : ζ pσ i q i ñ _q P S pΓ, p∆ q ăj $ p a j A j : ω j ñ ∆ j q j pe : # ΠpΘ S , p∆ j q j q rδ # dppω k q S q k preusepA j qq j sq P Γ Γ $ p dpσ i q i pa j q j let px j " A j q j in let y " pe # pω k q S # p∆ j q j q q in inj # dppω k q S q k px j q j # y : ϕ ñp∆ j q j , pTrueq˚q : δ # dppω k q S q k preusepA j qq j E-Match pϕ Þ Ñ pδ, inj, projq ζ pω ik q iPI,kPKi : ζ pτ j q j ñ _q P Γ Γ $ p a A : ϕ ñ ∆ ¨Γ, ∆, px ik : ω ik q kPI k , pproj # reusepAq » di ppω k q S q PI,kPK px ik q kPKi : ζ ppω k q S q PI,kPK q # $ p b i B i : ω ñ ∆ i 'i Γ $ p match a with pd i pτ j q j px ik q kPKi Ñ b i q iPI let y " A in match proj # y with p di ppω ik q S q PI, PK px ik q kPKi Ñ B i q iPI : ω ñ∆, pmatch x with di ppω k q S q PI,kPK px ik q kPKi Ñ ∆ i q i In practice, the elaboration is obtained by inference. We first construct an elaborated term where all ornamentation records are different, and type it using the normal ML inference (this always succeeds because the term can be instantiated with records defining identity ornaments). Then, according to the constraints on elaboration environments, ornaments with the same lifted type must be the same. This is in fact sufficient: we only have to merge the ornaments whose lifted types are unified by ML inference. We thus obtain the most general generic program. We describe our implementation of this process in Section 13.1.

Identity instantiation

The correctness of the elaboration (Theorem 12.1) is based on the fact that, when instantiated with the identity ornament, the elaborated term is equal (for the mML equality) to the base term. Along with parametricity, this result is sufficient to prove the correctness of the ornamentation.

Consider a generic term xxα, S, Ry : ω " a A. We obtain the identity instantiation by instantiating all ornaments with the identity ornament, all lifting requests with the base definition, and all patches with a patch that always return Unit. Definition 11.1 (Identity instantiation). Suppose xxα, S, Ry : ω " a A. Then, the identity instantiation of A, noted IdInst S,R is defined as follows:

• For all pϕ Þ Ñ pδ, proj, injq ζ pω i q i : ζ pτ q ñ βq P S, we instantiate ϕ with the identity ornament: we have IdInst S,R pβq " ζ pτ q , IdInst S,R pδq " δ ζ pτ q , IdInst S,R pprojq " proj ζ pτ q , IdInst S,R pinjq " inj ζ pτ q .

• For all e : # Θ Ñ δ # A P R, we set IdInst S,R peq " λ # Θ. rπ. Units.

• For all pxx ω , sy y : ω 1 q P R, we use the base term: IdInst S,R pyq " x p ω q Ś . ♦ Then, we obtain a well-typed instantiation in the base environment: Lemma 11.3. If $ G, α, S, R, then IdInst S,R exists and pG, αq ´$ IdInst S,R : pS, Rq `.

• For all β i , γ 1 pβ i q " pV q rω i s γ q q .

• For all ornaments pϕ Þ Ñ pδ, proj, injq ζ pω i q i : ζ pτ q ñ βq P S P S, we set γ 1 1 and γ 1 2 using the values and types in IdInst S,R and psq S respectively, and the relations as follows:

γ 1 R pβq " pV q rrpϕqs γ q q ; γ 1 R pδq " pλpv 1 , v 2 q. tpUnit, w 2 q | $ w 2 : γ 1 2 pδq # v 2 uq q

• For all patches e, γ 1 peq " pIdInst S,R peq, rpeqq.

• For all liftings y of x pω i q i , γ 1 pyq " px ppω i q Ś q i , rpyqq.

This is a valid relational environment:

• Ornaments are related by Theorem 10.1.

• Patches are related: the type of a patch is always of the form ΠpΓq.rδ # us for some term u. Consider u 1 and u 2 the two patches. Then, we apply some arguments described by Γ and evaluate the thunk, and compare the results in E q rδ # us γ 2 for some γ 2 . The left-hand side reduces to Unit. Suppose the right-hand side reduces to a value v 2 . Then, the relation for δ # u relates Unit to any value, thus the relation holds.

• Liftings are related by the condition on I.

We have by hypothesis on G: G, α, S, R $ p a A : ω ñ ∆. Then, by Lemma 11.1, α, S `, R S $ p A : ω S ñ ∆. Then, by Theorem 8.1, we have pγ 1

1 pAq, γ 1 2 pAqq P V p rω S s γ 1 We have ω S " ωrϕ Ð β ϕ s where β ϕ is the type variable associated to ϕ in S. γ 1 R associates β ϕ to Vrspϕqs γ . Moreover, γ 1 associates the pα i q i to the relation of the corresponding ω i interpreted in γ. Thus, by substitution, V p rω S s γ 1 " V p rωrpα i Ð ω i q i , sss γ,γ 1 " V p rωrpα i Ð ω i q i , sss γ (the last equality is because the variables in γ 1 do not appear in the type ωrpα i Ð ω i q i , ss).

In the pair of related terms pγ 1 1 pAq, γ 1 2 pAqq, the left-hand term is equal to ArIdInst S,R srα i Ð pω i q ´si . By Theorem 11.1 applied to the elaboration A of a, we have pβ i q i $ A : pωq Ś » a : pωq Ś . Then: α $ γ 1 1 pAq : pωq Ś rα i Ð pω i q ´si » arα i Ð pω i q ´si : pωq Ś rα i Ð pω i q ´si

The right-hand side term γ 1 2 pAq is Arpα i Ð pω i q `qi , psq RrpαiÐωiq i s , r `s. By Theorem 9.1:

2 pAq : pωrssq `» simplifypArpα i Ð pω i q `qi , psq RrpαiÐωiq i s , r `sq : pωrssq Finally, since the relation is stable by equality, and by composition with γ:

pγ 1 parα i Ð pω i q ´si q, γ 2 psimplifypArpα i Ð pω i q `qi , psq RrpαiÐωiq i s , r `sqqq P V p rωrpα i Ð ω i q i , sss γ