Home

Awesome

This Library provides several coq tactics and tacticals to deal with hypothesis during a proof.

Main page and documentation: https://github.com/Matafou/LibHyps

Demo file demo.v acts as a documentation.

Short description:

LibHyps provides utilities for hypothesis manipulations. In particular a new tactic especialize H and a set of tacticals to appy or iterate tactics either on all hypothesis of a goal or on "new' hypothesis after a tactic. It also provide syntax for a few predefined such iterators.

QUICK REF: especialize

This tactic was broken in coq v8.18. It is now fixed with some modification: see the remark about evars below

QUICK REF: Pre-defined tacticals /s /n...

The most useful user-dedicated tacticals are the following

Install

Quick install using opam

If you have not done it already add the coq platform repository to opam!

opam repo add coq-released https://coq.inria.fr/opam/released

and then:

opam install coq-libhyps

Quick install using github:

Clone the github repository:

git clone https://github.com/Matafou/LibHyps

then compile:

configure.sh
make
make install

Quick test:

Require Import LibHyps.LibHyps.

Demo files demo.v.

More information

Deprecation from 1.0.x to 2.0.x

KNOWN BUGS

Due to Ltac limitation, it is difficult to define a tactic notation tac1 ; { tac2 } which delays tac1 and tac2 in all cases. Sometimes (rarely) you will have to write (idtac; tac1); {idtac; tac2}. You may then use tactic notation like: Tactic Notation tac1' := idtac; tac1..

Examples

Require Import LibHyps.LibHyps.

Lemma foo: forall x y z:nat,
    x = y -> forall  a b t : nat, a+1 = t+2 -> b + 5 = t - 7 ->  (forall u v, v+1 = 1 -> u+1 = 1 -> a+1 = z+2)  -> z = b + x-> True.
Proof.
  intros.
  (* ugly names *)
  Undo.
  (* Example of using the iterator on new hyps: this prints each new hyp name. *)
  intros; {fun h => idtac h}.
  Undo.
  (* This gives sensible names to each new hyp. *)
  intros ; { autorename }.
  Undo.
  (* short syntax: *)
  intros /n.
  Undo.
  (* same thing but use subst if possible, and group non prop hyps to the top. *)
  intros ; { substHyp }; { autorename}; {move_up_types}.
  Undo.
  (* short syntax: *)  
  intros /s/n/g.
  Undo.
  (* Even shorter: *)  
  intros /s/n/g.

  (* Let us instantiate the 2nd premis of h_all_eq_add_add without copying its type: *)
  especialize h_all_eq_add_add_ with u at 2.
  { apply Nat.add_0_l. }
  (* now h_all_eq_add_add is specialized *)
  Undo 6.
  intros until 1.
  (** The taticals apply after any tactic. Notice how H:x=y is not new
    and hence not substituted, whereas z = b + x is. *)
  destruct x eqn:heq;intros /sng.
  - apply I.
  - apply I.
Qed.

Short Documentation

The following explains how it works under the hood, for people willing to apply more generic iterators to their own tactics. See also the code.

Iterator on all hypothesis

Iterators on ALL NEW hypothesis (since LibHyps-1.2.0)

Iterators on EACH NEW hypothesis

Customizable hypothesis auto naming system

Using previous taticals (in particular the ;!; tactical), some tactic allow to rename hypothesis automatically.

How to cstomize the naming scheme

The naming engine analyzes the type of hypothesis and generates a name mimicking the first levels of term structure. At each level the customizable tactic rename_hyp is called. One can redefine it at will. It must be of the following form:

(** Redefining rename_hyp*)
(* First define a naming ltac. It takes the current level n and
   the sub-term th being looked at. It returns a "name". *)
Ltac rename_hyp_default n th :=
   match th with
   | (ind1 _ _) => name (`ind1`)
   | (ind1 _ _ ?x ?y) => name (`ind1` ++ x#(S n)x ++ y$n)
   | f1 _ ?x = ?y => name (`f1` ++ x#n ++ y#n)
   | _ => previously_defined_renaming_tac1 n th (* cumulative with previously defined renaming tactics *)
   | _ => previously_defined_renaming_tac2 n th
   end.

(* Then overwrite the definition of rename_hyp using the ::= operator. :*)
Ltac rename_hyp ::= my_rename_hyp.

Where:

How to define variants of these tacticals?

Some more example of tacticals performing cleaning and renaming on new hypothesis.

(* subst or revert *)
Tactic Notation (at level 4) "??" tactic4(tac1) :=
  (tac1 ;; substHyp ;!; revertHyp).
(* subst or rename or revert *)
Tactic Notation "!!!" tactic3(Tac) := (Tac ;; substHyp ;!; revert_if_norename ;; autorename).
(* subst or rename or revert + move up if in (Set or Type). *)
Tactic Notation (at level 4) "!!!!" tactic4(Tac) :=
      (Tac ;; substHyp ;!; revert_if_norename ;; autorename ;; move_up_types).

About the logical "completeness" of especialize

Suppose we have this goal:

  Lemma foo: (forall x:nat, x = 1 -> (x>0) -> x < 0) -> False.
  Proof.
    intros h.

h : forall x : nat, x = 1 -> x > 0 -> x < 0
  ============================
  False

especialize h with x at 2.


  h : ?x = 1 -> ?x > 0 -> ?x < 0
  ============================
  ?x > 0

goal 2 (ID 88) is:
 False

Note that in this case it would be preferable (and logically more accurate) to have a hypothesis h2: ?x = 1 in the context, since the premise 2 of H needs only to be proved when premise 1 is true. Note however that in this kind of situation most users would wait to be able to prove premise 1 before instantiating premise 2. especialize does not cover this kind of subtleties. Another tactic is under development to support this kind of reasoning.

<!-- LocalWords: subgoal unifiable evars -->