Search code examples
coqltac

Matching expression context under `forall` with Ltac


Say I have the following definitions in Coq:

Inductive Compare := Lt | Eq | Gt.

Fixpoint compare (x y : nat) : Compare :=
  match x, y with
  | 0, 0   => Eq
  | 0, S _ => Lt
  | S _, 0 => Gt
  | S x', S y' => compare x' y'
  end.

Now consider this lemma:

Lemma foo : forall (x: nat),
    (forall z, match compare x z with
               | Lt => False
               | Eq => False
               | Gt => False
               end) -> nat -> False.
Proof.
  intros x H y.

At this point proof state looks like this:

   x : nat
   H : forall z : nat,
       match compare x z with
       | Lt => False
       | Eq => False
       | Gt => False
       end
   y : nat
   ============================
   False

I'd like to write Ltac match goal that will detect that:

a) there is a hypothesis x : nat that is used as an argument to compare somewhere inside a quantified hypothesis H

b) and there is some other hypothesis of type nat - namely y - that can be used to specialize the quantified hypothesis.

c) and once we have those two things specialize H to y

I tried doing it like this:

 match goal with
 | [ X : nat, Y : nat
   , H : forall (z : nat), context [ compare X z ] |- _ ] => specialize (H Y)
 end.

But there are at least two things that are wrong with this code:

  1. Using context under a forall seems disallowed.

  2. I can't figure out a correct way to pass X as argument to compare in a way that it is recognized as something that exists as a hypothesis.doing it like this:


Solution

  • If you want to check that X occurs in the quantified hypothesis H, it suffices to check that it occurs in H after it is instantiated with any value that does not contain X. For instance, you can instantiate H with Y by simply writing the application of H as a function to Y. Here is my proposal:

    match goal with | X : nat, H : _, Y : nat |- _ =>
      match type of (H Y) with | context[X] => specialize (H Y) end
    end.
    

    This Ltac text really checks that H is a function. If you want to be more precise and state that H should really be a universal quantification (or a product type), then you can check that the type of (H Y) also contains Y, as in the following fragment:

    match goal with | X : nat, H : _, Y : nat |- _ =>
      match type of (H Y) with | context[X] => 
        match type of (H Y) with | context [Y] => specialize (H Y) end
      end
    end.