Другой ответ касается разборчивой части, я сосредоточусь на ручном доказательстве. Ты пытался:
Lemma l2: A=B -> False.
apply (fun e:(A=B) => match e with end).
Defined.
Что следует отметить и заставляет меня часто чувствовать себя некомфортно при использовании Coq, так это то, что Coq принимает неточно определенные определения, которые он внутренне переписывает в хорошо типизированные термины. Это позволяет быть менее подробным, поскольку Coq добавляет некоторые части. Но с другой стороны, Coq манипулирует термином, отличным от того, который мы ввели.
Это ваше доказательство. Естественно, сопоставление с образцом на e
должно включать конструктор eq_refl
, который является единственным конструктором типа eq
. Здесь Coq обнаруживает, что равенство не используется, и, таким образом, понимает, как изменить ваш код, но то, что вы ввели, не является правильным сопоставлением с образцом.
Два ингредиента могут помочь понять, что здесь происходит:
- определение
eq
- полный синтаксис сопоставления с образцом с условиями
as
, in
и return
Во-первых, мы можем взглянуть на определение eq
.
Inductive eq {A : Type} (x : A) : A -> Prop := eq_refl : x = x.
Обратите внимание, что это определение отличается от того, которое кажется более естественным (во всяком случае, более симметричным).
Inductive eq {A : Type} : A -> A -> Prop := eq_refl : forall (x:A), x = x.
Это действительно важно, чтобы eq
определялся первым определением, а не вторым. В частности, для нашей проблемы важно то, что в x = y
x
является параметром, а y
- индексом. То есть x
является постоянным для всех конструкторов, а y
может отличаться в каждом конструкторе. У вас такая же разница с типом Vector.t
. Тип элементов вектора не изменится, если вы добавите элемент, поэтому он реализован как параметр. Однако его размер может меняться, поэтому он реализован в виде индекса.
Теперь давайте посмотрим на расширенный синтаксис сопоставления с образцом. Я даю здесь очень краткое объяснение того, что я понял. Не стесняйтесь обращаться к справочному руководству для получения более безопасной информации. . Предложение return
может помочь указать тип возвращаемого значения, который будет отличаться для каждой ветви. В этом предложении могут использоваться переменные, определенные в предложениях as
и in
сопоставления с образцом, которое связывает, соответственно, согласованный термин и индексы типа. Предложение return
будет интерпретироваться в контексте каждой ветви, заменяя переменные as
и in
, используя этот контекст, для проверки типов ветвей одну за другой и использовать для ввода match
с внешней точки зрения.
Вот надуманный пример с предложением as
:
Definition test n :=
match n as n0 return (match n0 with | 0 => nat | S _ => bool end) with
| 0 => 17
| _ => true
end.
В зависимости от значения n
мы не возвращаем один и тот же тип. Тип test
- forall n : nat, match n with | 0 => nat | S _ => bool end
. Но когда Coq может решить, в каком случае совпадение мы, он может упростить тип. Например:
Definition test2 n : bool := test (S n).
Здесь Coq знает, что, что бы ни было n
, S n
, заданное test
, будет иметь результат типа bool
.
Для равенства мы можем сделать нечто подобное, на этот раз используя предложение in
.
Definition test3 (e:A=B) : False :=
match e in (_ = c) return (match c with | B => False | _ => True end) with
| eq_refl => I
end.
Что тут происходит ? По сути, Coq проверяет типы отдельно ветвей match
и самого match
. В единственной ветви eq_refl
, c
равно A
(из-за определения eq_refl
, который создает экземпляр индекса с тем же значением, что и параметр), поэтому мы заявили, что вернули некоторое значение типа True
, здесь I
. Но если смотреть со стороны, c
равно B
(потому что e
относится к типу A=B
), и на этот раз предложение return
утверждает, что match
возвращает некоторое значение типа False
. Здесь мы используем возможности Coq для упрощения сопоставления с образцом в типах, которые мы только что видели с test2
. Обратите внимание, что мы использовали True
в других случаях, кроме B
, но нам не нужен True
в частности. Нам нужен только какой-то жилой тип, чтобы мы могли вернуть что-то в ветке eq_refl
.
Возвращаясь к странному термину, созданному Coq, метод, используемый Coq, делает нечто подобное, но в этом примере, безусловно, более сложное. В частности, Coq часто использует типы IDProp
, населенные idProp
, когда ему нужны бесполезные типы и термины. Они соответствуют True
и I
, использованным выше.
Наконец, я даю ссылку на обсуждение coq-club, которое действительно помогло мне понять, как расширенное сопоставление шаблонов набирается в Coq.
person
eponier
schedule
23.03.2017