使用coq反演策略的矛盾假设

时间:2018-05-22 16:55:44

标签: coq proof coq-tactic

从这个例子:

def getObject: ConnectionIO[Request]                      = ???
def saveObject(obj: Request): ConnectionIO[Request]       = ???
def processObject(obj: Request): monix.eval.Task[Request] = ???

val transaction: ConnectionIO[Request] = for {
    obj       <- getObject                                           //ConnectionIO[Request]
    processed <- Async[ConnectionIO].liftIO(processObject(obj).toIO) //ConnectionIO[Request]
    updated   <- saveObject(processed)                               //ConnectionIO[Request]
} yield updated
val result: Task[Request] = transaction.transact(xa)

只需在第二个假设上做Example foo : forall (X : Type) (x y z : X) (l j : list X), x :: y :: l = z :: j -> y :: l = x :: j -> x = y. 即可解决:

inversion

然而,在第一个假设中做Proof. intros X x y z l j eq1 eq2. inversion eq2. reflexivity. Qed. ,产生了明显矛盾的假设:

inversion

因为,在最后一个证据中,生成的假设是:

Proof.
  intros X x y z l j eq1 eq2. inversion eq2. inversion eq1. reflexivity. Qed.

但是,如果我没有遗漏一些明显的东西,那么H0 : y = x H1 : l = j H2 : x = z H3 : y :: l = j H1都不可能同时成立。

有人可以解释一下发生了什么吗?仅仅是这个例子是“糟糕的设计”(这两个假设都是矛盾的)而Coq倒置策略只是吞下它们吗?它是基于两个假设一起考虑的爆炸原理吗?如果是这样,那么仅仅通过从虚假中得出任何东西来证明这个例子是否可能?怎么样?

1 个答案:

答案 0 :(得分:3)

你的例子是假设相互矛盾的假设:它们暗示length l + 2等于length l + 1

Require Import Coq.Lists.List.
Require Import Omega.

Example foo : forall (X : Type) (x y z : X) (l j : list X),
  x :: y :: l = z :: j ->
  y :: l = x :: j ->
  x = y.
Proof.
  intros X x y z l j eq1 eq2.
  apply (f_equal (@length _)) in eq1.
  apply (f_equal (@length _)) in eq2.
  simpl in *.
  omega.
Qed.

根据爆炸原理,Coq能够得出一个矛盾的背景并不奇怪。

除了这种小怪异之外,所产生的假设是矛盾的这一事实并没有错:即使最初的假设是一致的,这种情境也会出现。考虑以下(公认的做作)证据:

Goal forall b c : bool, b = c -> c = b.
Proof.
intros b c e.
destruct b, c.
- reflexivity.
- discriminate.
- discriminate.
- reflexivity.
Qed.

第二和第三个分支具有相互矛盾的假设(true = falsefalse = true),即使最初的假设b = c是无害的。这个例子与原始例子略有不同,因为通过组合假设没有获得矛盾。相反,当我们调用destruct时,我们保证Coq通过考虑通过案例分析获得的一些子目标来证明结论。如果某些子目标恰好相互矛盾,甚至更好:那里没有任何工作要做。