Coq中记录结构模式匹配的困惑

Coq中记录结构模式匹配的困惑,coq,Coq,我使用Coq的时间很短,但我仍然会碰到一些东西。我定义了一个具有记录结构的集合。现在我需要做一些模式匹配来使用它,但我在正确使用它时遇到了问题。首先,这些是我的元素 Inductive element : Set := | empty : element . . . | fun_m : element -> element -> element | n_fun : nat -> element -> element . 我选择具有特定特征的元素,以便下一步生成它

我使用Coq的时间很短,但我仍然会碰到一些东西。我定义了一个具有记录结构的集合。现在我需要做一些模式匹配来使用它,但我在正确使用它时遇到了问题。首先,这些是我的元素

   Inductive element : Set :=
| empty  : element
.
.
.
| fun_m : element -> element -> element
| n_fun : nat -> element -> element
.
我选择具有特定特征的元素,以便下一步生成它们的子集:

Inductive esp_char : elements -> Prop :=
| esp1 : esp_char empty
| esp2 : forall (n : nat )(E : element), esp_char E -> esp_char (n_fun n E).

Record especial : Set := mk_esp{ E : element ; C : (esp_char E)}.
现在,我需要在“特殊”元素上使用定义和固定点,就我选择的两个。我已经阅读了记录在案的文档,我得到的是我需要做如下事情:

Fixpoint Size (E : especial): nat :=
match E with
|{|E := empty |}     => 0
|{|E := n_fun n E0|} => (Size E0) + 1
end.
当然,这告诉我我缺少元素归纳部分的所有内容,所以我添加了
{E:={u124;}=>0
,或者任何东西,只是为了使归纳完整。即使这样做,我也会发现这个问题:

|{|E := n_fun n E0|} => (Size E0) + 1

Error:
In environment
Size : especial -> nat
E : especial
f : element
i : esp_char f
n : nat
E0 : element
The term "E0" has type "element" while it is expected to have type "especial".
我无法解决的是最后一件事,我有一个引理证明,如果
n_-fun ne0
是“特殊的”,那么
E0
是特殊的,但我不能在不动点内这样构建它。我还定义了“所有元素”的大小,然后在定义中选择了“特殊”元素,但我希望能够直接在集合“特殊”上进行直接模式匹配。谢谢你的意见

编辑:忘了提到我也有一个强迫总是发送特别元素

编辑:这是我在发布之前采用的方法:

Fixpoint ElementSize (E : element): nat :=
match E with
| n_fun n E0 => (ElementSize E0) + 1
| _  => 0
 end.

Definition Size (E : especial) := ElementSize E.
我会尽力做到:

Lemma mk_especial_proof n E : esp_char (n_fun n E) -> esp_char E.
Proof. now intros U; inversion U. Qed.

Fixpoint Size (E : especial): nat := 
match E with
|{|E := empty              |} => 0
|{|E := n_fun n E0; C := P |} => (Size (mk_esp E0 (mk_especial_proof _ _ P))) + 1
|{|E := fun_m E1 E2        |} => 0
end.
但是,这将使终止检查失败。我不熟悉如何用记录来克服这个问题。我肯定会遵循我在评论中提到的方法(在基本数据类型上使用固定点)

编辑:添加了单固定点解决方案

Fixpoint size_e e :=
  match e with
  | empty       => 0
  | fun_m e1 e2 => 0
  | n_fun _   e => 1 + size_e e
  end.

Definition size_esp e := size_e (E e).
Lemma Small_lemma: forall b, Small (C b) -> Small b.
Proof. intros b H; now inversion H. Qed.

Fixpoint size (b : Big) : Small b -> nat :=
    match b with
      | A => fun _ => 0
      | B _ _ => fun _ => 0
      | C b' => fun H => 1 + size b' (Small_lemma _ H)
    end.

Definition Size (s:small) : nat :=
  let (b,H) := s in size b H.

我把你的例子简化为这个,但你可以很容易地回到你的定义。我们有一个集合和一个由归纳谓词定义的子集。通常我们使用sigma类型来表示,符号为
{b | Small b}
,但实际上它与示例中使用的
记录定义相同,所以不要介意:-)

这里有一个解决方案

Fixpoint size_e e :=
  match e with
  | empty       => 0
  | fun_m e1 e2 => 0
  | n_fun _   e => 1 + size_e e
  end.

Definition size_esp e := size_e (E e).
Lemma Small_lemma: forall b, Small (C b) -> Small b.
Proof. intros b H; now inversion H. Qed.

Fixpoint size (b : Big) : Small b -> nat :=
    match b with
      | A => fun _ => 0
      | B _ _ => fun _ => 0
      | C b' => fun H => 1 + size b' (Small_lemma _ H)
    end.

Definition Size (s:small) : nat :=
  let (b,H) := s in size b H.

为了能够使用
match
-分支中的假设
H
,将其作为函数参数发送到分支中。否则,b的销毁不会在
H
项上执行,Coq不能证明我们在
H
上进行了结构递归,当然这里的事情不一致,类型错误(提示,请尝试
关于C
。我建议您首先在
元素
上定义大小函数,然后使用记录访问器将其组合起来,以获得
特殊
的大小(原文如此).我完全按照你的建议做了,这似乎是最自然的方式,但我被要求只使用一个固定点,这就是我被卡住的地方。我编辑了一些拼写错误并添加了一些细节。哦,这似乎是一个奇怪的要求,请看答案,因为我无法在这里复制完整的代码。谢谢你,我同意另一种方式,sadly我需要这个(我也不理解它背后的原理)。我尝试了这个,但我得到了一个错误:对Size的递归调用的主参数等于“{E:=E0;C:=mk_特别证明ne0 P0}”,而不是“E”的子项。你知道这意味着什么或者我哪里出错了吗?请注意,另一种方法允许你用一个固定点来完成这项任务。错误消息意味着Coq无法确定
mk_esp…
是一个比输入项
E
小的术语。我已经用我最初对解决方案的理解编辑了我的帖子,我有一个固定点,并且一个定义,你能告诉我如何改变以使Fixpoint吸收定义吗?也谢谢你的解释。谢谢你的帮助,这正是我所做的,但这并不是一个有效的解决方案。现在我认为这只是出于固执…如果我看到其他方法,我会把它贴在这里好的,如果我理解的话没错,这有点奇怪…也许你可以发布确切的要求?