LARA

Coq Basic Tactics

We give in this page a few user-defined tactics that you can use to simplify your proofs. Feel free to also define your own tactics to automate the simple parts of your proofs.

 Require Import Coq.micromega.Psatz. (* `lia` tactic for linear integer arithmetic *)

(* enables use of `eauto with lia` *)
Hint Extern 1 => lia: lia.

(* enables use of `eauto with exfalso` *)
Hint Extern 1 => exfalso: exfalso.

(* enables use of `eauto with try_nil` *)
Hint Extern 1 => exists nil: try_nil.

(* destruct pairs in context *)
Ltac destruct_pairs :=
  match goal with
  | H: _ * _ |- _ => destruct H
  end.

(* destruct existentials in context *)
Ltac destruct_exists :=
  match goal with
  | H: exists x, _ |- _ => let freshX := fresh x in destruct H as [ freshX ]
  end.

(* destruct refinements in context *)
Ltac destruct_refinements :=
  match goal with
  | H: { x: _ | _ } |- _ => let freshX := fresh x in destruct H as [ freshX ]
  end.

(* one step using basic Coq tactics, using computation simplification *)
Ltac step0 :=
  (intuition auto) || congruence || subst ||
  destruct_exists || destruct_pairs || destruct_refinements.

(* one step using basic Coq tactics, with computation simplification *)
(* use `repeat step` for performing all possible simplifications *)
Ltac step := step0 || cbn in *.

(* enables use of `eauto with step` *)
Hint Extern 1 => repeat step: step.

(* performs case analysis whenever there is a `match` somewhere *)
(* you can e.g. use `repeat step || destruct_match` if you want to *)
(* perform as many simplifications and case analyses as possible *)
Ltac destruct_match :=
  match goal with
  | [ |- context[match ?t with _ => _ end]] =>
    let matched := fresh "m" in
    destruct t eqn:matched
  | [ H: context[match ?t with _ => _ end] |- _ ] =>
    let matched := fresh "m" in
    destruct t eqn:matched
end.

(* when the goal is an equality between two terms starting using the same constructor *)
(* this generates subgoals for proving that the arguments are equal *)
Ltac constructor_equality :=
  match goal with
  | |- ?F _ = ?F _ => is_constructor F; f_equal
  | |- ?F _ _ = ?F _ _ => is_constructor F; f_equal
  | |- ?F _ _ _ = ?F _ _ _ => is_constructor F; f_equal
  | |- ?F _ _ _ _ = ?F _ _ _ _ => is_constructor F; f_equal
  | |- ?F _ _ _ _ _ = ?F _ _ _ _ _ => is_constructor F; f_equal
  | |- ?F _ _ _ _ _ _ = ?F _ _ _ _ _ _ => is_constructor F; f_equal
  end.

(* when there is an equality between the same constructor in a hypothesis H *)
(* this creates new hypotheses stating that the arguments are equal *)
Ltac invert_constructor_equality :=
  match goal with
  | H: ?F _ = ?F _ |- _ => is_constructor F; inversion H; clear H
  | H: ?F _ _ = ?F _ _ |- _ => is_constructor F; inversion H; clear H
  | H: ?F _ _ _ = ?F _ _ _ |- _ => is_constructor F; inversion H; clear H
  | H: ?F _ _ _ _ = ?F _ _ _ _ |- _ => is_constructor F; inversion H; clear H
  | H: ?F _ _ _ _ _ = ?F _ _ _ _ _ |- _ => is_constructor F; inversion H; clear H
  | H: ?F _ _ _ _ _ _ = ?F _ _ _ _ _ _ |- _ => is_constructor F; inversion H; clear H
  end.

(* Try to apply some lemma in any hypothesis *)
Ltac apply_anywhere f :=
  match goal with
  | H: _ |- _ => apply f in H
  end.

(* Try to eapply some lemma in any hypothesis *)
Ltac eapply_anywhere f :=
  match goal with
  | H: _ |- _ => eapply f in H
  end.

(* Try to apply some hypothesis *)
Ltac apply_any :=
  match goal with
  | H: _ |- _ => apply H
  end.

(* Try to eapply some hypothesis *)
Ltac eapply_any :=
  match goal with
  | H: _ |- _ => eapply H
  end.

Hint Extern 1 => apply_any : apply_any.
Hint Extern 1 => eapply_any : eapply_any.

(* Attempt to instantiate one forall quantified hypothesis to another one *)
Ltac instantiate_any :=
  match goal with
  | H1: forall _, _ -> _, H2: _ |- _ => pose proof (H1 _ H2); clear H1
  | H1: forall _ _, _ -> _, H2: _ |- _ => pose proof (H1 _ _ H2); clear H1
  | H1: forall _ _ _, _ -> _, H2: _ |- _ => pose proof (H1 _ _ _ H2); clear H1
  | H1: forall _ _ _ _, _ -> _, H2: _ |- _ => pose proof (H1 _ _ _ _ H2); clear H1
  | H1: forall _ _ _ _ _, _ -> _, H2: _ |- _ => pose proof (H1 _ _ _ _ _ H2); clear H1
  | H1: forall _ _ _ _ _ _, _ -> _, H2: _ |- _ => pose proof (H1 _ _ _ _ _ _ H2); clear H1
  end.

(* Attempt to instantiate one forall quantified `iff` to a hypothesis *)
Ltac instantiate_any_iff :=
  match goal with
  | H1: forall _, _ <-> _, H2: _ |- _ => unfold iff in H1; pose proof (proj1 (H1 _) H2); clear H1
  | H1: forall _, _ <-> _, H2: _ |- _ => unfold iff in H1; pose proof (proj2 (H1 _) H2); clear H1
  | H1: forall _ _, _ <-> _, H2: _ |- _ => unfold iff in H1; pose proof (proj1 (H1 _ _) H2); clear H1
  | H1: forall _ _, _ <-> _, H2: _ |- _ => unfold iff in H1; pose proof (proj2 (H1 _ _) H2); clear H1
  | H1: forall _ _ _, _ <-> _, H2: _ |- _ => unfold iff in H1; pose proof (proj1 (H1 _ _ _) H2); clear H1
  | H1: forall _ _ _, _ <-> _, H2: _ |- _ => unfold iff in H1; pose proof (proj2 (H1 _ _ _) H2); clear H1
  | H1: forall _ _ _ _, _ <-> _, H2: _ |- _ => unfold iff in H1; pose proof (proj1 (H1 _ _ _ _) H2); clear H1
  | H1: forall _ _ _ _, _ <-> _, H2: _ |- _ => unfold iff in H1; pose proof (proj2 (H1 _ _ _ _) H2); clear H1
  | H1: forall _ _ _ __, _ <-> _, H2: _ |- _ =>
      unfold iff in H1; pose proof (proj1 (H1 _ _ _ _ _) H2); clear H1
  | H1: forall _ _ _ _ _, _ <-> _, H2: _ |- _ =>
      unfold iff in H1; pose proof (proj2 (H1 _ _ _ _ _) H2); clear H1
  | H1: forall _ _ _ _ _ _, _ <-> _, H2: _ |- _ =>
      unfold iff in H1; pose proof (proj1 (H1 _ _ _ _ _ _) H2); clear H1
  | H1: forall _ _ _ _ _ _, _ <-> _, H2: _ |- _ =>
      unfold iff in H1; pose proof (proj2 (H1 _ _ _ _ _ _) H2); clear H1
  end.