coq - 如何用复杂的模式匹配进行推理?

标签 coq

Coq 允许编写复杂的模式匹配,但随后它会分解它们,以便其内核可以处理它们。

例如,让我们考虑以下代码。

Require Import List. Import ListNotations.

Inductive bar := A | B | C.

Definition f (l : list bar) :=
  match l with
  | _ :: A :: _ => 1
  | _ => 2
  end.

我们对列表和第二个元素进行模式匹配。打印 f 表明 Coq 存储了它的更复杂的版本。

Print f.
(* f = fun l : list bar => match l with
                        | [] => 2
                        | [_] => 2
                        | _ :: A :: _ => 1
                        | _ :: B :: _ => 2
                        | _ :: C :: _ => 2
                        end
     : list bar -> nat
*)

问题是,在操作 f 的证明中,我必须处理 5 种情况,而不是 2 种,其中 4 种是多余的。

处理这个问题的最佳方法是什么?有没有办法对模式匹配进行推理,就好像它完全按照定义一样?

最佳答案

你是对的,Coq 实际上简化了模式匹配,导致出现很多冗余。 然而,有一些方法可以对您想要的案例分析进行推理,这与 Coq 的理解相反。

  • 使用函数function induction是一种方式。
  • 最近,Equations还允许您定义模式匹配,并自动派生归纳原理(您可以使用 funelim 调用)。 为了说服 coq 案例可以因式分解,您必须使用 View 的概念。 它们在方程 in the examples 的上下文中进行描述。 。 我将详细说明如何使您的示例适应它。
From Equations Require Import Equations.
Require Import List. Import ListNotations.

Inductive bar := A | B | C.

Equations discr (b : list bar) : Prop :=
  discr (_ :: A :: _) := False ;
  discr _ := True.

Inductive view : list bar -> Set :=
| view_foo : forall x y, view (x :: A :: y)
| view_other : forall l, discr l -> view l.

Equations viewc l : view l :=
    viewc (x :: A :: y) := view_foo x y ;
    viewc l := view_other l I.

Equations f (l : list bar) : nat :=
    f l with viewc l := {
    | view_foo _ _ => 1 ;
    | view_other _ _ => 2
    }.

Goal forall l, f l < 3.
Proof.
    intro l.
    funelim (f l).
    - repeat constructor.
    - repeat constructor.
Qed.

如您所见,funelim 仅生成两个子目标。

它可能有点繁重,因此如果您不想使用函数方程,您可能必须手动证明自己的归纳原理:

Require Import List. Import ListNotations.

Inductive bar := A | B | C.

Definition f (l : list bar) :=
  match l with
  | _ :: A :: _ => 1
  | _ => 2
  end.

Definition discr (l : list bar) : Prop :=
    match l with
    | _ :: A :: _ => False
    | _ => True
    end.

Lemma f_ind :
    forall (P : list bar -> nat -> Prop),
        (forall x y, P (x :: A :: y) 1) ->
        (forall l, discr l -> P l 2) ->
        forall l, P l (f l).
Proof.
    intros P h1 h2 l.
    destruct l as [| x [|[] l]].
    3: eapply h1.
    all: eapply h2.
    all: exact I.
Qed.

Goal forall l, f l < 3.
Proof.
    intro l.
    eapply f_ind.
    - intros. repeat constructor.
    - intros. repeat constructor.
Qed.

关于coq - 如何用复杂的模式匹配进行推理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57975665/

相关文章:

Coq - 在 if ... then ... else 中使用 Prop (True | False)

coq - 在 lambda 内根据等价关系重写

coq - `match` 能比 `rewrite` 快吗

coq - 使用列表删除功能

coq - 为什么 Coq 在对可强制项应用参数时不能推断出我的强制项?

coq - 无法自动化在 Coq 中手动工作的引理

coq - 为什么这个 Coq 定义失败了?归纳类型的 Coq 命名空间错误

automation - coq auto 说简单的应用失败,但它可以手动工作

coq - 在 Coq 中定义使用程序时,义务中缺少信息的问题

coq - 证明函数应用在两个等价函数上的相等性