Используя Coq 8.4pl3, я получаю сообщение об ошибке при индукции с вариантом eqn:, который не указан в разделе индукции в справочном руководстве.
(* Export below requires Software Foundations 4.0. *)
Require Export Logic.
Inductive disjoint (X : Type) (l1 l2 : list X) : Prop :=
| nil1 : l1 = [] -> disjoint X l1 l2
| nil2 : l2 = [] -> disjoint X l1 l2
| bothCons : forall x:X,
In x l1 ->
not (In x l2) ->
disjoint X l1 l2.
Fixpoint head (X : Type) (l : list X) : option X :=
match l with
| [] => None
| h :: t => Some h
end.
Fixpoint tail (X : Type) (l : list X) : list X :=
match l with
| [] => []
| h :: t => t
end.
Inductive NoDup (X : Type) (l : list X) : Prop :=
| ndNil : l = [] -> NoDup X l
| ndSingle : forall x:X, l = [x] -> NoDup X l
| ndCons : forall x:X, head X l = Some x ->
not (In x (tail X l)) /\ NoDup X (tail X l) ->
NoDup X l.
Theorem disjoint__app_NoDup :
forall (X : Type) (l1 l2 : list X),
disjoint X l1 l2 /\ NoDup X l1 /\ NoDup X l2 ->
NoDup X (l1 ++ l2).
Proof.
intros. induction H eqn:caseEqn.
Если я заменю последний шаг просто «индукцией H», я не получу ошибки, но с указанным выше аргументом eqn: я получу ошибку:
Ошибка: в заключении используется a.
(Раньше в формулировке теоремы отсутствовало условие, и вместо этого в той же ошибке указывался идентификатор d.)
Ссылки на ручные списки "используется в заключении" как ошибка из-за использования assert. Это имеет какой-то смысл, что за кулисами eqn: может генерировать утверждения, но у меня нет идентификатора a, видимого в контексте, и я не вижу, что Coq пытается автоматически с этим справиться.
Пытался заменить начало доказательства на
intros. remember H. induction H.
Теперь попытка выполнить индукцию дает ту же ошибку, что и раньше, только с H вместо a. (Когда в теореме отсутствовало дополнительное условие, Coq также явно добавил d в контекст, что идентично гипотезе H.)
Как я могу здесь двигаться дальше? Я стараюсь не терять информацию из контекста.
disjoint
(все строчные). - person Anton Trunov   schedule 01.09.2016[1;1
] и[2;2]
не пересекаются, но[1;1]++[2;2]
содержат дубликаты. Возможно, вам также следует потребоватьNoDup l1 /\ NoDup l2
. - person larsr   schedule 01.09.2016disjoint
- оно на самом деле не индуктивное, поскольку его конструкторы не включаютdisjoint
в качестве предпосылок, а только в качестве выводов. Таким образом,induction H eqn:caseEqn.
можно заменить наdestruct H eqn:caseEqn.
(2) Кроме того, конструкторbothCons
на самом деле является определением всей концепцииdisjoint
, мы можем вывести из негоnil1
иnil2
, так что вы можете определитьdisjoint
следующим образом:Definition disjoint {X : Type} (l1 l2 : list X) : Prop := forall x:X, In x l1 -> ~ (In x l2).
- person Anton Trunov   schedule 02.09.2016NoDup
в стандартная библиотека. - person Anton Trunov   schedule 02.09.2016Inductive disjoint_i {X : Type} : list X -> list X -> Prop := dnil : forall l2, disjoint_i [] l2 | dcons : forall l1 l2 x, ~ (In x l2) -> disjoint_i l1 l2 -> disjoint_i (x::l1) l2.
Это действительно индуктивное определение с независимыми случаями, и можно доказать, что оно эквивалентно неиндуктивному определению, которое я дал ранее. Возможно, его не очень удобно использовать при любых обстоятельствах из-за отсутствия симметрии, но я считаю, что его можно исправить. - person Anton Trunov   schedule 03.09.2016