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

支持自定义归纳键、易证等价性的Coq字典实现方案咨询

Coq中自定义键类型字典的实现方案(便于等价性证明)

针对你定义的键类型:

Inductive t : Type :=
| a
| b
| c : nat -> t.

下面给出三种便于证明等价性的字典实现方案,核心围绕你需要的重复更新同一键等价于最后一次更新、不同键更新顺序可交换这两个性质展开:

方案1:基于函数的字典实现

这是最简洁的实现方式,将字典直接定义为键到值的函数,更新操作就是函数的覆盖。

定义与操作

(* 假设值类型为V,可替换为任意类型 *)
Variable V : Type.

(* 字典类型:键到值的函数 *)
Definition dict := t -> V.

(* 更新操作:k !-> v ; d 表示用v覆盖d中k对应的值 *)
Definition update (k : t) (v : V) (d : dict) : dict :=
  fun k' => if eq_dec k k' then v else d k'.
(* 注:eq_dec是键类型的可判定相等,需要为t实现Decidable Eq实例 *)

(* 为t实现可判定相等 *)
Instance t_eq_dec : EqDec t eq.
Proof.
  unfold EqDec; intro x; induction x.
  - intro y; destruct y; [left; reflexivity | right; discriminate | right; discriminate].
  - intro y; destruct y; [right; discriminate | left; reflexivity | right; discriminate].
  - intro y; destruct y as [| | n'].
    + right; discriminate.
    + right; discriminate.
    + destruct (nat_eq_dec n n'); [left; congruence | right; congruence].
Qed.

等价性证明思路

利用函数外延性(Functional Extensionality),证明两个字典等价当且仅当它们对所有键的返回值相同:

  • 重复更新同一键:要证 update k v2 (update k v1 d) ≡ update k v2 d,只需对任意键k',分k'=k和k'≠k两种情况验证返回值一致即可。
  • 不同键更新顺序可交换:要证 update k1 v1 (update k2 v2 d) ≡ update k2 v2 (update k1 v1 d)(其中k1≠k2),同样对任意k'分三种情况:k'=k1、k'=k2、k'都不是,验证两边返回值相同。

方案2:基于有序键值对列表的实现

将字典表示为键值对的列表,新的更新放在列表头部,查找时取第一个匹配的键。这种实现的等价性可以定义为“所有键的查找结果一致”。

定义与操作

Variable V : Type.

(* 字典类型:键值对列表 *)
Definition dict := list (t * V).

(* 查找操作:从列表中找第一个匹配的键对应的值 *)
Fixpoint lookup (k : t) (d : dict) : option V :=
  match d with
  | nil => None
  | (k', v) :: tl => if eq_dec k k' then Some v else lookup k tl
  end.

(* 更新操作:将新的键值对放在列表头部 *)
Definition update (k : t) (v : V) (d : dict) : dict := (k, v) :: d.

等价性证明思路

首先定义字典的等价关系:d1 ≡ d2 <-> forall k, lookup k d1 = lookup k d2。

  • 重复更新同一键:证明 lookup k' (update k v2 (update k v1 d)) = lookup k' (update k v2 d),对k'分是否等于k讨论,显然头部的v2会覆盖之前的v1。
  • 不同键更新顺序可交换:当k1≠k2时,证明 lookup k' (update k1 v1 (update k2 v2 d)) = lookup k' (update k2 v2 (update k1 v1 d)),分k'是k1、k2、其他三种情况,验证两边查找结果一致。

方案3:基于结构化记录的实现

由于你的键类型t的构造子是有限的(固定的a、b,以及参数化的c:nat->t),可以将字典拆分为对应每个构造子的存储,这种实现的等价性证明最直观。

定义与操作

Variable V : Type.

(* 字典类型:结构化记录,对应每个键构造子的存储 *)
Record dict : Type := {
  val_a : V;
  val_b : V;
  val_c : nat -> V
}.

(* 更新操作:针对不同键类型修改对应字段 *)
Definition update (k : t) (v : V) (d : dict) : dict :=
  match k with
  | a => {| val_a := v; val_b := d.(val_b); val_c := d.(val_c) |}
  | b => {| val_a := d.(val_a); val_b := v; val_c := d.(val_c) |}
  | c n => {| val_a := d.(val_a); val_b := d.(val_b); val_c := fun m => if eq_nat_dec m n then v else d.(val_c) m |}
  end.

(* 查找操作:直接访问对应字段 *)
Definition lookup (k : t) (d : dict) : V :=
  match k with
  | a => d.(val_a)
  | b => d.(val_b)
  | c n => d.(val_c) n
  end.

等价性证明思路

字典的等价性直接用记录的逐字段相等(d1 = d2),因为记录的相等就是所有字段相等:

  • 重复更新同一键:比如更新a两次,第二次的update会直接覆盖val_a字段,显然等价于只保留最后一次更新。
  • 不同键更新顺序可交换:比如先更新a再更新b,和先更新b再更新a,修改的是不同的字段,最终的记录字段完全一致,所以相等。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 04:52:35