揭示coq中归纳定义项的结构

时间:2012-09-05 05:04:54

标签: lambda-calculus coq

在简单类型的lambda演算中输入推导是唯一的证据在纸面上是微不足道的。我熟悉的证据是通过对输入派生的完全归纳来进行的。但是,我无法证明键入派生,表示通过类型的输入派生,是唯一的。如果变量dec Γ x τ在环境x中的类型为τ,则谓词Γ为true。打字谓词J是通常定义的,只需读取简单类型的lambda演算的输入规则:

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的结构。例如,我可以在以下引理中引入d1d2,但不能在d1上导入,然后在相反的情况下破坏d2。 Coq给出的错误消息(抽象术语导致一个类型错误的术语)有点模糊,而Coq wiki没有提供任何帮助。作为参考,这是我试图证明的引理:

Lemma unique_derivation : ∀ Γ e τ (d₁ d₂ : J Γ e τ), d₁ = d₂.

在引入条款时我没有问题,例如,在证明类型是唯一的时候。

编辑:我添加了说明我遇到问题的结果所需的最少数量的定义。为了回应huitseeker的评论,选择了J,因为我想推断将派生类型作为结构化对象来进行,以便执行提取等操作并证明结果如唯一性,这在我之前没有在Coq中完成。

在回复评论的第一部分时,我可以inductiond1执行d2,但执行induction我无法在剩余的期限内使用destructcaseinduction。这意味着我无法公开d1d2的结构以推理两个证明树。我在尝试这样做时收到的错误表示,对剩余的术语进行抽象会导致一个类型错误的术语。

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 inductionCoq.Logic库中的一些结果,但没有成功。这些推导是独一无二的,似乎应该是一个容易证明的命题。

1 个答案:

答案 0 :(得分:1)

你有三个问题。

一个是使感应工作的纯粹技术问题。您可以使用dependent destruction策略解决主要难题(由Matthieu Sozeau on the Coq-Club mailing list提供)。这是一种反转策略。我不会假装了解它是如何工作的。

第二个困难是在一个基本案例中,对于环境。您需要证明list nat中的等式证明是唯一的;这适用于所有可判定的域,其工具位于Eqdep_dec模块中。

第三个困难是与问题有关。推导的唯一性并不依赖于对术语或派生结构的直接归纳,因为您的术语没有足够的类型信息来重构派生。在应用程序app e1 e2中,没有直接的方法来了解参数的类型。在简单类型的lambda演算中,类型重建确实成立,并且很容易证明;在较大的计算(具有多态或子类型)中,它可能不成立(例如,使用ML样式的多态,有一个唯一的类型方案和相关的派生,但有很多使用基类型的派生)

这是你的引理的快速证明。我省略了环境查找的单一性证明。你可以引入术语结构或派生结构 - 这个简单的证明是有效的,因为它们是相同的。

Require Import Unicode.Utf8.
Require Import Utf8_core.
Require Import List.
Require Import Program.Equality.

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 unique_variable_type :
  forall G x t1 t2, dec G x t1 -> dec G x t2 -> t1 = t2.
Proof.
  unfold dec; intros.
  assert (value t1 = value t2). congruence.
  inversion H1. reflexivity.
Qed.

Axiom unique_variable_type_derivation :
  forall G x t (d1 d2 : dec G x t), d1 = d2.

Lemma unique_type : forall G e t1 t2 (d1 : J G e t1) (d2 : J G e t2), t1 = t2.
Proof.
  intros G e; generalize dependent G.
  induction e; intros.

  dependent destruction d1. dependent destruction d2.
  apply (unique_variable_type G n); assumption.

  dependent destruction d1. dependent destruction d2.
  firstorder congruence.

  dependent destruction d1. dependent destruction d2.
  assert (arr τ₁ τ₂ = arr τ₁0 τ₂0).
  firstorder congruence.
  congruence.
Qed.

Lemma unique_derivation : forall G e t (d1 d2 : J G e t), d1 = d2.
Proof.
  intros G e; generalize dependent G.
  induction e; intros.

  dependent destruction d1. dependent destruction d2.
  f_equal. solve [apply (unique_variable_type_derivation G n)].

  dependent destruction d1. dependent destruction d2.
  f_equal. solve [apply IHe].

  dependent destruction d1. dependent destruction d2.
  assert (τ₁ = τ₁0). 2: subst τ₁.
  solve [eapply unique_type; eauto].
  f_equal; solve [firstorder].
Qed.