You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Coq中推进嵌套match的案例分析与证明?

解决Coq中write_to_stack_never_fails定理的证明卡壳问题

当前卡住的证明目标

执行到案例分析的分支后,得到如下目标:

1 goal (ID 110)
  
  addr : nat
  x : State
  l : list nat
  Heqo : write_list_index (repeat 0 (addr + 1)) addr 0 = Some l
  ============================
  match
    match write_list_index (repeat 0 (addr + 1)) addr 0 with
    | Some l' => Some (0 :: l')
    | None => None
    end
  with
  | Some stack' => Success (update_stack stack' (access_fault_handler (S addr) init_state))
  | None => Failure (access_fault_handler (S addr) init_state)
  end <> Failure x

该命题本应为真,但使用simpl无变化,改写Heqo也无法推进。

简化后的项目代码

Require Import Nat.
Require Import List.
Require Import Bool.
Import ListNotations.

Definition address := nat.
Definition variable := nat.

Record State: Set :=
  mkState {
    stack: list variable;
    }.

Inductive instruction: Set :=
| WriteToStack (addr: address) (value: variable).

Inductive insr_result: Set :=
| Success (state: State)
| Failure (state: State).

Definition has_access (addr: address) (state: State): bool :=
  match compare addr (length state.(stack)) with
  | Lt => true
  | _ => false
  end.

Fixpoint write_list_index {A: Type} (l: list A) (index: nat) (value: A)
  : option (list A) :=
  match l with
  | nil => None
  | h :: t => match index with
            | O => Some (value :: t)
            | S n => match (write_list_index t n value) with
                    | None => None
                    | Some l' => Some (h :: l')
                    end
            end
  end.

Definition update_stack (stack': list variable) (state: State): State :=
  {|
    stack := stack';
   |}.

Definition write_to_stack (addr: address) (value: variable) (state: State)
  (afh: address -> State -> State): insr_result :=
  if has_access addr state then
    match write_list_index state.(stack) addr value with
    | None => Failure state
    | Some stack' => Success (update_stack stack' state)
    end
  else
    let state := afh addr state in
    match write_list_index state.(stack) addr value with
    | None => Failure state
    | Some stack' => Success (update_stack stack' state)
    end.

Definition eval_insr (insr: instruction) (state: State) (afh: address -> State -> State): insr_result :=
  match insr with
  | WriteToStack addr value => write_to_stack addr value state afh
  end.


Definition access_fault_handler (addr: address) (state: State): State :=
  if addr <? length state.(stack) then
    state
  else
    let frame_size := addr - length state.(stack)+ 1 in
    {| stack := state.(stack) ++ (repeat 0 frame_size) |}.

Definition init_state: State := {| stack := nil; |}.

Theorem write_to_stack_never_fails: forall addr x, eval_insr (WriteToStack addr 0) init_state access_fault_handler <> Failure x.
Proof.
  intros.
  simpl.
  unfold write_to_stack. simpl.
  destruct addr.
  - simpl. unfold not. intros. inversion H.
  - simpl. destruct (write_list_index (repeat 0 (addr + 1)) addr 0) eqn:?.
    + (* Stuck *)

推进证明的方法

核心思路

利用假设Heqo将目标中重复的write_list_index调用替换为已知的Some l,此时目标会简化为判断Success构造的结果与Failure x不等——而Success和Failure是insr_result的互斥构造子,直接利用构造子的不相交性即可完成证明。

具体tactic序列

在卡住的分支中执行以下命令:

rewrite Heqo.
discriminate.

步骤解释

  1. rewrite Heqo:将目标里的write_list_index (repeat 0 (addr + 1)) addr 0全部替换为Some l,此时目标的match结构会直接走到Some stack'分支,生成Success类型的结果。
  2. discriminate:Coq内置的tactic,用于证明不同构造子构造的项不可能相等。这里Success _和Failure x是完全不同的构造子,discriminate会直接识别这种矛盾,完成证明。

如果需要更详细的步骤,也可以展开不等关系后用反证法:

rewrite Heqo.
unfold not.
intros H.
inversion H.

inversion H会拆解等式Success _ = Failure x,发现两个构造子不匹配,从而导出矛盾,完成证明。

内容的提问来源于stack exchange,提问作者kunkun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 07:27:50