Как уничтожить / обобщить перезаписанные операторы соответствия программы
При использовании Program
операторы соответствия переписываются в стиль "proof-passing". Это делает доказательства соответствия доступными в ветвях-что может быть критично.
Require Import ZArith.
Open Scope Z_scope.
Program Definition test (x:Z) : option (x <= 100) :=
match Z_le_gt_dec x 100 with
| left bound => Some _
| right bound => None
end.
Lemma test_gt_100 : forall x:Z, x > 100 -> test x = None.
Proof.
intros x bound.
unfold test.
В этом месте обычно было бы destruct (Z_le_gt_dec x 100)
, и доказательство тогда легко. Однако переписанное совпадение дает такой контекст:
x : Z
bound : x > 100
============================
match
Z_le_gt_dec x 100 as x0
return (x0 = Z_le_gt_dec x 100 -> option (x <= 100))
with
| left bound0 =>
fun Heq_anonymous : left bound0 = Z_le_gt_dec x 100 =>
Some (test_obligation_1 x bound0 Heq_anonymous)
| right bound0 => fun _ : right bound0 = Z_le_gt_dec x 100 => None
end eq_refl = None
При этом разрушение завершается неудачей:
Toplevel input, characters 20-48:
Error: Abstracting over the term "s" leads to a term
"fun s : {x <= 100} + {x > 100} =>
match s as x0 return (x0 = s -> option (x <= 100)) with
| left bound =>
fun Heq_anonymous : left bound = s =>
Some (test_obligation_1 x bound Heq_anonymous)
| right bound => fun _ : right bound = s => None
end eq_refl = None" which is ill-typed.
Двигаясь медленнее и стараясь просто generalize (Z_le_gt_dec x 100)
показывает, почему:
Toplevel input, characters 0-30:
Error: Illegal application (Type Error):
The term "test_obligation_1" of type
"forall x : Z,
let filtered_var := Z_le_gt_dec x 100 in
forall bound : x <= 100, left bound = filtered_var -> x <= 100"
cannot be applied to the terms
"x" : "Z"
"bound0" : "x <= 100"
"Heq_anonymous" : "left bound0 = s"
The 3rd term has type "left bound0 = s" which should be coercible to
"left bound0 = Z_le_gt_dec x 100".
Хотя это имеет некоторый смысл, я не знаю, что с этим делать.
(я поместил это в collacoq , Если это полезно. Не забудьте сначала выполнить только строку комментария, а затем дождаться загрузки всех библиотек, прежде чем импортировать ZArith.)
1 ответ:
Проблема здесь в том, что вы зависите от конкретного термина равенства, абстрагирование над ним должно позволить вам продолжить. (Это-общая хорошая практика, чтобы заявить леммы, которые независимы от доказательств).
Вот ваш пример, используя ssreflect's rewrite. К сожалению, я не смог заставить одного Кок сделать правильный выбор рисунка.
Comments "pkgs: coq-reals". From mathcomp Require Import ssreflect. Require Import Coq.ZArith.ZArith. Open Scope Z_scope. Program Definition test (x:Z) : option (x <= 100) := match Z_le_gt_dec x 100 with | left bound => Some _ | right bound => None end. Lemma test_gt_100 : forall x:Z, x > 100 -> test x = None. Proof. intros x hb; unfold test. assert (Z_le_gt_dec x 100 = right hb) as Hz. admit. move: eq_refl; rewrite {1 3}Hz. done.
[также в https://x80.org/collacoq/xareboqura.coq ]
С наилучшими пожеланиями, е.
EDIT: немного подробнее: на в начале аргументом соответствия является
Таким образом, мы модифицируем нашу цель так, что доказательство равенства не обязательно должно бытьeq_refl : forall x, x = x
, что нормально, так как функция внутри соответствия ожидает член типаZ.le .... = Z.le ....
. Однако при выполнении перезаписи тип в аннотации соответствия будет иметь видZ_le ... = right ...
, но если аргумент все ещеeq_refl
, это приведет к плохо набранному термину, так какeq_refl
никогда не может быть набран какZ.le ... = right ...
!eq_refl
, а затем переписываем.Почему доказательство было сделано с помощью
Было бы интересно добавить поддержку доказательства неуместности к программе thou. (Я игнорирую, если они уже есть).eq_refl
в первую очередь? Это обычно делается, чтобы иметь хорошее поведение сокращения при наличии доказательств равенства.