Yale University Department of Computer Science
Yale University Department of Computer Science
Adam Poswolsky
YALEU/DCS/TR-1364
July 2006
A Temporal-Logic Approach to
Functional Calculi for Dependent Types
and Higher-Order Encodings
Adam Poswolsky∗
Abstract
Dependent-types and higher-order encodings lead to concise and
elegant representations of complex data structures as evidenced by the
success of the logical framework LF [HHP93].
In this work we first design a functional calculus utilizing LF to
represent its data objects. To avoid problems commonly associated
with using the same function space for both representation (LF objects)
and computation, we separate the two as influenced by our previous
work [Sch05]. We then exploit the power of the past time connective
from temporal logic to design a meta-logic to reason about higher-
order abstract syntax. Sample programs that we discuss in this paper
include bracket abstraction and a theorem prover.
It is important to note that this technical report is an enhancement/
simplification of a previous technical report [Pos06] where past-time
was used as a modal operator in the meta-logic for LF. Here, we use
past-time on the meta-meta-level for LF.
1 Introduction
Temporal extensions of logics have proved useful for binding time analy-
sis [Dav96] and meta-programming [Tah04]. In this paper we show how
temporal logic can be used to develop a calculus with functions ranging over
the usual dependently typed and higher-order encodings of deductive sys-
tems in the logical framework LF [HHP93, Pfe99]. This technical report is
an enhancement/ simplification of a previous technical report [Pos06] where
past-time was used as a modal operator in the meta-logic for LF. Here, we
use past-time on the meta-meta-level for LF.
∗
Department of Computer Science, Yale University, CT
1
Dependent datatypes allow for type systems that are more expressive
than their simply-typed counterparts as types may be indexed by expres-
sions. For example, a list type could be indexed by its length, or a certificate
type could be indexed by the formula it is witnessing.
Both higher-order encodings, or higher-order abstract syntax (HOAS),
and hypothetical judgments employ functional abstraction of the logical
framework to model variable binding. This permits programmers to program
efficiently with complex data-structures without having to worry about the
representation of variables, binding constructs, or substitutions that are
prevalent in logic derivations, typing derivations, operational semantics, and
intermediate languages.
The challenge in designing a functional calculus for LF is that it must
provide two different function spaces [SDP01, Sch05]. In Section 2, we begin
by defining the logical framework LF. We then give a first-order meta-logic
for LF and prove soundness.
Rather than use temporal logic to represent propositions occurring at
different times, we use it to represent derivations occurring at different times.
To this end our temporal logic serves as a meta logic for the logic defined in
Section 2. We define our temporal meta logic in Section 3, discuss properties,
and prove soundness. All proofs in this paper have been encoded and verified
in Twelf [PS99] except that the underlying calculus is the simply-typed
version. Twelf code is digitally available upon request and can also be read
in Appendix A.
In Section 4, we discuss how the resulting calculus handles functions
over higher-order abstract encodings. The operators for programming with
higher-order abstract syntax correspond to admissible rules. This allows us
to statically reason about when parameters can be accessed. This compile-
time guarantee that parameters cannot escape their scope is the driving
force of this work. Current research with coverage checking and termination
checking will allow us to statically check that all cases are covered and
hence cumulatively get a static guarantee that a function is total without
the cumbersome caveat of possible runtime exceptions.
Next we derive a logically equivalent, but motivated for programming,
system in Section 5. In Section 6 we add a mechanism to conduct case
analysis, and finally in Section 7 we add recursion.
We illustrate the resulting λD calculus, or Delphin, with examples of
bracket abstraction and theorem proving in Section 8. We describe related
work in Section 9 before we conclude and assess results in Section 10.
Finally we invite the reader to consult the Delphin homepage for more
information: www.cs.yale.edu/∼delphin.
2
2 Meta-Logic for Dependently-Typed LF
We will start with a brief introduction to the Edinburgh logical frame-
work [HHP93], or LF, and then discuss our logic LhiΠ to reason about LF
objects.
We will define syntactic categories of objects M and types A to which
we assign the usual logic meaning. In our system we provide a clean divide
between the meta-level (computation) and the representation-level (LF).
The justification for this design is based on our previous work with the ∇-
calculus [Sch05], but simply stated it is necessary because we cannot reason
about arbitrary functions on the meta-level so our system syntactically en-
forces that representation-level functions cannot see computation-level ones.
We say hAi is true if and only if the type A is inhabited. If M is the witness
of inhabitation, we interpret M as a proof of hAi.
2.1 Preliminaries
Types are defined as: A, B ::= a | A M | Πx : A .B. Function types assign
names to their arguments in Πx : A .B. We reserve the notation A → B
as syntactic sugar when the return type is not dependent on its argument.
Types may be indexed by objects and we provide the construct A M to
represent such types. The syntactic category for objects is: M, N ::= x |
c | M N | λx : A .N . We write x for variables while a and c are type and
object constants, respectively. These constants are provided a priori in a
collection Σ ::= · | Σ, a : type | Σ, c : A. This should be seen as datatype
declaration, keeping in mind that our notion of datatype is non-standard
as we permit higher-order functions to be passed to constants without the
usual restriction that variables of the datatype that is being defined cannot
occur in negative positions.
With dependent types, not all types are valid. The kind system of
LF acts as a type system for types. Valid kinds are defined a follows:
K ::= type | Πx : A .K. The typing rules and kinding rules of LF may
not be as well-known as those of the simply typed λ-calculus, but they are
standard [HHP93]. We write Γ ` M : A for valid objects and Γ ` A : K for
valid types, in context Γ ::= · | Γ, x : A which assigns types to variables. We
take βη as the underlying notion of equivalence between λ-terms. Terms in
β-normal η-long form are also called canonical forms.
3
The existence of canonical forms is instrumental for encodings to be
adequate, which means that there exists a bijection between expressions of
the source language and their representations (as canonical forms) in the
logical framework.
Proof: By induction over the structure of t in one direction and the struc-
ture of the β-normal η-long form of ptq in the other.
4
Theorem 2.5 (Substitution [HHP93]) If Γ, x : A ` B : K and Γ ` M :
A then Γ ` [M/x]B : [M/x]K.
5
a context, Γ, suitable for the logical framework by simply filtering out any
meta-information. The resulting context is of the form:
Γ ::= · | Γ, u : A
6
[e/u]> = >
[e/u]⊥ = ⊥
[e/u](Πu ∈ τ .σ) = Πu0 ∈ [e/u]τ .[e/u]σ
0
Proof: This proof goes by induction over derivation E utilizing the defini-
tion of [e/u]%.
With this refined notion of formulas and a notion of formula level reduc-
tion, we now present LhiΠ . Note that an important implicit condition on all
7
the rules is that all elements of Ω are well-formed, as well as the resulting
type.
(u ∈ τ ) in Ω
ax
Ω`u∈τ
>R
Ω ` unit ∈ > no rule >L
⊥L
no rule ⊥R Ω1 , u ∈ ⊥, Ω2 ` void u ∈ σ
Ω, u ∈ τ ` e ∈ σ
ΠR
Ω ` λu ∈ τ .e ∈ Πu ∈ τ .σ
Ω1 , u ∈ (Πu0 ∈ τ .σ), Ω2 ` e ∈ τ
Ω1 , u ∈ (Πu0 ∈ τ .σ), Ω2 , w ∈ [e/u0 ]σ ` f ∈ %
ΠL
Ω1 , u ∈ (Πu0 ∈ τ .σ), Ω2 ` let w = u · e in f ∈ %
Ω ` e1 ∈ τ Ω ` e2 ∈ [e1 /u]σ
ΣR
Ω ` (e1 , e2 ) ∈ Σu ∈ τ .σ
All rules are standard except for hiR. This is the rule that drives the
system by bridging LF. One would notice that there is no corresponding L
rule. The reason for this is that it is handled by the thinning of the context.
The other rules handle dependencies standardly but by this design they
simply are pushing the dependencies to be handled by hiR and hiwffR.
The cut-rule (where substitution is defined) is admissible for this calcu-
lus.
[e/u]Ω2 is defined [e/u]σ is defined
Ω1 ` e ∈ τ Ω1 , u ∈ τ, Ω2 ` f ∈ σ
cut
Ω1 , [e/u]Ω2 ` [e/u]f ∈ [e/u]σ
8
2.3 Preliminaries
Before proving the admissibility of cut, we need some lemmas relating to
substitution.
Although the definition of substitution on expressions is determined by
the cut proof, we present it first since we will use it to prove some lemmas
regarding substitution.
[e/u]u ≡ e
0 0
[ λu ∈τ .e ]e 0
[(λu0 ∈ τ .e0 )/u] [ u
u0
]e λu0 ∈ τ .e0
≡ [ ]([ ]f )
(let w = u · e in f ) w u
[M/u]N ≡ [M/u]LF N
[(e1 , e2 )/u] [[[e2 ]]∗ ∗
/w2 ]([[[e1 ]] /w1 ]
≡
(let (w1 , w2 ) = u in f ) ([(e1 , e2 )/u]f ))
[w/u]e ≡ rename u to w in e
8
[f /u]e
(let w = u0 · e0 in f )
>
>
if u not free in e
<
[ ]e ≡
u >
> let w = u0 · e0 in [f /u]e
otherwise
:
8
[f /u]e
(let (w1 , w2 ) = u0 in f )
>
>
if u not free in e
<
[ ]e ≡
u > let (w1 , w2 ) = u0 in [f /u]e
>
otherwise
:
[(void w0 )/u] 0
≡ void w
(let w = u · e in f )
[(void w0 )/u] 0
≡ void w
(let (w1 , w2 ) = u in f )
[(void w)/u](void u) ≡ void w
M if u not free in M
[(void w)/u]M ≡
void w otherwise
If e = (λu0 ∈ τ 0 .e0 )
unit, or (e1 , e2 ), then
[e/u]M ≡ M
u 6= w, [e/u]w ≡ w
[e/u]unit ≡ unit
u 6= w, [e/u](void w) ≡ void w
0 0 0 0 0 0
[e/u](λu ∈ τ .e ) ≡ λu ∈ [e/u]τ .([e/u]e )
u 6= u0 , [e/u] 0
let w = u · ([e/u]e ) 0
≡
(let w = u0 · e in f )
0 in ([e/u]f )
[e/u](e1 , e2 ) ≡ ([e/u]e1 , [e/u]e2 )
u 6= u0 , [e/u] let (w1 , w2 ) = u0
≡
(let (w1 , w2 ) = u0 in f ) in ([e/u]f )
9
A weakened context Ω0 of Ω refers to an extension of Ω by new assump-
tions. Formally, we write Ω ≤ Ω0 .
Proof: By Induction.
Proof: By Induction.
Proof: Trivial.
Proof: Trivial. The second and third case appeals to the first since well-
formed types cannot have variables of non-hAi type occur free.
10
Lemma 2.13 (Substitution Distributive Property)
0
[e/u]([e0 /u0 ]τ ) = [ [e/u]e
u0 ]([e/u]τ )
0
Case: [e/u]([e0 /u0 ](Πw ∈ τ .σ)) = [ [e/u]e
u0 ]([e/u](Πw ∈ τ .σ))
0
Case: [e/u]([e0 /u0 ](Σw ∈ τ .σ)) = [ [e/u]e
u0 ]([e/u](Σw ∈ τ .σ))
Same As Previous.
0
Case: [e/u]([e0 /u0 ]>) = [ [e/u]e
u0 ]([e/u]>)
0
Case: [e/u]([e0 /u0 ]⊥) = [ [e/u]e
u0 ]([e/u]⊥)
11
0
Case: [e/u]([e0 /u0 ]hAi) = [ [e/u]e
u0 ]([e/u]hAi)
Subcase: e = N ,
[e/u]h[M/u0 ]LF Ai = h[N/u]LF ([M/u0 ]LF A)i
[ [N/u]M
u0 ]([N/u]hAi)
= [([N/u]LF M )/u0 ]([N/u]hAi) by Def.
= [([N/u]LF M )/u0 ]h[N/u]LF Ai by Def.
= h[([N/u]LF M )/u0 ]LF ([N/u]LF A)i by Def.
= h[N/u]LF ([M/u0 ]LF A)i by Distributivity of LF
12
2.4 Cut Admissibility Proof
Theorem 2.14 (Admissibility of cut) If D :: Ω1 ` e ∈ τ and E :: Ω1 , u ∈
τ, Ω2 ` f ∈ σ and [e/u]Ω2 is defined and [e/u]σ is defined, then Ω1 , [e/u]Ω2 `
[e/u]f ∈ [e/u]σ for some proof term [e/u]f .
Note that this lemma defines [e/u]f , i.e. substitution on terms of LhiΠ , but
we presented the results earlier, Section 2.3.
Case: D = Ω1 ` e ∈ τ
(u ∈ τ ) in (Ω1 , u ∈ τ, Ω2 )
E= ax
Ω1 , u ∈ τ, Ω2 ` u ∈ τ
13
D1 :: Ω1 , u0 ∈ τ ` e0 ∈ σ
Case: D = ΠR,
Ω1 ` λu0 ∈ τ .e0 ∈ Πu0 ∈ τ .σ
E1 :: Ω1 , u ∈ (Πu0 ∈ τ .σ), Ω2 ` e ∈ τ
E2 :: Ω1 , u ∈ (Πu0 ∈ τ .σ), Ω2 , w ∈ [e/u0 ]σ ` f ∈ %
E= ΠL
Ω1 , u ∈ (Πu0 ∈ τ .σ), Ω2 ` let w = u · e in f ∈ %
0 0
[ λu ∈τ
u
.e
]Ω2 is defined. by Assumption
λu0 ∈τ .e0
[ u ]% is defined. by Assumption
0 .e0 0 .e0
E10 :: Ω1 , [ λu ∈τ
u ]Ω2 ` [ λu ∈τ
u ]e ∈ τ
by IH on D and E1 and
Redundant Sub. Prop. (Lemma 2.12)
0 .e0
E20 :: Ω1 , [ λu ∈τ ]Ω , w ∈ [e/u 0 ]σ ` [ λu0 ∈τ .e0 ]f ∈ %
u 2 u
by IH on D and E2 and
Redundant Sub. Prop. (Lemma 2.12)
0 .e0
Ω1 , u0 ∈ τ ≤ Ω1 , [ λu ∈τ u ]Ω2 , u0 ∈ τ by Definition
λu0 ∈τ .e0
0
D1 :: Ω1 , [ u ]Ω2 , u ∈ τ ` e0 ∈ σ0
14
[Ω1 ]LF ` M : A
Case: D = hiR
Ω1 ` M ∈ hAi
E1 :: [(Ω1 , u ∈ hAi, Ω2 )]LF ` N : B
E= hiR
Ω1 , u ∈ hAi, Ω2 ` N ∈ hBi
15
D1 D2
Ω1 ` e1 ∈ τ Ω1 ` e2 ∈ [e1 /u0 ]σ
Case: D = ΣR
Ω ` (e1 , e2 ) ∈ Σu0 ∈ τ .σ
Ω1 , u ∈ (Σu0 ∈ τ .σ), Ω2 ,
E1 :: w1 ∈ τ, w2 ∈ [w1 /u0 ]σ ` f ∈ %
E= ΣL
Ω1 , u ∈ (Σu0 ∈ τ .σ), Ω2 ` let (w1 , w2 ) = u in f ∈ %
16
Now we handle commutative conversion on the left.
(w ∈ τ ) ∈ Ω1
Case: D = ax E = Ω1 , u ∈ τ, Ω2 ` e ∈ σ
Ω1 ` w ∈ τ
[w/u]Ω2 is defined. by Assumption
[w/u]σ is defined. by Assumption
Ω1 , [w/u]Ω2 ` rename u to w in e ∈ [w/u]σ
by variable renaming
Case:
D0 :: (u0 ∈ (Πu00 ∈ τ .σ)) ∈ Ω1
D1 :: Ω1 ` e0 ∈ τ
D2 :: Ω1 , w ∈ [e0 /u00 ]σ ` f ∈ %
D= ΠL
Ω1 ` let w = u0 · e0 in f ∈ %
E = Ω1 , u ∈ %, Ω2 ` e ∈ %0
17
Case:
D0 :: (u0 ∈ (Σu00 ∈ τ .σ)) ∈ Ω1
D1 :: Ω1 , w1 ∈ τ, w2 ∈ [w1 /u00 ]σ ` f ∈ %
D= ΣL
Ω1 ` let (w1 , w2 ) = u0 in f ∈ %
E = Ω1 , u ∈ %, Ω2 ` e ∈ %0
18
Case:
(w0 ∈ ⊥) ∈ Ω1
D= ⊥L
Ω1 ` void w0 ∈ (Πu0 ∈ τ .σ)
E1 :: Ω1 , u ∈ (Πu0 ∈ τ .σ), Ω2 ` e ∈ τ
E2 :: Ω1 , u ∈ (Πu0 ∈ τ .σ), Ω2 , w ∈ [e/u]σ ` f ∈ %
E= ΠL
Ω1 , u ∈ (Πu0 ∈ τ .σ), Ω2 ` let w = u · e in f ∈ %
Case:
(w0 ∈ ⊥) ∈ Ω1
D= ⊥L
Ω1 ` void w0 ∈ (Σu0 ∈ τ .σ)
Ω1 , u ∈ (Σu0 ∈ τ .σ), Ω2 ,
E1 :: w1 ∈ τ, w2 ∈ [w1 /u0 ]σ ` f ∈ %
E= ΣL
Ω1 , u ∈ (Σu0 ∈ τ .σ), Ω2 ` let (w1 , w2 ) = u · e in f ∈ %
19
Case:
(w ∈ ⊥) ∈ Ω1
D= ⊥L
Ω1 ` void w ∈ ⊥
E = Ω1 , u ∈ ⊥, Ω2 ` (void u) ∈ σ
Case:
(w ∈ ⊥) ∈ Ω1
D= ⊥L
Ω1 ` void w ∈ τ
E = Ω1 , u ∈ τ, Ω2 ` M ∈ hAi
20
Now we handle commutative conversion cases on the right.
Case: D = Ω1 ` e ∈ τ
(w ∈ σ) in (Ω1 , u ∈ τ, Ω2 )
E= ax, where u 6= w
Ω1 , u ∈ τ, Ω2 ` w ∈ σ
Case: D = Ω1 ` e ∈ τ
E= >R
Ω1 , u ∈ τ, Ω2 ` unit ∈ >
Case: D = Ω1 ` e ∈ τ
(w ∈ ⊥) ∈ (Ω1 , u ∈ τ, Ω2 )
E= ⊥L, where u 6= w
Ω1 , u ∈ τ, Ω2 ` void w ∈ σ
21
Case: D = Ω1 ` e ∈ τ
E1 :: Ω1 , u ∈ τ, Ω2 , u0 ∈ τ 0 ` e0 ∈ σ
E= ΠR
Ω1 , u ∈ τ, Ω2 ` λu0 ∈ τ 0 .e0 ∈ (Πu00 ∈ τ 0 .σ)
22
Case: D = Ω1 ` e ∈ τ
u 6= u0
E0 :: (u0 ∈ (Πu00 ∈ τ 0 .σ 0 )) ∈ (Ω1 , u ∈ τ, Ω2 )
E1 :: Ω1 , u ∈ τ, Ω2 ` e0 ∈ τ 0
E2 :: Ω1 , u ∈ τ, Ω2 , w ∈ [e0 /u00 ]σ 0 ` f ∈ %
E= ΠL
Ω1 , u ∈ τ, Ω2 ` let w = u0 · e0 in f ∈ %
by IH on D and E1
[e/u]([e0 /u00 ]σ 0 ) is defined.
by Not Undefined Prop. (Lemma 2.11)
[e/u]([e /u ]σ ) = [([e/u]e )/u ]([e/u]σ 0 )
0 00 0 0 00
` [e/u]f ∈ [e/u]%
by IH on D and E2
0 0
Ω1 , [e/u]Ω2 ` let w = u · ([e/u]e ) in ([e/u]f ) ∈ [e/u]%
by ΠL
23
Case: D = Ω1 ` e ∈ τ
E1 :: Ω1 , u ∈ τ, Ω2 ` e1 ∈ σ1
E2 :: Ω1 , u ∈ τ, Ω2 , ` e2 ∈ [e1 /u0 ]σ2
E= ΣR
Ω1 , u ∈ τ, Ω2 ` (e1 , e2 ) ∈ Σu0 ∈ σ1 .σ2
24
Case: D = Ω1 ` e ∈ τ
u 6= u0
E0 :: (u0 ∈ (Σu00 ∈ τ 0 .σ 0 )) ∈ (Ω1 , u ∈ τ, Ω2 )
E1 :: Ω1 , u ∈ τ, Ω2 , w1 ∈ τ 0 , w2 ∈ [w1 /u00 ]σ 0 ` f ∈ %
E= ΣL
Ω1 , u ∈ τ, Ω2 ` let (w1 , w2 ) = u0 in f ∈ %
25
2.5 Result
Thus we add the cut-rule to LhiΠ and obtain a logic with cut called LhiΠcut
Corollary 2.16 (Soundness) The logics LhiΠ and LhiΠcut are sound.
e if u = w
[e/u]w ≡
w otherwise
0 ∈τ .e0
[(λu0 ∈ τ .e0 )/u] [ λu ]e
[ u
u0 ]e0 λu0 ∈ τ .e0
(let w = u · e in f ) ≡ [ ]([ ]f )
w u
(let w = u0 · e0 in f )
[ ]e ≡ let w = u0 · e0 in [f /u]e
u
[(e1 , e2 )/u] [e2 /w2 ]([e1 /w1 ]
≡
(let (w1 , w2 ) = u in f ) ([(e1 , e2 )/u]f ))
[M/u]N ≡ [M/u]LF N
Definition 2.17 (Values) The following syntactic category denotes all val-
ues of the λhiΠ -calculus: v ::=| λu ∈ τ .e | unit | M | (v1 , v2 ).
26
With this computational view of LhiΠ we can show that for every ex-
pression e can always be reduced to a value v. We define reduction as the
reflexive, transitive closure of ≡. This property is called strong normaliza-
tion.
27
Similarly, we define Φ+ to take us one step to the future by adding a to
everything in Φ. Finally, we also define a thinning operation [Φ] that strips
all ’s from Φ to give us a context of the form Ω.
Φ− `
`e∈κ [Φ] ` e ∈ τ
R bridge
Φ`
` prev e ∈ κ Φ `` e ∈ τ
28
Proof: By induction on the typing judgment of LhiΠ and LhiΠ .
Thus, the following rule is admissible, which also serves as the elimination
rule for .
Φ+ `` e ∈ κ
future
Φ `` next e ∈ κ
We first need to show that if κ is derivable in the past then it is also
derivable now. We call this shifting and due to our design we can also show
that the proof-term stays the same. Since we are dealing with dependent-
types, this property proves to be crucial.
• If Φ− ` e ∈ κ then Φ `` e ∈ κ.
29
• If u is not free in κ, then [e/u]κ = κ
Proof: Trivial. The second and third case appeals to the first since well-
formed types cannot have variables of non- k hAi type occur free.
Proof: This proof goes by induction over derivation E utilizing the defini-
tion of [e/u]κ0 .
30
Theorem 3.8 (Admissibility of cut) If D :: Φ1 `` e ∈ κ and
` f ∈ κ0 and [e/u]Φ2 is defined and [e/u]κ0 is defined, then
E :: Φ1 , κ, Φ2 `
Φ1 , [e/u]Φ2 `` [e/u]f ∈ [e/u]κ0 .
Note that this lemma defines [e/u]f , i.e. substitution on terms of LhiΠ .
E1 :: (Φ1 , u ∈ κ, Φ2 )− `` f ∈ κ0
E= R
` prev f ∈ κ0
Φ1 , u ∈ κ, Φ2 `
E10 :: Φ1 − , u ∈ κ, Φ2 − `` f ∈ κ0
by Property of ( )− on E1
− −
F :: Φ1 `` [e/u]f ∈
, [e/u]Φ2 [e/u]κ0
by Induction Hypothesis on D1 and E10
0 −
F :: (Φ1 , [(prev e)/u]Φ2 ) `` [e/u]f ∈ [e/u]κ0
by Def. of Sub.
F :: Φ1 , [(prev e)/u]Φ2 `` prev ([e/u]f ) ∈ [(prev e)/u]κ0
00
D1 :: Φ1 − `
` previ e ∈ i σ
Case: D = R
` previ+1 e ∈ i+1 σ
Φ1 `
E1 :: [Φ1 , u ∈ i+1 σ, Φ2 ] ` f ∈ τ
E= bridge
Φ1 , u ∈ i+1 σ, Φ2 `` f ∈ τ
D0 :: [Φ1 ] ` e ∈ σ
by Shifting (Lemma 3.4) on D
E10 :: [Φ1 ], u ∈ σ, [Φ2 ] ` f ∈ τ
by Property of [ ] on E1
F :: [Φ1 ], [e/u][Φ2 ] ` [e/u]f ∈ [e/u]τ
by Admissibility of Cut in LhiΠ (Theorem 2.14)
0
F :: [Φ1 , [(prev i+1 e)/u]Φ2 ] ` [e/u]f ∈ [e/u]τ
by Def. of Sub.
F 00 :: Φ1 , [(previ+1 e)/u]Φ2 `` [e/u]f ∈ [(previ+1 e)/u]τ
by bridge and Def. of Sub.
31
D1 :: [Φ1 ] ` e ∈ τ
Case: D = bridge
Φ1 `
`e∈τ
E1 :: [Φ1 , u ∈ τ, Φ2 ] ` f ∈ σ
E= bridge
Φ1 , u ∈ τ, Φ2 `
`f ∈σ
D1 :: [Φ1 ] ` e ∈ τ
Case: D = bridge
Φ1 `
`e∈τ
E1 :: (Φ1 , u ∈ τ, Φ2 )− `` f ∈ κ
E= R
Φ1 , u ∈ τ, Φ2 `
` prev f ∈ κ
E10 :: (Φ1 , Φ2 )− `
`f ∈κ
by Property of ( )− on E1
F :: Φ1 , Φ2 `
` prev f ∈ κ
by R
[e/u]Φ2 = Φ2 and [e/u]κ = κ
By Redundant Substitution Lemma (Lemma 3.6)
since u cannot occur free by well-formedness of E10
F 0 :: Φ1 , [e/u]Φ2 `
` prev f ∈ [e/u]κ
by Above
Hence, we add the admissible cut rule to the proof theory of LhiΠ and
obtain a logic we refer to as LhiΠ cut (and a calculus we refer to as λhiΠ cut ).
Corollary 3.9 (Soundness) The logics LhiΠ and LhiΠ cut are sound.
32
3.1 Operational Behavior
As we did in Section 2.6 we interpret the proof of the admissibility of cut as
equivalences on proof terms.
Definition 3.10 (Values) The following syntactic category denotes all val-
ues of the λhiΠ -calculus: v ::=| λu ∈ τ .e | unit | M | (v1 , v2 ) | prev v.
This concludes the logical motivation for this paper. The remainder is
dedicated to interpreting the corresponding λhiΠ calculus as a functional
programming language. We first add an operator for programming with
33
higher-order encodings, which is just an admissible rule. We will then sim-
plify our logic to an equivalent form called Delphin (λD ) and proceed to add
operators that facilitate case analysis and recursion. It is beyond the scope
of this paper to give a completely logical account for these new concepts.
For example, in order to still guarantee cut-elimination, we would have to
show that all cases are covered, and that the recursion always terminates.
34
Notice that new will be used to introduce parameters into the context which
we can use to go under λ-binders.
Thus the final version of our logic, LhiΠ cut+ , is sound and defined as
follows:
Φ− ` `e∈κ [Φ] ` e ∈ τ
R bridge
Φ` ` prev e ∈ κ Φ `` e ∈ τ
Φ+ `
` e ∈ κ Φ, u ∈ τ `` e ∈ κ
future new
Φ`
` next e ∈ κ Ω `` νu ∈ τ .e ∈ κ
5 Delphin
Our design has led us to a three-tiered system with an explicit bridge and
meta rule, called LhiΠ cut+ . In addition we have three contexts to reason
about. We have Γ at the bottom, Ω at its meta-level, and Φ at its meta-meta-
level. However, since both logics can communicate, we present an equivalent
simplified version so we don’t need bridge and meta and in addition get rid
of dealing with Ω. Since we are also shifting our focus to computation we
take the liberty of replacing the sequent let version of application with the
more natural version, e1 e2 .
Therefore, we present here the equivalent logic LD (or calculus λD ),
which will be the focus for the rest of this paper. Note that the purpose of
this section is twofold – it both summarizes the logical system to this point
and simplifies it into one judgment, Φ `d e ∈ κ
Types remain unchanged and are:
κ, α ::= κ | τ
τ, σ, % ::= > | ⊥ | Πu ∈ τ .σ | Σu ∈ τ .σ | hAi
35
We collapse the logics together by having the ax rule do the work of
merge in transforming the context. Note that we can interpret the ax rule
as shifting all hypothesis to the present thereby enforcing that only the
temporal rules have any access to time information, which is our desired
semantics.
(u ∈ i τ ) in Φ
ax top
Φ `d u ∈ τ Φ `d unit ∈ >
Φ, u ∈ τ `d e ∈ σ
lam
Φ `d λu ∈ τ .e ∈ Πu ∈ τ .σ
Φ `d e1 ∈ (Πu0 ∈ τ .σ) Φ `d e2 ∈ τ
app
d 0
Φ ` e1 e2 ∈ [e2 /u ]σ
Φ `d e1 ∈ τ Φ `d e2 ∈ [e1 /u]σ
pair
Φ `d (e1 , e2 ) ∈ Σu ∈ τ .σ
Φ `d e ∈ (Σw1 ∈ τ .σ) Φ, w1 ∈ τ, w2 ∈ σ `d f ∈ %
openPair
Φ `d let (w1 , w2 ) = e in f ∈ %
Φ `d e ∈ ⊥ [Φ]LF ` M : A
bot hiI
Φ `d void e ∈ σ Φ `d M ∈ hAi
Φ− `d e ∈ κ Φ+ `d e ∈ κ
past future
Φ `d prev e ∈ κ Φ `d next e ∈ κ
Φ, u ∈ τ `d e ∈ κ
new
Φ `d νu ∈ τ .e ∈ κ
36
supported pairs, then we would just define our thinning operation to cast
it appropriately. However, LF does not support pairing. We could alterna-
tively adopt a fst and snd notation and have the thinning operation extend
the context by opening up all the pairs, but this would just be a hack and
make things needlessly more convoluted.
Substitution on types remains unchanged (only defined for LF terms)
and is as follows:
[e/u]> = >
[e/u]⊥ = ⊥
[e/u](Πu ∈ τ .σ) = Πu0 ∈ [e/u]τ .[e/u]σ
0
37
In order to prove that LhiΠ cut+ is equivalent to LD we proceed by
proving this in both directions separately.
(u ∈ τ ) in Ω
Case: D = ax
Ω`u∈τ
Ω `d u ∈ τ by ax
Case: D = >R
Ω ` unit ∈ >
38
Case: D = ⊥L
Ω1 , u ∈ ⊥, Ω2 ` void u ∈ σ
Ω `d u ∈ ⊥ by ax
Ω `d void u ∈ σ by bot
D1 :: Ω, u ∈ τ ` e ∈ σ
Case: D = ΠR
Ω ` λu ∈ τ .e ∈ Πu ∈ τ .σ
Ω, u ∈ τ `d e0 ∈ σ by IH on D1
Ω `d λu ∈ τ .e0 ∈ Πu ∈ τ .σ by lam
D1 :: Ω1 , u ∈ (Πu0 ∈ τ .σ), Ω2 ` e ∈ τ
D2 :: Ω1 , u ∈ (Πu0 ∈ τ .σ), Ω2 , w ∈ [e/u0 ]σ ` f ∈ %
Case: D = ΠL
Ω1 , u ∈ (Πu0 ∈ τ .σ), Ω2 ` let w = u · e in f ∈ %
39
D1 D2
Ω ` e1 ∈ τ Ω ` e2 ∈ [e1 /u]σ
Case: D = ΣR
Ω ` (e1 , e2 ) ∈ Σu ∈ τ .σ
Ω `d e01 ∈ τ by IH on D1
If e1 = M1 then e01 = M1 by IH on D1
[e01 /u]σ = [e1 /u]σ by Above and Redundant Sub.
(Lemma 2.12)
Ω `d e02 ∈ [e01 /u]σ by IH on D2
Ω `d (e01 , e02 ) ∈ Σu ∈ τ .σ by pair
D1
[Ω]LF ` M : A
Case: D = hiR
Ω ` M ∈ hAi
Ω `d M ∈ hAi by hiI on D1
D1
Ω`
`e∈τ
Case: D = meta
Ω`e∈τ
Φ `d e0 ∈ τ
and if e = M then e0 = M . by IH on D1
40
Part 2: By Induction on cut-free derivations D :: Φ `` e ∈ κ.
D1
Φ− `
`e∈κ
Case: D = R
Φ`
` prev e ∈ κ
Φ− `d e0 ∈ κ by IH on D1
If e = previ M then e0 = previ M by IH on D1
Φ `d prev e0 ∈ κ by past
If (prev e = previ M ) then (prev e0 = previ M ) by Above
D1
[Φ] ` e ∈ τ
Case: D = bridge
Φ`
`e∈τ
[Φ] `d e0 ∈ τ by IH on D1
If e = M then e0 = M by IH on D1
Φ `d e0 ∈ τ by DeShifting (Lemma 5.2)
If e = previ M then e0 = previ M by Above
D1
Φ+ `
` e ∈ κ
Case: D = future
Φ`
` next e ∈ κ
Φ+ `d e0 ∈ κ by IH on D1
Φ `d next e0 ∈ κ by future
D1
Φ, u ∈ τ `
` e ∈ κ
Case: D = new
Ω`
` νu ∈ τ .e ∈ κ
Φ, u ∈ τ `d e0 ∈ κ by IH on D1
Φ `d νu ∈ τ .e0 ∈ κ by new
41
Lemma 5.5 (LD to LhiΠ cut+ )
If Φ `d e ∈ κ then there exists an e0 such that Φ `` e0 ∈ κ and
Proof: By Induction on D :: Φ `d e ∈ κ.
(u ∈ i τ ) in Φ
Case: D = ax
Φ `d u ∈ τ
Case: D = top
Φ `d unit ∈ >
D1
Φ, u ∈ τ `d e ∈ σ
Case: D = lam
Φ `d λu ∈ τ .e ∈ Πu ∈ τ .σ
42
D1 D2
Φ `d e1 ∈ (Πu0 ∈ τ .σ) Φ `d e2 ∈ τ
Case: D = app
Φ `d e1 e2 ∈ [e2 /u0 ]σ
D1 D2
Φ `d e1 ∈ τ Φ `d e2 ∈ [e1 /u]σ
Case: D = pair
Φ `d (e1 , e2 ) ∈ Σu ∈ τ .σ
[Φ] ` e01 ∈ τ by IH on D1
If e1 = M then e01 = M by IH on D1
[e01 /u]σ = [e1 /u]σ by Above and Redundant Sub.
(Lemma 2.12)
[Φ] ` e02 ∈ [e01 /u]σ by IH on D2
[Φ] ` (e01 , e02 ) ∈ Σu ∈ τ .σ by ΣR
Φ`` (e01 , e02 ) ∈ Σu ∈ τ .σ by bridge
43
D1 D2
Φ `d e ∈ (Σw1 ∈ τ .σ) Φ, w1 ∈ τ, w2 ∈ σ `d f ∈ %
Case: D = openPair
Φ `d let (w1 , w2 ) = e in f ∈ %
D1
Φ `d e ∈ ⊥
Case: D = bot
Φ `d void e ∈ σ
[Φ] ` e0 ∈ ⊥ by IH on D1
[Φ], u ∈ ⊥ ` void u ∈ σ by ⊥L
[Φ] ` [e0 /u](void u) ∈ σ by cut
Φ`` [e0 /u](void u) ∈ σ by bridge
D1
[Φ]LF ` M : A
Case: D = hiI
Φ `d M ∈ hAi
D1
Φ− `d e∈κ
Case: D = past
Φ `d prev e ∈ κ
Φ− ` ` e0 ∈ κ by IH on D1
If e = previ M then e0 = previ M by IH on D1
Φ` ` prev e0 ∈ κ by R
If (prev e = previ M ) then (prev e0 = previ M ) by Above
44
D1
Φ+ `d e ∈ κ
Case: D = future
Φ `d next e ∈ κ
Φ+ `` e0 ∈ κ by IH on D1
Φ`` next e0 ∈ κ by future
D1
Φ, u ∈ τ `d e ∈ κ
Case: D = new
Φ `d νu ∈ τ .e ∈ κ
` e0 ∈ κ
Φ, u ∈ τ ` by IH on D1
Φ` ` νu ∈ τ .e0 ∈ κ by new
5.2 Result
Theorem 5.6 (Delphin is Equivalent to LhiΠ cut+ )
The logic presented here, LD is equivalent to LhiΠ cut+ .
45
substitution and typical behavior. Due to space limitations we omit the
operational semantics, but note that any operational semantics respecting
the term equivalences (which we get from the proof of the admissibility of
cut) is acceptable.
Values in λD remain the same as in Definition 3.10, and are:
46
all its leading prev’s.
v if u = u0
i 0
[(prev v)/u]u ≡
u0 otherwise
[v/u]unit ≡ unit
[v/u](void e) ≡ void (v/u)e
[v/u](λu0 ∈ τ .e) ≡ λu0 ∈ [v/u]τ .[v/u]e
[v/u](e1 e2 ) ≡ ([v/u]e1 ) ([v/u]e2 )
prev ([v 0 /u]e) if v = prev v 0
[v/u](prev e) ≡
prev e otherwise
[v/u](next e) ≡ next([prev v/u]e)
[v/u](e1 , e2 ) ≡ ([v/u]e1 , [v/u]e2 )
[v/u]let (w1 , w2 ) = e in f ≡ let (w1 , w2 ) = [v/u]e in [v/u]f
[v/u](νu ∈ τ .e) ≡ νu0 ∈ [v/u]τ .[v/u]e
0
[M/u]LF N if v = M
[v/u]N ≡
N otherwise
6 Case Analysis
The idea of case analysis is conceptually simple, but bares many interesting
facts, primarily due to the presence of dependent types. In the simply
typed scenario, given a variable u ∈ hexpi, where expressions are defined in
Example 2.2, u will be instantiated during run-time by a canonical object Γ `
M : exp. As our logical framework possesses the canonical form property,
a straightforward analysis yields that M = lam (λx : exp .N x), or M =
app N1 N2 or M = x, where x : exp is in Γ. In the first case we may assume
that we can compute N : exp → exp, a variable of functional type, from M .
In the second case we can compute N1 : exp and N2 : exp. In the third case,
we can extract parameter x out of M . It is this last case which we need to
pay careful attention to. When considering cases over a datatype we need
to consider all the ways to construct it and in addition the possibility for
parameters of that type to exist (which is created using new).
47
Therefore we add a case statement to our language.
Φ1 `d e ∈ α Φ1 , [e/w]Φ2 `d f ∈ [e/w]κ
base
Φ1 , w ∈ α, Φ2 `w (e in f ) ∈ κ
Φ1 , u ∈ κ, w ∈ α, Φ2 `w p ∈ κ0
patternVar
Φ1 , w ∈ α, Φ2 `w (u ∈ κ .p) ∈ κ0
Φ1 , u ∈ κ, w ∈ α, Φ2 `w p ∈ κ0
patternParam
Φ1 , w ∈ α, Φ2 `w (∇u ∈ κ .p) ∈ κ0
48
closed. For example, based on Example 2.4, Φ could be ·, u ∈ hoi, w ∈ hnd ui.
Therefore we can do case analysis over u but not w. However, we can do
case analysis over Σ types. Therefore, if Φ = ·, u0 ∈ Σu ∈ hoi .hnd ui then
we can do case analysis over u0 . The key insight to case is that in order to
case on hnd ui we are simultaneously doing case also on u.
Therefore, we extend our case statement in a straightforward way to
accept multiple variables imitating the behavior of doing case on a variable
with a Σ type.
Φ = Φ1 , w1 ∈ α1 , . . . , w2 ∈ α2 , . . . wm ∈ αm , Φ2
· ` (Σw1 ∈ α1 .Σw2 ∈ α2 . . . . αm ) wff
for all 1 ≤ i ≤ k, Φ `(w1 ,...,wm ) pi ∈ κ
case, k ≥ 0
Φ `d case (w1 , . . . , wm ) of (p1 | . . . | pk ) ∈ κ
Φ = Φ1 , w1 ∈ α1 , . . . , w2 ∈ α2 , . . . wm ∈ αm , Φ2
Φ1 `d (e1 , . . . , em ) ∈ (Σw1 ∈ α1 .Σw2 ∈ α2 . . . . αm )
[ we11 ,...,e d e1 ,...,em
,...,wm ]Φ ` f ∈ [ w1 ,...,wm ]κ
m
base
Φ `(w1 ,...,wm ) ((e1 , . . . , em ) in f ) ∈ κ
Φ1 , u ∈ κ, w1 ∈ α1 , Φ2 `(w1 ,...,wm ) p ∈ κ0
patternVar
Φ1 , w1 ∈ α1 , Φ2 `(w1 ,...,wm ) (u ∈ κ .p) ∈ κ0
Φ1 , u ∈ κ, w1 ∈ α1 , Φ2 `(w1 ,...,wm ) p ∈ κ0
patternParam
Φ1 , w1 ∈ α1 , Φ2 `(w1 ,...,wm ) (∇u ∈ κ .p) ∈ κ0
49
types are straightforward. For instance, pattern matching on pairs is pair-
wise. Matching prev e with prev e0 is successful if we can match e with e0 .
And pattern matching on computational (non-LF) function types is defined
weakly just as syntactic equality. Due to the higher-order nature of our
logical framework, pattern-matching on terms of type hAi is in general not
decidable. In our experience, a decidable fragment of higher-order pattern
matching (which also works for the dependently typed LF) is that of Miller
patterns [Mil91], into which all of our examples fall (especially those in Sec-
tion 8). In addition, a strictness analysis [PS98] on bound variables can
ensure that their respective instantiations are uniquely determined during
program execution.
In the same spirit of presenting the operational behavior in terms of
equivalence rules, we present the following equivalence rules to illustrate the
behavior of pattern variables.
Example 6.1 (Derivability) Recall from example 2.2 the definition of un-
typed λ-terms in the logical framework as objects of type “exp”.
2. The expression νu ∈ hexpi .prev hui is not well-formed, because · `d hui ∈ hexpi
is not derivable.
3. The expression
is well-formed.
50
`d prev hlam ei ∈ hexpi by R
x ∈ hexpi, e ∈ hexp → expi
`d (prev hlam ei) ∈ [e x/y]( hexpi) by Substitution
· ` exp wff by LF
· `d hexpi wff by hiwffR
7 General Recursion
Next, we extend Delphin by an explicit recursion operator. In general,
recursion immediately breaks the logical meaning of the calculus, as non-
51
terminating programs cannot be interpreted as proofs unless it is guaranteed
to be well-founded. However, we are now focusing on the computational
aspects. Thus we add a general recursion principle.
e, f ::= . . . | µu ∈ κ .e
Φ, u ∈ κ `d e ∈ κ
rec
Φ `d (µu ∈ κ .e) ∈ κ
Unrolling this fix-point means to drive it deeper and deeper into the expres-
sion until no occurrences are left. We give some examples of the recursion
operator next, in Section 8.
8 Examples
Next, we give a few illustrative toy examples of λD -programs. We first
introduce some extra syntactic sugar so we can typeset our programs a little
nicer.
let u = e in f ≡ (λu ∈ τ .f )e
when τ is inferable.
52
8.1 Structural Identity
Recall the encoding of the untyped λ-calculus from Example 2.2. We use the
hypothetical judgment E = F to define when two λ-expressions are equal.
u
x=x
..
.
E 1 = F1 E 2 = F2 E=F
cp app cp lamx,u
E1 @E2 = F1 @E2 lam x. E = lam x. F
cp app : cp E1 F1 → cp E2 F2
→ cp (app E1 E2 ) (app F1 F2 ),
53
We explain each of the three cases in turn. The e = app E1 E2 case
is straightforward. The result of the recursive calls is combined into the
desired proof by cp app.
The e = lam E 0 case illustrates our ability to go under representation-
level λ’s using next and ν. next brings us one step into the future, its type
τ ensures that the result can be interpreted in the present. Next, we create
a new parameter x and recurse on E 0 x. The result is valid in the future.
To ensure that the type checker knows that we eventually return to the
present, we stipulate D to exist in the past, which is sufficient to guarantee
that “prev cp lam D” is valid now. Thus neither x nor u can escape their
scope.
The final case is the parameter case. There will be only one u ∈ hcp x xi
in the context during runtime, which is promptly returned. This illustrates
the difference between ∇ and . Variables bound by ∇ are only instantiated
by parameters, which are introduced by new. Variables bound by can be
instantiated with anything. If we replaced the ∇ quantified variables in the
last case with ’s then since the pattern is just x, this branch could non
deterministically return anything.
In this example there is no nondeterministic behavior because all pattern
variables occur strict [PS98] in the pattern. We will exploit the nondeter-
ministic behavior later in our theorem prover example. However, we can
eliminate the nondeterminism by making sure that pattern variables occur
strict in the pattern. In the implementation we can generate a warning if it
doesn’t.
8.2 Combinators
Recall the definition of the natural deduction calculus from Example 2.4. We
will give an algorithmic procedure that converts natural deduction deriva-
tions into the Hilbert calculus.
`o⊃p `o
K MP
`o⊃p⊃o `p
S
` (o ⊃ p ⊃ q) ⊃ (o ⊃ p) ⊃ (o ⊃ q)
54
Following the standard Judgments-as-types paradigm, our encoding is:
comb : o → type,
pKq = K: comb (A ⇒ B ⇒ A)
pSq = S: comb ((A ⇒ B ⇒ C) ⇒ (A ⇒ B)
⇒ A ⇒ C)
pM P q = MP : comb(A ⇒ B) → comb A → comb B
55
fun ba (A ∈ hoi) (B ∈ hoi) (F ∈ hcomb A → comb Bi)
: hcomb A ⇒ Bi
= case (A, B, F ) of
A ∈ hoi .B ∈ hoi .∇z ∈ hcomb Bi .(A, B, λx : comb A .z)
in (MP K z)
56
fun convert (A ∈ hoi) (D ∈ hnd Ai) : hcomb Ai
= case (A, D) of
A ∈ hoi .∇u ∈ hcomb A → nd Ai .∇c ∈ hcomb Ai .
(A, u c)
in c
The last case illustrates how a parameter of functional type may intro-
duce information to be used when the parameter is matched. Rather than
introduce a parameter u of type hnd Bi, we introduce a parameter of type
hcomb B → nd Bi that carries a combinator as “payload.” In our exam-
ple, the payload is another parameter b ∈ hcomb Bi, the image of u under
convert. This technique is known as payload-carrying parameters and is
applicable to a wide range of examples [Sch05].
57
latter applies impe to proofs of C in the hope to discover a proof of A.
= case A of
9 Related Work
Both research with higher-order and abstract syntax and research with pro-
gramming with dependent types are related to the λD -calculus.
58
of programming with higher-order encodings without being confined by a
rigidly defined iteration construct as proposed in [SDP01] and [Lel98],
which separates representation-level from computation-level functions via a
modality within one single λ-calculus.
Closely related to our work are programming languages with freshness [GP99],
which provide a built-in α-equivalence relation for first-order encodings but
provide neither βη nor any support for higher-order encodings. Also closely
related are meta-programming languages, such as MetaML [TS00], which
provide hierarchies of computation levels but do not single out a particular
level for representation. Many other attempts have been made to combine
higher-order encodings and functional programming, in particular Honsell,
Miculan, and Scagnetto’s embedding of the π-calculus in Coq[HMS01], and
Momigliano, Amber, and Crole’s Hybrid system [MAC03].
59
such complex data structures.
Epigram [MM04] is a novel system based on Lego, which provides a
functional calculus of total functions, it stops short, however of providing
higher-order encodings.
Our work is based upon our earlier work with the ∇-calculus [Sch05]
which lacked dependent-types and followed a more ad-hoc approach than
our logically motivated work here. Our work with the ∇-calculus has also
inspired Westbrook’s similar work called λF V [Wes06]. This calculus is de-
signed to include coverage checking in the type-system. Work on λF V is still
ongoing, including a proof for type safety.
10 Conclusion
In this paper we have given a formulation of temporal logic designed to
reason about derivations under a different logic at different times. It is
being turned into a novel programming language, which is called Delphin
and currently under development. Please visit www.cs.yale.edu/∼delphin for
more information. And finally, with the appropriate syntactical enforceable
side conditions of coverage and termination, λD is a meta-logic for the logical
framework LF.
We have shown examples of programming with proofs including combi-
nator transformations and theorem proving. In future work we will study
meta-theoretic properties of the system including coverage and termination,
which will allow us to guarantee that our functions are complete proofs. We
are also concentrating on the implementation efforts.
60
A Appendix: Twelf Proofs
A.1 sources.cfg
num.elf
formulas.elf
seq.elf
lfProps.elf
seqProps.elf
shiftSeq.elf
cutAdmis.elf
natDed.elf
natToSeq.elf
seqToNat.elf
examples.elf
61
A.2 num.elf
% Adam Poswolsky
% Properties of numbers
% Here we encode natural numbers and prove some properties.
%
% Show it is impossible for le (s X) X
%
emptyType : type. %name emptyType EE.
62
%terminates {X} (impossibleLessNum X _ _).
%total {X} (impossibleLessNum X _ _).
63
A.3 formulas.elf
% Adam Poswolsky
% Encoding of our language
% And Properties on Formulas themselves.
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Representation-Level
% A,B ::= a (type constant) | A arrow B
% Note: We will use M,N for the objects.
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Meta-Level
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Formulas T,S ::= top, bot, T imp S, past T, inj A
% Note: We will use D,E for the objects.
%
% However, for our encoding we make a distinction
% between those types starting with "past". All
% proofs will be over all formulas, "o", but this
% distinction helps because we often want to distinguish
% between it being "past" or anything else.
%
% The reason for this is that our system requires
% that changes are made to the context. Namely, the
% number of pasts in front of everything in the context
% can go up or down. The trick we will use to capture this
% (see seq.elf) takes advantage of this restriction.
%
%
top : pureO.
bot : pureO.
imp : pureO -> pureO -> pureO. %infix right 10 imp.
inj : lftp -> pureO.
pair : pureO -> pureO -> pureO.
! : pureO -> o.
past: o -> o.
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Properties
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% stripPast +X1 +T1 -X2 -T2
% This will strip away all pasts in front of T1 yielding T2.
% And X2 = X1 - (number of leading pasts of T1)
%
stripPast : nat -> o -> nat -> pureO -> type. %name stripPast SP.
stripPastPure : stripPast X (! TP) X TP.
stripPastPast : stripPast X1 T1 X2 TP -> stripPast (s X1) (past T1) X2 TP.
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Some Props of stripPast
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
64
<- stripToLess SP L
<- leAddOneRight L L’.
%worlds (lftypeConsBlock) (stripToLess _ _).
%total {SP} (stripToLess SP _).
65
A.4 seq.elf
% Adam Poswolsky
% Encoding of Sequent Calculus version
%{
IMPORTANT: How to read the rules:
Therefore, when reading the rules one must keep in mind that:
% !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
% !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
hyp X T -> conc Y S
is meant to be interpreted as:
}%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Context (explained above)
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
hyp : nat -> pureO -> type. %name hyp H (h sh).
%block hypBlock : some {X:nat}{TP:pureO} block {h:hyp X TP}.
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Representation-Level
% M,N ::= c (object constant) | lam x:A.M | app M N
%
% The "casting" operation is captures by castHyp with
% shiftLF
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Meta-Level
66
% (actual rule is placed in comments before encoded rule)
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
conc : nat -> o -> type. %name conc (D E F) (d e f).
%{ AXIOM
T is in Omega
--------------- axiom, where |T| removes leading pasts of T
Omega |-- |T|
}%
axiom : le X Y -> hyp X TP -> conc Y (! TP).
%{ IMPR
Omega, TP1 |-- TP2
--------------------- impr
Omega |-- TP1 imp TP2
}%
impr : (hyp X TP1 -> conc X (! TP2))
-> conc X (! (TP1 imp TP2)).
%{ IMPL
(past...past)(TP1 imp TP2) in Omega,
Omega |-- TP1 Omega,TP2 |--- S
---------------------------------- impl
Omega |-- S
}%
impl : le X Y -> hyp X (TP1 imp TP2) -> conc Y (! TP1)
-> (hyp Y TP2 -> conc Y (! S)) -> conc Y (! S).
%{ TOP
--------------- topr
Omega |--- top
}%
topr : conc _ (! top).
%{ BOTL
-------------------------------------- botl
Omega,(past...past)bot,Omega’ |--- TP
}%
botl : le X Y -> hyp X bot -> conc Y (! TP).
%{ PASTR
(remove past from Omega) |-- T
------------------------------------- pastr
Omega |-- past T
}%
pastr : conc X T -> conc (s X) (past T).
%{ INJR
(cast Omega to LF) |-- A
------------------------------------- injr
Omega |-- inj A
}%
injr : exp X A -> conc X (! (inj A)).
%{ PAIRR
Omega |-- TP1 Omega |-- TP2
------------------------------------ pairr
Omega |-- pair TP1 TP2
}%
pairr : conc X (! TP1) -> conc X (! TP2) -> conc X (! (pair TP1 TP2)).
%{ PAIRL
(past...past)(pair TP1 TP2) in Omega,
Omega, TP1, TP2 |--- S
67
-------------------------------------- pairl
Omega |-- S
}%
pairl : le X Y -> hyp X (pair TP1 TP2)
-> (hyp Y TP1 -> hyp Y TP2 -> conc Y (! S))
-> conc Y (! S).
68
A.5 lfProps.elf
% Adam Poswolsky
% Properties of the Representation-Level (LF) of our system.
%
% There is no "past" on the LF level itself, so we have more freedom
% with the index. Namely if (exp Y A -> exp X B) and Y <= X, then
% we can change it to (exp Y’ A -> exp X B) where Y’ can be anything <= X.
%
shiftNegExpLF : le (s Y) X -> (exp Y A -> exp X B) -> (exp (s Y) A -> exp X B) -> type.
%mode shiftNegExpLF +L +M -M2.
shiftNegExpLFLam : shiftNegExpLF L ([n] lam (M n)) ([n] lam (M’ n))
<- ({m} shiftNegExpLF L ([n] M n m) ([n] M’ n m)).
shiftNegExpLFApp : shiftNegExpLF L ([n] app (M1 n) (M2 n)) ([n] app (M1’ n) (M2’ n))
<- shiftNegExpLF L M1 M1’
<- shiftNegExpLF L M2 M2’.
shiftNegExpLFShift1 : shiftNegExpLF base ([n] shiftLF (M n)) ([n] app (shiftLF (lam M)) n).
shiftNegExpLFShift2 : shiftNegExpLF (one L) ([n] shiftLF (M n)) ([n] shiftLF (M’ n))
<- shiftNegExpLF L M M’.
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This is an important judgment which says that if we have a function
% from (hyp Y (inj A) -> exp X B) then we can create (exp Y A -> exp X B)
%
% Note that the reverse direction is trivial (just use castHyp)
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
convertHypExp : (hyp Y (inj A) -> exp X B) -> (exp Y A -> exp X B) -> type.
%mode convertHypExp +M -M2.
convertHypExpLam : convertHypExp ([h] lam (M h)) ([n] lam (M’ n))
<- ({m} convertHypExp ([h] M h m) ([n] M’ n m)).
convertHypExpApp : convertHypExp ([h] app (M1 h) (M2 h)) ([n] app (M1’ n) (M2’ n))
<- convertHypExp M1 M1’
<- convertHypExp M2 M2’.
convertHypExpShift : convertHypExp ([h] shiftLF (M h)) ([n] shiftLF (M’ n))
<- convertHypExp M M’.
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Strengthening (#1)
%
% if (hyp Y TP -> exp X A) and TP is not an Inj, then the function
% cannot use its argument.
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
notInj : pureO -> type. %name notInj NI ni.
notInjImp : notInj (TP1 imp TP2).
notInjPair : notInj (pair TP1 TP2).
notInjTop : notInj top.
notInjBot : notInj bot.
69
strengthenLFNI : notInj TP -> (hyp Y TP -> exp X A) -> exp X A -> type.
%mode strengthenLFNI +NI +M -M2.
strengthenLFNILam : strengthenLFNI NI ([h] lam (N h)) (lam N’)
<- ({m} strengthenLFNI NI ([h] N h m) (N’ m)).
strengthenLFNIApp : strengthenLFNI NI ([h] app (N1 h) (N2 h)) (app N1’ N2’)
<- strengthenLFNI NI N1 N1’
<- strengthenLFNI NI N2 N2’.
strengthenLFNIShift : strengthenLFNI NI ([h] shiftLF (N h)) (shiftLF N’)
<- strengthenLFNI NI N N’.
strengthenLFNICast : strengthenLFNI NI ([h] castHyp H) (castHyp H).
strengthenLFNIBlockCase : strengthenLFNI NI ([h] N) N.
%worlds ( hypBlock | lfexpBlock | lftypeConsBlock) (strengthenLFNI _ _ _).
%total {N} (strengthenLFNI _ N _).
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Strengthening (#2)
%
% If (hyp Y TP -> exp X A) and Y > X, then the function cannot
% use its argument.
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Strengthening (#3)
%
% If (exp Y B -> exp X A) and Y > X, then the function cannot
% use its argument.
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
strengthenLF2 : le Y X -> (exp (s X) A -> exp Y B) -> exp Y B -> type.
%mode strengthenLF2 +L +M -M2.
strengthenLF2Lam : strengthenLF2 L ([n] lam (M n)) (lam M’)
<- ({m} strengthenLF2 L ([n] M n m) (M’ m)).
strengthenLF2App : strengthenLF2 L ([n] app (M1 n) (M2 n)) (app M1’ M2’)
<- strengthenLF2 L M1 M1’
<- strengthenLF2 L M2 M2’.
strengthenLF2Shift : strengthenLF2 L ([n] shiftLF (M n)) (shiftLF M’)
<- leRemoveOneLeft L L’
<- strengthenLF2 L’ M M’.
strengthenLF2Identity : strengthenLF2 L ([n] n) M
<- impossibleLessNum _ L EE
<- fromEmptyComesAllLF EE M.
strengthenLF2BlockAndCast : strengthenLF2 L ([m] M) M.
%worlds ( hypBlock | lfexpBlock | lftypeConsBlock) (strengthenLF2 _ _ _).
%total {M} (strengthenLF2 _ M _).
70
A.6 seqProps.elf
% Adam Poswolsky
% Properties of our Meta-Level
% This includes reversing pastr (future rule),
% Weakening, and Strengthening.
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Weakening... for example, if Omega,A |-- B then Omega,(past A) |-- B
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
weakenHypLF’ : (hyp (s X) TP -> exp Y B) -> (hyp X TP -> exp Y B) -> type.
%mode weakenHypLF’ +M1 -M2.
weakenHypLF’Lam : weakenHypLF’ ([sh] lam (M sh)) ([h] lam (M’ h))
<- ({m} weakenHypLF’ ([sh] M sh m) ([h] M’ h m)).
weakenHypLF’App : weakenHypLF’ ([sh] app (M1 sh) (M2 sh)) ([h] app (M1’ h) (M2’ h))
<- weakenHypLF’ M1 M1’
<- weakenHypLF’ M2 M2’.
weakenHypLF’Shift : weakenHypLF’ ([sh] shiftLF (M sh)) ([h] shiftLF (M’ h))
<- weakenHypLF’ M M’.
weakenHypLF’Cast1 : weakenHypLF’ ([sh] castHyp H) ([h] castHyp H).
weakenHypLF’Cast2 : weakenHypLF’ ([sh] castHyp sh) ([h] (shiftLF (castHyp h))).
weakenHypLF’BlockCase : weakenHypLF’ ([sh] M) ([h] M).
%worlds (hypBlock | lfexpBlock | lftypeConsBlock) (weakenHypLF’ _ _).
%total {M} (weakenHypLF’ M _).
weakenHyp’ : (hyp (s X) TP -> conc Y S) -> (hyp X TP -> conc Y S) -> type.
%mode weakenHyp’ +F1 -F2.
weakenHyp’Axiom1 : weakenHyp’ ([sh] axiom L H) ([h] axiom L H).
weakenHyp’Axiom2 : weakenHyp’ ([sh] axiom L sh) ([h] axiom L’ h)
<- leRemoveOneLeft L L’.
weakenHyp’Pairr : weakenHyp’ ([sh] pairr (D1 sh) (D2 sh)) ([h] pairr (D1’ h) (D2’ h))
<- weakenHyp’ D1 D1’
<- weakenHyp’ D2 D2’.
71
%worlds (hypBlock | lfexpBlock | lftypeConsBlock) (weakenHyp’ _ _).
%total {F} (weakenHyp’ F _).
weakenHyp : le X2 X1 -> (hyp X1 TP -> conc X* S*) -> (hyp X2 TP -> conc X* S*) -> type.
%mode weakenHyp +L +E1 -E2.
weakenHypBase : weakenHyp base E1 E1.
weakenHypOne : weakenHyp (one L) E1 E2
<- weakenHyp’ E1 E1’
<- weakenHyp L E1’ E2.
%worlds (hypBlock | lfexpBlock | lftypeConsBlock) (weakenHyp _ _ _).
%total {L} (weakenHyp L _ _).
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Strengthening... (Part 1 of 2)
% if (hyp X TP -> conc Y T) and X > Y, then
% the function doesn’t use its argument.
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
strengthen : le Y X -> (hyp (s X) TP -> conc Y T) -> conc Y T -> type.
%mode strengthen +L +E -D.
strengthenAxiom1 : strengthen L ([h] axiom L’ H) (axiom L’ H).
strengthenAxiom2 : strengthen L ([h] axiom L’ h) D
<- leAddOneBoth L L1
<- leTrans L1 L’ L2
<- impossibleLessNum _ L2 EE
<- fromEmptyComesAll EE D.
strengthenImpl1 : strengthen L ([h] impl L’ H (D1 h) (D2 h)) (impl L’ H D1’ D2’)
<- strengthen L D1 D1’
<- ({h’} strengthen L ([h] D2 h h’) (D2’ h’)).
strengthenImpl2 : strengthen L ([h] impl L’ h (D1 h) (D2 h)) D
<- leAddOneBoth L L1
<- leTrans L1 L’ L2
<- impossibleLessNum _ L2 EE
<- fromEmptyComesAll EE D.
strengthenPairr : strengthen L ([h] pairr (D1 h) (D2 h)) (pairr D1’ D2’)
<- strengthen L D1 D1’
<- strengthen L D2 D2’.
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Important Admissible Rule:
% We now define the future rule (reverse of pastr).
72
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Strengthening... (Part 2 of 2)
% if Omega,A |-- (past B)
% and A is not (past A*), then Omega |-- (past B)
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
strengthenP : (hyp X _ -> conc X (past T)) -> conc X (past T) -> type.
%mode strengthenP +D -D’.
strengthenPcase : strengthenP D (pastr E’)
<- ({h} futureRule (D h) (D’ h))
<- strengthen base D’ E’.
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% equivalent Conclusion
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
equivConc : conc X T -> stripPast X T Y TP -> conc Y (! TP) -> type.
%mode equivConc +D1 +SP -E.
equivConcSPbase : equivConc E SP E.
equivConcSPpast : equivConc D1 (stripPastPast SP) E
<- futureRule D1 D1’
<- equivConc D1’ SP E.
%worlds (hypBlock | lfexpBlock | lftypeConsBlock) (equivConc _ _ _).
%total {SP} (equivConc _ SP _).
73
A.7 shiftSeq.elf
% Adam Poswolsky
% Encoding of Shift Property in Sequent Calculus
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Shifting:
% Namely, if Omega |-- (past T) then Omega |-- T
% and/or if Omega |-- T then (past Omega) |-- T
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% STEP 1 : Copy from a conc’ to conc
% Note that this system is identical except we added !! (to shift hyps)
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
conc’ : nat -> o -> type. %name conc’ (D’ E’) (d’ e’).
exp’ : nat -> lftp -> type. %name exp’ (M’ N’) (m’ n’).
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% LF Level
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Meta Level
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Copying from conc’ to conc
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
copyLF’ : exp’ X A -> exp X A -> type. %name copyLF’ C c.
%mode copyLF’ +M’ -M.
copyC’ : conc’ X T -> conc X T -> type. %name copyC’ C c.
%mode copyC’ +D’ -D.
copyH’ : hyp’ Y TP -> le X Y -> hyp X TP -> type. %name copyH’ C c.
%mode copyH’ +H’ -L -H.
74
shiftLFGeneral : le X Y -> exp X A -> exp Y A -> type.
%mode shiftLFGeneral +L +M -M’.
shiftLFGeneralBase : shiftLFGeneral base M M.
shiftLFGeneralInd : shiftLFGeneral (one L) M (shiftLF M’)
<- shiftLFGeneral L M M’.
%worlds (copyBlock | lfcopyBlock | lftypeConsBlock ) (shiftLFGeneral _ _ _).
%total {L} (shiftLFGeneral L _ _).
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
75
% STEP 2
% Shifting conc Y T to conc’ (s Y) T
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
76
shift’-pairl: shift’ (pairl L H D) (pairl’ L’ H’ D’)
<- ({h} {h’} map’ h base h’
-> ({h2} {h2’} map’ h2 base h2’
-> shift’ (D h2 h) (D’ h2’ h’)))
<- map’ H base H’
<- leAddOneBoth L L’.
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Final Shift Stage : Put it together to get from conc Y A to conc (s Y) A
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77
A.8 cutAdmis.elf
% Adam Poswolsky
% Encoding of Admissibility of Cut
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Admissibility of Cut:
% Namely, if Omega |-- T and Omega, T |-- S then Omega |-- S
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
ca : {T} conc X T -> stripPast X T Y TP -> (hyp Y TP -> conc X S) -> conc X S -> type.
caPure : {TP} conc X (! TP) -> (hyp X TP -> conc X S) -> conc X S -> type.
% %%%%%%%%%%%%%%%%%%%%%
% Bridge ca and caPure
% %%%%%%%%%%%%%%%%%%%%%
ca_bridge : ca (! TP) D stripPastPure E F
<- caPure TP D E F.
% %%%%%%%%%%%%%%%%%%%%%
% Essential Conversions
% %%%%%%%%%%%%%%%%%%%%%
caPure_impl_r : caPure (TP1 imp TP2) (impr D) ([h] impl L h (E1 h) (E2 h)) F3
<- caPure (TP1 imp TP2) (impr D) E1 E1’
<- ({h2}{h2’} copyH’ h2’ base h2 -> map’ h2 base (!! h2’) ->
caPure (TP1 imp TP2) (impr D) ([h] E2 h h2) (E2’ h2))
<- caPure TP1 E1’ D F1
<- caPure TP2 F1 E2’ F3.
caPure_injr_r : caPure (inj A) (injr N) ([h] injr (M h)) (injr (M’ N))
<- convertHypExp M M’.
caPure_pairl_r : caPure (pair TP1 TP2) (pairr D1 D2) ([h] pairl L h (E h)) F*
<- ({h2}{h2’} copyH’ h2’ base h2 -> map’ h2 base (!! h2’)
-> ({h3}{h3’} copyH’ h3’ base h3 -> map’ h3 base (!! h3’) ->
caPure (pair TP1 TP2) (pairr D1 D2) ([h] E h h2 h3) (E’ h2 h3)))
<- ({h2}{h2’} copyH’ h2’ base h2 -> map’ h2 base (!! h2’)
-> caPure TP1 D1 ([h] E’ h h2) (F2 h2))
<- caPure TP2 D2 F2 F*.
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Shift on left.
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% If we have pastr on the left but not pastr on the right,
% then we shift the result on the left and call the IH.
%
ca_pastr_l2 : ca (past T) (pastr D) (stripPastPast SP) ([h] impl L h (E1 h) (E2 h)) F
<- ca (past T) (pastr D) (stripPastPast SP) E1 E1’
<- ({h2}{h2’} copyH’ h2’ base h2 -> map’ h2 base (!! h2’) ->
ca (past T) (pastr D) (stripPastPast SP) ([h] E2 h h2) (E2’ h2))
<- shift D D’
<- stripAddOne SP SP’
<- stripToLess SP’ L’
78
<- ca T D’ SP’ ([h] impl L’ h E1’ E2’) F.
ca_pastr_l3a : ca (past T) (pastr D) (stripPastPast (SP : stripPast X1 T X2 (inj B))) ([h] injr (M h)) F
<- shift D D’
<- stripAddOne SP SP’
<- stripToLess SP’ L’
<- convertHypExp M M’
<- shiftNegExpLF L’ M’ M’’
<- ca T D’ SP’ ([h] injr (([x] M’’ (castHyp x)) h)) F.
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Commutative Conversions (on left)
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%{
% Here we need to take care of the case when we have botl on the left
% and an E of the form ([h] impl _ h _ _), ([h] pairl _ h _ _ _),
% or ([h] botl _ h _), or ([h] injr (M h))
}%
caPure_botl_l_impl_r1 : caPure _ (botl L H) ([h] impl L* h _ _) (botl L H).
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Strengthening Conversion for past and inj
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
79
<- strengthenP ([h] pastr (E’ h)) F.
caPure_strengthenBotlPastr3 : caPure _ (botl _ _) ([h] pastr (E’ h)) F
<- strengthenP ([h] pastr (E’ h)) F.
caPure_strengthenInjrPastr4 : caPure _ (injr _) ([h] pastr (E’ h)) F
<- strengthenP ([h] pastr (E’ h)) F.
caPure_strengthenInjrPastr5 : caPure _ (pairr _ _) ([h] pastr (E’ h)) F
<- strengthenP ([h] pastr (E’ h)) F.
caPure_strengthenInjrPastr6 : caPure _ (impl _ _ _ _) ([h] pastr (E’ h)) F
<- strengthenP ([h] pastr (E’ h)) F.
caPure_strengthenInjrPastr7 : caPure _ (pairl _ _ _) ([h] pastr (E’ h)) F
<- strengthenP ([h] pastr (E’ h)) F.
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Commutative Conversions (on right)
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
80
A.9 natDed.elf
% Adam Poswolsky
% Formulation of Natural Deduction version
% And some basic properties.
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Natural Deduction Meta Level
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
concND : nat -> o -> type. %name concND (D E F) (d e f).
%
% When introducing a function whose argument has type (inj A)
% we need to also introduce an (exp _ A) for use by the LF level.
% Therefore, when the argument is an (inj A), the natural extension
% would look like (concND X’ (inj AA) -> exp X’ AA -> concND X T)
% But this is no better than just (exp X’ AA -> concND X T), so
% we just use that.
%
MlamInj : (exp X A -> concND X (! TP2)) -> concND X (! ((inj A) imp TP2)).
MlamNI : notInj TP ->
(concND X (! TP) -> concND X (! TP2)) -> concND X (! (TP imp TP2)).
Mapp : concND X (!(TP1 imp TP2)) -> concND X (! TP1) -> concND X (! TP2).
topND : concND X (! top).
prev : concND X T -> concND (s X) (past T).
inject : exp X A -> concND X (!(inj A)).
pairI : concND X (! TP1) -> concND X (! TP2) -> concND X (! (pair TP1 TP2)).
% Note that shift is an admissible rule from the others... it is trivial to prove on paper
% But we won’t go crazy again (see shiftSeq.elf) and prove it here.
shiftND : concND X T -> concND (s X) T.
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% BASIC PROPERTIES
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Strengthening
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
81
strengthenFunND : notInj TP -> (hyp X TP -> concND X (! TP) -> concND Y T) -> (concND X (! TP) -> concND Y T) -> type.
%mode strengthenFunND +NI +F -F’.
strengthenFunND_BotND : strengthenFunND NI ([h][d] botND (D h d)) ([d] botND (D’ d))
<- strengthenFunND NI D D’.
strengthenFunND_MlamInj : strengthenFunND NI ([h][d] MlamInj (F h d)) ([d] MlamInj (F’ d))
<- ({n’} strengthenFunND NI ([h][d] F h d n’) ([d] F’ d n’)).
strengthenFunND_MlamNI : strengthenFunND NI ([h][d] MlamNI NI’ (F h d)) ([d] MlamNI NI’ (F’ d))
<- ({e} strengthenFunND NI ([h][d] F h d e) ([d] F’ d e)).
strengthenFunND_Mapp : strengthenFunND NI ([h][d] Mapp (D1 h d) (D2 h d)) ([d] Mapp (D1’ d) (D2’ d))
<- strengthenFunND NI D1 D1’
<- strengthenFunND NI D2 D2’.
strengthenFunND_TopND : strengthenFunND NI ([h][d] topND) ([d] topND).
strengthenFunND_Prev : strengthenFunND NI ([h][d] prev (D h d)) ([d] prev (D’ d))
<- strengthenFunND NI D D’.
strengthenFunND_Inject : strengthenFunND NI ([h][_] inject (M h)) ([d] inject M’)
<- strengthenLFNI NI M M’.
strengthenFunND_PairI : strengthenFunND NI ([h][d] pairI (D1 h d) (D2 h d)) ([d] pairI (D1’ d) (D2’ d))
<- strengthenFunND NI D1 D1’
<- strengthenFunND NI D2 D2’.
strengthenND : le X Y -> (concND (s Y) (! TP) -> concND X T) -> concND X T -> type.
%mode strengthenND +L +F -F’.
strengthenND_BotND : strengthenND L ([d] botND (D d)) (botND D’)
<- strengthenND L D D’.
strengthenND_MlamInj : strengthenND L ([d] MlamInj (F d)) (MlamInj F’)
<- ({n’} strengthenND L ([d] F d n’) (F’ n’)).
strengthenND_MlamNI : strengthenND L ([d] MlamNI NI’ (F d)) (MlamNI NI’ F’)
<- ({e} strengthenND L ([d] F d e) (F’ e)).
strengthenND_Mapp : strengthenND L ([d] Mapp (D1 d) (D2 d)) (Mapp D1’ D2’)
<- strengthenND L D1 D1’
<- strengthenND L D2 D2’.
strengthenND_TopND : strengthenND L ([d] topND) (topND).
strengthenND_Prev : strengthenND L ([d] prev (D d)) (prev D’)
<- leRemoveOneLeft L L’
<- strengthenND L’ D D’.
strengthenND_Inject : strengthenND L ([_] inject M) (inject M).
strengthenND_PairI : strengthenND L ([d] pairI (D1 d) (D2 d)) (pairI D1’ D2’)
<- strengthenND L D1 D1’
82
<- strengthenND L D2 D2’.
strengthenFunNDLF : (hyp X (inj A) -> exp X A -> concND Y T) -> (exp X A -> concND Y T) -> type.
%mode strengthenFunNDLF +F -F’.
strengthenFunNDLF_BotND : strengthenFunNDLF ([h][n] botND (D h n)) ([n] botND (D’ n))
<- strengthenFunNDLF D D’.
strengthenFunNDLF_MlamInj : strengthenFunNDLF ([h][n] MlamInj (F h n)) ([n] MlamInj (F’ n))
<- ({n’} strengthenFunNDLF ([h][n] F h n n’) ([n] F’ n n’)).
strengthenFunNDLF_MlamNI : strengthenFunNDLF ([h][n] MlamNI NI (F h n)) ([n] MlamNI NI (F’ n))
<- ({e} strengthenFunNDLF ([h][n] F h n e) ([n] F’ n e)).
strengthenFunNDLF_Mapp : strengthenFunNDLF ([h][n] Mapp (D1 h n) (D2 h n)) ([n] Mapp (D1’ n) (D2’ n))
<- strengthenFunNDLF D1 D1’
<- strengthenFunNDLF D2 D2’.
strengthenFunNDLF_TopND : strengthenFunNDLF ([h][n] topND) ([n] topND).
strengthenFunNDLF_Prev : strengthenFunNDLF ([h][n] prev (D h n)) ([n] prev (D’ n))
<- strengthenFunNDLF D D’.
strengthenFunNDLF_Inject : strengthenFunNDLF ([h][n] inject (M h n)) ([n] inject (([n’] M’ n’ n’) n))
<- ({n} convertHypExp ([h] M h n) (M’ n)).
strengthenFunNDLF_PairI : strengthenFunNDLF ([h][n] pairI (D1 h n) (D2 h n)) ([n] pairI (D1’ n) (D2’ n))
<- strengthenFunNDLF D1 D1’
<- strengthenFunNDLF D2 D2’.
83
<- ({m1}{m2} strengthenFunNDLF ([h][n] D2 h n m1 m2) ([n] D2’ n m1 m2)).
strengthenNDLF_Mapp : strengthenNDLF L ([n] Mapp (D1 n) (D2 n)) (Mapp D1’ D2’)
<- strengthenNDLF L D1 D1’
<- strengthenNDLF L D2 D2’.
strengthenNDLF_PairI : strengthenNDLF L ([n] pairI (D1 n) (D2 n)) (pairI D1’ D2’)
<- strengthenNDLF L D1 D1’
<- strengthenNDLF L D2 D2’.
84
%worlds (NDPureblock | hypBlock | lfexpBlock | lftypeConsBlock) (futureRuleND _ _).
%total {D} (futureRuleND D _).
strengthenNDpast : (concND X (! TP) -> concND X (past T)) -> concND X (past T) -> type.
%mode strengthenNDpast +D -D’.
strengthenNDpastcase : strengthenNDpast D (prev E’)
<- ({e} futureRuleND (D e) (D’ e))
<- strengthenND base D’ E’.
strengthenNDLFpast : (exp X A -> concND X (past T)) -> concND X (past T) -> type.
%mode strengthenNDLFpast +D -D’.
strengthenNDLFpastcase : strengthenNDLFpast D (prev E’)
<- ({m} futureRuleND (D m) (D’ m))
<- strengthenNDLF base D’ E’.
85
A.10 natToSeq.elf
% Adam Poswolsky
% Conversion from Natural Deduction to Sequent Calculus.
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Convert Natural Deduction to Sequent Calculus
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
NDtoSQ : concND X T -> conc X T -> type.
%mode NDtoSQ +DN -D.
% %%%%%%%%%%%%%%%%%%%
% Meta Level
% %%%%%%%%%%%%%%%%%%%
86
-> NDtoSQ (D2 n n2) (D2’ h n h2 n2)))
<- ca _ D1’ stripPastPure ([h] pairl base h ([h1][h2] D2’ h1 (castHyp h1) h2 (castHyp h2))) F.
87
A.11 seqToNat.elf
% Adam Poswolsky
% Conversion from Sequent Calculus to Natural Deduction
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% First, a property we need when converting Sequent to Natural Deduction
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
NDprop : concND X (!(inj A)) -> (exp X A -> concND X T) -> concND X T -> type.
%mode NDprop +D +F -D’.
NDprop_pure : NDprop D E (Mapp (MlamInj E) D).
NDprop_impure : NDprop D E F
<- strengthenNDLFpast E F.
%worlds (hypBlock | lfexpBlock | NDPureblock | lftypeConsBlock) (NDprop _ _ _).
%terminates {F} (NDprop _ F _).
%total {F} (NDprop _ F _).
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Now Convert Sequent Calculus to Natural Deduction
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Meta Cases
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
88
<- strengthenFunND notInjImp F’ F*.
89
SQtoND_pairl00 : SQtoND (pairl L H D) (pairE00 F00 notInjTop notInjTop F3)
<- hypToCN L H F00
<- ({h}{h’} copyH’ h’ base h -> map’ h base (!! h’) -> {e} SQtoND (axiom base h) e -> hypToCN base h e
-> ({h2}{h2’} copyH’ h2’ base h2 -> map’ h2 base (!! h2’) -> {e2} SQtoND (axiom base h2) e2 -> hypToCN base h2 e2 ->
SQtoND (D h h2) (F h e h2 e2)))
<- ({h}{e} strengthenFunND notInjTop (F h e) (F2 h e))
<- ({e2} strengthenFunND notInjTop ([h][e] F2 h e e2) ([e] F3 e e2)).
90
-> calcShiftLF’ m2 (shiftLF’ n2) -> hypToCN base h2 (inject m2) -> SQtoND (D h h2) (F h e h2 m2)))
<- ({h}{e} strengthenFunNDLF (F h e) (F2 h e))
<- ({m2} strengthenFunND notInjBot ([h][e] F2 h e m2) ([e] F3 e m2)).
91
<- ({e2} strengthenFunND notInjPair ([h][e] F2 h e e2) ([e] F3 e e2)).
92
A.12 examples.elf
% Adam Poswolsky
% Example Section
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% LF Application on Meta-Level
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
liftedApp : conc X (!(inj (A arrow B))) -> conc X (!(inj A)) -> conc X (!(inj B)) -> type.
%mode liftedApp +D1 +D2 -F.
liftedAppCase : liftedApp D1 D2 E
<- ({h1}{h1’} copyH’ h1’ base h1 -> map’ h1 base (!! h1’) ->
ca _ D2 stripPastPure ([h2] injr (app (castHyp h1) (castHyp h2)))
(F h1))
<- ca _ D1 stripPastPure F E.
%worlds (mapcopyBlock | lfmapcopyBlock | lftypeConsBlock) (liftedApp _ _ _).
%total {} (liftedApp _ _ _).
93
References
[Aug98] Lennart Augustsson. Cayenne - a language with dependent types. In International Conference on
Functional Programming, pages 239–250, 1998.
[Chu40] Alonzo Church. A formulation of the simple theory of types. Journal of Symbolic Logic, 5:56–68, 1940.
[CX05] Chiyan Chen and Hongwei Xi. Combining programming with theorem proving. In Intenational
Conference on Functional Programming, 2005.
[Dav96] Rowan Davies. A temporal-logic approach to binding-time analysis. In Logic in Computer Science,
pages 184–195, 1996.
[GP99] Murdoch Gabbay and Andrew Pitts. A new approach to abstract syntax involving binders. In
G. Longo, editor, Proceedings of the 14th Annual Symposium on Logic in Computer Science (LICS’99),
pages 214–224, Trento, Italy, July 1999. IEEE Computer Society Press.
[HHP93] Robert Harper, Furio Honsell, and Gordon Plotkin. A framework for defining logics. Journal of the
Association for Computing Machinery, 40(1):143–184, January 1993.
[HMS01] Furio Honsell, Marino Miculan, and Ivan Scagnetto. π-calculus in (Co)inductive-type theory. Theo-
retical Computer Science, 253(2):239–285, 2001.
[Hof99] Martin Hofmann. Semantical analysis for higher-order abstract syntax. In G. Longo, editor, Proceed-
ings of the 14th Annual Symposium on Logic in Computer Science (LICS’99), pages 204–213, Trento,
Italy, July 1999. IEEE Computer Society Press.
[Lel98] Pierre Leleu. Induction et Syntaxe Abstraite d’Ordre Supérieur dans les Théories Typées. PhD thesis,
Ecole Nationale des Ponts et Chaussees, Marne-la-Vallee, France, December 1998.
[MAC03] Alberto Momigliano, Simon Ambler, and Roy Crole. A definitional approach to primitive recursion
over higher order abstract syntax. In Alberto Momigliano and Marino Miculan, editors, Proceedings
of the Merlin Workshop, Uppsala, Sweden, June 2003. ACM Press.
[Mil90] Dale Miller. An extension to ML to handle bound variables in data structures: Preliminary report.
In Proceedings of the Logical Frameworks BRA Workshop, Nice, France, May 1990.
[Mil91] Dale Miller. Unification of simply typed lambda-terms as logic programming. In Koichi Furukawa,
editor, Eighth International Logic Programming Conference, pages 255–269, Paris, France, June 1991.
MIT Press.
[MM04] Conor McBride and James McKinna. The view from the left. Journale of Functional Programming,
14(1), 2004.
[Pau94] Lawrence C. Paulson. Isabelle: A Generic Theorem Prover. Springer-Verlag LNCS 828, 1994.
[Pfe95] Frank Pfenning. Structural cut elimination. In D. Kozen, editor, Proceedings of the Tenth Annual
Symposium on Logic in Computer Science, pages 156–166, San Diego, California, June 1995. IEEE
Computer Society Press.
[Pfe99] Frank Pfenning. Logical frameworks. In Alan Robinson and Andrei Voronkov, editors, Handbook of
Automated Reasoning. Elsevier Science Publishers, 1999. In preparation.
[Pos06] Adam Poswolsky and Carsten Schürmann. Extended Report: A Temporal-Logic Approach to Pro-
gramming with Dependent Types and Higher-Order Encodings. Yale University Tech Report TR-
1355, 2006.
http://www.cs.yale.edu/publications/techreports/tr1355.pdf
[PS98] Frank Pfenning and Carsten Schürmann. Algorithms for equality and unification in the presence of
notational definitions. In T. Altenkirch, W. Naraschewski, and B. Reus, editors, Types for Proofs and
Programs. Springer-Verlag LNCS 1657, 1998. To appear.
[PS99] Frank Pfenning and Carsten Schürmann. System description: Twelf — a meta-logical framework
for deductive systems. In H. Ganzinger, editor, Proceedings of the 16th International Conference on
Automated Deduction (CADE-16), pages 202–206, Trento, Italy, July 1999. Springer-Verlag LNAI
1632.
[Wes06] Edwin Westbrook Free Variable Types Trends in Functional Programming (TFP 2006)
http://www.cs.nott.ac.uk/∼nhn/TFP2006/Papers
/21-Westbrook-FreeVariableTypes.pdf
94
[Sch01] Carsten Schürmann. Recursion for higher-order encodings. In Laurent Fribourg, editor, Proceedings
of the Conference on Computer Science Logic (CSL 2001), pages 585–599, Paris, France, August 2001.
Springer Verlag LNCS 2142.
[Sch05] Carsten Schürmann, Adam Poswolsky, and Jeffrey Sarnat. The ∇-calculus. Functional programming
with higher-order encodings. Typed Lambda Calculus and Applications, TLCA’05 Nara, Japan, 2005.
[SDP01] Carsten Schürmann, Joëlle Despeyroux, and Frank Pfenning. Primitive recursion for higher-order
abstract syntax. Theoretical Computer Science, (266):1–57, 2001.
[SP98] Carsten Schürmann and Frank Pfenning. Automated theorem proving in a simple meta-logic for LF.
In Claude Kirchner and Hélène Kirchner, editors, Proceedings of the 15th International Conference on
Automated Deduction (CADE-15), pages 286–300, Lindau, Germany, July 1998. Springer-Verlag LNAI
1421.
[Sti92] Colin Stirling. Handbook of Logic in Computer Science, volume 2, chapter Modal and Temporal Logics,
pages 478–563. Oxford, 1992.
[Tah04] Walid Taha. A gentle introduction to multi-stage programming. In Don Batory, Charles Con-
sel, Christian Lengauer, and Martin Odersky, editors, Domain-specific Program Generation, LNCS.
Springer-Verlag, 2004. to appear.
[TS00] Walid Taha and Tim Sheard. MetaML: Multi-stage programming with explicit annotations. Theoret-
ical Computer Science, 248(1-2), 2000.
[WaIW05] Edwin Westbrook and Aaron Stump adn Ian Wehrman. A language based approach to functionally
correct imperative programming. In Intenational Conference on Functional Programming, 2005.
[XP99] Hongwei Xi and Frank Pfenning. Dependent types in practical programming. In A. Aiken, editor,
Conference Record of the 26th Symposium on Principles of Programming Languages (POPL’99), pages
214–227. ACM Press, January 1999.
95