1 Introduction

In this work we consider a new type system for a call-by-value language, with control operators, polymorphism and dependent products. It is intended to serve as a theoretical basis for a proof assistant focusing on program proving, in a language similar to OCaml or SML. The proof mechanism relies on dependent products and equality types \(t \equiv u\), where t and u are (possibly untyped) terms of the language. Equality types are interpreted as \(\top \) if the denoted equivalence holds and as \(\bot \) otherwise.

In our system, proofs are written using the same language as programs. For instance, a pattern-matching corresponds to a case analysis in a proof, and a recursive call to the use of an induction hypothesis. A proof is first and foremost a program, hence we may say that we follow the “program as proof” principle, rather than the usual “proof as program” principle. In particular, proofs can be composed as programs and with programs to form proof tactics.

Programming in our language is similar to programming in any dialect of ML. For example, we can define the type of unary natural numbers, and the corresponding addition function.

figure afigure a

We can then prove properties of addition such as add Z[] n \(\equiv \) n for all n in nat. This property can be expressed using a dependent product over nat and an equality type.

figure bfigure b

The term \(\texttt {8<}\) (to be pronounced “scissors”) can be introduced whenever the goal is derivable from the context with equational reasoning. Our first proof is immediate since we have add Z[] n \(\equiv \) n by definition of add.

Let us now show that add n Z[] \(\equiv \) n for every n in nat. Although the statement of this property is similar to the previous one, its proof is slightly more complex and requires case analysis and induction.

figure cfigure c

In the S[nn] case, the induction hypothesis (i.e. add nn Z[] \(\equiv \) nn) is obtained by a recursive call. It is then used to conclude the proof using equational reasoning. Note that in our system, programs that are considered as proofs need to go through a termination checker. Indeed, a looping program could be used to prove anything otherwise. The proofs addZeroN and addNZero are obviously terminating, and hence valid.

Several difficulties arise when combining call-by-value evaluation, side-effects, dependent products and equality over programs. Most notably, the expressiveness of dependent products is weakened by the value restriction: elimination of dependent product can only happen on arguments that are syntactic values. In other words, the typing rule

figure dfigure d

cannot be proved safe if u is not a value. This means, for example, that we cannot derive a proof of add (add Z[] Z[]) Z[] \(\equiv \) add Z[] Z[] by applying addNZero (which has type \(\varPi \) n:nat (add n Z[] \(\equiv \) n)) to add Z[] Z[] since it is not a value. The restriction affects regular programs in a similar way. For instance, it is possible to define a list concatenation function append with the following type.

$$\begin{aligned} \varPi \texttt {n:nat} \varPi \texttt {m:nat List(n)} \Rightarrow \texttt {List(m)} \Rightarrow \texttt {List(add n m)} \end{aligned}$$

However, the append function cannot be used to implement a function concatenating three lists. Indeed, this would require being able to provide append with a non-value natural number argument of the form add n m.

Surprisingly, the equality types and the underlying observational equivalence relation provide a solution to the lack of expressiveness of dependent products. The value restriction can be relaxed to obtain the rule

figure efigure e

which only requires u to be equivalent to some value v. The same idea can be applied to every rule requiring value restriction. The obtained system is conservative over the one with the syntactic restriction. Indeed, finding a value equivalent to a term that is already a value can always be done using the reflexivity of the equivalence relation.

Although the idea seems simple, proving the soundness of the new typing rules semantically is surprisingly subtle. A model is built using classical realizability techniques in which the interpretation of a type A is spread among two sets: a set of values \(\llbracket A \rrbracket \) and a set of terms \(\llbracket A \rrbracket ^{\bot \bot }\). The former contains all values that should have type A. For example, \(\llbracket \) nat \(\rrbracket \) should contain the values of the form S[S[...Z[]...]]. The set \(\llbracket A \rrbracket ^{\bot \bot }\) is the completion of \(\llbracket A \rrbracket \) with all the terms behaving like values of \(\llbracket A \rrbracket \) (in the observational sense). To show that the relaxation of the value restriction is sound, we need the values of \(\llbracket A \rrbracket ^{\bot \bot }\) to also be in \(\llbracket A \rrbracket \). In other words, the completion operation should not introduce new values. To obtain this property, we need to extend the language with a new, non-computable instruction internalizing equivalence. This new instruction is only used to build the model, and will not be available to the user (nor will it appear in an implementation).

2 About Effects and Value Restriction

A soundness issue related to side-effects and call-by-value evaluation arose in the seventies with the advent of ML. The problem stems from a bad interaction between side-effects and Hindley-Milner polymorphism. It was first formulated in terms of references [30, 4, 14, 15, 29]). However, they all introduced a complexity that contrasted with the elegance and simplicity of ML’s type system (for a detailed account, see [31, Sect. 2] and [5, Sect. 2]).

A simple and elegant solution was finally found by Andrew Wright in the nineties. He suggested restricting generalization in let-bindingsFootnote 1 to cases where the bound term is a syntactic value [30, 31]. In slightly more expressive type systems, this restriction appears in the typing rule for the introduction of the universal quantifier. The usual rule

figure ffigure f

cannot be proved safe (in a call-by-value system with side-effects) if t is not a syntactic value. Similarly, the elimination rule for dependent product (shown previously) requires value restriction. It is possible to exhibit a counter-example breaking the type safety of our system if it is omitted [13].

In this paper, we consider control structures, which have been shown to give a computational interpretation to classical logic by Timothy Griffin [6]. In 1991, Robert Harper and Mark Lillibridge found a complex program breaking the type safety of ML extended with Lisp’s call/cc [7]. As with references, value restriction solves the inconsistency and yields a sound type system. Instead of using control operators like call/cc, we adopt the syntax of Michel Parigot’s \(\lambda \mu \)-calculus [24]. Our language hence contains a new binder \(\mu \alpha \,t\) capturing the continuation in the \(\mu \)-variable \(\alpha \). The continuation can then be restored in t using the syntax \(u*\alpha \) Footnote 2. In the context of the \(\lambda \mu \)-calculus, the soundness issue arises when evaluating \(t\,(\mu \alpha \,u)\) when \(\mu \alpha \,u\) has a polymorphic type. Such a situation cannot happen with value restriction since \(\mu \alpha \,u\) is not a value.

3 Main Results

The main contribution of this paper is a new approach to value restriction. The syntactic restriction on terms is replaced by a semantical restriction expressed in terms of an observational equivalence relation denoted \((\equiv )\). Although this approach seems simple, building a model to prove soundness semantically (Theorem 6) is surprisingly subtle. Subject reduction is not required here, as our model construction implies type safety (Theorem 7). Furthermore our type system is consistent as a logic (Theorem 8).

In this paper, we restrict ourselves to a second order type system but it can easily be extended to higher-order. Types are built from two basic sorts of objects: propositions (the types themselves) and individuals (untyped terms of the language). Terms appear in a restriction operator \(A \upharpoonright t \equiv u\) and a membership predicate \(t \in A\). The former is used to define the equality types (by taking \(A = \top \)) and the latter is used to encode dependent product.

$$ \varPi _{a : A} B \quad :=\quad \forall a (a \in A \Rightarrow B)$$

Overall, the higher-order version of our system is similar to a Curry-style HOL with ML programs as individuals. It does not allow the definition of a type which structure depends on a term (e.g. functions with a variable number of arguments). Our system can thus be placed between HOL (a.k.a. \(F_\omega \)) and the pure calculus of constructions (a.k.a. CoC) in (a Curry-style and classical version of) Barendregt’s \(\lambda \)-cube.

Throughout this paper we build a realizability model à la Krivine [12] based on a call-by-value abstract machine. As a consequence, formulas are interpreted using three layers (values, stacks and terms) related via orthogonality (Definition 9). The crucial property (Theorem 4) for the soundness of semantical value restriction is that

$$ \phi ^{\bot \bot } \cap \varLambda _v = \phi $$

for every set of values \(\phi \) (closed under \((\equiv )\)). \(\varLambda _v\) denotes the set of all values and \(\phi ^\bot \) (resp. \(\phi ^{\bot \bot }\)) the set of all stacks (resp. terms) that are compatible with every value in \(\phi \) (resp. stacks in \(\phi ^\bot \)). To obtain a model satisfying this property, we need to extend our programming language with a term \(\delta _{v,w}\) which reduction depends on the observational equivalence of two values v and w.

4 Related Work

To our knowledge, combining call-by-value evaluation, side-effects and dependent products has never been achieved before. At least not for a dependent product fully compatible with effects and call-by-value. For example, the Aura language [10] forbids dependency on terms that are not values in dependent applications. Similarly, the \(F^\star \) language [28] relies on (partial) let-normal forms to enforce values in argument position. Daniel Licata and Robert Harper have defined a notion of positively dependent types [16] which only allow dependency over strictly positive types. Finally, in language like ATS [32] and DML [33] dependent types are limited to a specific index language.

The system that seems the most similar to ours is NuPrl [2], although it is inconsistent with classical reasoning. NuPrl accommodates an observational equivalence \((\sim )\) (Howe’s “squiggle” relation [8]) similar to our \((\equiv )\) relation. It is partially reflected in the syntax of the system. Being based on a Kleene style realizability model, NuPrl can also be used to reason about untyped terms.

The central part of this paper consists in a classical realizability model construction in the style of Jean-Louis Krivine [12]. We rely on a call-by-value presentation which yields a model in three layers (values, terms and stacks). Such a technique has already been used to account for classical ML-like polymorphism in call-by-value in the work of Guillaume Munch-Maccagnoni [21]Footnote 3. It is here extended to include dependent products.

The most actively developed proof assistants following the Curry-Howard correspondence are Coq and Agda [18, 22]. The former is based on Coquand and Huet’s calculus of constructions and the latter on Martin-L?f’s dependent type theory [3, 17]. These two constructive theories provide dependent types, which allow the definition of very expressive specifications. Coq and Agda do not directly give a computational interpretation to classical logic. Classical reasoning can only be done through the definition of axioms such as the law of the excluded middle. Moreover, these two languages are logically consistent, and hence their type-checkers only allow terminating programs. As termination checking is a difficult (and undecidable) problem, many terminating programs are rejected. Although this is not a problem for formalizing mathematics, this makes programming tedious.

The TRELLYS project [1] aims at providing a language in which a consistent core can interact with type-safe dependently-typed programming with general recursion. Although the language defined in [1] is call-by-value and allows effect, it suffers from value restriction like Aura [10]. The value restriction does not appear explicitly but is encoded into a well-formedness judgement appearing as the premise of the typing rule for application. Apart from value restriction, the main difference between the language of the TRELLYS project and ours resides in the calculus itself. Their calculus is Church-style (or explicitly typed) while ours is Curry-style (or implicitly typed). In particular, their terms and types are defined simultaneously, while our type system is constructed on top of an untyped calculus.

Another similar system can be found in the work of Alexandre Miquel [20], where propositions can be classical and Curry-style. However the rest of the language remains Church style and does not embed a full ML-like language. The PVS system [23] is similar to ours as it is based on classical higher-order logic. However this tool does not seem to be a programming language, but rather a specification language coupled with proof checking and model checking utilities. It is nonetheless worth mentioning that the undecidability of PVS’s type system is handled by generating proof obligations. Our system will take a different approach and use a non-backtracking type-checking and type-inference algorithm.

5 Syntax, Reduction and Equivalence

The language is expressed in terms of a Krivine Abstract Machine [11], which is a stack-based machine. It is formed using four syntactic entities: values, terms, stacks and processes. The distinction between terms and values is specific to the call-by-value presentation, they would be collapsed in call-by-name. We require three distinct countable sets of variables:

  • \(\mathcal {V}_\lambda = \{x, y, z...\}\) for \(\lambda \)-variables,

  • \(\mathcal {V}_\mu = \{\alpha , \beta , \gamma ...\}\) for \(\mu \)-variables (also called stack variables) and

  • \(\mathcal {V}_\iota = \{a, b, c...\}\) for term variables. Term variables will be bound in formulas, but never in terms.

We also require a countable set \(\mathcal {L} = \{l, l_1, l_2...\}\) of labels to name record fields and a countable set \(\mathcal {C} = \{C, C_1, C_2...\}\) of constructors.

Definition 1

Values, terms, stacks and processes are mutually inductively defined by the following grammars. The names of the corresponding sets are displayed on the right.

$$\begin{aligned} v,w \;::=\;&x \;\;\vert \;\;\lambda x\;t \;\;\vert \;\;C[v] \;\;\vert \;\;\{l_i = v_i\}_{i \in I}&(\varLambda _v)\\ t,u \;::=\;&a \;\;\vert \;\;v \;\;\vert \;\;t\;u \;\;\vert \;\;\mu \alpha \;t \;\;\vert \;\;p \;\;\vert \;\;v.l \;\;\vert \;\;\text {case}_{v}\;[C_i[x_i] \rightarrow t_i]_{i \in I} \;\;\vert \;\;\delta _{v,w}&(\varLambda )\\ \pi ,\rho \;::=\;&\alpha \;\;\vert \;\;v.\pi \;\;\vert \;\;[t]\pi&(\varPi )\\ p,q \;::=\;&t *\pi&(\varLambda \times \varPi ) \end{aligned}$$

Terms and values form a variation of the \(\lambda \mu \)-calculus [24] enriched with ML-like constructs (i.e. records and variants). For technical purposes that will become clear later on, we extend the language with a special kind of term \(\delta _{v,w}\). It will only be used to build the model and is not intended to be accessed directly by the user. One may note that values and processes are terms. In particular, a process of the form \(t *\alpha \) corresponds exactly to a named term \([\alpha ]t\) in the most usual presentation of the \(\lambda \mu \)-calculus. A stack can be either a stack variable, a value pushed on top of a stack, or a stack frame containing a term on top of a stack. These two constructors are specific to the call-by-value presentation, only one would be required in call-by-name.

Remark 1

We enforce values in constructors, record fields, projection and case analysis. This makes the calculus simpler because only \(\beta \)-reduction will manipulate the stack. We can define syntactic sugars such as the following to hide the restriction from the programmer.

$$ t.l\;:=\;(\lambda x\,x.l)\,t C[t]\;:=\;(\lambda x\,C[x])\,t $$

Definition 2

Given a value, term, stack or process \(\psi \) we denote \(FV_\lambda (\psi )\) (resp. \(FV_\mu (\psi )\), \(TV(\psi )\)) the set of free \(\lambda \)-variables (resp. free \(\mu \)-variables, term variables) contained in \(\psi \). We say that \(\psi \) is closed if it does not contain any free variable of any kind. The set of closed values and the set of closed terms are denoted \(\varLambda _v^*\) and \(\varLambda ^*\) respectively.

Remark 2

A stack, and hence a process, can never be closed as they always at least contain a stack variable.

5.1 Call-by-Value Reduction Relation

Processes form the internal state of our abstract machine. They are to be thought of as a term put in some evaluation context represented using a stack. Intuitively, the stack \(\pi \) in the process \(t *\pi \) contains the arguments to be fed to t. Since we are in call-by-value the stack also handles the storing of functions while their arguments are being evaluated. This is why we need stack frames (i.e. stacks of the form \([t] \pi \)). The operational semantics of our language is given by a relation \((\succ )\) over processes.

Definition 3

The relation \((\succ ) \subseteq (\varLambda \times \varPi )^2\) is defined as the smallest relation satisfying the following reduction rules.

$$\begin{aligned} t\;u *\pi \;\;\;\;&\succ \;\;\; u *[t] \pi \\ v *[t] \pi \;\;\;\;&\succ \;\;\; t *v.\pi \\ \lambda x\;t *v.\pi \;\;\;\;&\succ \;\;\; t[x \!:=\! v] *\pi \\ \mu \alpha \;t *\pi \;\;\;\;&\succ \;\;\; t[\alpha \!:=\! \pi ] *\pi \\ p *\pi \;\;\;\;&\succ \;\;\; p\\ \{l_i = v_i\}_{i \in I}.l_k *\pi \;\;\;\;&\succ \;\;\; v_k *\pi&{k \in I}\\ \text {case}_{C_k[v]}\;[C_i[x_i] \rightarrow t_i]_{i \in I} *\pi \;\;\;\;&\succ \;\;\; t_k[x_k \!:=\! v] *\pi&{k \in I} \end{aligned}$$

We will denote \((\succ ^{+})\) its transitive closure, \((\succ ^{*})\) its reflexive-transitive closure and \((\succ ^k)\) its k-fold application.

The first three rules are those that handle \(\beta \)-reduction. When the abstract machine encounters an application, the function is stored in a stack-frame in order to evaluate its argument first. Once the argument has been completely computed, a value faces the stack-frame containing the function. At this point the function can be evaluated and the value is stored in the stack ready to be consumed by the function as soon as it evaluates to a \(\lambda \)-abstraction. A capture-avoiding substitution can then be performed to effectively apply the argument to the function. The fourth and fifth rules handle the classical part of computation. When a \(\mu \)-abstraction is reached, the current stack (i.e. the current evaluation context) is captured and substituted for the corresponding \(\mu \)-variable. Conversely, when a process is reached, the current stack is thrown away and evaluation resumes with the process. The last two rules perform projection and case analysis in the expected way. Note that for now, states of the form \(\delta _{v,w} *\pi \) are unaffected by the reduction relation.

Remark 3

For the abstract machine to be simpler, we use right-to-left call-by-value evaluation, and not the more usual left-to-right call-by-value evaluation.

Lemma 1

The reduction relation \((\succ )\) is compatible with substitutions of variables of any kind. More formally, if p and q are processes such that \(p \succ q\) then:

  • for all \(x \in \mathcal {V}_\lambda \) and \(v \in \varLambda _v\), \(p[x := v] \succ q[x := v]\),

  • for all \(\alpha \in \mathcal {V}_\mu \) and \(\pi \in \varPi \), \(p[\alpha := \pi ] \succ q[\alpha := \pi ]\),

  • for all \(a \in \mathcal {V}_\iota \) and \(t \in \varLambda \), \(p[a := t] \succ q[a := t]\).

Consequently, if \(\sigma \) is a substitution for variables of any kind and if \(p \succ q\) (resp. \(p \succ ^{*} q\), \(p \succ ^{+} q\), \(p \succ ^k q\)) then \(p\sigma \succ q\sigma \) (resp. \(p\sigma \succ ^{*} q\sigma \), \(p\sigma \succ ^{+} q\sigma \), \(p\sigma \succ ^k q\sigma \)).

Proof

Immediate case analysis on the reduction rules.

We are now going to give the vocabulary that will be used to describe some specific classes of processes. In particular we need to identify processes that are to be considered as the evidence of a successful computation, and those that are to be recognised as expressing failure.

Definition 4

A process \(p \in \varLambda \times \varPi \) is said to be:

  • final if there is a value \(v \in \varLambda _v\) and a stack variable \(\alpha \in \mathcal {V}_\mu \) such that \(p = v *\alpha \),

  • \(\delta \) -like if there are values \(v, w \in \varLambda _v\) and a stack \(\pi \in \varPi \) such that \(p = \delta _{v,w} *\pi \),

  • blocked if there is no \(q \in \varLambda \times \varPi \) such that \(p \succ q\),

  • stuck if it is not final nor \(\delta \)-like, and if for every substitution \(\sigma \), \(p\sigma \) is blocked,

  • non-terminating if there is no blocked process \(q \in \varLambda \times \varPi \) such that \(p \succ ^{*} q\).

Lemma 2

Let p be a process and \(\sigma \) be a substitution for variables of any kind. If p is \(\delta \)-like (resp. stuck, non-terminating) then \(p\sigma \) is also \(\delta \)-like (resp. stuck, non-terminating).

Proof

Immediate by definition.

Lemma 3

A stuck state is of one of the following forms, where \(k \notin I\).

Proof

Simple case analysis.

Lemma 4

A blocked process \(p \in \varLambda \times \varPi \) is either stuck, final, \(\delta \)-like, or of one of the following forms.

Proof

Straight-forward case analysis using Lemma 3.

5.2 Reduction of \(\delta _{v,w}\) and Equivalence

The idea now is to define a notion of observational equivalence over terms using a relation \((\equiv )\). We then extend the reduction relation with a rule reducing a state of the form \(\delta _{v,w} *\pi \) to \(v *\pi \) if \(v \not \equiv w\). If \(v \equiv w\) then \(\delta _{v,w}\) is stuck. With this rule reduction and equivalence will become interdependent as equivalence will be defined using reduction.

Definition 5

Given a reduction relation R, we say that a process \(p \in \varLambda \times \varPi \) converges, and write \(p \Downarrow _R\), if there is a final state \(q \in \varLambda \times \varPi \) such that \(p R^{*} q\) (where \(R^{*}\) is the reflexive-transitive closure of R). If p does not converge we say that it diverges and write \(p \Uparrow _R\). We will use the notations \(p \Downarrow _i\) and \(p \Uparrow _i\) when working with indexed notation symbols like \((\twoheadrightarrow _i)\).

Definition 6

For every natural number i we define a reduction relation \((\twoheadrightarrow _i)\) and an equivalence relation \((\equiv _i)\) which negation will be denoted \((\not \equiv _i)\).

$$ (\twoheadrightarrow _i) = (\succ ) \cup \{(\delta _{v,w} *\pi , v *\pi ) \;|\; \exists j < i, v \not \equiv _j w\} $$
$$ (\equiv _i) = \{(t,u) \;|\; \forall j \le i, \forall \pi , \forall \sigma , {t\sigma *\pi \Downarrow _j} \Leftrightarrow {u\sigma *\pi \Downarrow _j}\} $$

It is easy to see that \((\twoheadrightarrow _0) = (\succ )\). For every natural number i, the relation \((\equiv _i)\) is indeed an equivalence relation as it can be seen as an intersection of equivalence relations. Its negation can be expressed as follows.

$$ (\not \equiv _i) = \{(t,u), (u,t) \;|\; \exists j \le i, \exists \pi , \exists \sigma , {t\sigma *\pi \Downarrow _j} \wedge {u\sigma *\pi \Uparrow _j}\} $$

Definition 7

We define a reduction relation \((\twoheadrightarrow )\) and an equivalence relation \((\equiv )\) which negation will be denoted \((\not \equiv )\).

$$ (\twoheadrightarrow ) = \bigcup _{i\in \mathbb {N}} {(\twoheadrightarrow _i)} \;\;\;\;\;\; \;\;\;\;\;\; (\equiv ) = \bigcap _{i\in \mathbb {N}} {(\equiv _i)} $$

These relations can be expressed directly (i.e. without the need of a union or an intersection) in the following way.

$$\begin{aligned} (\equiv )&= \{(t,u) \;|\; \forall i, \forall \pi , \forall \sigma , {t\sigma *\pi \Downarrow _i} \Leftrightarrow {u\sigma *\pi \Downarrow _i}\}\\ (\not \equiv )&= \{(t,u), (u,t) \;|\; \exists i, \exists \pi , \exists \sigma , {t\sigma *\pi \Downarrow _i} \wedge {u\sigma *\pi \Uparrow _i}\}\\ (\twoheadrightarrow )&= (\succ ) \cup \{(\delta _{v,w} *\pi , v *\pi ) \;|\; v \not \equiv w\} \end{aligned}$$

Remark 4

Obviously \((\twoheadrightarrow _i) \subseteq (\twoheadrightarrow _{i+1})\) and \((\equiv _{i+1}) \subseteq (\equiv _i)\). As a consequence the construction of \((\twoheadrightarrow _i)_{i\in \mathbb {N}}\) and \((\equiv _i)_{i\in \mathbb {N}}\) converges. In fact \((\twoheadrightarrow )\) and \((\equiv )\) form a fixpoint at ordinal \(\omega \). Surprisingly, this property is not explicitly required.

Theorem 1

Let t and u be terms. If \(t \equiv u\) then for every stack \(\pi \in \varPi \) and substitution \(\sigma \) we have \(t\sigma *\pi \Downarrow _{\twoheadrightarrow } \Leftrightarrow u\sigma *\pi \Downarrow _{\twoheadrightarrow }\).

Proof

We suppose that \(t \equiv u\) and we take \(\pi _0 \in \varPi \) and a substitution \(\sigma _0\). By symmetry we can assume that \({t\sigma _0 *\pi _0} \Downarrow _\twoheadrightarrow \) and show that \({u\sigma _0 *\pi _0} \Downarrow _\twoheadrightarrow \). By definition there is \(i_0 \in \mathbb {N}\) such that \({t\sigma _0 *\pi _0} \Downarrow _{i_0}\). Since \(t \equiv u\) we know that for every \(i \in \mathbb {N}\), \(\pi \in \varPi \) and substitution \(\sigma \) we have \({t\sigma *\pi } \Downarrow _i \Leftrightarrow {u\sigma *\pi } \Downarrow _i\). This is true in particular for \(i = i_0\), \(\pi = \pi _0\) and \(\sigma = \sigma _0\). We hence obtain \({u\sigma _0 *\pi _0} \Downarrow _{i_0}\) which give us \({u\sigma _0 *\pi _0} \Downarrow _\twoheadrightarrow \).

Remark 5

The converse implication is not true in general: taking \(t = \delta _{\lambda x\,x,\{\}}\) and \(u = \lambda x\,x\) gives a counter-example. More generally \({p\Downarrow _\twoheadrightarrow } \Leftrightarrow {q\Downarrow _\twoheadrightarrow }\) does not necessarily imply \({p\Downarrow _i} \Leftrightarrow {q\Downarrow _i}\) for all \(i\in \mathbb {N}\).

Corollary 1

Let t and u be terms and \(\pi \) be a stack. If \(t \equiv u\) and \({t *\pi } \Downarrow _\twoheadrightarrow \) then \({u *\pi } \Downarrow _\twoheadrightarrow \).

Proof

Direct consequence of Theorem 1 using \(\pi \) and an empty substitution.

5.3 Extensionality of the Language

In order to be able to work with the equivalence relation \((\equiv )\), we need to check that it is extensional. In other words, we need to be able to replace equals by equals at any place in terms without changing their observed behaviour. This property is summarized in the following two theorems.

Theorem 2

Let v and w be values, E be a term and x be a \(\lambda \)-variable. If \(v \equiv w\) then \(E[x := v] \equiv E[x := w]\).

Proof

We are going to prove the contrapositive so we suppose \(E[x := v] \not \equiv E[x := w]\) and show \(v \not \equiv w\). By definition there is \(i \in \mathbb {N}\), \(\pi \in \varPi \) and a substitution \(\sigma \) such that \((E[x := v])\sigma *\pi \Downarrow _i\) and \((E[x := w])\sigma *\pi \Uparrow _i\) (up to symmetry). Since we can rename x in such a way that it does not appear in \(dom(\sigma )\), we can suppose \(E\sigma [x := v\sigma ] *\pi \Downarrow _i\) and \(E\sigma [x := w\sigma ] *\pi \Uparrow _i\). In order to show \(v \not \equiv w\) we need to find \(i_0 \in \mathbb {N}\), \(\pi _0 \in \varPi \) and a substitution \(\sigma _0\) such that \(v\sigma _0 *\pi _0 \Downarrow _{i_0}\) and \(w\sigma _0 *\pi _0 \Uparrow _{i_0}\) (up to symmetry). We take \(i_0 = i\), \(\pi _0 = [\lambda x\;E\sigma ]\pi \) and \(\sigma _0 = \sigma \). These values are suitable since by definition \({v\sigma _0 *\pi _0 } \twoheadrightarrow _{i_0} {E\sigma [x := v\sigma ] *\pi } \Downarrow _{i_0}\) and \({w\sigma _0 *\pi _0} \twoheadrightarrow _{i_0} {E\sigma [x := w\sigma ] *\pi } \Uparrow _{i_0}\).

Lemma 5

Let s be a process, t be a term, a be a term variable and k be a natural number. If \(s[a := t] \Downarrow _k\) then there is a blocked state p such that \(s \succ ^{*} p\) and either

  • \(p = v *\alpha \) for some value v and a stack variable \(\alpha \),

  • \(p = a *\pi \) for some stack \(\pi \),

  • \(k > 0\) and \(p = \delta (v,w) *\pi \) for some values v and w and stack \(\pi \), and in this case \(v[a := t] \not \equiv _j w[a := t]\) for some \(j < k\).

Proof

Let \(\sigma \) be the substitution \([a := t]\). If s is non-terminating, Lemma 2 tells us that \(s\sigma \) is also non-terminating, which contradicts \(s\sigma \Downarrow _k\). Consequently, there is a blocked process p such that \(s \succ ^{*} p\) since \((\succ ) \subseteq (\twoheadrightarrow _k)\). Using Lemma 1 we get \(s\sigma \succ ^{*} p\sigma \) from which we obtain \(p\sigma \Downarrow _{k}\). The process p cannot be stuck, otherwise \(p\sigma \) would also be stuck by Lemma 2, which would contradict \(p\sigma \Downarrow _{k}\). Let us now suppose that \(p = \delta _{v,w} *\pi \) for some values v and w and some stack \(\pi \). Since \(\delta _{v\sigma ,w\sigma } *\pi \Downarrow _k\) there must be \(i < k\) such that \(v\sigma \not \equiv _j w\sigma \), otherwise this would contradict \(\delta _{v\sigma ,w\sigma } *\pi \Downarrow _k\). In this case we necessarily have \(k > 0\), otherwise there would be no possible candidate for i. According to Lemma 4 we need to rule out four more forms of therms: \(x.l *\pi \), \(x *v.\pi \), \(case_x\;B *\pi \) and \(b *\pi \) in the case where \(b \not = a\). If p was of one of these forms the substitution \(\sigma \) would not be able to unblock the reduction of p, which would contradict again \(p\sigma \Downarrow _{k}\).

Lemma 6

Let \(t_1\), \(t_2\) and E be terms and a be a term variable. For every \(k \in \mathbb {N}\), if \(t_1 \equiv _k t_2\) then \(E[a \!:=\! t_1] \equiv _k E[a \!:=\! t_2]\).

Proof

Let us take \(k \in \mathbb {N}\), suppose that \(t_1 \equiv _k t_2\) and show that \(E[a \!:=\! t_1] \equiv _k E[a \!:=\! t_1]\). By symmetry we can assume that we have \(i \le k\), \(\pi \in \varPi \) and a substitution \(\sigma \) such that \((E[a \!:=\! t_1])\sigma *\pi \Downarrow _i\) and show that \((E[a \!:=\! t_2])\sigma *\pi \Downarrow _i\). As we are free to rename a, we can suppose that it does not appear in \(dom(\sigma )\), \(TV(\pi )\), \(TV(t_1)\) or \(TV(t_2)\). In order to lighten the notations we define \(E' = E\sigma \), \(\sigma _1 = [a \!:=\! t_1\sigma ]\) and \(\sigma _2 = [a \!:=\! t_2\sigma ]\). We are hence assuming \(E'\sigma _1 *\pi \Downarrow _i\) and trying to show \(E'\sigma _2 *\pi \Downarrow _i\).

We will now build a sequence \((E_i,\pi _i,l_i)_{i \in I}\) in such a way that \(E'\sigma _1 *\pi \twoheadrightarrow ^{*}_k E_i\sigma _1 *\pi _i\sigma _1\) in \(l_i\) steps for every \(i \in I\). Furthermore, we require that \((l_i)_{i \in I}\) is increasing and that it has a strictly increasing subsequence. Under this condition our sequence will necessarily be finite. If it was infinite the number of reduction steps that could be taken from the state \(E'\sigma _1 *\pi \) would not be bounded, which would contradict \(E'\sigma _1 *\pi \Downarrow _i\). We now denote our finite sequence \((E_i,\pi _i,l_i)_{i \le n}\) with \(n \in \mathbb {N}\). In order to show that \((l_i)_{i \le n}\) has a strictly increasing subsequence, we will ensure that it does not have three equal consecutive values. More formally, we will require that if \(0 < i < n\) and \(l_{i-1} = l_i\) then \(l_{i+1} > l_i\).

To define \((E_0,\pi _0,l_0)\) we consider the reduction of \(E' *\pi \). Since we know that \((E' *\pi )\sigma _1 = E'\sigma _1 *\pi \Downarrow _i\) we use Lemma 5 to obtain a blocked state p such that \({E' *\pi } \succ ^j p\). We can now take \(E_0 *\pi _0 = p\) and \(l_0 = j\). By Lemma 1 we have \((E' *\pi )\sigma _1 \succ ^j {E_0\sigma _1 *\pi _0\sigma _1}\) from which we can deduce that \((E' *\pi )\sigma _1 \twoheadrightarrow ^{*}_k {E_0\sigma _1 *\pi _0\sigma _1}\) in \(l_0 = j\) steps.

To define \((E_{i+1},\pi _{i+1},l_{i+1})\) we consider the reduction of the process \(E_i\sigma _1 *\pi _i\). By construction we know that \({E'\sigma _1 *\pi } \twoheadrightarrow ^{*}_k {E_i\sigma _1 *\pi _i\sigma _1 = (E_i\sigma _1 *\pi _i)\sigma _1}\) in \(l_i\) steps. Using Lemma 5 we know that \(E_i *\pi _i\) might be of three shapes.

  • If \({E_i *\pi _i} = {v *\alpha }\) for some value v and stack variable \(\alpha \) then the end of the sequence was reached with \(n = i\).

  • If \(E_i = a\) then we consider the reduction of \(E_i\sigma _1 *\pi _i\). Since \((E_i\sigma _1 *\pi _i)\sigma _1 \Downarrow _k\) we know from Lemma 5 that there is a blocked process p such that \({E_i\sigma _1 *\pi _i} \succ ^j p\). Using Lemma 1 we obtain that \({E_i\sigma _1 *\pi _i\sigma _1} \succ ^j p\sigma _1\) from which we can deduce that \({E_i\sigma _1 *\pi _i\sigma _1} \twoheadrightarrow _k p\sigma _1\) in j steps. We then take \(E_{i+1} *\pi _{i+1} = p\) and \(l_{i+1} = l_i + j\). Is it possible to have \(j=0\)? This can only happen when \(E_i\sigma _1 *\pi _i\) is of one of the three forms of Lemma 5. It cannot be of the form \(a *\pi \) as we assumed that a does not appear in \(t_1\) or \(\sigma \). If it is of the form \(v *\alpha \), then we reached the end of the sequence with \(i + 1 = n\) so there is no trouble. The process \(E_i\sigma _1 *\pi _i\) may be of the form \(\delta (v,w) *\pi \), but we will have \(l_{i+2} > l_{i+1}\).

  • If \(E_i = \delta (v,w)\) for some values v and w we have \(m < k\) such that \(v\sigma _1 \not \equiv _m w\sigma _1\). Hence \({E_i\sigma _1 *\pi _i = \delta (v\sigma _1,w\sigma _1) *\pi _i} \twoheadrightarrow _k {v\sigma _1 *\pi _i}\) by definition. Moreover \({E_i\sigma _1 *\pi _i\sigma _1} \twoheadrightarrow _k {v\sigma _1 *\pi _i\sigma _1}\) by Lemma 1. Since \({E'\sigma _1 *\pi } \twoheadrightarrow ^{*}_k {E_i\sigma _1 *\pi _i\sigma _1}\) in \(l_i\) steps we obtain that \({E'\sigma _1 *\pi } \twoheadrightarrow ^{*}_k {v\sigma _1 *\pi _i\sigma _1}\) in \(l_i + 1\) steps. This also gives us \({(v\sigma _1 *\pi _i)\sigma _1 = v\sigma _1 *\pi _i\sigma _1} \Downarrow _k\). We now consider the reduction of the process \(v\sigma _1 *\pi _i\). By Lemma 5 there is a blocked process p such that \({v\sigma _1 *\pi _i} \succ ^j p\). Using Lemma 1 we obtain \({v\sigma _1 *\pi _i\sigma _1} \succ ^j p\sigma _1\) from which we deduce that \({v\sigma _1 *\pi _i\sigma _1} \twoheadrightarrow ^{*}_k p\sigma _1\) in j steps. We then take \(E_{i+1} *\pi _{i+1} = p\) and \(l_{i+1} = l_i + j + 1\). Note that in this case we have \(l_{i+1} > l_i\).

Intuitively \((E_i,\pi _i,l_i)_{i \le n}\) mimics the reduction of \(E'\sigma _1 *\pi \) while making explicit every substitution of a and every reduction of a \(\delta \)-like state.

To end the proof we show that for every \(i \le n\) we have \({E_i\sigma _2 *\pi _i\sigma _2} \Downarrow _k\). For \(i = 0\) this will give us \({E'\sigma _2 *\pi } \Downarrow _k\) which is the expected result. Since \(E_n *\pi _n = v *\alpha \) we have \(E_n\sigma _2 *\pi _n\sigma _2 = v\sigma _2 *\alpha \) from which we trivially obtain \({E_n\sigma _2 *\pi _n\sigma _2} \Downarrow _k\). We now suppose that \({E_{i+1}\sigma _2 *\pi _i\sigma _2} \Downarrow _k\) for \(0 \le i < n\) and show that \({E_i\sigma _2 *\pi _i\sigma _2} \Downarrow _k\). By construction \(E_i *\pi _i\) can be of two shapesFootnote 4:

  • If \(E_i=a\) then \({t_1\sigma *\pi _i} \twoheadrightarrow ^{*}_k {E_{i+1} *\pi _{i+1}}\). Using Lemma 1 we obtain \(t_1\sigma *\pi _i\sigma _2 \twoheadrightarrow _k E_{i+1}\sigma _2 *\pi _i\sigma _2\) from which we deduce \(t_1\sigma *\pi _i\sigma _2 \Downarrow _k\) by induction hypothesis. Since \(t_1 \equiv _k t_2\) we obtain \({t_2\sigma *\pi _i\sigma _2 = (E_i *\pi _i)\sigma _2} \Downarrow _k\).

  • If \(E_i = \delta (v,w)\) then \({v *\pi _i} \twoheadrightarrow _k {E_{i+1} *\pi _{i+1}}\) and hence \(v\sigma _2 *\pi _i\sigma _2 \twoheadrightarrow _k E_{i+1}\sigma _2 *\pi _{i+1}\sigma _2\) by Lemma 1. Using the induction hypothesis we obtain \({v\sigma _2 *\pi _i\sigma _2} \Downarrow _k\). It remains to show that \({\delta (v\sigma _2,w\sigma _2) *\pi _i\sigma _2} \twoheadrightarrow ^{*}_k {v\sigma _2 *\pi _i\sigma _2}\). We need to find \(j < k\) such that \(v\sigma _2 \not \equiv _j w\sigma _2\). By construction there is \(m < k\) such that \(v\sigma _1 \not \equiv _m w\sigma _1\). We are going to show that \(v\sigma _2 \not \equiv _m w\sigma _2\). By using the global induction hypothesis twice we obtain \(v\sigma _1 \equiv _m v\sigma _2\) and \(w\sigma _1 \equiv _m v\sigma _2\). Now if \(v\sigma _2 \equiv _m w\sigma _2\) then \(v\sigma _1 \equiv _m v\sigma _2 \equiv _m w\sigma _2 \equiv _m w\sigma _1\) contradicts \(v\sigma _1 \not \equiv w\sigma _1\). Hence we must have \(v\sigma _2 \not \equiv _m w\sigma _2\).

Theorem 3

Let \(t_1\), \(t_2\) and E be three terms and a be a term variable. If \(t_1 \equiv t_2\) then \(E[a \!:=\! t_1] \equiv E[a \!:=\! t_2]\).

Proof

We suppose that \(t_1 \equiv t_2\) which means that \(t_1 \equiv _i t_2\) for every \(i \in \mathbb {N}\). We need to show that \(E[a \!:=\! t_1] \equiv E[a \!:=\! t_2]\) so we take \(i_0 \in \mathbb {N}\) and show \(E[a \!:=\! t_1] \equiv _{i_0} E[a \!:=\! t_2]\). By hypothesis we have \(t_1 \equiv _{i_0} t_2\) and hence we can conclude using Lemma 6.

6 Formulas and Semantics

The syntax presented in the previous section is part of a realizability machinery that will be built upon here. We aim at obtaining a semantical interpretation of the second-order type system that will be defined shortly. Our abstract machine slightly differs from the mainstream presentation of Krivine’s classical realizability which is usually call-by-name. Although call-by-value presentations have rarely been published, such developments are well-known among classical realizability experts. The addition of the \(\delta \) instruction and the related modifications are however due to the author.

6.1 Pole and Orthogonality

As always in classical realizability, the model is parametrized by a pole, which serves as an exchange point between the world of programs and the world of execution contexts (i.e. stacks).

Definition 8

A pole is a set of processes \(\bot \!\!\!\bot \subseteq \varLambda \times \varPi \) which is saturated (i.e. closed under backward reduction). More formally, if we have \(q \in \bot \!\!\!\bot \) and \(p \twoheadrightarrow q\) then \(p \in \bot \!\!\!\bot \).

Here, for the sake of simplicity and brevity, we are only going to use the pole

$$ \bot \!\!\!\bot = \{p \in \varLambda \times \varPi \;|\; p \Downarrow _\twoheadrightarrow \} $$

which is clearly saturated. Note that this particular pole is also closed under the reduction relation \((\twoheadrightarrow )\), even though this is not a general property. In particular \(\bot \!\!\!\bot \) contains all final processes.

The notion of orthogonality is central in Krivine’s classical realizability. In this framework a type is interpreted (or realized) by programs computing corresponding values. This interpretation is spread in a three-layered construction, even though it is fully determined by the first layer (and the choice of the pole). The first layer consists of a set of values that we will call the raw semantics. It gathers all the syntactic values that should be considered as having the corresponding type. As an example, if we were to consider the type of natural numbers, its raw semantics would be the set \(\{\bar{n} \;|\; n \in \mathbb {N}\}\) where \(\bar{n}\) is some encoding of n. The second layer, called falsity value is a set containing every stack that is a candidate for building a valid process using any value from the raw semantics. The notion of validity depends on the choice of the pole. Here for instance, a valid process is a normalizing one (i.e. one that reduces to a final state). The third layer, called truth value is a set of terms that is built by iterating the process once more. The formalism for the two levels of orthogonality is given in the following definition.

Definition 9

For every set \(\phi \subseteq \varLambda _v\) we define a set \(\phi ^\bot \subseteq \varPi \) and a set \(\phi ^{\bot \bot } \subseteq \varLambda \) as follows.

$$\begin{aligned} \phi ^\bot&= \{\pi \in \varPi \;|\; \forall v \in \phi , v *\pi \in \bot \!\!\!\bot \}\\ \phi ^{\bot \bot }&= \{t \in \varLambda \;|\; \forall \pi \in \phi ^\bot , t *\pi \in \bot \!\!\!\bot \} \end{aligned}$$

We now give two general properties of orthogonality that are true in every classical realizability model. They will be useful when proving the soundness of our type system.

Lemma 7

If \(\phi \subseteq \varLambda _v\) is a set of values, then \(\phi \subseteq \phi ^{\bot \bot }\).

Proof

Immediate following the definition of \(\phi ^{\bot \bot }\).

Lemma 8

Let \(\phi \subseteq \varLambda _v\) and \(\psi \subseteq \varLambda _v\) be two sets of values. If \(\phi \subseteq \psi \) then \(\phi ^{\bot \bot } \subseteq \psi ^{\bot \bot }\).

Proof

Immediate by definition of orthogonality.

The construction involving the terms of the form \(\delta _{v,x}\) and \((\equiv )\) in the previous section is now going to gain meaning. The following theorem, which is our central result, does not hold in every classical realizability model. Obtaining a proof required us to internalize observational equivalence, which introduces a non-computable reduction rule.

Theorem 4

If \(\varPhi \subseteq \varLambda _v\) is a set of values closed under \((\equiv )\), then \(\varPhi ^{\bot \bot } \cap \varLambda _v = \varPhi \).

Proof

The direction \(\varPhi \subseteq \varPhi ^{\bot \bot } \cap \varLambda _v\) is straight-forward using Lemma 7. We are going to show that \(\varPhi ^{\bot \bot } \cap \varLambda _v \subseteq \varPhi \), which amounts to showing that for every value \(v \in \varPhi ^{\bot \bot }\) we have \(v \in \varPhi \). We are going to show the contrapositive, so let us assume \(v \not \in \varPhi \) and show \(v \not \in \varPhi ^{\bot \bot }\). We need to find a stack \(\pi _0\) such that \(v *\pi _0 \not \in \bot \!\!\!\bot \) and for every value \(w \in \varPhi \), \(w *\pi _0 \in \bot \!\!\!\bot \). We take \(\pi _0 = [\lambda x\;\delta _{x,v}]\;\alpha \) and show that is is suitable. By definition of the reduction relation \(v *\pi _0\) reduces to \(\delta _{v,v} *\alpha \) which is not in \(\bot \!\!\!\bot \) (it is stuck as \(v \equiv v\) by reflexivity). Let us now take \(w \in \varPhi \). Again by definition, \(w *\pi _0\) reduces to \(\delta _{w,v} *\alpha \), but this time we have \(w \not \equiv v\) since \(\varPhi \) was supposed to be closed under \((\equiv )\) and \(v \not \in \varPhi \). Hence \(w *\pi _0\) reduces to \({w *\alpha } \in \bot \!\!\!\bot \).

It is important to check that the pole we chose does not yield a degenerate model. In particular we check that no term is able to face every stacks. If it were the case, such a term could be use as a proof of \(\bot \).

Theorem 5

The pole \(\bot \!\!\!\bot \) is consistent, which means that for every closed term t there is a stack \(\pi \) such that \(t *\pi \not \in \bot \!\!\!\bot \).

Proof

Let t be a closed term and \(\alpha \) be a stack constant. If we do not have \(t *\alpha \Downarrow _\twoheadrightarrow \) then we can directly take \(\pi = \alpha \). Otherwise we know that \(t *\alpha \twoheadrightarrow ^{*}v *\alpha \) for some value v. Since t is closed \(\alpha \) is the only available stack variable. We now show that \(\pi = [\lambda x\;\{\}]\{\}.\beta \) is suitable. We denote \(\sigma \) the substitution \([\alpha := \pi ]\). Using a trivial extension of Lemma 1 to the \((\twoheadrightarrow )\) relation we obtain \(t *\pi = (t *\alpha )\sigma \twoheadrightarrow ^{*}(v *\alpha )\sigma = v\sigma *\pi \). We hence have \(t *\pi \twoheadrightarrow ^{*}v\sigma *[\lambda x\;\{\}]\{\}.\beta \twoheadrightarrow ^2 \{\} *\{\}.\beta \not \in \bot \!\!\!\bot \).

6.2 Formulas and Their Semantics

In this paper we limit ourselves to second-order logic, even though the system can easily be extended to higher-order. For every natural number n we require a countable set \({\mathcal {V}}_n = \{{X}_n, {Y}_n, {Z}_n ...\}\) of n-ary predicate variables.

Definition 10

The syntax of formulas is given by the following grammar.

$$\begin{aligned} A,B \;::=\;&{X}_n(t_1, ..., t_n) \;\;\vert \;\;A \Rightarrow B \;\;\vert \;\;\forall a\; A \;\;\vert \;\;\exists a\; A \;\;\vert \;\;\forall X_n\; A \;\;\vert \;\;\exists X_n\; A \\ \;\;\vert \;\;&\{l_i : A_i\}_{i \in I} \;\;\vert \;\;[C_i : A_i]_{i \in I} \;\;\vert \;\;t \in A \;\;\vert \;\;A \upharpoonright t \equiv u \end{aligned}$$

Terms appear in several places in formulas, in particular, they form the individuals of the logic. They can be quantified over and are used as arguments for predicate variables. Besides the ML-like formers for sums and products (i.e. records and variants) we add a membership predicate and a restriction operation. The membership predicate \(t \in A\) is used to express the fact that the term t has type A. It provides a way to encode the dependent product type using universal quantification and the arrow type. In this sense, it is inspired and related to Krivine’s relativization of quantifiers.

$$ \varPi _{a:A}\;B \quad :=\quad \forall a (a \in A \Rightarrow B) $$

The restriction operator can be thought of as a kind of conjunction with no algorithmic content. The formula \(A \upharpoonright t \equiv u\) is to be interpreted in the same way as A if the equivalence \(t \equiv u\) holds, and as \(\bot \) otherwiseFootnote 5. In particular, we will define the following types:

$$ A \upharpoonright t \not \equiv u := A \upharpoonright t \equiv u \Rightarrow \bot \quad \quad t \equiv u := \top \upharpoonright t \equiv u \quad \quad t \not \equiv u := \top \upharpoonright t \not \equiv u $$

To handle free variables in formulas we will need to generalize the notion of substitution to allow the substitution of predicate variables.

Definition 11

A substitution is a finite map \(\sigma \) ranging over \(\lambda \)-variables, \(\mu \)-variables, term and predicate variables such that:

  • if \(x \in dom(\sigma )\) then \(\sigma (x) \in \varLambda _v\),

  • if \(\alpha \in dom(\sigma )\) then \(\sigma (\alpha ) \in \varPi \),

  • if \(a \in dom(\sigma )\) then \(\sigma (a) \in \varLambda \),

  • if \(X_n \in dom(\sigma )\) then \(\sigma (X_n) \in {\varLambda ^n \rightarrow \mathcal {P}({{\varLambda }_v}/\!\!\equiv )}\).

Remark 6

A predicate variable of arity n will be substituted by a n-ary predicate. Semantically, such predicate will correspond to some total (set-theoretic) function building a subset of \(\varLambda _v/\!\!\equiv \) from n terms. In the syntax, the binding of the arguments of a predicate variables will happen implicitly during its substitution.

Definition 12

Given a formula A we denote FV(A) the set of its free variables. Given a substitution \(\sigma \) such that \(FV(A) \subseteq dom(\sigma )\) we write \(A[\sigma ]\) the closed formula built by applying \(\sigma \) to A.

In the semantics we will interpret closed formulas by sets of values closed under the equivalence relation \((\equiv )\).

Definition 13

Given a formula A and a substitution \(\sigma \) such that \(A[\sigma ]\) is closed, we define the raw semantics \(\llbracket A \rrbracket _\sigma \subseteq \varLambda _v/\!\!\equiv \) of A under the substitution \(\sigma \) as follows.

In the model, programs will realize closed formulas in two different ways according to their syntactic class. The interpretation of values will be given in terms of raw semantics, and the interpretation of terms in general will be given in terms of truth values.

Definition 14

Let A be a formula and \(\sigma \) a substitution such that \(A[\sigma ]\) is closed. We say that:

  • \(v \in \varLambda _v\) realizes \(A[\sigma ]\) if \(v \in \llbracket A \rrbracket _\sigma \),

  • \(t \in \varLambda \) realizes \(A[\sigma ]\) if \(t \in \llbracket A \rrbracket _\sigma ^{\bot \bot }\).

6.3 Contexts and Typing Rules

Before giving the typing rules of our system we need to define contexts and judgements. As explained in the introduction, several typing rules require a value restriction in our context. This is reflected in typing rule by the presence of two forms of judgements.

Definition 15

A context is an ordered list of hypotheses. In particular, it contains type declarations for \(\lambda \)-variables and \(\mu \)-variables, and declaration of term variables and predicate variables. In our case, a context also contains term equivalences and inequivalences. A context is built using the following grammar.

$$\begin{aligned} \varGamma , \varDelta \;::=\;&\bullet \;\;\vert \;\;\varGamma , x : A \;\;\vert \;\;\varGamma , \alpha : \lnot A \;\;\vert \;\;\varGamma , a : Term \\ \;\;\vert \;\;&\varGamma , X_n : Pred_n \;\;\vert \;\;\varGamma , t \equiv u \;\;\vert \;\;\varGamma , t \not \equiv u \end{aligned}$$

A context \(\varGamma \) is said to be valid if it is possible to derive \(\varGamma \;\text {Valid}\) using the rules of Fig. 1. In the following, every context will be considered valid implicitly.

Fig. 1.
figure 1figure 1

Rules allowing the construction of a valid context.

Definition 16

There are two forms of typing judgements:

  • \(\varGamma \vdash _{\!\!\!\text {val}}v : A\) meaning that the value v has type A in context \(\varGamma \),

  • \(\varGamma \vdash t : A\) meaning that the term t has type A in context \(\varGamma \).

Fig. 2.
figure 2figure 2

Second-order type system.

The typing rules of the system are given in Fig. 2. Although most of them are fairly usual, our type system differs in several ways. For instance the last four rules are related to the extensionality of the calculus. One can note the value restriction in several places: both universal quantification introduction rules and the introduction of the membership predicate. In fact, some value restriction is also hidden in the rules for the elimination of the existential quantifiers and the elimination rule for the restriction connective. These rules are presented in their left-hand side variation, and only values can appear on the left of the sequent. It is not surprising that elimination of an existential quantifier requires value restriction as it is the dual of the introduction rule of a universal quantifier.

An important and interesting difference with existing type systems is the presence of \(\uparrow \) and \(\downarrow \). These two rules allow one to go from one kind of sequent to the other when working on values. Going from \(\varGamma \vdash _{\!\!\!\text {val}}v : A\) to \(\varGamma \vdash v : A\) is straight-forward. Going the other direction is the main motivation for our model. This allows us to lift the value restriction expressed in the syntax to a restriction expressed in terms of equivalence. For example, the two rules

figure gfigure g
figure hfigure h

can be derived in the system (see Fig. 3). The value restriction can be removed similarly on every other rule. Thus, judgements on values can be completely ignored by the user of the system. Transition to value judgements will only happen internally.

Fig. 3.
figure 3figure 3

Derivation of the rules \(\forall _{i,\equiv }\) and \(\varPi _{e,\equiv }\).

6.4 Adequacy

We are now going to prove the soundness of our type system by showing that it is compatible with our realizability model. This property is specified by the following theorem which is traditionally called the adequacy lemma.

Definition 17

Let \(\varGamma \) be a (valid) context. We say that the substitution \(\sigma \) realizes \(\varGamma \) if:

  • for every x : A in \(\varGamma \) we have \(\sigma (x) \in \llbracket A \rrbracket _\sigma \),

  • for every \(\alpha : \lnot A\) in \(\varGamma \) we have \(\sigma (\alpha ) \in \llbracket A \rrbracket _\sigma ^\bot \),

  • for every a : Term in \(\varGamma \) we have \(\sigma (a) \in \varLambda \),

  • for every \(X_n : Pred_n\) in \(\varGamma \) we have \(\sigma (X_n) \in \varLambda ^n \rightarrow \varLambda _v/\!\!\equiv \),

  • for every \(t \equiv u\) in \(\varGamma \) we have \(t\sigma \equiv u\sigma \) and

  • for every \(t \not \equiv u\) in \(\varGamma \) we have \(t\sigma \not \equiv u\sigma \).

Theorem 6

(Adequacy). Let \(\varGamma \) be a (valid) context, A be a formula such that \(FV(A) \subseteq dom(\varGamma )\) and \(\sigma \) be a substitution realizing \(\varGamma \).

  • If \(\varGamma \vdash _{\!\!\!\text {val}}v : A\) then \(v\sigma \in \llbracket A \rrbracket _\sigma \),

  • if \(\varGamma \vdash t : A\) then \(t\sigma \in \llbracket A \rrbracket _\sigma ^{\bot \bot }\).

Proof

We proceed by induction on the derivation of the judgement \(\varGamma \vdash _{\!\!\!\text {val}}v:A\) (resp. \(\varGamma \vdash t:A\)) and we reason by case on the last rule used.

(\(\text {ax}\)) By hypothesis \(\sigma \) realizes \(\varGamma , x : A\) from which we directly obtain \(x\sigma \in \llbracket A \rrbracket _\sigma \).

(\(\uparrow \)) and (\(\downarrow \)) are direct consequences of Lemma 7 and Theorem 4 respectively.

(\(\Rightarrow _e\)) We need to prove that \(t\sigma \;u\sigma \in \llbracket B \rrbracket ^{\bot \bot }_\sigma \), hence we take \(\pi \in \llbracket B \rrbracket ^{\bot }_\sigma \) and show \(t\sigma \;u\sigma *\pi \in \bot \!\!\!\bot \). Since \(\bot \!\!\!\bot \) is saturated, we can take a reduction step and show \(u\sigma *[t\sigma ]\pi \in \bot \!\!\!\bot \). By induction hypothesis \(u\sigma \in \llbracket A \rrbracket ^{\bot \bot }_\sigma \) so we only have to show \([t\sigma ]\pi \in \llbracket A \rrbracket ^{\bot }_\sigma \). To do so we take \(v \in \llbracket A \rrbracket _\sigma \) and show \(v *[t\sigma ]\pi \in \bot \!\!\!\bot \). Here we can again take a reduction step and show \(t\sigma *v.\pi \in \bot \!\!\!\bot \). By induction hypothesis we have \(t\sigma \in \llbracket A \Rightarrow B \rrbracket ^{\bot \bot }_\sigma \), hence it is enough to show \(v.\pi \in \llbracket A \Rightarrow B \rrbracket ^{\bot }_\sigma \). We now take a value \(\lambda x\;t_x \in \llbracket A \Rightarrow B \rrbracket _\sigma \) and show that \(\lambda x\;t_x *v.\pi \in \bot \!\!\!\bot \). We then apply again a reduction step and show \(t_x[x := v] *\pi \in \bot \!\!\!\bot \). Since \(\pi \in \llbracket B \rrbracket ^{\bot }_\sigma \) we only need to show \(t_x[x := v] \in \llbracket B \rrbracket ^{\bot \bot }_\sigma \) which is true by definition of \(\llbracket A \Rightarrow B \rrbracket _\sigma \).

(\(\Rightarrow _i\)) We need to show \(\lambda x\;t\sigma \in \llbracket A \Rightarrow B \rrbracket _\sigma \) so we take \(v \in \llbracket A \rrbracket _\sigma \) and show \(t\sigma [x \!:=\! v] \in \llbracket B \rrbracket ^{\bot \bot }_\sigma \). Since \(\sigma [x := v]\) realizes \(\varGamma , x:A\) we can conclude using the induction hypothesis.

(\(\mu \)) We need to show that \(\mu \alpha \;t\sigma \in \llbracket A \rrbracket ^{\bot \bot }_\sigma \) hence we take \(\pi \in \llbracket A \rrbracket ^{\bot }_\sigma \) and show \(\mu \alpha \;t\sigma *\pi \in \bot \!\!\!\bot \). Since \(\bot \!\!\!\bot \) is saturated, it is enough to show \(t\sigma [\alpha := \pi ] *\pi \in \bot \!\!\!\bot \). As \(\sigma [\alpha := \pi ]\) realizes \(\varGamma , \alpha :\lnot A\) we conclude by induction hypothesis.

(\(*\)) We need to show \(t\sigma *\alpha \sigma \in \llbracket B \rrbracket ^{\bot \bot }_\sigma \), hence we take \(\pi \in \llbracket B \rrbracket ^{\bot }_\sigma \) and show that \((t\sigma *\alpha \sigma ) *\pi \in \bot \!\!\!\bot \). Since \(\bot \!\!\!\bot \) is saturated, we can take a reduction step and show \(t\sigma *\alpha \sigma \in \bot \!\!\!\bot \). By induction hypothesis \(t\sigma \in \llbracket A \rrbracket ^{\bot \bot }_\sigma \) hence it is enough to show \(\alpha \sigma \in \llbracket A \rrbracket ^{\bot }_\sigma \) which is true by hypothesis.

(\(\in _i\)) We need to show \(v\sigma \in \llbracket v \in A \rrbracket _\sigma \). We have \(v\sigma \in \llbracket A \rrbracket _\sigma \) by induction hypothesis, and \(v\sigma \equiv v\sigma \) by reflexivity of \((\equiv )\).

(\(\in _e\)) By hypothesis we know that \(\sigma \) realizes \(\varGamma , x : u \in A\). To be able to conclude using the induction hypothesis, we need to show that \(\sigma \) realizes \(\varGamma , x : A, x \equiv u\). Since we have \(\sigma (x) \in \llbracket u \in A \rrbracket _\sigma \), we obtain that \(x\sigma \in \llbracket A \rrbracket _\sigma \) and \(x\sigma \equiv u\sigma \) by definition of \(\llbracket u \in A \rrbracket _\sigma \).

(\(\upharpoonright _i\)) We need to show \(t\sigma \in \llbracket A \upharpoonright u_1 \equiv u_2 \rrbracket ^{\bot \bot }_\sigma \). By hypothesis \(u_1\sigma \equiv u_2\sigma \), hence \(\llbracket A \upharpoonright u_1 \equiv u_2 \rrbracket _\sigma = \llbracket A \rrbracket _\sigma \). Consequently, it is enough to show that \(t\sigma \in \llbracket A \rrbracket ^{\bot \bot }_\sigma \), which is exactly the induction hypothesis.

(\(\upharpoonright _e\)) By hypothesis we know that \(\sigma \) realizes \(\varGamma , x : A \upharpoonright u_1 \equiv u_2\). To be able to use the induction hypothesis, we need to show that \(\sigma \) realizes \(\varGamma , x : A, u_1 \equiv u_2\). Since we have \(\sigma (x) \in \llbracket A \upharpoonright u_1 \equiv u_2 \rrbracket _\sigma \), we obtain that \(x\sigma \in \llbracket A \rrbracket _\sigma \) and that \(u_1\sigma \equiv u_2\sigma \) by definition of \(\llbracket A \upharpoonright u_1 \equiv u_2 \rrbracket _\sigma \).

(\(\forall _i\)) We need to show that \(v\sigma \in \llbracket \forall a\; A \rrbracket _\sigma = \bigcap _{t \in \varLambda } \llbracket A \rrbracket _{\sigma [a := t]}\) so we take \(t \in \varLambda \) and show \(v\sigma \in \llbracket A \rrbracket _{\sigma [a := t]}\). This is true by induction hypothesis since \(a \not \in FV(\varGamma )\) and hence \(\sigma [a:=t]\) realizes \(\varGamma \).

(\(\forall _e\)) We need to show \(t\sigma \in \llbracket A[a := u] \rrbracket ^{\bot \bot }_\sigma = \llbracket A \rrbracket ^{\bot \bot }_{\sigma [a := u\sigma ]}\) for some \(u \in \varLambda \). By induction hypothesis we know \(t\sigma \in \llbracket \forall a\;A \rrbracket ^{\bot \bot }_\sigma \), hence we only need to show that \(\llbracket \forall a\; A \rrbracket ^{\bot \bot }_\sigma \subseteq \llbracket A \rrbracket ^{\bot \bot }_{\sigma [a := u\sigma ]}\). By definition we have \(\llbracket \forall a\; A \rrbracket _\sigma \subseteq \llbracket A \rrbracket _{\sigma [a := u\sigma ]}\) so we can conclude using Lemma 8.

(\(\exists _e\)) By hypothesis we know that \(\sigma \) realizes \(\varGamma , x : \exists a\;A\). In particular, we know that \(\sigma (x) \in \llbracket \exists a\;A \rrbracket _\sigma \), which means that there is a term \(u \in \varLambda ^*\) such that \(\sigma (x) \in \llbracket A \rrbracket _{\sigma [a := u]}\). Since \(a \notin FV(\varGamma )\), we obtain that the substitution \(\sigma [a := u]\) realizes the context \(\varGamma , x : A\). Using the induction hypothesis, we finally get \(t\sigma = t\sigma [a := u] \in \llbracket B \rrbracket ^{\bot \bot }_{\sigma [a := u]} = \llbracket B \rrbracket ^{\bot \bot }_\sigma \) since \(a \notin TV(t)\) and \(a \notin FV(B)\).

(\(\exists _i\)) The proof for this rule is similar to the one for ( \(\forall _e\) ). We need to show that \(\llbracket A[a := u] \rrbracket ^{\bot \bot }_\sigma = \llbracket A \rrbracket ^{\bot \bot }_{\sigma [a := u\sigma ]} \subseteq \llbracket \exists a\;A \rrbracket ^{\bot \bot }_\sigma \). This follows from Lemma 8 since \(\llbracket A \rrbracket _{\sigma [a := u\sigma ]} \subseteq \llbracket \exists a\;A \rrbracket _\sigma \) by definition.

(\(\forall _I\)), \((\forall _E)\), \((\exists _E)\) and \((\exists _I)\) are similar to similar to (\(\forall _i\)), (\(\forall _e\)), (\(\exists _e\)) and (\(\exists _i\)).

(\(\times _i\)) We need to show that \(\{l_i = v_i\sigma \}_{i \in I} \in \llbracket \{l_i : A_i\}_{i \in I} \rrbracket _\sigma \). By definition we need to show that for all \(i \in I\) we have \(v_i\sigma \in \llbracket A_i \rrbracket _\sigma \). This is immediate by induction hypothesis.

(\(\times _e\)) We need to show that \(v\sigma .l_i \in \llbracket A_i \rrbracket ^{\bot \bot }_\sigma \) for some \(i \in I\). By induction hypothesis we have \(v\sigma \in \llbracket \{l_i : A_i\}_{i \in I} \rrbracket _\sigma \) and hence v has the form \(\{l_i = v_i\}_{i \in I}\) with \(v_i\sigma \in \llbracket A_i \rrbracket _\sigma \). Let us now take \(\pi \in \llbracket A_i \rrbracket ^{\bot }_\sigma \) and show that \(\{l_i = v_i\sigma \}_{i \in I}.l_i *\pi \in \bot \!\!\!\bot \). Since \(\bot \!\!\!\bot \) is saturated, it is enough to show \(v_i\sigma *\pi \in \bot \!\!\!\bot \). This is true since \(v_i\sigma \in \llbracket A_i \rrbracket _\sigma \) and \(\pi \in \llbracket A_i \rrbracket ^{\bot }_\sigma \).

(\(+_i\)) We need to show \(C_i[v\sigma ] \in \llbracket [C_i : A_i]_{i \in I} \rrbracket _\sigma \) for some \(i \in I\). By induction hypothesis \(v\sigma \in \llbracket A_i \rrbracket _\sigma \) and hence we can conclude by definition of \(\llbracket [C_i : A_i]_{i \in I} \rrbracket _\sigma \).

(\(+_e\)) We need to show \(case_{v\sigma }\;[C_i[x] \rightarrow t_i\sigma ]_{i \in I} \in \llbracket B \rrbracket ^{\bot \bot }_\sigma \). By induction hypothesis \(v\sigma \in \llbracket [C_i of A_i]_{i \in I} \rrbracket _\sigma \) which means that there is \(i \in I\) and \(w \in \llbracket A_i \rrbracket _\sigma \) such that \(v\sigma = C_i[w]\). We take \(\pi \in \llbracket B \rrbracket ^{\bot }_\sigma \) and show \(\text {case}_{C_i[w]}\;[C_i[x] \rightarrow t_i\sigma ]_{i \in I} *\pi \in \bot \!\!\!\bot \). Since \(\bot \!\!\!\bot \) is saturated, it is enough to show \(t_i\sigma [x := w] *\pi \in \bot \!\!\!\bot \). It remains to show that \(t_i\sigma [x := w] \in \llbracket B \rrbracket ^{\bot \bot }_\sigma \). To be able to conclude using the induction hypothesis we need to show that \(\sigma [x := w]\) realizes \(\varGamma , x : A_i, C_i[x] \equiv v\). This is true since \(\sigma \) realizes \(\varGamma \), \(w \in \llbracket A_i \rrbracket _\sigma \) and \(C_i[w] \equiv v\sigma \) by reflexivity.

(\(\equiv _{v,l}\)) We need to show \(t[x := w_1]\sigma = t\sigma [x := w_1\sigma ] \in \llbracket A \rrbracket _\sigma \). By hypothesis we know that \(w_1\sigma \equiv w_2\sigma \) from which we can deduce \(t\sigma [x := w_1\sigma ] \equiv t\sigma [x := w_2\sigma ]\) by extensionality (Theorem 2). Since \(\llbracket A \rrbracket _\sigma \) is closed under \((\equiv )\) we can conclude using the induction hypothesis.

(\(\equiv _{t,l}\)), (\(\equiv _{v,r}\)) and (\(\equiv _{t,r}\)) are similar to (\(\equiv _{v,l}\)), using extensionality (Theorems 2 and 3).

Remark 7

For the sake of simplicity we fixed a pole \(\bot \!\!\!\bot \) at the beginning of the current section. However, many of the properties presented here (including the adequacy lemma) remain valid with similar poles. We will make use of this fact in the proof of the following theorem.

Theorem 7

(Safety). Let \(\varGamma \) be a context, A be a formula such that \(FV(A) \subseteq dom(\varGamma )\) and \(\sigma \) be a substitution realizing \(\varGamma \). If t is a term such that \(\varGamma \vdash t : A\) and if \(A[\sigma ]\) is pure (i.e. it does not contain any \(\_ \Rightarrow \_\)), then for every stack \(\pi \in \llbracket A \rrbracket _\sigma ^\bot \) there is a value \(v \in \llbracket A \rrbracket _\sigma \) and \(\alpha \in \mathcal {V}_\mu \) such that \({t\sigma *\pi } \twoheadrightarrow ^{*}{v *\alpha }\).

Proof

We do a proof by realizability using the following pole.

$$\bot \!\!\!\bot _A = \{ p \in \varLambda \times \varPi \;|\;p \twoheadrightarrow ^{*}v *\alpha \;\wedge \; v \in \llbracket A \rrbracket _\sigma \}$$

It is well-defined as A is pure and hence \(\llbracket A \rrbracket _\sigma \) does not depend on the pole. Using the adequacy lemma (Theorem 6) with \(\bot \!\!\!\bot _A\) we obtain \(t\sigma \in \llbracket A \rrbracket _\sigma ^{\bot \bot }\). Hence for every stack \(\pi \in \llbracket A \rrbracket _\sigma ^\bot \) we have \({t\sigma *\pi } \in \bot \!\!\!\bot _A\). We can then conclude using the definition of the pole \(\bot \!\!\!\bot _A\).

Remark 8

It is easy to see that if \(A[\sigma ]\) is closed and pure then \(v \in \llbracket A \rrbracket _\sigma \) implies that \(\bullet \vdash v : A\).

Theorem 8

(Consistency). There is no t such that \(\bullet \vdash t : \bot \).

Proof

Let us suppose that \(\bullet \vdash t : \bot \). Using adequacy (Theorem 6 ) we obtain that \(t \in \llbracket \bot \rrbracket _\sigma ^{\bot \bot }\). Since \(\llbracket \bot \rrbracket _\sigma = \emptyset \) we know that \(\llbracket \bot \rrbracket _\sigma ^\bot = \varPi \) by definition. Now using Theorem 5 we obtain \(\llbracket \bot \rrbracket _\sigma ^{\bot \bot } = \emptyset \). This is a contradiction.

7 Deciding Program Equivalence

The type system given in Fig. 2 does not provide any way of discharging an equivalence from the context. As a consequence the truth of an equivalence cannot be used. Furthermore, an equational contradiction in the context cannot be used to derive falsehood. To address these two problems, we will rely on a partial decision procedure for the equivalence of terms. Such a procedure can be easily implemented using an algorithm similar to Knuth-Bendix, provided that we are able to extract a set of equational axioms from the definition of \((\equiv )\). In particular, we will use the following lemma to show that several reduction rules are contained in \((\equiv )\).

Lemma 9

Let t and u be terms. If for every stack \(\pi \in \varPi \) there is \(p \in \varLambda \times \varPi \) such that \(t *\pi \succ ^* p\) and \(u *\pi \succ ^* p\) then \(t \equiv u\).

Proof

Since \((\succ ) \subseteq (\twoheadrightarrow _i)\) for every \(i \in \mathbb {N}\), we can deduce that \(t *\pi \twoheadrightarrow _i^* p\) and \(u *\pi \twoheadrightarrow _i^* p\) for every \(i \in \mathbb {N}\). Using Lemma 1 we can deduce that for every substitution \(\sigma \) we have \(t\sigma *\pi \twoheadrightarrow _i^* p\sigma \) and \(u\sigma *\pi \twoheadrightarrow _i^* p\sigma \) for all \(i \in \mathbb {N}\). Consequently we obtain \(t \equiv u\).

The equivalence relation contains call-by-value \(\beta \)-reduction, projection on records and case analysis on variants.

Theorem 9

For every \(x \in \mathcal {V}_\lambda \), \(t \in \varLambda \) and \(v \in \varLambda _v\) we have \((\lambda x\;t) v \equiv t[x := v]\).

Proof

Immediate using Lemma 9.

Theorem 10

For all k such that \(1 \le k \le n\) we have the following equivalences.

$$(\lambda x\;t) v \equiv t[x := v] \text {case}_{C_k[v]}\;[C_i[x_i] \rightarrow t_i]_{1 \le i \le n} \equiv t_k[x_k := v]$$

Proof

Immediate using Lemma 9.

To observe contradictions, we also need to derive some inequivalences on values. For instance, we would like to deduce a contradiction if two values with a different head constructor are assumed to be equivalent.

Theorem 11

Let C, \(D \in \mathcal {C}\) be constructors, and v, \(w \in \varLambda _v\) be values. If \(C \ne D\) then \(C[v] \not \equiv D[w]\).

Proof

We take \(\pi = [\lambda x\; \text {case}_{x}\;[C[y] \rightarrow y\;|\;D[y] \rightarrow \varOmega ]] \alpha \) where \(\varOmega \) is an arbitrary diverging term. We then obtain \(C[v] *\pi \Downarrow _0\) and \(D[w] *\pi \Uparrow _0\).

Theorem 12

Let \(\{l_i = v_i\}_{i \in I}\) and \(\{l_j = v_j\}_{j \in J}\) be two records. If k is a index such that \(k \in I\) and \(k \notin J\) then we have \(\{l_i = v_i\}_{i \in I} \not \equiv \{l_j = v_j\}_{j \in J}\).

Proof

Immediate using the stack \(\pi = [\lambda x\; x.l_k] \alpha \).

Theorem 13

For every \(x \in \mathcal {V}_\lambda \), \(v \in \varLambda _v\), \(t \in \varLambda \), \(C \in \mathcal {C}\) and for every record \(\{l_i = v_i\}_{i \in I}\) we have the following inequivalences.

$$ \lambda x\; t \not \equiv C[v] \quad \quad \quad \lambda x\; t \not \equiv \{l_i = v_i\}_{i \in I} \quad \quad \quad C[v] \not \equiv \{l_i = v_i\}_{i \in I} $$

Proof

The proof is mostly similar to the proofs of the previous two theorems. However, there is a subtlety with the second inequivalence. If for every value v the term \(t[x:=v]\) diverges, then we do not have \(\lambda x\;t \not \equiv \{\}\). Indeed, there is no evaluation context (or stack) that is able to distinguish the empty record \(\{\}\) and a diverging function. To solve this problem, we can extend the language with a new kind of term \(\text {unit}_v\) and extend the relation \((\succ )\) with the following rule.

$$\text {unit}_{\{\}} *\pi \quad \succ \quad \{\} *\pi $$

The process \(\text {unit}_v *\pi \) is stuck for every value \(v \ne \{\}\). The proof can the be completed using the stack \(\pi = [\lambda x\;\text {unit}_x] \alpha \).

The previous five theorems together with the extensionality of \((\equiv )\) and its properties as an equivalence relation can be used to implement a partial decision procedure for equivalence. We will incorporate this procedure into the typing rules by introducing a new form of judgment.

Definition 18

An equational context \(\mathcal {E}\) is a list of hypothetical equivalences and inequivalences. Equational contexts are built using the following grammar.

$$ \mathcal {E} \;:=\; \bullet \;\;|\;\; \mathcal {E}, t \equiv u \;\;|\;\; \mathcal {E}, t \not \equiv u $$

Given a context \(\varGamma \), we denote \(\mathcal {E}_\varGamma \) its restriction to an equational context.

Definition 19

Let \(\mathcal {E}\) be an equational context. The judgement \(\mathcal {E} \vdash \bot \) is valid if and only if the partial decision procedure is able to derive a contradiction in \(\mathcal {E}\). We will write \(\mathcal {E} \vdash t \equiv u\) for \(\mathcal {E}, t \not \equiv u \vdash \bot \) and \(\mathcal {E} \vdash t \not \equiv u\) for \(\mathcal {E}, t \equiv u \vdash \bot \)

To discharge equations from the context, the following two typing rules are added to the system.

figure ifigure i
figure jfigure j

The soundness of these new rules follows easily since the decision procedure agrees with the semantical notion of equivalence. The axioms that were given at the beginning of this section are only used to partially reflect the semantical equivalence relation in the syntax. This is required if we are to implement the decision procedure.

Another way to use an equational context is to derive a contradiction directly. For instance, if we have a context \(\varGamma \) such that \(\mathcal {E}_\varGamma \) yields a contradiction, one should be able to finish the corresponding proof. This is particularly useful when working with variants and case analysis. For instance, some branches of the case analysis might not be reachable due to constraints on the matched term. For instance, we know that in the term

$$\text {case}_{C[v]}\;[C[x] \rightarrow x \;|\; D[x] \rightarrow t]$$

the branch corresponding to the D constructor will never be reached. Consequently, we can replace t by any term and the computation will still behave correctly. For this purpose we introduce a special value \(\texttt {8<}\) on which the abstract machine fails. It can be introduced with the following typing rule.

figure kfigure k

The soundness of this rule is again immediate.

8 Further Work

The model presented in the previous sections is intended to be used as the basis for the design of a proof assistant based on a call-by-value ML language with control operators. A first prototype (with a different theoretical foundation) was implemented by Christophe Raffalli [27]. Based on this experience, the design of a new version of the language with a clean theoretical basis can now be undertaken. The core of the system will consist of three independent components: a type-checker, a termination checker and a decision procedure for equivalence.

Working with a Curry style language has the disadvantage of making type-checking undecidable. While most proof systems avoid this problem by switching to Church style, it is possible to use heuristics making most Curry style programs that arise in practice directly typable. Christophe Raffalli implemented such a system [26] and from his experience it would seem that very little help from the user is required in general. In particular, if a term is typable then it is possible for the user to provide hints (e.g. the type of a variable) so that type-checking may succeed. This can be seen as a kind of completeness.

Proof assistants like Coq [18] or Agda [22] both have decidable type-checking algorithms. However, these systems provide mechanisms for handling implicit arguments or meta-variables which introduce some incompleteness. This does not make these systems any less usable in practice. We conjecture that going even further (i.e. full Curry style) provides a similar user experience.

To obtain a practical programming language we will need support for recursive programs. For this purpose we plan on adapting Pierre Hyvernat’s termination checker [9]. It is based on size change termination and has already been used in the first prototype implementation. We will also need to extend our type system with inductive (and coinductive) types [19, 25]. They can be introduced in the system using fixpoints \(\mu X\,A\) (and \(\nu X\,A\)).