You are on page 1of 28

University of Tehran

Department of Mathematics, Statistics and


Computer Science
July 2023

Implementation of Calculus of
Constructions in Coq

For:
By:
Logic Programming
Mahdi Heydari
Dr. Alizadeh
Contents
1 Lambda Cube Expressions 2
1.1 Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2 Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.3 Equality of Two expressions . . . . . . . . . . . . . . . . . . . . . 3
1.4 Free Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.5 Bind vars . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.6 Variables of an Expression . . . . . . . . . . . . . . . . . . . . . . 6
1.7 Substitution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

2 β-Reduction in CoC 7
2.1 One Step β-Reduction . . . . . . . . . . . . . . . . . . . . . . . . 7
2.2 Multi step β-reduction . . . . . . . . . . . . . . . . . . . . . . . . 9
2.3 β-equality . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

3 Typing in CoC 12
3.1 Basic Definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.2 Typing (Derivation) Rules . . . . . . . . . . . . . . . . . . . . . . 15

4 Properties of CoC 17
4.1 Thinning Lemma . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
4.2 Permutation Lemma . . . . . . . . . . . . . . . . . . . . . . . . . 18
4.3 Generation Lemma . . . . . . . . . . . . . . . . . . . . . . . . . . 18
4.3.1 Var Generation . . . . . . . . . . . . . . . . . . . . . . . . 18
4.3.2 Application Generation . . . . . . . . . . . . . . . . . . . 21
4.3.3 Abstraction Generation . . . . . . . . . . . . . . . . . . . 23
4.3.4 Pi Generation . . . . . . . . . . . . . . . . . . . . . . . . 24

1
Introduction
The Calculus of Constructions (CoC) is a foundational higher-order typed lambda
calculus, renowned for its versatile type system that establishes a direct link be-
tween propositions and types, as well as proofs and terms. In this project,
we undertake the task of defining CoC in the Coq programming language as
part of the Computer Science bachelor course “Logic Programming.” Through
this project, we aim to deepen our understanding of CoC (or Lambda Cube)
and its formal reasoning capabilities, while also gaining practical experience in
implementing complex type systems and conducting rigorous proofs using Coq.

1 Lambda Cube Expressions


1.1 Variables
In the context of the Calculus of Constructions (CoC), variables play a crucial
role, representing both type and term variables in lower lambda calculi. In
CoC, we define the set of variables as a countable set, represented using natural
numbers in Coq. Specifically, we utilize the Coq code:

Definition variable : Type := nat.

1.2 Expressions
In the realm of the Calculus of Constructions (CoC), expressions encompass all
terms within the system. To precisely capture the rich variety of expressions
that CoC supports, we employ an inductive definition in Coq:

Inductive expression : Type :=


| Var : variable ‐> expression
| Star : expression
| Box : expression
| AppExp : expression ‐> expression ‐> expression
| AbsExp : variable ‐> expression ‐> expression ‐> expression
| PiExp : variable ‐> expression ‐> expression ‐> expression.

An inductive definition is well-suited for describing the structure of CoC expres-


sions since it allows us to build expressions from simpler constituents, thereby
enabling a recursive construction. Each constructor in the definition corresponds
to a distinct form of expression in CoC:

1. Var: Represents a variable term in CoC, where the variable is specified as


an argument.

2. Star(∗): Denotes the universe or ”type of types” in CoC, allowing for the
formation of higher-order types.

2
3. Box(□): Represents the type of all types, signifying that the term inhabits
all possible types.
4. AppExp: Represents the application of one expression to another, enabling
function application and abstraction.
5. AbsExp: Stands for the abstraction of a variable in an expression, forming
lambda-abstractions in CoC.
6. PiExp: Denotes dependent function types, where the return type depends
on the value of a variable, akin to dependent products.

By utilizing an inductive definition for expressions, we achieve a powerful and


flexible representation of the various constructs supported by CoC. This ap-
proach facilitates reasoning about expressions, pattern matching, and conduct-
ing proofs involving the diverse forms of terms and types in CoC.

1.3 Equality of Two expressions


The function Exp_eqb is a recursive function that compares two expressions
E1 and E2 and returns a boolean value indicating whether they are equal or
not. The comparison is based on the structure of the expressions, checking the
equality of variables and sub-expressions recursively. The definition of Exp_eqb
is as follows:

Fixpoint Exp_eqb (E1 E2 : expression) : bool :=


match E1, E2 with
| Var a , Var b => eqb a b
| Star, Star => true
| Box, Box => true
| AppExp T11 T12, AppExp T21 T22 => (Exp_eqb T11 T21) &&
(Exp_eqb T12 T22)
| AbsExp x1 T11 T12 , AbsExp x2 T21 T22 => (eqb x1 x2) &&
(Exp_eqb T11 T21) &&
(Exp_eqb T12 T22)
| PiExp x1 T11 T12 , PiExp x2 T21 T22 => (eqb x1 x2) &&
(Exp_eqb T11 T21) &&
(Exp_eqb T12 T22)
| _, _ => false
end.

Explanation of cases:

• For the case of two variables Var a and Var b, it checks if a is equal
to b using the eqb function, which compares natural numbers (variable
names).
• For the cases of Star and Box, since they are constructors without any
parameters, they are considered equal, and thus, it returns true.

3
• For the cases of application expressions AppExp T11 T1 and AppExp T21
T22, it checks if the sub-expressions T11 and T12 in E1 are equal to the
corresponding sub-expressions T21 and T22 in E2. It returns true only if
both pairs of sub-expressions are equal.
• For the cases of abstraction expressions AbsExp x1 T11 T12 and AbsExp
x2 T21 T22, it checks if the variable x1 is equal to x2, and then it recur-
sively compares the sub-expressions T11 and T21 as well as T12 and T22.
It returns true only if all the conditions are satisfied.
• Similarly, for the cases of pi expressions PiExp x1 T11 T12 and PiExp
x2 21 T22, it performs the same checks and comparisons as in the case
of abstraction expressions.

In summary, the function Exp_eqb provides a way to determine whether two


expressions are structurally equal by comparing their constructors, variables,
and sub-expressions recursively. If both expressions are equal, it returns true,
otherwise, it returns false.

1.4 Free Variables


A free variable is a variable that appears in an expression without being bound
by an abstraction (e.g., lambda or pi) within the expression. Identifying free
variables is essential for formal reasoning and manipulation of expressions, as
they indicate the variables that can potentially be replaced or substituted with-
out changing the meaning of the expression. The definition for the set of free
variables for an expression is as follows:

• (Var) FreeVar(a) = [a], where ’a’ is a variable.


• (Star) FreeVar(∗) = ∅(empty set).

• (Box) FreeVar(□) = ∅(empty set).


• (Appl) FreeVar(MN) = FreeVar(M )++ FreeVar(N ), where M and N are
expressions.
• (Abs) FreeVar(λx : M. N ) = (FreeVar(M ) + + FreeVar(N )) \ {x}, where
x is a variable and M and N are expressions.
• (Pi) FreeVar(Πx : M. N ) = (FreeVar(M ) + + FreeVar(N )) \ {x}, where
x is a variable and M and N are expressions.

To efficiently compute the free variables in CoC expressions, we utilize a Fixpoint


definition in Coq:

4
Fixpoint FreeVars (E : expression) : list variable :=
match E with
| Var a => [a]
| Star => []
| Box => []
| AppExp T1 T2 => (FreeVars T1) ++ (FreeVars T2)
| AbsExp v T1 T2 => remove PeanoNat.Nat.eq_dec v (FreeVars(T1) ++
FreeVars(T2))
| PiExp v T1 T2 => remove PeanoNat.Nat.eq_dec v (FreeVars(T1) ++
FreeVars(T2))
end.

1.5 Bind vars


A bind variable is a variable that is introduced and defined within a specific
abstraction (e.g., lambda or pi) in an expression. The scope of a bind variable
is limited to the abstraction in which it is defined and cannot be used outside
of that scope. Identifying bind variables is crucial for understanding the scope
and meaning of expressions, especially in cases where the same variable name
may be used in different abstractions within an expression.
The definition for the set of bind variables for an expression is as follows

• (Var) BindVars(a) = ∅ (empty set), where ‘a’ is a variable.


• (Star) BindVars(∗) = ∅.
• (Box) BindVars(□) = ∅.
• (Appl) BindVars(M N ) = BindVars(M ) + + BindVars(N ), where M and
N are expressions.
• (Abs) BindVars(λx : M. N ) = [x] + +(BindVars(M ) + + BindVars(N )),
where x is a variable and M and N are expressions.
• (Pi) BindVars(Π x : M.N ) = [x] + +(BindVars(M ) + + BindVars(N )),
where x is a variable and M and N are expressions.

To efficiently compute the bind variables in CoC expressions, we utilize a Fixpoint


definition in Coq:

Fixpoint BindVars (E:expression) : list variable :=


match E with
| Var a => []
| Star => []
| Box => []
| AppExp T1 T2 => (BindVars T1) ++ (BindVars T2)
| AbsExp v T1 T2 => [v] ++ ((BindVars T1) ++ (BindVars T2))
| PiExp v T1 T2 => [v] ++ ((BindVars T1) ++ (BindVars T2))
end.

5
1.6 Variables of an Expression
To compute the list of variables that appear in an expression (Free, Bind, or
Bound), it’s enough to concatenate the list of bound and free variables in the ex-
pression. The function VarsExp(E: expression) accomplishes this by calling
the functions BindVars and FreeVars, which respectively compute the list of
variables bound by abstractions and the list of free variables in the expression.
The result is the concatenation of these two lists, representing all the variables
that appear in the expression, whether they are bound or free. The definition
of VarsExp is as follows:

Definition VarsExp (E:expression) : list variable := BindVars E


++ FreeVars E.

By using VarsExp, we obtain a comprehensive list of all variables involved


in an expression, making it easy to perform various operations and analyses on
the expression based on the variables that are present.

1.7 Substitution
Substitution is a fundamental operation in lambda calculus and many other
formal systems. It involves replacing occurrences of a variable in an expression
with another expression. In the context of the CoC (Calculus of Constructions),
substitution is used to replace free occurrences of variables in an expression
with other expressions. This operation is essential for performing reductions,
beta-reductions, and other manipulations on expressions while preserving their
meaning.

Fixpoint subst (A : expression) (x : variable) (N : expression) : expression :=


match A with
| Var y => if (eqb x y) then N
else Var y
| Star => Star
| Box => Box
| AppExp T1 T2 => AppExp (subst T1 x N) (subst T2 x N)
| AbsExp y T1 T2 => if (eqb y x) then A
else AbsExp y (subst T1 x N) \\
(subst T2 x N)
| PiExp y T1 T2 => if (eqb y x) then A
else PiExp y (subst T1 x N) \\
(subst T2 x N)
end.

The subst function uses pattern matching to traverse the structure of the
expression A. It handles various cases based on the constructors of the expres-
sions, and for each case, it decides whether to perform the substitution or keep
the original expression unchanged.

6
Here’s the explanation of each case:

• Var y: If the variable y is equal to the variable x, then N will replace


x, and the new expression will be N. Otherwise, the variable y remains
unchanged.
• Star and Box: In these cases, the substitution does not change the ex-
pressions Star and Box, so they remain unchanged.

• AppExp T1 T2: The substitution is applied recursively to both subexpres-


sions T1 and T2, as they may contain occurrences of the variable x.
• AbsExp y T1 T2: If the variable y is equal to x, then A remains un-
changed since x is bound in this abstraction. Otherwise, the substitution
is applied recursively to both subexpressions T1 and T2.

• PiExp y T1 T2: Similar to the AbsExp case, if the variable y is equal to


x, then A remains unchanged since x is bound in this dependent function
type. Otherwise, the substitution is applied recursively to both subex-
pressions T1 and T2.

Now, it’s mentioned that there are problems in the PiExp and AbsExp cases.
Based on the provided code, it seems that the substitution is not handling
variable capture properly. Variable capture occurs when the variable being
substituted (x) is already bound within the abstraction, and the substitution
might unintentionally change the meaning of the expression.
While this issue might cause problems in some contexts, it doesn’t seem to
affect the validity of the lemmas about typing that are intended to be proven
using this substitution. The correctness of the typing lemmas might still hold,
depending on how these lemmas are defined and used in other parts of the code.
In a more formal setting, such as Coq proofs, it is essential to ensure that
substitution preserves the intended meaning of expressions and avoids variable
capture issues. In practice, it’s crucial to use a well-defined and capture-avoiding
substitution function for formal reasoning and manipulation of expressions in
lambda calculus and related formal systems.

2 β-Reduction in CoC
2.1 One Step β-Reduction
One-step beta reduction is a notion in lambda calculus that represents the pro-
cess of reducing an expression to its normal form in a single reduction step.
Each reduction step involves applying a beta reduction, which replaces a redex
(reducible expression) with its corresponding body.

Inductive OneStepBetaReduct : expression ‐> expression ‐> Prop :=

7
| BasicLambda : forall (x : variable)(A B N : expression),
OneStepBetaReduct (AppExp (AbsExp x A B) N) (subst B x N)

| BasicPi : forall (x : variable)(A B N : expression),


OneStepBetaReduct (AppExp (PiExp x A B) N) (subst B x N)

| CompLeftApp : forall (A B C: expression), (OneStepBetaReduct A B) ‐>


OneStepBetaReduct (AppExp C A ) (AppExp C B )

| CompRightApp : forall (A B C: expression), (OneStepBetaReduct A B) ‐>


OneStepBetaReduct (AppExp A C) (AppExp B C)

| CompAbs : forall (x : variable)(A B C: expression),


(OneStepBetaReduct A B) ‐>
OneStepBetaReduct (AbsExp x C A) (AbsExp x C B)

| CompPi : forall (x : variable)(A B C: expression),


(OneStepBetaReduct A B) ‐>
OneStepBetaReduct (PiExp x C A) (PiExp x C B)

| CompAbs2 : forall (x : variable)(A B C: expression),


(OneStepBetaReduct A B) ‐>
OneStepBetaReduct (AbsExp x A C) (AbsExp x B C)

| CompPi2 : forall (x : variable)(A B C: expression),


(OneStepBetaReduct A B) ‐>
OneStepBetaReduct (PiExp x A C) (PiExp x B C).
The code defines the OneStepBetaReduct relation as an inductive type, rep-
resenting one-step beta reductions between expressions. The OneStepBetaReduct
relation is defined using constructors that represent different reduction rules.
Each constructor specifies how one expression can be reduced to another in a
single step. Explanation of the constructors:
1. BasicLambda: Represents the application of a lambda abstraction to an
argument. When an expression of the form AppExp (AbsExp x A B) N
is encountered, it can be reduced by substituting the argument N for the
bound variable x in the body B. This is the standard beta reduction rule.
2. BasicPi: Represents the application of a dependent function type to
an argument. Similar to BasicLambda, when an expression of the form
AppExp (PiExp x A B) N is encountered, it can be reduced by substi-
tuting the argument N for the bound variable x in the body B.
3. CompLeftApp: Represents a reduction on the left side of an application.
If A can be reduced to B in one step (OneStepBetaReduct A B), then the
expression AppExp C A can be reduced to AppExp C B by applying the
same reduction on the function part of the application.

8
4. CompRightApp: Represents a reduction on the right side of an appli-
cation. Similar to CompLeftApp, if A can be reduced to B in one step
(OneStepBetaReduct A B), then the expression AppExp A C can be re-
duced to AppExp B C by applying the same reduction on the argument
part of the application.
5. CompAbs and CompPi: Represents reductions inside an abstraction. If A
can be reduced to B in one step (OneStepBetaReduct A B), then the
expression AbsExp x C A (or PiExp x C A) can be reduced to AbsExp
x C B (or PiExp x C B) by applying the same reduction inside the ab-
straction.
6. CompAbs2 and CompPi2: Similar to CompAbs and CompPi, but repre-
sents reductions outside an abstraction. If A can be reduced to B in one
step (OneStepBetaReduct A B), then the expression AbsExp x A C (or
PiExp x A C) can be reduced to AbsExp x B C (or PiExp x B C) by
applying the same reduction outside the abstraction.
It’s important to note that the definition of one-step beta reduction in the
provided code may have some redundancy and can potentially lead to multiple
reduction paths for the same expression. This is because some constructors
are similar to others and can result in overlapping reductions. However, the
code intends to capture different possible reduction rules explicitly, even if they
may not be strictly necessary for a concise definition of one-step beta reduction.
Despite this, the overall validity of the lemmas about typing might still hold, as
the essence of beta reduction is captured by the constructors.

2.2 Multi step β-reduction


Expanding one-step beta reduction to multi-step beta reduction involves defin-
ing a relation that represents the possibility of reducing an expression to an-
other expression in multiple reduction steps. The provided code defines the
BetaReduct relation as an inductive type to capture multi-step beta reduc-
tions.
Inductive BetaReduct : expression ‐> expression ‐> Prop :=
| reflex : forall (E : expression), BetaReduct E E
| trans : forall (E1 E2 E3 : expression),
OneStepBetaReduct E1 E2 ‐>
BetaReduct E2 E3 ‐>
BetaReduct E1 E3.
Explanation of the constructors:
1. reflex: The reflex constructor represents the reflexivity of the beta
reduction relation. For any expression E, it states that E is in a beta
reduction relation with itself. This serves as the base case for multi-step
reductions, indicating that an expression can be reduced to itself in zero
steps.

9
2. trans: The trans constructor represents the transitivity of the beta re-
duction relation. It states that if E1 can be reduced to E2 in one step
(OneStepBetaReduct E1 E2), and E2 can be reduced to E3 in multiple
steps (BetaReduct E2 E3), then E1 can be reduced to E3 in multiple
steps. This constructor allows us to chain individual reduction steps to-
gether to obtain multi-step reductions.

By using these two constructors, we can build a chain of one-step beta reductions
to establish a multi-step beta reduction between two expressions. For example,
if E1 can be reduced to E2 in one step, E2 can be reduced to E3 in one step,
and E3 can be reduced to E4 in one step, then we can derive BetaReduct E1
E4 using the transitivity property. This chain can continue for any number of
steps, leading to a multi-step reduction relation between expressions.
The BetaReduct relation allows us to reason about the reachability of dif-
ferent expressions through beta reductions. It forms the foundation for studying
the notion of beta equivalence, which involves exploring whether two expres-
sions are related by a series of beta reductions, regardless of the number of
reduction steps required to reach the equivalent form.

2.3 β-equality
The BetaEquiv relation is defined to capture the notion of beta equivalence
between two expressions. Beta equivalence represents the idea that two expres-
sions can be transformed into each other through a series of beta reductions,
regardless of the number of reduction steps required. It takes into account both
the one-directional and multi-directional relationship between expressions.
Inductive BetaEquiv : expression ‐> expression ‐> Prop :=
| OneDirectionRight : forall (E1 E2 : expression) (H : BetaReduct E1 E2),
BetaEquiv E1 E2
| OneDirectionLeft : forall (E1 E2 : expression)(H : BetaEquiv E1 E2),
BetaEquiv E2 E1
| MultipleDirection : forall (E1 E2 E3: expression)(H : BetaEquiv E1 E2)
(H : BetaEquiv E2 E3),
BetaEquiv E1 E3.
Explanation of the constructors:

1. OneDirectionRight: The OneDirectionRight constructor represents


the one-directional relationship between expressions. If there exists a
multi-step beta reduction BetaReduct E1 E2, then E1 is beta equiva-
lent to E2, denoted as BetaEquiv E1 E2.

2. OneDirectionLeft: The OneDirectionLeft constructor captures the


reverse direction of beta equivalence. If E1 is beta equivalent to E2, de-
noted as BetaEquiv E1 E2, then E2 is also beta equivalent toE1, denoted
as BetaEquiv E2 E1.

10
3. MultipleDirection: The MultipleDirection constructor represents
the transitivity of beta equivalence. It states that if E1 is beta equivalent
to E2, denoted as BetaEquiv E1 E2, and E2 is beta equivalent to E3,
denoted as BetaEquiv E2 E3, then E1 is also beta equivalent to E3, de-
noted as BetaEquiv E1 E3. This constructor allows us to chain multiple
beta reductions together, establishing the equivalence relation for a series
of expressions.
By using these constructors, the BetaEquiv relation provides a comprehen-
sive way to reason about beta equivalence between expressions. It allows us to
explore the different paths and possibilities of transforming one expression into
another through beta reductions. This notion of beta equivalence is essential in
type theory and lambda calculus, as it enables us to identify expressions that
have the same meaning and behave identically under evaluation, even though
they may have different syntactic representations.
To ensure that the relation of beta equivalence (BetaEquiv) has the reflex-
ivity property, we must verify that for any expression E, E is beta equivalent to
itself (BetaEquiv E E). This property is crucial to establish that beta equiva-
lence forms an equivalence relation.
The theorem Beta_equiv_Reflexivity that we proved earlier demon-
strates this reflexivity property, ensuring that every expression is beta equiva-
lent to itself. By proving this theorem, we have verified that beta equivalence
is indeed reflexivity, as it satisfies the condition of reflexivity (every expression
is beta equivalent to itself).
Theorem Beta_equiv_Reflexivity: forall (E : expression), BetaEquiv E E.
Proof.
intros. apply OneDirectionRight. apply (reflex).
Qed.
Proof explanation: To prove this theorem, we use the OneDirectionRight
constructor of the BetaEquiv relation. The OneDirectionRight constructor
asserts that if there exists a multi-step beta reduction from expression E1 to
expression E2, then E1 is beta equivalent to E2. In our case, we want to show
that there exists a multi-step beta reduction from expression E to itself, which
will prove that E is beta equivalent to itself.
1. intros: We start the proof by introducing a variable E, representing an
arbitrary expression.
2. apply OneDirectionRight: We use the OneDirectionRight construc-
tor to show that E is beta equivalent to itself. This requires us to demon-
strate the existence of a multi-step beta reduction that relates E to itself.
3. apply (reflex): To establish the multi-step beta reduction needed for
OneDirectionRight, we use the reflex constructor of the BetaReduct
relation. The reflex constructor states that every expression is related
to itself by a single step of beta reduction (reflexivity property of beta
reduction).

11
By using reflex, we create a one-step beta reduction from expression E to itself.
Then, using the OneDirectionRight constructor, we conclude that E is beta
equivalent to itself (BetaEquiv E E).

3 Typing in CoC
3.1 Basic Definitions
Typing is the process of assigning types to expressions, which ensures that ex-
pressions adhere to the type system rules. The typing judgments in CoC are
denoted as Γ ⊢ M : A where Γ is the context, M is the expression being typed,
and A is its corresponding type. The context Γ is a list of declarations, each
containing a variable and its associated expression. The typing rules are defined
through an inductive data type called statement, which consists of a construc-
tor representing different typing judgments, named as State, that relates an
expression M to its type A. Additionally, there is a data type declaration,
representing individual variable declarations with their associated expressions.
In summary,
Statement: stands for relation(typing) between two expression,
Inductive statement : Type :=
| State : expression ‐> expression ‐> statement.
Declaration: stands for relation(typing) between a variable and an expression,
Inductive declaration : Type :=
| Decl : variable ‐> expression ‐> declaration.
Context: stands for list of declarations,
Definition context : Type := list declaration.
The notion of subcontext is also defined through the inductive data type
subContext, representing the inclusion relationship between two contexts (same
order).
Inductive subContext : context ‐> context ‐> Prop :=
| subEmpty : subContext [] []
| subCons : forall (x : variable)(E:expression)(G1 G2 : context),
(subContext G1 G2) ‐>
subContext ((Decl x E)::G1) ((Decl x E)::G2)
| subInc : forall (x : variable)(E:expression)(G1 G2 : context),
(subContext G1 G2) ‐>
subContext G1 ((Decl x E)::G2).
Again subContext must meet the symmetry property means a context like G is
subcontext of itself or subcontext G G. Now let’s check some properties of
sub context relation.
For any context G, the empty context [ ] is a subcontext of G, i.e., subContext
[] G.

12
Theorem sub_Cntx_emp : forall (G:context), subContext [] G.
Proof.
intros. induction G.
‐ apply subEmpty.
‐ destruct a. apply subInc. apply IHG.
Qed.
Proof. (Theorem sub_Cntx_emp): We will use induction on the context G.

Base case (G = []): In this case, we need to show that subContext []


[] holds. The constructor “subEmpty” directly provides the proof for this case.

By the definition of “subContext,” we have two constructors: “subCons” and


“subInc.”

1. subCons: Since we know subContext [] G' holds, we can use the subCons
constructor with the induction hypothesis to obtain subContext ((Decl
x E) :: []) ((Decl x E) :: G').
2. subInc: By applying the induction hypothesis “IHG” for the context G
in the inductive step, we have subContext [] G'. Thus, we can use the
“subInc” constructor to get subContext [] ((Decl x E) :: G').

In either case, we have shown that subContext [] ((Decl x E) :: G')


holds, completing the induction step.

Therefore, by the principle of induction, we have proven that subContext


[] G holds for any context G.

For any context G, the context G is a subcontext of itself, i.e., subContext


G G.

Theorem sub_Cntx_Reflex : forall (G:context), subContext G G.


Proof.
intros. induction G.
‐ apply subEmpty.
‐ destruct a. apply subCons. apply IHG.
Qed.

Proof. (Theorem sub_Cntx_Reflex) We will again use induction on the con-


text G.
Base case (G = []): In this case, we need to show that subContext [] []
holds. The constructor subEmpty directly provides the proof for this case. In-
ductive step (G = (Decl x E) :: G'): Assuming that subContext G' G'
holds by the induction hypothesis, we want to show that subContext ((Decl
x E) :: G') ((Decl x E) :: G') holds. By the definition of subContext,
we have two constructors: subCons and subInc. In either case, we have shown

13
that subContext ((Decl x E) :: G') ((Decl x E) :: G') holds, com-
pleting the induction step. Therefore, by the principle of induction, we have
proven that subContext G G holds for any context G.
Both properties are important for the correct usage of subcontext in formal
reasoning and manipulation of CoC expressions.
To begin defining the typing rules, we require an additional function to check
the appearance of a variable in a context. The function VarExistence is used
to determine whether an arbitrary variable v is present in a given context C or
not. It returns a boolean value, where true indicates that the variable exists
in the context, and false indicates that it does not.

Fixpoint VarExistence (C : context)(v : variable) : bool :=


match C with
| [] => false
| d :: C' =>
match d with
| Decl a _ => eqb a v || VarExistence C' v
end
end.

Explanation of the code:

1. The function VarExistence takes two arguments: C (the context) and v


(the variable we want to check for existence).
2. It uses a pattern matching construct to handle the different cases of the
context C.

3. If the context is empty (i.e., C = []), the function returns false as there
are no declarations to check.
4. If the context is not empty and contains at least one declaration (i.e., d
:: C'), it proceeds to check the variable v against the variable a in the
declaration d.
5. If the variable v is equal to the variable a in the declaration d (i.e., eqb
a v is true), then the function returns true to indicate that v is present
in the context.
6. If the variable v is not equal to the variable a in the declaration d,
the function recursively calls itself with the rest of the context C' (i.e.,
VarExistence C' v) to continue checking the remaining declarations for
the existence of v.
7. The function uses the || operator to combine the results of the checks for
different declarations. If v is found in any of the declarations, the function
will return true; otherwise, it will return false.

14
3.2 Typing (Derivation) Rules

(sort) ∅⊢∗ : □

Γ⊢A:s
(var)
Γ, x : A ⊢ x : A

Γ⊢A:B Γ⊢C:s
(weak)
Γ, x : C ⊢ A : B

Γ ⊢ A : s1 Γ, x : A ⊢ B : s2
(f orm)
Γ ⊢ Πx : A. B : s2

Γ ⊢ M : Πx : A. B Γ⊢N :A
(appl)
Γ ⊢ M N : B[x := N ]

Γ, x : A ⊢ M : B Γ ⊢ Πx : A. B : s
(abst)
Γ ⊢ λx : A. M : Πx : A. B
Γ⊢A:B Γ ⊢ B′ : s
(conv) if B =β B ′
Γ ⊢ A : B′

Inductive typing : context ‐> expression ‐> expression ‐> Prop :=


(* Sort *)

| sort : typing [] (Star) (Box)

(* Var *)

| varTerm : forall (Gamma :context) (A:expression) (v : variable),


(typing Gamma A (Star)) ‐> (VarExistence Gamma v = false) ‐>
typing (Decl v A::Gamma) (Var v) A
| varType : forall (Gamma :context) (A:expression) (v : variable),
(typing Gamma A (Box)) ‐> (VarExistence Gamma v = false) ‐>
typing (Decl v A::Gamma) (Var v) A

(* Weak *)

| weakTerm : forall (Gamma:context) (A B D:expression)(v : variable),


(typing Gamma A B) ‐> (typing Gamma D (Star)) ‐>
(VarExistence Gamma v = false) ‐> typing (Decl v D::Gamma) A B
| weakType : forall (Gamma:context) (A B D:expression)(v : variable),
(typing Gamma A B) ‐> (typing Gamma D Box) ‐>
(VarExistence Gamma v = false) ‐> typing (Decl v D::Gamma) A B

(* Form *)

15
| formL2 : forall (Gamma:context) (A B : expression)(v : variable),
(typing Gamma A (Star)) ‐> (typing (Decl v A::Gamma) B (Star)) ‐>
typing (Gamma) (PiExp v A B) (Star)
| formLArrow : forall (Gamma:context) (A B : expression)(v : variable),
(typing Gamma A (Box)) ‐> (typing (Decl v A::Gamma) B (Star)) ‐>
typing (Gamma) (PiExp v A B) (Star)
| formLw : forall (Gamma:context) (A B : expression)(v : variable),
(typing Gamma A (Box)) ‐> (typing (Decl v A::Gamma) B (Box)) ‐>
typing (Gamma) (PiExp v A B) (Box)
| formLP : forall (Gamma:context) (A B : expression)(v : variable),
(typing Gamma A (Star)) ‐> (typing (Decl v A::Gamma) B (Box)) ‐>
typing (Gamma) (PiExp v A B) (Box)

(* appl *)

| appl : forall (Gamma:context) (A B M N : expression) (v : variable),


(typing Gamma M (PiExp v A B)) ‐> (typing Gamma N A) ‐>
typing (Gamma) (AppExp M N) (subst B v N)

(* abst *)

| abst : forall (Gamma:context) (A B M : expression) (v : variable) (s : expression),


(s = Star) \/ (s = Box) ‐> (typing ((Decl v A)::Gamma) M B) ‐>
(typing Gamma (PiExp v A B) s) ‐> typing (Gamma) (AbsExp v A M) (PiExp v A B)

(* appl *)

| conv : forall (Gamma:context) (A B B': expression) (s:expression),


(s = Star) \/ (s = Box) ‐> (typing Gamma A B) ‐> (typing Gamma B' s) ‐>
(BetaEquiv B B') ‐> (typing Gamma A B').

The given code defines the typing rules for the Calculus of Constructions
(CoC) using the “typing” relation, which is an inductive predicate that takes
a context, an expression, and its type, and asserts that the expression has the
specified type in the given context.

1. Sort: The first rule states that the expressions Star is of sort Box. This
rule is represented as a constructor sort that takes an empty context and
maps Star(∗) to Box(□).
2. Var: The varTerm and varType rules handle the typing of variables. For
a variable v to be well-typed in the context Gamma, it must have a type A
with sort Star for varTerm and sort Box for varType in the same context.
The VarExistence function is used to ensure that the variable v does not
already exist in the context, preventing shadowing of variable names.

16
3. Weak: The weakTerm and weakType rules are weakening rules that allow
the addition of new variables to the context. For an expression A to
have type B in an extended context with a new variable v and type D,
the original context must already contain the typing of A with B and D
having sorts Star and Box, respectively.

4. Form: The formL2, formLArrow, formLw, and formLP rules handle the
formation of dependent function types (Pi types). These rules allow the
formation of Pi types when the domains A have sort Star or Box, and the
co-domains B have sort Star(∗) or Box(□).
5. Appl: The appl rule handles the application of a function M to an ar-
gument N . For M to be well-typed in context Gamma, it must have type
PiExp v A B, meaning it is a function that takes an argument of type A
and returns a result of type B. The argument N must have type A in the
same context. The result of the application is the substitution of N for
the variable v in B.
6. Abst: The abst rule deals with the abstraction of variables in lambda
expressions. It allows the formation of a lambda abstraction with the
variable v of type A and body M . The s variable represents the sort of
the resulting Pi type, which can be either Star or Box. The typing of M
is checked in an extended context with the variable v and its type A, and
the resulting Pi type should have sort Star or Box accordingly.

7. Conv: The conv rule handles type conversion or conversion between ex-
pressions with different sorts. It allows for the conversion of expression A
to B ′ when B ′ is equivalent to B in the context Gamma and the sorts of B
and B ′ match.

In summary, the typing relation captures the typing rules of the Calculus of
Constructions, ensuring that expressions are well-typed in a given context with
respect to their sorts and types. The use of the VarExistence function helps
maintain the uniqueness of variable names in the context, preventing shadowing
and ambiguity in the typing rules.

4 Properties of CoC
First let’s describe a well-formed context. The wellFormedContext definition
states that a context Gamma is well-formed if there exist expressions A and B
such that the typing relation Γ ⊢ A : B or (typing Gamma A B) holds for them.
Definition wellFormedContext (Gamma : context): Prop :=
exists (A B : expression),(typing Gamma A B).

17
4.1 Thinning Lemma
Let Γ′ and Γ′′ be contexts such that Γ′ ⊆ Γ′′ . If Γ′ ⊢ A : B and Γ′′ is well-formed,
then also Γ′′ ⊢ A : B. The Thinning Lemma is formalized as follows:
Lemma ThinningLemma : forall(Gamma1 Gamma2 : context)(A B : expression),
(subContext Gamma1 Gamma2) ‐>
(typing Gamma1 A B) /\
(wellFormedContext Gamma2) ‐>
(typing Gamma2 A B).
Proof.
Admitted.

4.2 Permutation Lemma


Let Γ and Γ′′ be contexts such that Γ′′ is a permutation of Γ′ . If Γ′ ⊢ A : B and

Γ′′ is well-formed, then also Γ′′ ⊢ A : B. The Permutation Lemma is formalized


as follows:

Lemma PermutationLemma : forall(Gamma1 Gamma2 : context)(A B : expression),


(Permutation Gamma1 Gamma2) ‐>
(typing Gamma1 A B) /\
(wellFormedContext Gamma2) ‐>
(typing Gamma2 A B).
Proof.
Admitted.
Both lemmas provide important results when reasoning about well-typed con-
texts in the Calculus of Constructions. They help to establish the preservation
of well-typed expressions under subcontext and context permutation operations.
However, the proofs of these lemmas are omitted in this context, indicated by
the Admitted keyword. This indicates that the proofs are omitted in this con-
text and can be demonstrated using the current definitions available.

4.3 Generation Lemma


4.3.1 Var Generation
If Γ ⊢ x : C, then there exist a sort s and an expression B such that B =β
C, Γ ⊢ B : s and x : B ∈ Γ. Definition in Coq:
Lemma Generation1: forall (Gamma : context) (x: variable) (C : expression),
(typing Gamma (Var x) C) ‐>
exists (s B : expression),((s = Star) \/
(s = Box)) ‐>
(BetaEquiv B C) /\
(typing Gamma B s) /\
(In (Decl x B) Gamma).

18
Proof. The proof is by induction on the derivation. As a matter of fact, the
lemma just inverts the deduction rules and applies weakening (or thinning): it
considers the shape of the subject term and describes how it could have been
derived. This is by the rule for forming a term of that shape, followed by
applications of conversion and weakening, that don’t change the subject, but
only the context, the environment or the type.

(*Proof of generation1*)
Proof.
intros. remember (Var x) as x0. induction H; try discriminate.
(* (Term) Var Case *)
‐ exists Star. exists A. simpl. intros. split.
‐‐ apply Beta_equiv_symmetry.
‐‐ split.
‐‐‐ apply weakTerm; try apply H. apply H0.
‐‐‐ left.
injection Heqx0. intros. rewrite H2. reflexivity.
(* (Type) Var Case *)
‐ exists Box, A. simpl. intros. split.
‐‐ apply Beta_equiv_symmetry.
‐‐ split.
‐‐‐ apply weakType; try apply H.
‐‐‐‐ apply H0.
‐‐‐ left. injection Heqx0. intros. rewrite H2. reflexivity.
(* (Term) weak case *)
‐ apply IHtyping1 in Heqx0. destruct Heqx0. destruct H2. exists x0, x1.
intros. apply H2 in H3. split.
‐‐ apply H3.
‐‐ split.
‐‐‐ apply weakTerm.
‐‐‐‐ apply H3.
‐‐‐‐ apply H0.
‐‐‐‐ apply H1.
‐‐‐ simpl. right. apply H3.
(* (Type) weak case *)
‐ apply IHtyping1 in Heqx0. destruct Heqx0. destruct H2. exists x0, x1.
intros. apply H2 in H3. split.
‐‐ apply H3.
‐‐ split.
‐‐‐ apply weakType.
‐‐‐‐ apply H3.
‐‐‐‐ apply H0.
‐‐‐‐ apply H1.
‐‐‐ simpl. right. apply H3.
(* Conv case *)
‐ apply IHtyping1 in Heqx0. destruct Heqx0. destruct H3. exists x0, x1.

19
intros. apply H3 in H4. split.
‐‐ destruct H4. apply (MultipleDirection x1 B B' H4 H2).
‐‐ apply H4.
Qed.
The first part of the proof starts with the induction on the typing derivation
(inductive proof of the typing relation). The goal is to prove the existence of
expressions s and B, such that s is either Star or Box, and B is beta-equivalent
to C. Additionally, we need to show that B is well-typed in the context Gamma
with sort s and that the declaration of x with type B is present in the context
Gamma.
1. Base Case: Discrimination If the typing derivation starts with an axiom
or an application, it cannot be matched with the goal of proving the
existence of expressions s and B. Hence, in these cases, we can use the
try discriminate tactic to proceed to other cases.
2. (Term) Var Case: In this case, the derivation starts with either varTerm
or varType rules. We use the remember tactic to give a name x0 to
the expression Var x. Then, we proceed with induction on the typing
derivation. exists Star. exists A. simpl. intros. split.:
• In this part, we introduce the expressions Star and A for the vari-
ables s and B, respectively, and prove that s is Star using the exists
tactic. We also show that A is beta-equivalent to itself using the
Beta_equiv_symmetry theorem.
• Then, we split the goal into three subgoals, corresponding to the
three properties we need to prove:
– Prove that A is well-typed in the context Gamma with sort Star.
(Induction Assumption)
– Prove that the declaration of x with type A is present in the
context Gamma. (Induction Assumption)
– Prove that Star is either Star or Box (which is trivial, as it is
a tautology)
3. (Type) Var Case: This case is similar to the (Term) Var Case but with
different typing rules (varTerm and varType).
4. (Term) weak case: Here, we apply the induction hypothesis (IHtyping1) to
the first subexpression (term) of an application. This allows us to find ex-
pressions x0 and x1 with the desired properties for the first subexpression.
Then, we use these expressions to satisfy the goal.
5. (Type) weak case: This case is similar to the (Term) weak case but with
different typing rules (weakTerm and weakType).
6. Conv case: In this case, we apply the induction hypothesis (IHtyping1)
to the first subexpression (term) of a conversion. This allows us to find

20
expressions x0 and x1 with the desired properties for the first subexpres-
sion. Then, we use these expressions, along with the beta-equivalence of
B and B ′ (proved using the MultipleDirection lemma), to satisfy the
goal.

4.3.2 Application Generation


If Γ ⊢ M N : C, then M has a Π-type, i.e. there exist expressions A and B such
that Γ ⊢ M : Πx : A. B; moreover, N fits in this Π-type: Γ ⊢ N : A, and finally,
C =β B[x := N ]. Definition in Coq:

Lemma Generation2: forall (Gamma : context)(M N C : expression),


(typing Gamma (AppExp M N) C) ‐>
exists (x:variable)(A B : expression),
(typing Gamma M (PiExp x A B)) /\
(typing Gamma N A) /\
BetaEquiv C (subst B x N).

Proof. The proof of Generation2 follows a similar approach to Generation1.


It proceeds by induction on the derivation of the typing relation. The main
idea is to examine the shape of the subject term AppExp M N and describe how
it could have been derived. The proof inverts the deduction rules, considering
each possible case of forming an application expression, followed by applications
of conversion and weakening.

Proof.
intros. remember (AppExp M N) as x0. induction H; try discriminate.
(* weakTerm *)
‐ apply IHtyping1 in Heqx0. destruct Heqx0. destruct H2. destruct H2.
exists x, x0, x1. split. apply weakTerm.
‐‐ apply H2.
‐‐ apply H0.
‐‐ apply H1.
‐‐ split.
‐‐‐ apply weakTerm.
‐‐‐‐ apply H2.
‐‐‐‐ apply H0.
‐‐‐‐ apply H1.
‐‐‐ apply H2.

(* weakType *)
‐ apply IHtyping1 in Heqx0. destruct Heqx0. destruct H2. destruct H2.
exists x, x0, x1. split. apply weakType.
‐‐ apply H2.
‐‐ apply H0.

21
‐‐ apply H1.
‐‐ split.
‐‐‐ apply weakType.
‐‐‐‐ apply H2.
‐‐‐‐ apply H0.
‐‐‐‐ apply H1.
‐‐‐ apply H2.

(* appl *)
‐ injection Heqx0. intros. exists v, A, B. rewrite <‐ H1. rewrite <‐ H2.
split.
‐‐ apply H.
‐‐ split.
‐‐‐ apply H0.
‐‐‐ apply Beta_equiv_symmetry.

(* Conv *)
‐ apply IHtyping1 in Heqx0. destruct Heqx0. destruct H3. destruct H3.
exists x, x0, x1. split.
‐‐ apply H3.
‐‐ split.
‐‐‐ apply H3.
‐‐‐ destruct H3. destruct H4.
apply (MultipleDirection B' B (subst x1 x N) \\
((OneDirectionLeft B B' H2)) H5).
Qed.

1. (Term) weak case: In this case, we apply the induction hypothesis (IHtyp-
ing1) to the first subexpression (term) of an application. This allows us to
find expressions x0 and x1 with the desired properties for the first subex-
pression. Then, we use these expressions to satisfy the goal.
2. (Type) weak case: This case is similar to the (Term) weak case but with
different typing rules (weakTerm and weakType).
3. appl case: In this case, the derivation starts with the appl rule, which
states that if M has a type PiExp x A B and N has a type A in the
context Gamma, then AppExp M N has a type subst B x N in Gamma. We
use the injection tactic to rewrite the goal and find expressions v, A,
and B with the desired properties.
4. Conv case: In this case, we apply the induction hypothesis (IHtyping1)
to the first subexpression (term) of a conversion. This allows us to find
expressions x0 and x1 with the desired properties for the first subexpres-
sion. Then, we use these expressions, along with the beta-equivalence of
B and B ′ (proved using the MultipleDirection lemma), to satisfy the
goal.

22
4.3.3 Abstraction Generation
If Γ ⊢ λx : A. b : C, then there are a sort s and an expression B such that
C =β Πx : A. B, where Γ ⊢ Πx : A. B : s. Definition in Coq:
Lemma Generation3: forall (Gamma : context)(x:variable)(A b C: expression),
(typing Gamma (AbsExp x A b) C) ‐>
exists (s : expression)(B:expression),((s = Star) \/
(s = Box)) ‐>
(typing Gamma (PiExp x A B) s) /\
(BetaEquiv C (PiExp x A B)).
Proof. The proof starts by considering each possible case of forming an abstrac-
tion expression AbsExp x A b and applies the induction hypothesis to the first
subexpression b. For each case, we need to consider the possibility of weakening,
where the type B might change in the new context.

Proof.
intros. remember (AbsExp x A b) as x0. induction H; try discriminate.

(* WeakTerm *)

‐ apply IHtyping1 in Heqx0. destruct Heqx0. destruct H2.


exists x0, x1. intros. split.
‐‐ apply weakTerm.
‐‐‐ apply H2. apply H3.
‐‐‐ apply H0.
‐‐‐ apply H1.
‐‐ apply H2. apply H3.

(* WeakType *)

‐ apply IHtyping1 in Heqx0. destruct Heqx0. destruct H2.


exists x0, x1. intros. split.
‐‐ apply weakType.
‐‐‐ apply H2. apply H3.
‐‐‐ apply H0.
‐‐‐ apply H1.
‐‐ apply H2. apply H3.
(* Abs *)

‐ injection Heqx0. intros. exists s, B. intros.


rewrite <‐ H3. rewrite <‐ H4. split.
‐‐ apply H1.
‐‐ apply Beta_equiv_symmetry.

23
‐ apply IHtyping1 in Heqx0. destruct Heqx0. destruct H3.
exists x0, x1. intros. apply H3 in H4. split.
‐‐ apply H4.
‐‐ destruct H4. apply (MultipleDirection B' B (PiExp x A x1) \\
((OneDirectionLeft B B' H2)) H5).
Qed.

1. WeakTerm Case: The induction hypothesis is applied to the premise


typing Gamma (AbsExp x A b) Star. This gives us an expression x0
and a type x1 such that typing Gamma b x1 and BetaEquiv Star x1.
We then choose x0 as the sort s and x1 as the type B.
2. WeakType Case: Similar to the previous case, the induction hypothesis is
applied to typing Gamma (AbsExp x A b) Box, resulting in an expres-
sion x0 and a type x1 satisfying typing Gamma b x1 and BetaEquiv
Box x1. We choose x0 as the sort s and x1 as the type B.
3. Abs Case: In this case, we apply the induction hypothesis directly to
typing (Decl x A::Gamma) b B, which gives us a type s and an ex-
pression B such that typing (Decl x A::Gamma) b B and BetaEquiv
C B. We use s as the sort and B as the type.

4. Conv Case: Here, we apply the induction hypothesis to typing Gamma


(AbsExp x A b) B', where BetaEquiv C B'. We get x0 and x1 such
that typing Gamma b x1 and BetaEquiv B' x1. Using x0 as the sort
and x1 as the type, we apply the MultipleDirection lemma to prove
BetaEquiv C (PiExp x A x1).

Overall, the proof inverts the deduction rules for abstraction expressions and
uses the induction hypothesis to find appropriate types and expressions for
the abstraction, while considering the possibility of weakening or changing the
context when needed. The result is the existence of an appropriate type B and
sort s such that the subject AbsExp x A b can be seen as a Pi-type PiExp x
A B with sort s, and C is beta-equivalent to PiExp x A B.

4.3.4 Pi Generation
If Γ ⊢ Πx : A. B : C, then there are s1 and s2 such that C ≡ s2 , and moreover:
Γ ⊢ A : s1. Definition in Coq:

Lemma Generation4: forall (Gamma : context)(x : variable)(A B C: expression),


(typing Gamma (PiExp x A B) C) ‐>
exists (s1 s2 : expression),
((s1 = Star) \/ (s1 = Box)) ‐>
((s2 = Star) \/ (s2 = Box)) ‐>
(BetaEquiv s2 C) /\
(typing Gamma A s1).

24
Proof. The Generation4 proof involves an induction on the derivation of the
typing relation. The goal is to find expressions s1 and s2 such that the subject
PiExp x A B can be considered as a Pi-type with sort s1 , and C can be con-
sidered as a sort s2 . Additionally, we want to show that C is beta-equivalent to
s2 , and A is of sort s1.

intros. remember (PiExp x A B) as D. induction H; try discriminate.


(* WeakTerm *)
‐ destruct IHtyping1. apply HeqD. destruct H2. exists x0, x1.
intros. apply H2 in H3. split.
‐‐ apply H3.
‐‐ apply weakTerm.
‐‐‐‐ apply H3.
‐‐‐‐ apply H0.
‐‐‐‐ apply H1.
‐‐ apply H4.
(* WeakType *)
‐ destruct IHtyping1. apply HeqD. destruct H2. exists x0, x1.
intros. apply H2 in H3. split.
‐‐ apply H3.
‐‐ apply weakType.
‐‐‐‐ apply H3.
‐‐‐‐ apply H0.
‐‐‐‐ apply H1.
‐‐ apply H4.
(* Form1 *)
‐ inversion HeqD. exists Star, Star. intros.
split.
‐‐ apply Beta_equiv_symmetry.
‐‐ rewrite <‐ H3. apply H.
(* Form2 *)
‐ inversion HeqD. exists Box, Star . intros. split.
‐‐ apply Beta_equiv_symmetry.
‐‐ rewrite <‐ H3. apply H.
(* Form3 *)
‐ inversion HeqD. exists Box, Box . intros. split.
‐‐ apply Beta_equiv_symmetry.
‐‐ rewrite <‐ H3. apply H.
(* Form4 *)
‐ inversion HeqD. exists Star, Box . intros. split.
‐‐ apply Beta_equiv_symmetry.
‐‐ rewrite <‐ H3. apply H.
(* Conv *)
‐ apply IHtyping1 in HeqD. destruct HeqD. destruct H3.
exists x0, x1. intros. apply H3 in H4. destruct H4. split.
‐‐ apply (MultipleDirection x1 B0 B' H4 H2).

25
‐‐ apply H6.
‐‐ apply H5.
Qed.

1. WeakTerm Case: The induction hypothesis is applied to typing Gamma


(PiExp x A B) Star, resulting in expressions x0 and x1 satisfying typing
Gamma A x0 and BetaEquiv Star x1. We choose x0 and x1 as s1 and
s2 , respectively, and then apply the induction hypothesis to prove the
desired result.
2. WeakType Case: Similar to the previous case, the induction hypothesis
is applied to typing Gamma (PiExp x A B) Box, yielding expressions
x0 and x1 satisfying typing Gamma A x0 and BetaEquiv Box x1. We
choose x0 and x1 as s1 and s2 , respectively, and then apply the induction
hypothesis to prove the desired result.
3. Form1 Case: In this case, PiExp x A B is already of sort Star, and we
know that A must also have sort Star. We choose Star for both s1 and s2 ,
and the result follows directly from the Form1 rule of the typing relation.
4. Form2 Case: In this case, PiExp x A B is of sort Box, and we know that
A must have sort Star. We choose Box for s1 and Star for s2 . Then, we
apply the induction hypothesis to typing Gamma A Star, which yields x0
and x1 satisfying typing Gamma A x0 and BetaEquiv Star x1. Since
s2 = Star and BetaEquiv Star x1, we have the desired result.
5. Form3 Case: Similar to the previous case, we choose Box for both s1 and
s2 . Then, by applying the induction hypothesis to typing Gamma A Box,
we obtain the desired result.
6. Form4 Case: Similar to the Form2 and Form3 cases, we choose Star for
s1 and Box for s2 . Then, by applying the induction hypothesis to typing
Gamma A Box, we obtain the desired result.
7. Conv Case: The induction hypothesis is applied to typing Gamma (PiExp
x A B) x2, where x2 is an arbitrary sort (Star or Box). We get expres-
sions x0 and x1 such that typing Gamma A x0 and BetaEquiv x2 x1.
We choose x0 and x1 as s1 and s2 , respectively, and then apply the induc-
tion hypothesis to typing Gamma x1 x2, which yields the desired result.

Conclusion
In conclusion, this article presents a formalization of the Lambda C (CoC)
language in Coq, covering various essential aspects such as expressions, beta
equivalence, and typing rules. By providing rigorous definitions and proofs, we
have established a solid foundation for reasoning about the Lambda C language

26
within the Coq proof assistant. The Generation lemma, as one of the key re-
sults, sheds light on the derivation process and demonstrates the power of Coq
in verifying the language’s properties. Additionally, numerous other lemmas
and tests can be further explored to bolster our confidence in the correctness
and completeness of the formalization. This work not only advances our under-
standing of Lambda C but also showcases the effectiveness of Coq as a powerful
tool for formal verification and reasoning about complex languages and systems.

References
[1] Documentation | the coq proof assistant. https://coq.inria.fr/
documentation. (Accessed on 07/24/2023).

[2] Henk Barendregt, S. Abramsky, D. Gabbay, T. Maibaum, and Henk (Hen-


drik) Barendregt. Lambda calculi with types. 10 2000.
[3] Herman Geuvers. Properties of a lambda calculus with definitions.
http://www.cs.ru.nl/~herman/PUBS/PropLamCDef.pdf. (Accessed on
07/24/2023).

[4] The Coq development team. The Coq proof assistant reference manual,
2004. Version 8.0.
[5] Rob Nederpelt and Herman Geuvers. Type Theory and Formal Proof: An
Introduction. Cambridge University Press, 2014.

27

You might also like