Types类型系统
Set Warnings "-notation-overridden,-parsing".
From Coq Require Import Arith.Arith.
From PLF Require Import Maps.
From PLF Require Import Imp.
From PLF Require Import Smallstep.
Hint Constructors multi.
有类型算数表达式
Inductive tm : Type :=
| tru : tm
| fls : tm
| test : tm → tm → tm → tm
| zro : tm
| scc : tm → tm
| prd : tm → tm
| iszro : tm → tm.
对'值(values)'的定义包括 tru,fls 以及数值……
Inductive bvalue : tm → Prop :=
| bv_tru : bvalue tru
| bv_fls : bvalue fls.
Inductive nvalue : tm → Prop :=
| nv_zro : nvalue zro
| nv_scc : ∀ t, nvalue t → nvalue (scc t).
Definition value (t : tm) := bvalue t ∨ nvalue t.
Hint Constructors bvalue nvalue.
Hint Unfold value.
Hint Unfold update.
操作语义
(ST_TestTru) | |
test tru then t1 else t2 --> t1 |
(ST_TestFls) | |
test fls then t1 else t2 --> t2 |
t1 --> t1' | (ST_Test) |
test t1 then t2 else t3 --> test t1' then t2 else t3 |
t1 --> t1' | (ST_Scc) |
scc t1 --> scc t1' |
(ST_PrdZro) | |
prd zro --> zro |
numeric value v1 | (ST_PrdScc) |
prd (scc v1) --> v1 |
t1 --> t1' | (ST_Prd) |
prd t1 --> prd t1' |
(ST_IszroZro) | |
iszro zro --> tru |
numeric value v1 | (ST_IszroScc) |
iszro (scc v1) --> fls |
t1 --> t1' | (ST_Iszro) |
iszro t1 --> iszro t1' |
Reserved Notation "t1 '-->' t2" (at level 40).
Inductive step : tm → tm → Prop :=
| ST_TestTru : ∀ t1 t2,
(test tru t1 t2) --> t1
| ST_TestFls : ∀ t1 t2,
(test fls t1 t2) --> t2
| ST_Test : ∀ t1 t1' t2 t3,
t1 --> t1' →
(test t1 t2 t3) --> (test t1' t2 t3)
| ST_Scc : ∀ t1 t1',
t1 --> t1' →
(scc t1) --> (scc t1')
| ST_PrdZro :
(prd zro) --> zro
| ST_PrdScc : ∀ t1,
nvalue t1 →
(prd (scc t1)) --> t1
| ST_Prd : ∀ t1 t1',
t1 --> t1' →
(prd t1) --> (prd t1')
| ST_IszroZro :
(iszro zro) --> tru
| ST_IszroScc : ∀ t1,
nvalue t1 →
(iszro (scc t1)) --> fls
| ST_Iszro : ∀ t1 t1',
t1 --> t1' →
(iszro t1) --> (iszro t1')
where "t1 '-->' t2" := (step t1 t2).
Hint Constructors step.
请注意 step 关系并不在意步进表达式是否有全局意义——它只是检查'下一步'
的归约操作是否在正确的操作对象上。比如,项 succ true
无法前进一步,但这个几乎显然无意义的项
scc (test tru then tru else tru)
却可以前进一步(注意是在卡住之前)。
scc (test tru then tru else tru)
正规式和值
Notation step_normal_form := (normal_form step).
Definition stuck (t : tm) : Prop :=
step_normal_form t ∧ ¬ value t.
Hint Unfold stuck.
练习:3 星, standard (value_is_nf)
(提示:在证明中的某个地方,你需要使用归纳来推理某个项,这个项已知是数值。
归纳可以对项本身进行,也可以对它是数值这个证据进行。两种方法均可完成证明,
但你发现一种要比另一种稍微简短一点。作为练习,请尝试使用这两种方法完成证明。) ☐
练习:3 星, standard, optional (step_deterministic)
使用 value_is_nf 来证明 step 关系是确定的。定型
在非形式化的记号中,类型关系经常写做 ⊢ t \in T,并读做“t 有类型 T”。
⊢ 符号叫做“十字转门(turnstile)”。下面,我们会看到更加丰富的类型关系,其中
我们会在 ⊢ 左侧添加一个或多个“上下文(context)”。目前暂时来说,上下文总是空的。
(T_Tru) | |
⊢ tru ∈ Bool |
(T_Fls) | |
⊢ fls ∈ Bool |
⊢ t1 ∈ Bool ⊢ t2 ∈ T ⊢ t3 ∈ T | (T_Test) |
⊢ test t1 then t2 else t3 ∈ T |
(T_Zro) | |
⊢ zro ∈ Nat |
⊢ t1 ∈ Nat | (T_Scc) |
⊢ scc t1 ∈ Nat |
⊢ t1 ∈ Nat | (T_Prd) |
⊢ prd t1 ∈ Nat |
⊢ t1 ∈ Nat | (T_IsZro) |
⊢ iszro t1 ∈ Bool |
Reserved Notation "'⊢' t '∈' T" (at level 40).
Inductive has_type : tm → ty → Prop :=
| T_Tru :
⊢ tru \in Bool
| T_Fls :
⊢ fls \in Bool
| T_Test : ∀ t1 t2 t3 T,
⊢ t1 \in Bool →
⊢ t2 \in T →
⊢ t3 \in T →
⊢ test t1 t2 t3 \in T
| T_Zro :
⊢ zro \in Nat
| T_Scc : ∀ t1,
⊢ t1 \in Nat →
⊢ scc t1 \in Nat
| T_Prd : ∀ t1,
⊢ t1 \in Nat →
⊢ prd t1 \in Nat
| T_Iszro : ∀ t1,
⊢ t1 \in Nat →
⊢ iszro t1 \in Bool
where "'⊢' t '∈' T" := (has_type t T).
Hint Constructors has_type.
Example has_type_1 :
⊢ test fls zro (scc zro) \in Nat.
Proof.
apply T_Test.
- apply T_Fls.
- apply T_Zro.
- apply T_Scc.
+ apply T_Zro.
Qed.
(因为我们在提示数据库(hint database)中包括了类型关系的所有构造子,
因此 auto 策略可以自动完成这个证明。)
重要的一点是认识到类型关系是一个'保守的(conservative)'
(或'静态的(static)')近似:它不考虑项被归约时会发生什么——特别地,
它并不计算项的正规式的类型。
Example has_type_not :
¬ ( ⊢ test fls zro tru \in Bool ).
Proof.
intros Contra. solve_by_inverts 2. Qed.
intros Contra. solve_by_inverts 2. Qed.
Example scc_hastype_nat__hastype_nat : ∀ t,
⊢ scc t \in Nat →
⊢ t \in Nat.
Proof.
(* 请在此处解答 *) Admitted.
☐
⊢ scc t \in Nat →
⊢ t \in Nat.
Proof.
(* 请在此处解答 *) Admitted.
☐
Lemma bool_canonical : ∀ t,
⊢ t \in Bool → value t → bvalue t.
Proof.
intros t HT [Hb | Hn].
- assumption.
- induction Hn; inversion HT; auto.
Qed.
intros t HT [Hb | Hn].
- assumption.
- induction Hn; inversion HT; auto.
Qed.
Lemma nat_canonical : ∀ t,
⊢ t \in Nat → value t → nvalue t.
Proof.
intros t HT [Hb | Hn].
- inversion Hb; subst; inversion HT.
- assumption.
Qed.
intros t HT [Hb | Hn].
- inversion Hb; subst; inversion HT.
- assumption.
Qed.
可进性
练习:3 星, standard (finish_progress)
请完成 progress 性质的形式化证明。(在开始前请确保你理解了下一个练习中的非
形式化证明——这会节省很多你的时间。)
Proof with auto.
intros t T HT.
induction HT...
(* 对于显然是值的情形,比如 T_Tru 和 T_Fls,我们直接使用 auto 完成。*)
- (* T_Test *)
right. inversion IHHT1; clear IHHT1.
+ (* t1 是值 *)
apply (bool_canonical t1 HT1) in H.
inversion H; subst; clear H.
∃ t2...
∃ t3...
+ (* t1 可前进一步 *)
inversion H as [t1' H1].
∃ (test t1' t2 t3)...
(* 请在此处解答 *) Admitted.
intros t T HT.
induction HT...
(* 对于显然是值的情形,比如 T_Tru 和 T_Fls,我们直接使用 auto 完成。*)
- (* T_Test *)
right. inversion IHHT1; clear IHHT1.
+ (* t1 是值 *)
apply (bool_canonical t1 HT1) in H.
inversion H; subst; clear H.
∃ t2...
∃ t3...
+ (* t1 可前进一步 *)
inversion H as [t1' H1].
∃ (test t1' t2 t3)...
(* 请在此处解答 *) Admitted.
☐
'定理':如果 ⊢ t \in T,那么 t 要么是值,要么存在某个 t' 使 t --> t'。
'证明':对 ⊢ t \in T 的导出式进行归纳。
练习:3 星, advanced (finish_progress_informal)
请完成非形式化的证明:- 如果导出式的最后一条规则是 T_Test,那么 t = test t1 then t2 else t3,
其中 ⊢ t1 \in Bool,⊢ t2 \in T 以及 ⊢ t3 \in T。
根据归纳假设,t1 要么是值,要么可前进一步到某个 t1'。
- 如果 t1 是值,那么根据典范形式(canonical forms)引理以及
⊢ t1 \in Bool 的事实,可得 t1 是一个 bvalue——也即,
它要么是 tru 要么是 fls。如果 t1 = tru,由 ST_TestTru
可得 t 前进到 t2;而当 t1 = fls 时,由 ST_TestFls
可得 t 前进到 t3。不论哪种情况,t 都可以前进一步,这是我们
想要证明的。
- 如果 t1 自己可以前进一步,那么根据 ST_Test 可得 t 也可以。
- (* 请在此处解答 *)
(* 请勿修改下面这一行: *)
Definition manual_grade_for_finish_progress_informal : option (nat×string) := None.
☐
Definition manual_grade_for_finish_progress_informal : option (nat×string) := None.
☐
请完成 preservation 性质的形式化证明。(和上次一样,在开始前请确保你理解了
下一个练习中的非形式化证明。)
Proof with auto.
intros t t' T HT HE.
generalize dependent t'.
induction HT;
(* 每个情形都需要引入一些东西 *)
intros t' HE;
(* 我们还需要处理一些不可能发生的情形 *)
try solve_by_invert.
- (* T_Test *) inversion HE; subst; clear HE.
+ (* ST_TESTTru *) assumption.
+ (* ST_TestFls *) assumption.
+ (* ST_Test *) apply T_Test; try assumption.
apply IHHT1; assumption.
(* 请在此处解答 *) Admitted.
intros t t' T HT HE.
generalize dependent t'.
induction HT;
(* 每个情形都需要引入一些东西 *)
intros t' HE;
(* 我们还需要处理一些不可能发生的情形 *)
try solve_by_invert.
- (* T_Test *) inversion HE; subst; clear HE.
+ (* ST_TESTTru *) assumption.
+ (* ST_TestFls *) assumption.
+ (* ST_Test *) apply T_Test; try assumption.
apply IHHT1; assumption.
(* 请在此处解答 *) Admitted.
☐
'定理':如果 ⊢ t \in T 且 t --> t',那么 ⊢ t' \in T。
'证明':对 ⊢ t \in T 的导出式进行归纳。
练习:3 星, advanced (finish_preservation_informal)
请完成非形式化的证明:- 如果导出式的最后一条规则是 T_Test,那么 t = test t1
then t2 else t3,其中 ⊢ t1 \in Bool, ⊢ t2 \in T 以及 ⊢ t3
\in T。
- 如果最后的规则是 ST_TestTru,那么 t' = t2。但是我们有
⊢ t2 \in T,所以证明完成。
- 如果最后的规则是 ST_TestFls,那么 t' = t3。但是我们有
⊢ t3 \in T,所以证明完成。
- 如果最后的规则是 ST_Test,那么 t' = test t1' then t2
else t3,其中 t1 --> t1'。我们知道 ⊢ t1 \in Bool,
因此根据归纳假设可得 ⊢ t1' \in Bool。正如需要的那样,规则
T_Test 为我们提供了 ⊢ test t1' then t2 else t3 \in T。
- (* 请在此处解答 *)
(* 请勿修改下面这一行: *)
Definition manual_grade_for_finish_preservation_informal : option (nat×string) := None.
☐
Definition manual_grade_for_finish_preservation_informal : option (nat×string) := None.
☐
练习:3 星, standard (preservation_alternate_proof)
现在请对'求值'导出式(而非类型导出式)进行归纳来证明保型性定理。 请仔细阅读和思考上面证明中最开始的几行,确保你理解了他们是在做什么。 本证明的开始部分类似,但并不完全一样。Theorem preservation' : ∀ t t' T,
⊢ t \in T →
t --> t' →
⊢ t' \in T.
Proof with eauto.
(* 请在此处解答 *) Admitted.
☐
Definition multistep := (multi step).
Notation "t1 '-->*' t2" := (multistep t1 t2) (at level 40).
Corollary soundness : ∀ t t' T,
⊢ t \in T →
t -->* t' →
~(stuck t').
Proof.
intros t t' T HT P. induction P; intros [R S].
destruct (progress x T HT); auto.
apply IHP. apply (preservation x y T HT H).
unfold stuck. split; auto. Qed.
intros t t' T HT P. induction P; intros [R S].
destruct (progress x T HT); auto.
apply IHP. apply (preservation x y T HT H).
unfold stuck. split; auto. Qed.
额外练习
练习:2 星, standard, recommended (subject_expansion)
在学习了主语归约属性后,你可能会好奇其相反的属性——主语'扩张'(subject expasion) ——是否也成立。也即,如果有 t --> t' 且 ⊢ t' \in T,是否总是有 ⊢ t \in T?如果是的话,请证明它。如果不是的话,请给出一个反例。 (你并不需要在 Coq 中证明你的反例,不过也可以这样做。)练习:2 星, standard (variation1)
假设我们为类型关系添加新的规则:| T_SccBool : ∀ t,
⊢ t \in Bool →
⊢ scc t \in Bool
- step 的确定性
(* 请在此处解答 *)
- 可进性
(* 请在此处解答 *)
- 保型性
(* 请在此处解答 *)
练习:2 星, standard (variation2)
假设,我们仅为 step 关系添加新的规则:| ST_Funny1 : ∀ t2 t3,
(test tru t2 t3) --> t3
练习:2 星, standard, optional (variation3)
假设,我们仅添加新的规则:| ST_Funny2 : ∀ t1 t2 t2' t3,
t2 --> t2' →
(test t1 t2 t3) --> (test t1 t2' t3)
☐
练习:2 星, standard, optional (variation4)
假设,我们仅添加新的规则:| ST_Funny3 :
(prd fls) --> (prd (prd fls))
☐
练习:2 星, standard, optional (variation5)
假设,我们仅添加新的规则:| T_Funny4 :
⊢ zro \in Bool
☐
练习:2 星, standard, optional (variation6)
假设,我们仅添加新的规则:| T_Funny5 :
⊢ prd zro \in Bool
☐
练习:3 星, standard, optional (more_variations)
请使用上面的模式编写更多的练习。尝试有选择地使某些性质不再成立—— 即,对定义的改变只会导致某一个性质不再成立,而其他仍然成立。
(* 请在此处解答 *)
☐
☐
练习:1 星, standard (remove_prdzro)
归约规则 ST_PrdZro 可能有一点反直觉:我们想要让 zro 的前趋变为未定义的, 而非定义为 zro。我们是否可以通过仅仅移除 step 中的某条规则达到这一点? 这样做会导致别的问题出现吗?练习:4 星, advanced (prog_pres_bigstep)
假设我们的求值关系是以大步语义方式定义的。请陈述类似的可进性和保型性定理。 (你不需要证明他们。)(* 2022-03-14 05:28:22 (UTC+00) *)