Recent years have seen great advances in formalisation of mathematics in type theory, in particular with the development of homotopy type theory [hottbook]. Such formalisations are an important step towards machine assisted verification of mathematical proofs. Rather than adapting classical set theory-based mathematics to type theory, new synthetic approaches sometimes offer simpler and clearer presentations in type theory. As an example of the synthetic approach, consider synthetic homotopy theory [hottbook], which formalises homotopy theory in type theory, not by formalising a topological space as a type with structure, but rather by thinking of types as topological spaces directly. Particular spaces such as the circle can then be constructed as types using higher inductive types. Synthetic homotopy theory can be formally related to classical homotopy theory via the simplicial sets interpretation of homotopy type theory [Simplicial:model], interpreting types essentially as topological spaces.
Just like any other branch of mathematics, domain theory and denotational semantics for programming languages with recursion should be formalised in type theory and, as was the case of homotopy theory, synthetic approaches can provide clearer and more abstract proofs. In the case of domain theory, the synthetic approach means treating types as domains, rather than constructing domains internally in type theory as types with an order relation. The result of this should be a considerable simplification of denotational semantics when expressed in type theory. For example, function types of a higher-order object language can be modelled simply as the function types of type theory, rather than as some type of Scott continuous maps. To model recursion, some form of fixed point construction must be added to type theory, but, as is well known, an unrestricted fixed point combinator makes the logical reading of type theory inconsistent.
1.1 Synthetic guarded domain theory
In this paper we follow the approach of guarded recursion [Nak00], which introduces a new type constructor , pronounced “later”. Elements of are to be thought of as elements of type available only one time step from now, and the introduction form makes anything available now, also available later. The fixed point operator has type
and maps an to a fixed point of . Guarded recursion also assumes solutions to all guarded recursive type equations, i.e., equations where all occurences of the type variable are under a , as for example in the equation
used to define the lifting monad below, but guarded recursive equations can also have negative or even non-functorial occurences.
One application of guarded recursion is for programming with coinductive types. This requires a notion of clocks used to index delays. For example, if is a clock and is a type then is a type. If is a clock variable not free in and , then can be universally quantified in to give the type which can be shown to be a coinductive solution to . Almost everything we do in this paper uses a single implicit clock variable and all uses of should be thought of as indexed by this clock. More details can be found in Section 2.
Recent work has shown how guarded recursion can be used to construct syntactic models and operational reasoning principles for (also combinations of) advanced programming language features including general references, recursive types, countable non-determinism and concurrency [BMSS12, BBM14, SB14]. These models often require solving recursive domain equations which are beyond the reach of domain theoretic methods. When viewing these syntactic models through the topos of trees model of guarded recursion [BMSS12] one recovers step-indexing [App01], a technique for sidestepping recursive domain equations by indexing the interpretation of types by numbers, counting the number of unfoldings of the equation. Thus guarded recursion can be more accurately described as synthetic step-indexing. Indeed, guarded recursion provides a type system for constructing step-indexed models, in which the type equations sidestepped by step-indexing can be solved using guarded recursive types.
This work is part of a programme of developing denotational semantics using guarded recursion with the expectation that this will not only be simpler to formalise in type theory than the classical domain theoretic semantics, but also generalise to languages with advanced features for which step-indexing has been used for operational reasoning. This programme was initiated in previous work [PMB15], in which a model of PCF (simply typed lambda calculus with fixed points) was developed in Guarded Dependent Type Theory () [BGCMB16] an extensional type theory with guarded recursive types and terms. By aligning the fixpoint unfoldings of PCF with the steps of the metalanguage (represented by ), we proved a computational adequacy result for the model inside type theory. Guarded recursive types were used both in the denotational semantics (to define a lifting monad) and in the proof of computational adequacy. Likewise, the fixed point operator of was used both to model fixed points of PCF and as a proof principle.
Here we extend our previous work in two ways. First we extend the denotational semantics and adequacy proof to languages with recursive types. Secondly, we define a relation capturing extensionally equal elements in the model.
More precisely, we consider the language FPC (simply typed lambda calculus extended with general recursive types) with a call-by-name operational semantics. Working internally in this language can be given a denotational semantics in the synthetic style discussed above. In particular, function types of FPC are interpreted simply as the function types of . Base types are interpreted using the lifting monad satisfying the isomorphism (1). In particular the unit type of FPC is interpreted as isomorphic to , so that denotationally, a program of this type is either a value now, or a delayed computation. Recursive types are modelled as guarded recursive types satisfying the isomorphism
(in the case of closed types). This means that the introduction rule for recursive types (folding a term) can be interpreted as . To interpret unfolding of terms of recursive types we construct, for every FPC type a map , and interpret unfolding as . As a consequence, folding followed by unfolding is interpreted as the map defined as . This composition is not the identity, rather the denotational semantics counts the number of fold-unfold reductions needed to evaluate a term to a value.
Thus, to state a precise soundness theorem, the operational semantics also needs to count the fold-unfold reductions. To do this, we define a judgement to mean that reduces to in a sequence of reductions containing exactly fold-unfold reductions, and an equivalent big-step semantics . One might hope to formulate an adequacy theorem stating that for of type , (where is the introduction form for ) if and only if . Unfortunately this is not true. For example, if the type is empty, but the identity type is equivalent to , a non-standard truth value different from . To state an exact correspondence between the operational and denotational semantics we use the guarded transitive closure of the small-step semantics which synchronises the steps of FPC with those of . This is defined as if , and , where is a fold-unfold reduction in an evaluation context.
The adequacy theorem states that if and only if . We prove this working inside , and the proof shows an interesting aspect of guarded domain theory: It uses a logical relation between syntax and semantics defined by induction over the structure of types. The case of recursive types requires a solution to a recursive type equation. In the setting of classical domain theory, the existence of this solution requires a separate argument [Pit96], but here it is simply a guarded recursive type.
The second contribution is a relation capturing extensionally equal elements in the model. As mentioned above, the denotational semantics distinguishes between computations computing the same value in a different number of steps. In this paper we construct a relation on the denotational semantics of each type relating elements extensionally equal elements, i.e., elements that compute the same value in a different number of steps. This relation is defined on the global interpretation of types defined from by quantifying over the implicit clock variable (see Section 1.1 above). This is necessary, because, as can be seen from the denotational semantics of guarded recursion, any relation on relating to for any will also necessarily relate non-termination to . On the other hand, it is possible to define such a relation on which is the coinductive solution to . This is then lifted to function types in the usual way for logical relations: Two functions are related it they map related elements to related elements, and to recursive types using a solution to a guarded recursive type equation. We prove a soundness result for this relation stating that if the (global) denotation of two terms are related, then the terms are contextually equivalent.
Finally we show that it is possible to execute the denotational semantics. Of course, FPC is a non-total programming language, so to run FPC programs in type theory, these must be given a time-out to ensure termination. We demonstrate the technique in the case of boolean typed programs and show that the denotation of a program executes to true with a time-out of steps if and only if the program evaluates to true in less than steps in the operational semantics.
All constructions and proofs are carried out working informally in . This work illustrates the strength of , and indeed influenced the design of the type theory.
1.3 Related work
Escardó constructs a model of PCF using a category of ultrametric spaces [Esc99]. Since this category can be seen as a subcategory of the topos of trees [BMSS12], our previous work on PCF is a synthetic version of Escardó’s model. Escardó’s model also distinguishes between computations computing the same value in a different number of steps, and captures extensional behaviour using a logical relation similar to the one constructed here. Escardó however, does not consider recursive types. Although Escardó’s model was useful for intuitions, the synthetic construction in type theory presented here is very different, in particular the proof of adequacy, which here is formulated in guarded dependent type theory.
Synthetic approaches to domain theory have been developed based on a wide range of models dating back to [Hyl91, Ros86]. Indeed, the internal languages of these models can be used to construct models of FPC and prove computational adequacy [Sim02]. A more axiomatic approach was developed in Reus’s work [Reu96] where an axiomatisation of domain theory is postulated a priori inside the Extended Calculus of Constructions.
There has also been work on (non-synthetic) adaptations of domain theory to type theory [BKV09, BBKV10, Dockins14]. However, due to the mistmatch between set-theory and type theory “some of the proofs and constructions are much more complex than they would classically and one does sometimes have to pay attention to which of two classically-equivalent forms of definition one works with” [BKV09]. More recently Altenkirch et al. [ADK17] have shown how to encode the free pointed -cpo as a quotient inductive-inductive types (QIIT). This looks like a more promising direction for domain theory in type theory, but this has not yet been developed to models of programming languages.
The lifting monad used in this paper is a guarded recursive variant of Capretta’s delay monad [Cap05] considered by among others [BKV09, BBKV10, Dan12, CUV15, ADK17, Veltri17]. The monad is coinductively generated by the constructors and . As reported by Danielsson [Dan12], working with the partiality monad requires convincing Agda of productivity of coinductive definitions using workarounds. In this paper productivity is ensured by the type system for guarded recursion.
In the delay monad, two computations of type can be distinguished by their number of steps. To address this issue, Capretta also defines a weak bisimulation on this monad, similar to the one defined in Definition 6.2, and proves the combination of the delay monad with the weak bisimulation is a monad using setoids. Chapman et al.[CUV15, Veltri17] avoid using setoids, but they crucially rely on proposition extensionality and the axiom of countable choice. Altenkirch et al. [ADK17] show that under the assumption of countable choice, their free pointed -cpo construction is equivalent to quotiented delay monad of Chapman et al. We work crucially with the non-quotiented delay monad when defining the denotational semantics, since the steps are necessary for guarded recursion.
This is an extended version of a conference publication [MP16]. A number of proofs that were omitted from the previous version due to space restrictions have been included in this version. There is also a slight difference in approach: the conference version defined a big-step operational semantics equivalent to the guarded transitive closure of the small-step operational semantics of Figure 2 below. This operational semantics synchronises the steps of FPC with those of the meta-language, and capturing this in a big-step semantics was quite tricky. Here, instead, we define a simpler big-step operational semantics and prove this equivalent to the “global” small-step semantics (Lemma 3.2). The results on executing the denotational semantics presented in Section 7 are also new.
Since this work was carried out, the extensional type theory that we work in in this paper has been extended in two directions towards intensionality and implementation. The first direction is Guarded Cubical Type Theory [BBCGV16], extending the fragment of without universal quantification over clocks with constructions from Cubical Type Theory [CCHM15]. Guarded Cubical Type Theory even has a prototype implementation. The other direction is Clocked Type Theory [clott], a variant of the fragment of without identity types in which delayed substitutions (Section 5.1) are encoded using a new notion of ticks on a clock. Clocked Type Theory has a strongly normalising reduction semantics. Since neither theory is complete, we stick to as our type theory for this paper.
The paper is organized as follows.
Section 2 gives a brief introduction to the most important concepts of . More advanced constructions of the type theory are introduced as needed. Section 3 defines the encoding of FPC and its operational semantics in . The denotational semantics is defined and soundness is proved in Section 4. Computational adequacy is proved in Section 5, and the relation capturing extensional equivalence is defined in Section 6. Section 7 shows how to execute the denotational semantics of boolean programs. We conclude and discuss future work in Section 8.
We thank Nick Benton, Lars Birkedal, Aleš Bizjak, and Alex Simpson for helpful discussions and suggestions.
2 Guarded recursion
In this paper we work informally within a type theory with dependent types, inductive types and guarded recursion. Although inductive types are not mentioned in [BGCMB16] the ones used here can be safely added – as they can be modelled in the topos of trees model – and so the arguments of this paper can be formalised in Guarded Dependent Type Theory () [BGCMB16]. We start by recalling some core features of this theory, but postpone delayed substitutions to Section 5.1
since these are not needed for the moment.
When working in type theory, we use for judgemental equality of types and terms and for propositional equality (sometimes when we want to be explicit about the type). We also use for (external) set theoretical equality.
The core of guarded recursion consists of the type constructor and the fixed point operator satisfying
both introduced in Section 1.1. Elements of type are intuitively elements of type available one time step from now. To illustrate the power of the fixed point operator, consider a type of guarded streams satisfying
This is a guarded recursive type in the sense that the recursion variable appears under a , and its elements are to be thought of as streams, whose head is immediately available and whose tails take one time step to compute. The fixed point operator can be used to define guarded streams by recursion. For example, the constant stream of a number can be defined as , where the type isomorphism (3) is left implicit. Note that the type of the fixed point operator prevents us from defining elements like , which are not productive, in the sense that any element of the stream can be computed in finite time. In fact, the type precisely captures productive recursive stream definitions.
The type constructor is an applicative functor in the sense of [MP08], which means that there is a “later application” written infix, satisfying
among other axioms (see also [BM13]). In particular, extends to a functor mapping to . Moreover, the operator distributes over the identity type as follows
Guarded dependent type theory comes with universes in the style of Tarski. In this paper, we will just use a single universe . Readers familiar with [BGCMB16] should think of this as , but since we work with a unique clock , we will omit the subscript. The universe comes with codes for type operations, including for binary sum types, codes for dependent sums and products, and satisfying
where we use for the type corresponding to an element . The type of allows us to solve recursive type equations using the fixed point combinator. For example, if is small, i.e., has a code in , the type equation (1) can be solved by computing a code of as
and then by taking the elements using . More precisely, defining as , unfolds to which is equal to which is equal to . In this paper, we will only apply the monad to small types .
To ease presentation, we will usually not distinguish between types and type operations on the one hand, and their codes on the other. We will still refer use the notation , but write for the composition . We generally leave implicit.
2.1 The topos of trees model
The topos of trees is the category of presheaves over , the first infinite ordinal. The category models guarded recursion [BMSS12] and provides useful intuitions, and so we briefly recall it.
A closed type is modelled as an object of the topos of trees, i.e., as a family of sets indexed by natural numbers together with restriction maps as in the following diagram
A term of type in context , for closed types, is modelled as a morphism in , i.e., as a family of functions obeying the naturality condition as in the following diagram
The type operator is modelled as an endofunctor in such that , . Intuitively, is the th approximation for computations of type , thus describes the type as it looks if we have computational steps to reason about it.
Using the proposition-as-types principle, types like are non-standard truth values. Following the intuition that is the type as it looks, if we have steps to reason about it, is the truth value of propositions that appear true for computation steps, but then are falsified after . In fact, in the model, equals , but equals zero as depicted by the following diagram
The global elements of a closed type is the set of morphisms from the constant object to in . This can be thought of as the limit of the sequence of (8) as a diagram in Set. This construction gives us the global view of a type as it allows us to observe all the computation at once. For example, the global elements of correspond to those of simply by discarding the first component. Note that objects can have equal sets of global elements without being isomorphic. In particular and are not isomorphic.
For guarded recursive type equations, describes the th unfolding of the type equation. For example, fixing an object , the unique solution to (1) is
with restriction maps defined using the restriction maps of . In particular, if is a constant presheaf, i.e., for some fixed and identities, then we can think of as with restriction map given by , and for . The set of global elements of is then isomorphic to . In particular, if , the set of global elements is , the natural numbers extended with a point at infinity.
The global elements of , correspond to the elements of Capretta’s partiality monad [Cap05] defined as the coinductive solution to the type equation
Similarly, the type of can be modelled as . Note that if these products associate to the right, we can even model (3) as an identity. The restriction maps of this type are projections, and the global elements of this type correspond to streams in the usual sense.
2.2 Universal quantification over clocks
The type of guarded streams mentioned above, is not the usual coinductive type of streams. For example, a term in context is a causal function of streams, i.e., one where the first elements of the output depend only on the first elements of the input. This can be seen e.g. in the topos of trees model, where such a term is modelled by a family of maps commuting with projections. Causality is crucial to the encoding of productivity in types mentioned above.
On the other hand, a closed term is modelled by a global element of and thus corresponds to a real stream of numbers. Likewise, if only depends on a variable , then denotes a map from the set of natural numbers to that of streams, because the context is modelled as the constant topos of trees object , with restriction maps being identities. More generally, say a context is independent of time if it is modelled as a constant object, i.e, one where all restriction maps are isomorphisms. The denotation of a term in a context independent of time, corresponds to a map from to the set of streams.
The idea of independence of time can be captured syntactically using a notion of clocks, and universal quantification over these [AM13]. We now briefly recall this as implemented in , referring to [BGCMB16] for details.
In all types and terms are typed in a clock context, i.e., a finite set of names of clocks. For each clock , there is a type constructor , a fixed point combinator, and so on. Each clock carries its own notion of time, and the idea of a context being independent of time mentioned above, can be captured as a clock not appearing in a context.
If is a type in a context where does not appear, one can form the type , binding . This construction behaves in many ways similarly to polymorphic quantification over types in System F. There is an associated binding introduction form (applicable to terms where does not appear free in the context), and elimination form having type whenever .
Semantically, a closed type in the empty clock variable context is modelled by a set, and a type in a context of a single clock is modelled as an object in the topos of trees. In the latter case, universal quantification over the single clock is modelled by taking the set of global elements. As we saw above, these sets correspond to coinductive types, and this also holds in the type theory: If is the type of streams guarded on clock , i.e., satisfies , then one can prove [AM13, Mog14] that the type behaves as a coinductive type of streams. Similarly, if , and is not free in , then is a coinductive solution to . This isomorphism arises as a composite of isomorphisms
the components of which we recall below. Using these encodings one can use guarded recursion to program with coinductive types in such a way that typing guarantees productivity. We refer to [BM15] for a full model of guarded recursion with clocks, in particular for how to model types with more than one free clock variable.
The isomorphism (14) arises from a general type isomorphism holding for all . The direction from right to left is induced by . For the direction from left to right, a form of elimination for is needed, but note that an unrestricted such of type in combination with fixed points makes the type system inconsistent. Instead allows for a restricted elimination rule for : If is of type in a context where does not appear free, then has type . Using we can define a term :
The term can be proved to be an isomorphism by the axioms
If is not free in , the type is isomorphic to , justifying the isomorphism (13). The map is simply . The other direction is given by application to a clock constant , which we assume exists. These can be proved to be inverses of each other using the clock irrelevance axiom, which states that if and does not appear free in , then for all and . Using and the isomorphism , one can prove that is isomorphic to , reflecting the fact that there are no global elements of in the model, as mentioned earlier. We refer to [BGCMB16] for details.
The isomorphism (12) is a special case of an isomorphism
distributing over sums for all small types and . To describe this isomorphism, encode sum types as where is defined by cases by and . The result of applying the left to right direction of the isomorphism to is defined by cases of . If , note that for any , using the clock irrelevance axiom
and so has type
and so we can define in this case . The case of is similar. In fact, this construction generalises to an isomorphism
valid whenever is not free in .
Finally we note the following extensionality rule for quantification over clocks.
In most of this paper we will work in a setting of a unique implicit clock , and simply write for to avoid cluttering all definitions and calculations with clocks.
For the proof of computational adequacy we will need one more construction from : The delayed substitutions. These will be recalled in Section 5.1.
This section defines the syntax, typing judgements and operational semantics of FPC. These are inductive types in guarded type theory, but, as mentioned earlier, we work informally in type theory, and in particular remain agnostic with respect to choice of representation of syntax with binding.
The typing judgements of FPC are defined in an entirely standard way. The grammar for terms of FPC
should be read as an inductive type of terms in the standard way. Likewise the grammars for types and contexts and the typing judgements defined in Figure 1 should be read as defining inductive types in type theory, allowing us to do proofs by induction over e.g. typing judgements.
We denote by , and the types of closed FPC types and terms, and values of FPC and by the type of all (also open) terms. By a value we mean a closed term matching the grammar
Well formed types
3.1 Operational semantics
Guarded transitive closure of the small-step semantics
Figure 2 defines a big-step and a small-step operational semantics for FPC, as well as two transitive closures of the latter. All these definitions should be read as inductive types. Since the denotational semantics of FPC is intensional, counting reduction steps, it is necessary to also count the steps in the operational semantics in order to state the soundness and adequacy theorems precisely. More precisely, the semantics counts the number of unfold-fold reductions in the same fashion in which Escardó counted fix-point reduction for PCF.
where is a term, a natural number, and a value, should be read as ’ evaluates in steps to a value . We can define more standard big-step evaluation predicates as follows
We note that the semantics is trivially deterministic.
The small-step semantics is deterministic: if and , then and .
Of the two transitive closures of the small-step semantics defined in Figure 2 the first is a standard one, equivalent to the big-step operational semantics. The second is a guarded version which synchronises the steps of FPC with those of the metalogic. This is needed for the statement of the soundness and adequacy theorems, and also allows for guarded recursion to be used in the proofs of these. The next lemma states the relationship between the big-step semantics and the two transitive closures of the small-step semantics
Let and be FPC terms, a value and a natural number. Then
Note that in particular implies . The opposite implication does not hold, as we shall see in the examples below.
The first statement is a essentially a textbook result on operational semantics, and we omit the proof.
For the second statement the proof from left to right is by induction on . The case of is trivial, so consider the case when and . When , by definition , and by induction hypothesis we know that . Thus, holds for any , and so also , since is not free in the assumption . When by induction hypothesis and thus, for any , . As before, this allows us to conclude .
The right to left implication is proved by induction on . When the clock is not free in and so is isomorphic to , which implies . When the assumption implies that , and . By the type isomorphism (15) the latter implies , which by the induction hypothesis implies . Thus we conclude .
As an example of a recursive FPC type, one can encode the natural numbers as
Using this definition we can define the term of PCF. If is a term of type nat and , are terms of type define as
where are fresh. It is easy to see that iff and that iff for any term of type nat. For example, is . On the other hand, is equivalent to , showing that and are not equivalent.
Recursive types introduce divergent terms. For example, given a type , the Turing fixed point combinator on can be encoded as follows:
An easy induction shows that , where is the empty type.
If with a value and a term, then
is logically equivalent to if , where is the empty type
If, on the other hand, is divergent in the sense that for any there exists an such that , then is equivalent to .
4 Denotational Semantics
We now define the denotational semantics of FPC. First we recall the definition of the guarded recursive version of the lifting monad on types from [PMB15]. This is defined as the unique solution to the guarded recursive type equation
which exists because the recursive variable is guarded by a . Recall (Section 2) that guarded recursive types are defined as fixed points of endomaps on the universe, so is only defined for small types . We will only apply to small types in this paper.
The isomorphism induces a map and a map . An element of is either of the form or . We think of these cases as values “now” or computations that “tick”. Moreover, given with a -algebra (i.e., equipped with a map ), we can lift to a homomorphism of -algebras as follows
Formally is defined as a fixed point of a term of type . Recall that is the application of the functor to the map , thus is an algebra homomorphism.
Intuitively is the type of computations possibly returning an element of , recording the number of steps used in the computation. We can define the divergent computation as and a “delay” map of type for any as . The latter can be thought of as adding a step to a computation. The lifting extends to a functor. For a map the action on morphisms can be defined using the unique extension as .
4.1 Interpretation of types
A type judgement is interpreted as a map of type , where is the cardinality of the set of variables in . This interpretation map is defined by a combination of induction and guarded recursion for the case of recursive types as in Figure 3.
More precisely, the case of recursive types is defined to be the fixed point of a map from to defined as follows:
The first equation is the application of rule (2) for the guarded fix-point combinator, whereas the second equation is derived by distributivity over the later application operator described by rule (4). Finally, the last equation is derived by the fact that the elements of the code of the later operator is the later operator on types (rule (6)).
We prove now the substitution lemma for types which states that substitution behaves as expected, namely that substituting type variables in the syntax with syntactic types corresponds to applying a dependent type to a type . This can be proved using guarded recursion in the case of recursive types.
Lemma 4.1 (Substitution Lemma for Types)
Let be a well-formed type with variables in and let be of type . If then
The proof is by induction on . Most cases are straightforward, and we just show the case of . The proof of this case is by guarded recursion, and thus we assume that
Assuming (without loss of generality) that is not we get the following series of equalities
The latter equals
By direct use of the Substitution Lemma we can prove that the interpretation of the recursive type equals the interpretation of the unfolding of the recursive type itself, only one step later. Intuitively, this means that we need to consume one computational step to look at the data.
For all types and environments of type ,
The interpretation of every closed type carries a -algebra structure, i.e., a map , defined by guarded recursion and structural induction on as in Figure 4. The case of recursive types is welltyped by Lemma 4.2, and can be formally constructed as a fixed point of a term of type
as follows. Suppose , and define essentially as in Figure 4 but with the clause for recursive types being defined as
Here is defined as using a generalisation of to dependent products to be defined in Section 5.1. Define as the fixed point of . Then
Using the we define the delay operation which, intuitively, takes a computation and adds one step.
4.2 Interpretation of terms
Figure 5 defines the interpretation of judgements as functions from to where . In the case of case, the function is the extension of to a homomorphism defined as in (21) above, using the fact that all types carry a -algebra structure. The interpretation of is welltyped because has type which by Lemma 4.2 is equal to . In the case of unfold, since has type , which by Lemma 4.2 is equal to , the type of is .
If then .
Straightforward by definition of the interpretation and by the type equality from Lemma 4.2.
Next lemma proves substitution is well-behaved for terms. The proof is standard textbook result from domain theory (e.g. [Winskel93, Streicher06]).
Lemma 4.4 (Substitution Lemma)
Let be a context such that , and let be a term for each . If further , then
By induction on the typing judgement .
The cases for , , , , , are standard.
For the case we start from
By substitution equals . We also know that its denotation equals by induction hypothesis this is equal to
which is now by definition what we wanted. The case for is similar.
Now the case for . By definition we know that is equal
which is by definition of the interpretation equal to
where is as in Figure 5. By induction hypothesis we know that this is equal to
which is equal by definition to
Now the fixed point cases. For the case we know that is equal by definition of the substitution function to
which by definition of interpretation is . By induction hypothesis this is equal to
which by definition is . For the case we know that is equal by defintion to which is by definition of the interpretation equal to . By induction hypothesis we get which is by definition
We now aim to show a soundness theorem for the interpretation of FPC. We do this by first showing soundness of the single step reduction as in the next lemma. As usual in denotational semantics, this proves that the model is agnostic to operational reductions.
Let be a closed term of type . If then
The proof goes by induction on . The cases when follow straightforwardly from the structure of the denotational model.
The case follows directly from Lemma 4.3.
The case for is straightforward from by Substitution Lemma 4.4.
The case for and the case for
follow directly by definition.
Also the elimination for the product, namely and follow directly from the definition of the interpretation.
Now we prove the inductive cases. For the case we know that by definition . By induction hypothesis we know that , thus By definition of and this is equal to .
Now the case for
The induction hypothesis gives , and so Lemma 4.6 applies proving the case.
The case for and for are similar to the previous case.
Finally, the case for . By definition we know that
By induction hypothesis this is equal to which by Lemma 4.7 is equal to thus concluding.
The two most complicated cases of the proof of Lemma 4.5, namely the unfold-fold reductions and case, are captured in the following two lemmas. In particular, the first of these states that the interpretation of case is a -algebra homomorphism. In other words, case analysing over a computation that perform ticks and then produces a result is equal to a computation that produces ticks and then performs case analysis over a terminating computation producing a value .
The interpretation of case is a homomorphism of -algebras in the first variable, i.e.,