S:Types
We have type constants atomic, existential, prop and nulltype. They will be used to assign types to formulas. E.g. ∀nn = 0 receives the type nat → atomic, and ∀n,m∃k n + m = k receives the type nat → nat → existential. The type prop is used for predicate variables, e.g. R of arity nat,nat -> prop. Types of formulas will be necessary for normalization by evaluation of proof terms. The type nulltype will be useful when assigning to a formula the type of a program to be extracted from a proof of this formula. Types not involving the types atomic, existential, prop and nulltype are called object types.
Type variable names are alpha,beta…; alpha is provided by default. To have infinitely many type variables available, we allow appended indices: alpha1,alpha2,alpha3… will be type variables. The only type constants are atomic,existential,prop and nulltype.
2.1. Generalitites for substitutions, type substitutions.
SS:GenSubst
(make-substitution args vals) | |||||
(make-substitution-wrt arg-val-equal? args vals) | |||||
(make-subst arg val) | |||||
(make-subst-wrt arg-val-equal? arg val) | |||||
empty-subst |
Composition ϑσ of two substitutions
ϑ | = ((x1 s1)…(xm sm)), | ||
σ | = ((y1 t1)…(yn tn)) |
(compose-substitutions-wrt | substitution-proc arg-equal? | ||||
arg-val-equal? subst1 subst2) |
We shall have occasion to use these general substitution procedures for the following kinds of substitutions
The following substitutions will make sense for a
In particular, for type substitutions tsubst we have
(type-substitute type tsubst) | |||||
(type-subst type tvar type1) | |||||
(compose-t-substitutions tsubst1 tsubst2) |
(display-t-substitution tsubst) |
2.2. Simultaneous free algebras as base types.
We allow the formation of inductively generated types μ, where
= α1,…,αn is a list of distinct type variables, and
is a list of “constructor
types” whose argument types contain α1,…,αn in strictly positive positions
only.
For instance, μα(α,α → α) is the type of natural numbers; here the list (α,α → α) stands for two generation principles: α for “there is a natural number” (the number 0), and α → α for “for every natural number there is another one” (its successor).
Let an infinite supply of type variables α,β be given. Let = (αj)j=1,…,m be a
list of distinct type variables. Types ρ,σ,τ,μ,ν ∈ Types and constructor types
κ ∈ KT(
) are defined inductively as follows.
![]() | |||
![]() ![]() |
Examples.
unit | := μαα, | ||||||
boole | := μα (α,α), | ||||||
nat | := μα (α,α → α), | ||||||
ytensor(α1)(α2) | := μα.α1 → α2 → α, | ||||||
ypair(α1)(α2) | := μα.(unit → α1) → (unit → α2) → unit → α, | ||||||
yplus(α1)(α2) | := μα.(α1 → α,α2 → α), | ||||||
list(α1) | := μα (α,α1 → α → α), | ||||||
(tree,tlist) | := μ(α,β)(α,β → α,β,α → β → β), | ||||||
btree | := μα (α,α → α → α), | ||||||
𝒪 | := μα (α,α → α,(nat → α) → α), | ||||||
𝒯0 | := nat, | ||||||
𝒯n+1 | := μα (α,(𝒯n → α) → α). |
To add and remove names for type variables, we use
(add-tvar-name name1 ...) | |||
(remove-tvar-name name1 ...) |
(make-tvar index name) | constructor | ||||||
(tvar-to-index tvar) | accessor | ||||||
(tvar-to-name tvar) | accessor | ||||||
(tvar? x). |
(new-tvar type) |
To introduce simultaneous free algebras we use
An example is
(add-param-algs
(list "labtree" "labtlist") ’alg-typeop 2 ’("LabLeaf" "alpha1=>labtree") ’("LabBranch" "labtlist=>alpha2=>labtree") ’("LabEmpty" "labtlist") ’("LabTcons" "labtree=>labtlist=>labtlist" pairscheme-op)) |
This simultaneously introduces the two free algebras labtree and labtlist, both finitary, whose constructors are LabLeaf, LabBranch, LabEmpty and LabTcons (written as an infix pair operator, hence right associative). The constructors are introduced as “self-evaluating” constants; they play a special role in our semantics for normalization by evaluation.
In case there are no parameters we use add-algs, and in case there is no need for a simultaneous definition we use add-alg or add-param-alg.
For already introduced algebras we need constructors and accessors
(alg-form? x) | incomplete test | ||||||
(alg? x) | complete test | ||||||
(finalg? type) | incomplete test | ||||||
(ground-type? x) | incomplete test |
We require that there is at least one nullary constructor in every free algebra; hence, it has a “canonical inhabitant”. For arbitrary types this need not be the case, but occasionally (e.g. for general logical problems, like to prove the drinker formula) it is useful. Therefore
(make-inhabited type term1 ...) |
which returns the canonical inhabitant; it is an error to apply this procedure to a non-inhabited type. We do allow non-inhabited types to be able to implement some aspects of [7, 1]
To remove names for algebras we use
(remove-alg-name name1 ...) |
Examples. Standard examples for finitary free algebras are the type nat of unary natural numbers, and the type btree of binary trees. The domain ℐnat of unary natural numbers is defined (as in [4]) as a solution to a domain equation.
We always provide the finitary free algebra unit consisting of exactly one element, and boole of booleans; objects of the latter type are (cf. loc. cit.) true, false and families of terms of this type, and in addition the bottom object of type boole.
Tests:
(arrow-form? type) | |||
(star-form? type) | |||
(object-type? type) |
We also need constructors and accessors for arrow types
(make-arrow arg-type val-type) | constructor | ||||||
(arrow-form-to-arg-type arrow-type) | accessor | ||||||
(arrow-form-to-val-type arrow-type) | accessor |
(make-star type1 type2) | constructor | ||||||
(star-form-to-left-type star-type) | accessor | ||||||
(star-form-to-right-type star-type) | accessor. |
(mk-arrow type1 ... type) | |||||||
(arrow-form-to-arg-types type <n>) | all (first n) argument types | ||||||
(arrow-form-to-final-val-type type) | type of final value. |
(type? x) | |||
(type-to-string type). |
Implementation. Type variables are implemented as lists: