在Coq

时间:2018-11-22 11:06:46

标签: coq

我正在尝试在Coq中定义一个固定点,其中一个函数定义通过一个参数引用另一个,但是我遇到了一些令人困惑的错误。

我已经将定义最小化了:

Require Import Coq.Init.Notations.
Require Import Coq.Init.Datatypes.

Inductive Wrapper (T : Type) :=
  | Wrap : T -> Wrapper T
  .
Inductive Unwrapper :=
  | Empty : Unwrapper
  | Unwrap : Wrapper Unwrapper -> Unwrapper
  .

Fixpoint Unwrapper_size (u : Unwrapper) {struct u} : nat :=
  match u with
  | Empty => O
  | Unwrap w => Wrapper_size w
  end

with Wrapper_size (w : Wrapper Unwrapper) {struct w} : nat :=
  match w with
  | Wrap _ t => Unwrapper_size t
  end.

这将导致此错误:

Recursive definition of Wrapper_size is ill-formed.
In environment
Unwrapper_size : Unwrapper -> nat
Wrapper_size : Wrapper Unwrapper -> nat
w : Wrapper Unwrapper
t : Unwrapper
Recursive call to Unwrapper_size has principal argument equal to
"t" instead of a subterm of "w".
Recursive definition is:
"fun w : Wrapper Unwrapper =>
match w with
| Wrap _ t => Unwrapper_size t
end".

在这里,t显然是w的一个子项— w是我们要匹配的t的子项,但Coq不接受。这是什么错误,我该如何解决?

1 个答案:

答案 0 :(得分:3)

假设您还对其他参数使用了Wrapper。然后,您需要中断相互递归并使函数与数据类型“平行”。所以你想写Wrapper_size: Wrapper T -> (T -> nat) -> nat

然后您可以在Wrapper_size Unwrapper_size中使用Unwrapper_size:Coq应该在终止检查中做足够的内联,以确认这是安全的。

在此示例中,手动进行内联也很容易:Unwrapper_size将在Unwrap (Wrap _ t)上匹配并在t上递归。