`match goal` не соответствует выражению let destructuring

#coq #coq-tactic

#coq #coq-тактика

Вопрос:

Я пытаюсь доказать теорему, включающую функцию, которая использует let выражение деструктурирования, и пытаюсь использовать match goal тактику для уничтожения правой стороны, но по какой-то причине шаблон не соответствует, как я ожидал:

 match goal with
  (* why doesn't this match? *)
  | [ |- context[let _ := ?X in _] ] => destruct X
end.
  

Вот фрагмент кода, который должен быть доступен для выполнения, если у вас есть Cpdt сертифицированное программирование с зависимыми типами (я большой сторонник его стиля автоматизации).

Я нашел доказательство, но я планирую доказать еще много теорем с аналогичной формой, и я хотел бы иметь автоматическую тактику, способную доказать многие из них.

 Set Implicit Arguments. Set Asymmetric Patterns.
Require Import List Cpdt.CpdtTactics.
Import ListNotations.

Section PairList.
  Variable K V: Set.
  Variable K_eq_dec: forall x y: K, {x = y}   {x <> y}.
  Variable V_eq_dec: forall x y: V, {x = y}   {x <> y}.

  Definition Pair: Type := (K * V).
  Definition PairList := list Pair.
  (* ... *)

  Fixpoint set (l: PairList) (key: K) (value: V): PairList :=
    match l with
    | [] => [(key, value)]
    | pr::l' => let (k, _) := pr in
      if K_eq_dec key k then (key, value)::l' else pr::(set l' key value)
    end.

  Theorem set_NotEmpty: forall (before after: PairList) key value,
    after = set before key value -> after <> [].
  Proof.
    intros before after. induction before.
    - crush.
    - intros. rewrite -> H. simpl.

      (* the context at this step:
        1 subgoal

          K, V : Set
          K_eq_dec : ...
          V_eq_dec : ...
          a : Pair
          before : list Pair
          after : PairList
          IHbefore: ...
          key : K
          value : V
          H : ...
          ============================
          (let (k, _) := a in
           if K_eq_dec key k
           then (key, value) :: before
           else
            a :: set before key value) <> []
      *)

      (* a successful proof
        destruct a.
        destruct (K_eq_dec key k); crush.
      *)

      match goal with
        (* why doesn't this match? *)
        | [ |- context[let _ := ?X in _] ] => destruct X
        | [ |- context[(() <> [])] ] => idtac X
      end.
      (* the above command prints this:
        (let (k, _) := a in
         if K_eq_dec key k
         then (key, value) :: before
         else
          a :: set before key value)
      *)
  Qed.
End PairList.
  

Ответ №1:

Деструктурирующие разрешения на самом деле совпадают, поэтому вам нужно искать match . Когда тактика не соответствует, вы можете увидеть все выражения в вашей цели, разделенные с Set Printing All.

       match goal with
        | [ |- context[let _ := ?X in _] ] => destruct X
        (* ADD THIS LINE *)
        | [ |- context[match ?X with _ => _ end]] => destruct X
        | [ |- context[(() <> [])] ] => idtac X
      end.
  

Комментарии:

1. Это сработало отлично! Спасибо! Однако мне любопытно, есть ли какая-то основная причина match goal , по которой работает с if операторами, а не с операторами let? Эта строка работает при возникновении if | [ |- context[if ?X then _ else _] ] => destruct X , и я понимаю, что операторы if также являются сахаром для a match .

2. Ли-Яо Ся начал свое сообщение с «деструктурирования lets are …» Обозначение, которое вы использовали в своем вопросе, предназначено для простого let, а не для деструктурирования. Существует два вида let конструкций, и только одна из них является sugar для соответствия.