比较树的相互递归函数
Mutually Recursive Function to Compare Trees
我正在尝试在类似树的类型上编写比较函数。
它有一个应该是字符串的值,但为了简单起见,我暂时将它设为 nat。它还有一个哈希来帮助加快比较,稍后将被 Sint63 取代,但为了现在简单起见,我将其设为 nat。
Require Import Coq.Lists.List.
Import Coq.Lists.List.ListNotations.
Inductive Info: Type :=
mkInfo :
forall
(value: nat)
(children: list Info)
(hash: nat),
Info.
比较函数必须尽快短路,为此它会在尝试子项之前尝试使用散列或值。使用散列可能会导致顺序可能不顺眼,但唯一重要的是该顺序具有确定性。
Fixpoint compare_info (x y: Info) {struct x} :=
match x with
| mkInfo xvalue xchildren xhash =>
match y with
| mkInfo yvalue ychildren yhash =>
match Nat.compare xhash yhash with
| Lt => Lt
| Gt => Gt
| Eq =>
match Nat.compare xvalue yvalue with
| Lt => Lt
| Gt => Gt
| Eq => compare_children xchildren ychildren
end
end
end
end
with compare_children (xs ys: list Info) {struct xs} :=
match xs with
| [] =>
match ys with
| [] => Eq
| _ => Lt
end
| (x'::xs') =>
match ys with
| [] => Gt
| (y'::ys') =>
match compare_info x' y' with
| Lt => Lt
| Gt => Gt
| Eq => compare_children xs' ys'
end
end
end
.
问题是我收到以下错误:
Recursive definition of compare_children is ill-formed.
In environment
compare_info : Info -> Info -> comparison
compare_children : list Info -> list Info -> comparison
xs : list Info
ys : list Info
x' : Info
xs' : list Info
y' : Info
ys' : list Info
Recursive call to compare_info has principal argument equal to
"x'" instead of "xs'".
Recursive definition is:
"fun xs ys : list Info =>
match xs with
| [] => match ys with
| [] => Eq
| _ :: _ => Lt
end
| x' :: xs' =>
match ys with
| [] => Gt
| y' :: ys' =>
match compare_info x' y' with
| Eq => compare_children xs' ys'
| Lt => Lt
| Gt => Gt
end
end
end".
我之前在单个递归函数中帮助 Coq 了解哪个元素是递归的,但我认为我以前没有用相互递归函数做过。
我不想使用 Program Fixpoint,因为我过去发现这使得证明函数的事情变得非常困难。
我想知道是否有另一种方法以 Coq 可接受的方式编写此函数?
感谢您的帮助
您使用的类型是Nested Inductive Type
。您的代码是正确的,只有一个纯技术时刻:compare_children
的定义应定义为本地固定点,而不是相互固定点。
Fixpoint compare_info (x y: Info) {struct x} :=
match x with
| mkInfo xvalue xchildren xhash =>
match y with
| mkInfo yvalue ychildren yhash =>
match Nat.compare xhash yhash with
| Lt => Lt
| Gt => Gt
| Eq =>
match Nat.compare xvalue yvalue with
| Lt => Lt
| Gt => Gt
| Eq => ((fix compare_children (xs ys: list Info) {struct xs} :=
(match xs with
| [] =>
match ys with
| [] => Eq
| _ => Lt
end
| (x'::xs') =>
match ys with
| [] => Gt
| (y'::ys') =>
match compare_info x' y' with
| Lt => Lt
| Gt => Gt
| Eq => compare_children xs' ys'
end
end
end)) xchildren ychildren)
end
end
end
end.
有关详细信息,请参阅 Certified Programming with Dependent Types by Adam Chlipala. Needed Chapter 在线(搜索 Nested Inductive)。书中也有此类类型的归纳原理的例子。
我正在尝试在类似树的类型上编写比较函数。
它有一个应该是字符串的值,但为了简单起见,我暂时将它设为 nat。它还有一个哈希来帮助加快比较,稍后将被 Sint63 取代,但为了现在简单起见,我将其设为 nat。
Require Import Coq.Lists.List.
Import Coq.Lists.List.ListNotations.
Inductive Info: Type :=
mkInfo :
forall
(value: nat)
(children: list Info)
(hash: nat),
Info.
比较函数必须尽快短路,为此它会在尝试子项之前尝试使用散列或值。使用散列可能会导致顺序可能不顺眼,但唯一重要的是该顺序具有确定性。
Fixpoint compare_info (x y: Info) {struct x} :=
match x with
| mkInfo xvalue xchildren xhash =>
match y with
| mkInfo yvalue ychildren yhash =>
match Nat.compare xhash yhash with
| Lt => Lt
| Gt => Gt
| Eq =>
match Nat.compare xvalue yvalue with
| Lt => Lt
| Gt => Gt
| Eq => compare_children xchildren ychildren
end
end
end
end
with compare_children (xs ys: list Info) {struct xs} :=
match xs with
| [] =>
match ys with
| [] => Eq
| _ => Lt
end
| (x'::xs') =>
match ys with
| [] => Gt
| (y'::ys') =>
match compare_info x' y' with
| Lt => Lt
| Gt => Gt
| Eq => compare_children xs' ys'
end
end
end
.
问题是我收到以下错误:
Recursive definition of compare_children is ill-formed.
In environment
compare_info : Info -> Info -> comparison
compare_children : list Info -> list Info -> comparison
xs : list Info
ys : list Info
x' : Info
xs' : list Info
y' : Info
ys' : list Info
Recursive call to compare_info has principal argument equal to
"x'" instead of "xs'".
Recursive definition is:
"fun xs ys : list Info =>
match xs with
| [] => match ys with
| [] => Eq
| _ :: _ => Lt
end
| x' :: xs' =>
match ys with
| [] => Gt
| y' :: ys' =>
match compare_info x' y' with
| Eq => compare_children xs' ys'
| Lt => Lt
| Gt => Gt
end
end
end".
我之前在单个递归函数中帮助 Coq 了解哪个元素是递归的,但我认为我以前没有用相互递归函数做过。
我不想使用 Program Fixpoint,因为我过去发现这使得证明函数的事情变得非常困难。
我想知道是否有另一种方法以 Coq 可接受的方式编写此函数?
感谢您的帮助
您使用的类型是Nested Inductive Type
。您的代码是正确的,只有一个纯技术时刻:compare_children
的定义应定义为本地固定点,而不是相互固定点。
Fixpoint compare_info (x y: Info) {struct x} :=
match x with
| mkInfo xvalue xchildren xhash =>
match y with
| mkInfo yvalue ychildren yhash =>
match Nat.compare xhash yhash with
| Lt => Lt
| Gt => Gt
| Eq =>
match Nat.compare xvalue yvalue with
| Lt => Lt
| Gt => Gt
| Eq => ((fix compare_children (xs ys: list Info) {struct xs} :=
(match xs with
| [] =>
match ys with
| [] => Eq
| _ => Lt
end
| (x'::xs') =>
match ys with
| [] => Gt
| (y'::ys') =>
match compare_info x' y' with
| Lt => Lt
| Gt => Gt
| Eq => compare_children xs' ys'
end
end
end)) xchildren ychildren)
end
end
end
end.
有关详细信息,请参阅 Certified Programming with Dependent Types by Adam Chlipala. Needed Chapter 在线(搜索 Nested Inductive)。书中也有此类类型的归纳原理的例子。