У меня есть тип списков, головы и хвосты которых должны быть в определенном смысле "совместимы":
Inductive tag := A | B. (* Just an example *)
Inductive element : tag -> tag -> Set :=
| AA : element A A
| AB : element A B
| BB : element B B. (* Also just an example *)
Inductive estack : tag -> tag -> Set :=
| ENil : forall t, estack t t
| ECons : forall r s t, element r s -> estack s t -> estack r t.
Однако мне этот код не очень нравится по следующим причинам:
- Он не является модульным: конструкторы специальных списков данных неразрывно связаны с доказательствами совместимости орла и решки — тегами.
- Это не одобряет повторное использование кода: я вынужден переопределить обычные функции списка (например, конкатенацию списков) и повторно доказать обычные теоремы о списках (такие как ассоциативность конкатенации списков).
Я имею в виду другой подход, который состоит из трех шагов:
Определение одного типа теговых элементов (в отличие от семейства теговых типов элементов):
Inductive taggedElement := Tagged : forall t1 t2, element t1 t2 -> taggedElement.
Определение типа произвольных (т. е. действительных или недействительных) списков тегированных элементов:
Definition taggedElementStack := list taggedElement.
Определение действительного списка помеченных элементов как кортежа, элементы которого являются произвольным списком помеченных элементов и доказательством того, что элементы совместимы с соседними.
(* I have no idea how to do this in Coq, hence the question! * * I am going to use pseudomathematical notation. I am not well versed in either * mathematics or theoretical computer science, so please do not beat me with a * stick if I say something that is completely bogus! * * I want to construct the type * * (tes : taggedElementStack, b : proof that P(tes) holds) * * where P(tes) is a predicate that is only true when, for every sublist of tes, * including tes itself, the heads and tails are compatible. *)
Как мне выполнить третий шаг в Coq?