为什么coq互感类型必须具有相同的参数?

时间:2013-06-25 23:00:54

标签: comparison coq recursive-datastructures game-theory induction

关注Arthur's suggestion后,我将Fixpoint关系更改为共同Inductive关系,“建立”游戏之间的不同比较而不是“向下钻取”。

但现在我收到一条全新的错误消息:

Error: Parameters should be syntactically the same for each inductive type.

我认为错误信息是说我需要所有这些互感定义的相同精确参数。

我意识到有一些简单的黑客来解决这个问题(未使用的虚拟变量,包含forall内部所有内容的长函数类型),但我不明白为什么我应该这样做。

有人可以解释这种对互感类型的限制背后的逻辑吗?是否有更优雅的方式来写这个?这种限制是否也意味着相互之间的归纳调用必须使用相同的参数(在这种情况下,我不知道任何黑客可以保存大量的代码重复)?

(所有类型和术语的定义,例如compare_quest,game,g1side等,与我first question中的定义相同。

Inductive gameCompare (c : compare_quest) : game -> game -> Prop :=
 | igc : forall g1 g2 : game,
    innerGCompare (nextCompare c) (compareCombiner c) (g1side c) (g2side c) g1 g2 ->
    gameCompare c g1 g2
with innerGCompare (next_c : compare_quest) (cbn : combiner) (g1s g2s : side)
    : game -> game -> Prop :=
 | compBoth : forall g1 g2 : game,
    cbn (listGameCompare next_c cbn (g1s g1) g2)
        (gameListCompare next_c cbn g1 (g2s g2)) ->
    innerGCompare next_c cbn g1s g2s g1 g2
with listGameCompare (c : compare_quest) (cbn : combiner) : gamelist -> game -> Prop :=
 | emptylgCompare : cbn_init cbn -> forall g2 : game, listGameCompare c cbn emptylist g2
 | otlgCompare : forall (g1_cdr : gamelist) (g1_car g2 : game),
    (cbn (listGameCompare c cbn g1_cdr g2) (gameCompare c g1_car g2)) ->
    listGameCompare c cbn (listCons g1_car g1_cdr) g2
with gameListCompare (c : compare_quest) (cbn : combiner) : game -> gamelist -> Prop :=
 | emptyglCompare : cbn_init cbn -> forall g1 : game, gameListCompare c cbn g1 emptylist
 | otglCompare : forall (g1 g2_car : game) (g2_cdr : gamelist),
    (cbn (gameListCompare c cbn g1 g2_cdr) (gameCompare c g1 g2_car)) ->
    gameListCompare c cbn g1 (listCons g2_car g2_cdr).

在CGT中,通常有两个玩家(名为LeftRight)轮流玩游戏,让最后一步的玩家获胜。每个游戏(意味着游戏中的每个位置)都可以被视为一组Left选项和一组Right选项,写为{G_L | G_R}。在比较两款游戏时,他们可以通过四种不同的方式进行比较:<>=||

如果A < B严格优于B A,则Left游戏为A > B,无论谁先行。{如果A优于B Left A = B,则A + -BA || B如果这两个游戏是相同的(在某种意义上,游戏Left的总和是零游戏,那么首先输掉的玩家就输了)。并且,A <= B如果哪个游戏更适合A,则取决于谁先行。

检查两场比赛之间比较的一种方法如下:

  • Left如果所有<| B的{​​{1}}个孩子都是A <|B所有A <| B的孩子都是。

  • A如果<= B有一个正确的孩子A <=B任何>=的左子女。

  • 同样适用于>|A

那么,通过查看哪一对关系适用于两个游戏BA < B,可以确定A<=BA<|B和{{1} }),A=BA<=BA>=B),A > BA>=BA>|B)或A || B({{ 1}}和A<|B)。

这是wiki article on CGT

1 个答案:

答案 0 :(得分:2)

这个限制非常有趣,我之前从未遇到过。我没有看到为什么要拒​​绝这段代码的原因。我最好的选择是,当人们设计Coq的基础时,这种限制使得一些证据变得更容易,并且因为没有多少人对它感到烦恼,所以它只是保持这种状态。不过,我可能完全错了;我知道参数和参数(即箭头右侧的参数和参数)对某些事情的处理方式略有不同。例如,与参数相比,定义归纳类型时强加的Universe约束对参数的限制较少。

也许这应该转发给Coq Club邮件列表? :)

您无需将所有内容放在箭头右侧即可使其正常工作。您可以做的一件事是将除compare_quest参数之外的所有内容放在右侧。当你使用你在构造函数中定义的相同类型的归纳时,你给出的参数不必与你在标题上给出的参数相同,所以没关系:

Inductive gameCompare (c : compare_quest) : game -> game -> Prop :=
 | igc : forall g1 g2 : game,
    innerGCompare (nextCompare c) (compareCombiner c) (g1side c) (g2side c) g1 g2 ->
    gameCompare c g1 g2

with innerGCompare (c : compare_quest) : combiner -> side -> side ->
    game -> game -> Prop :=
 | compBoth : forall cbn g1s g2s (g1 g2 : game),
    cbn (listGameCompare c cbn (g1s g1) g2)
        (gameListCompare c cbn g1 (g2s g2)) ->
    innerGCompare c cbn g1s g2s g1 g2

with listGameCompare (c : compare_quest) : combiner -> gamelist -> game -> Prop :=
 | emptylgCompare : forall cbn, cbn_init cbn -> forall g2 : game, listGameCompare c cbn emptylist g2
 | otlgCompare : forall cbn (g1_cdr : gamelist) (g1_car g2 : game),
    (cbn (listGameCompare c cbn g1_cdr g2) (gameCompare c g1_car g2)) ->
    listGameCompare c cbn (listCons g1_car g1_cdr) g2

with gameListCompare (c : compare_quest) : combiner -> game -> gamelist -> Prop :=
 | emptyglCompare : forall cbn, cbn_init cbn -> forall g1 : game, gameListCompare c cbn g1 emptylist
 | otglCompare : forall cbn (g1 g2_car : game) (g2_cdr : gamelist),
    (cbn (gameListCompare c cbn g1 g2_cdr) (gameCompare c g1 g2_car)) ->
    gameListCompare c cbn g1 (listCons g2_car g2_cdr).

不幸的是,尝试评估这会产生一个新错误:(

Error: Non strictly positive occurrence of "listGameCompare" in
 "forall (cbn : Prop -> Prop -> Prop) (g1s g2s : game -> gamelist)
    (g1 g2 : game),
  cbn (listGameCompare c cbn (g1s g1) g2) (gameListCompare c cbn g1 (g2s g2)) ->
  innerGCompare c cbn g1s g2s g1 g2".

这个错误在Coq中更为常见。它抱怨你将你定义的类型作为cbn的参数传递,因为这可能导致该类型出现在箭头的 left (负面事件),这是已知会导致逻辑上的不一致。

认为你可以通过在最后三种类型的构造函数中内联compareCombiner来解决这个问题,这可能需要对代码进行一些重构。再说一遍,我很确定必须有更好的方法来定义它,但我不明白你想要做的很好,所以我的帮助在那里有点受限。

更新:我已经开始了一系列关于在Coq中正式化一些CGT的文章。你可以找到第一个here