Following Arthur's suggestion, I changed my Fixpoint
relation to a mutual Inductive
relation which "builds up" the different comparisons between games rather than "drilling down".
But now I am receiving an entirely new error message:
Error: Parameters should be syntactically the same for each inductive type.
I think the error message is saying that I need the same exact parameters for all of these mutual inductive definitions.
I realize there are simple hacks to get around this (unused dummy variables, long functional types with everything inside the forall
), but I don't see why I should have to.
Can somebody explain the logic behind this restriction on mutual inductive types ? Is there a more elegant way to write this ? Does this restriction also imply that the inductive calls to each other must all use the same parameters (in which case I don't know of any hacks save hideous amounts of code duplication) ?
(The definitions of all the types and terms such as compare_quest, game, g1side etc. are unchanged from what they were in my 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).
In CGT, generally two players (named Left
and Right
) take turns playing a game where the player to make the last move wins. Each game (meaning each position in a game) can be read as a set of Left
's options and a set of Right
's options written as {G_L | G_R}
. When comparing two games, they can compare in any of four different ways: <
, >
, =
, or ||
.
A game is A < B
if B
is strictly better than A
for Left
, regardless of who goes first. A > B
if A
is better than B
for Left
. A = B
if the two games are equivalent (in the sense that the sum of games A + -B
is a zero-game so that the player who goes first loses). And, A || B
if which game is better for Left
depends who goes first.
One way to check the comparison between two games is as follows:
A <= B
if all ofA
'sLeft
children are<| B
andA <|
all ofB
's right children.A <| B
ifA
has a right child which is<= B
or ifA <=
any ofB
's left children.And, similarly for
>=
and>|
.
So, then by seeing which pair of these relations apply to two games A
and B
, it's possible to determine whether A < B
(A<=B
and A<|B
), A=B
(A<=B
and A>=B
), A > B
(A>=B
and A>|B
), or A || B
(A<|B
and A>|B
).
Here's the wiki article on CGT.