我一直在使用Coq很短的时间,我仍然碰到了一些东西。我已经定义了一个带有Record结构的集合。现在我需要进行一些模式匹配才能使用它,但是我在使用它时遇到了问题。首先,这些是我的要素。
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)}.
现在,我需要在'especial'元素上使用定义和修复点,只需要我选择的两个元素。我已经阅读了关于Record的文档,我得到的是我需要做这样的事情:
Fixpoint Size (E : especial): nat :=
match E with
|{|E := empty |} => 0
|{|E := n_fun n E0|} => (Size E0) + 1
end.
当然这告诉我,我错过了元素的归纳部分的所有内容,所以我添加{|E := _ |}=> 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 n E0
是'特殊'那么E0
是特殊的,但是我不能这么做在Fixpoint内部。我还定义了“所有元素”的大小,然后在定义中选择了“特殊”的大小,但我希望能够直接在集合“特殊”上进行直接模式匹配。感谢您的投入。
编辑:忘记提及我也有强制要求总是发送元素。
编辑:这是我发布之前的方法:
Fixpoint ElementSize (E : element): nat :=
match E with
| n_fun n E0 => (ElementSize E0) + 1
| _ => 0
end.
Definition Size (E : especial) := ElementSize E.
答案 0 :(得分:0)
我试过这样做:
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).
答案 1 :(得分:0)
我将您的示例简化为此,但您可以轻松返回到您的定义。我们有一个集合,以及由归纳谓词定义的子集。通常使用符号{b | Small b}
来使用sigma类型,但它实际上与示例中使用的Record
定义相同,所以不要介意: - )。
Inductive Big : Set := (* a big set *)
| A
| B (b0 b1:Big)
| C (b: Big).
Inductive Small : Big -> Prop := (* a subset *)
| A' : Small A
| C' (b:Big) : Small b -> Small (C b).
Record small := mk_small { b:Big ; P:Small b }.
这是一个解决方案。
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.
为了能够在H
- 分支中使用假设match
,它将作为函数参数发送到分支。否则,不会在H
项上执行b的销毁,而Coq无法证明我们在H
上进行了结构递归。