在简单类型的 lambda 演算中类型推导是唯一的证明在纸上是微不足道的。我熟悉的证明是通过对类型推导的完全归纳来进行的。但是,我无法证明通过类型派生类型表示的类型派生是唯一的。在这里,如果变量的类型为 environment ,则谓词dec Γ x τ
为真。类型谓词像往常一样定义,只需读取简单类型 lambda 演算的类型规则:x
τ
Γ
J
Inductive J (Γ : env) : term → type → Set :=
| tvar : ∀ x τ, dec Γ x τ → J γ (var x) τ
| tabs : ∀ τ₁ τ₂ e, J (τ₁ :: γ) e τ₂ → J γ (abs τ₁ e) (arr τ₁ τ₂)
| tapp : ∀ τ₁ τ₂ e₁ e₂, J γ e₁ (arr τ₁ τ₂) → J γ e₂ τ₁ → J γ (app e₁ e₂) τ₂.
J
在证明类型派生是唯一的时,我无法暴露类型术语的结构。例如,我可以对以下引理中的任何一个d1
或d2
在其中进行归纳,但不能对d1
then destruct进行归纳d2
,反之亦然。Coq 给出的错误消息(对术语进行抽象会导致输入错误的术语)有点模糊,并且 Coq wiki 没有提供任何帮助。作为参考,这是我试图证明的引理:
Lemma unique_derivation : ∀ Γ e τ (d₁ d₂ : J Γ e τ), d₁ = d₂.
在归纳术语时我没有问题,例如,在证明类型是唯一的时。
编辑:我添加了最少数量的定义来说明我遇到问题的结果。作为对 huitseeker 评论的回应,之所以选择这种类型J
是因为我想将派生类型作为结构化对象进行推理,以便执行提取等操作并证明唯一性等结果,这是我以前在 Coq 中没有做过的。
针对评论的第一部分,我可以执行induction
or d1
,d2
但执行后induction
我不能使用destruct
, case
, orinduction
剩下的术语。这意味着我不能公开两者的结构,d1
并且无法d2
对这两个证明树进行推理。当我尝试这样做时收到的错误表明,对剩余术语进行抽象会导致术语输入错误。
Require Import Unicode.Utf8.
Require Import Utf8_core.
Require Import List.
Inductive type : Set :=
| tau : type
| arr : type → type → type.
Inductive term : Set :=
| var : nat → term
| abs : type → term → term
| app : term → term → term.
Definition dec (Γ : list type) x τ : Prop :=
nth_error γ x = Some τ.
Inductive J (Γ : list type) : term → type → Set :=
| tvar : ∀ x τ, dec Γ x τ → J Γ (var x) τ
| tabs : ∀ τ₁ τ₂ e, J (τ₁ :: Γ) e τ₂ → J Γ (abs τ₁ e) (arr τ₁ τ₂)
| tapp : ∀ τ₁ τ₂ e₁ e₂, J Γ e₁ (arr τ₁ τ₂) → J Γ e₂ τ₁ → J Γ (app e₁ e₂) τ₂.
Lemma derivations_unique : ∀ Γ e τ (d1 d2 : J Γ e τ), d1 = d2.
Proof. admit. Qed.
我已经尝试过从库中获得dependent induction
一些结果Coq.Logic
,但没有成功。推导是独一无二的,这似乎是一个容易证明的命题。