This file collects a number of basic lemmas and tactics for better proof automation, structuring large proofs, or rewriting. Most of the rewriting support is ported from ss-reflect.
Symbols starting with vlib__ are internal.

Require Import Logic.Eqdep.
Require Import Bool.
Require Import Arith.
Require Import ZArith.
Require Import String.

Open Scope bool_scope.
Open Scope list_scope.

Set Implicit Arguments.

Axioms


Require ClassicalFacts.
Require Export FunctionalExtensionality.
Require Export ProofIrrelevance.

Ltac exten := apply functional_extensionality.

Coersion of bool into Prop


Coersion of bools into Prop
Coercion is_true (b : bool) : Prop := b = true.

Hints for auto

Very basic automation


Set up for basic simplification


Adaptation of the ss-reflect "done" tactic.

Ltac vlib__basic_done :=
  solve [trivial with vlib | apply sym_equal; trivial | discriminate | contradiction].

Ltac done := trivial with vlib; hnf; intros;
  solve [try vlib__basic_done; split;
         try vlib__basic_done; split;
         try vlib__basic_done; split;
         try vlib__basic_done; split;
         try vlib__basic_done; split; vlib__basic_done
    | match goal with H : ¬ _ |- _solve [case H; trivial] end].

A variant of the ssr "done" tactic that performs "eassumption".

Ltac edone := try eassumption; trivial; hnf; intros;
  solve [try eassumption; try vlib__basic_done; split;
         try eassumption; try vlib__basic_done; split;
         try eassumption; try vlib__basic_done; split;
         try eassumption; try vlib__basic_done; split;
         try eassumption; try vlib__basic_done; split;
         try eassumption; vlib__basic_done
    | match goal with H : ¬ _ |- _solve [case H; trivial] end].

Tactic Notation "by" tactic(tac) := (tac; done).
Tactic Notation "eby" tactic(tac) := (tac; edone).

Boolean reflection


These definitions are ported from ssr-bool.
Negation lemmas
Section NegationLemmas.

  Variables (b c : bool).

  Lemma negbT : b = falsenegb b.
  Lemma negbTE: negb bb = false.
  Lemma negbF : bnegb b = false.
  Lemma negbFE: negb b = falseb.
  Lemma negbNE: negb (negb b) → b.

  Lemma negbLR : b = negb cnegb b = c.

  Lemma negbRL : negb b = cb = negb c.

  Lemma contra : (cb) → negb bnegb c.

End NegationLemmas.

Lemmas for ifs, which allow reasoning about the condition without repeating it inside the proof.
Section BoolIf.

Variables (A B : Type) (x : A) (f : AB) (b : bool) (vT vF : A).

Inductive if_spec : AboolSet :=
  | IfSpecTrue : bif_spec vT true
  | IfSpecFalse : b = falseif_spec vF false.

Lemma ifP : if_spec (if b then vT else vF) b.

Lemma if_same : (if b then vT else vT) = vT.

Lemma if_neg : (if negb b then vT else vF) = if b then vF else vT.

Lemma fun_if : f (if b then vT else vF) = if b then f vT else f vF.

Lemma if_arg : fT fF : AB,
  (if b then fT else fF) x = if b then fT x else fF x.

End BoolIf.

The reflection predicate
Inductive reflect (P : Prop) : boolSet :=
  | ReflectT : Preflect P true
  | ReflectF : ¬ Preflect P false.

Internal reflection lemmas
Section ReflectCore.

Variables (P : Prop) (b : bool) (Hb : reflect P b) (Q : Prop) (c : bool).

Lemma introNTF : (if c then ¬ P else P) → negb b = c.

Lemma introTF : (if c then P else ¬ P) → b = c.

Lemma elimNTF : negb b = cif c then ¬ P else P.

Lemma elimTF : b = cif c then P else ¬ P.

Lemma equivPif : (QP) → (PQ) → if b then Q else ¬ Q.

Lemma xorPif : Q P¬ (Q P)if b then ¬ Q else Q.

End ReflectCore.

Internal negated reflection lemmas
Section ReflectNegCore.

Variables (P : Prop) (b : bool) (Hb : reflect P (negb b)) (Q : Prop) (c : bool).

Lemma introTFn : (if c then ¬ P else P) → b = c.

Lemma elimTFn : b = cif c then ¬ P else P.

Lemma equivPifn : (QP) → (PQ) → if b then ¬ Q else Q.

Lemma xorPifn : Q P¬ (Q P)if b then Q else ¬ Q.

End ReflectNegCore.

User-oriented reflection lemmas
Section Reflect.

Variables (P Q : Prop) (b b' c : bool).
Hypotheses (Pb : reflect P b) (Pb' : reflect P (negb b')).

Lemma introT : Pb.
Lemma introF : ¬ Pb = false.
Lemma introN : ¬ Pnegb b.
Lemma introNf : Pnegb b = false.
Lemma introTn : ¬ Pb'.
Lemma introFn : Pb' = false.

Lemma elimT : bP.
Lemma elimF : b = false¬ P.
Lemma elimN : negb b¬P.
Lemma elimNf : negb b = falseP.
Lemma elimTn : b'¬ P.
Lemma elimFn : b' = falseP.

Lemma introP : (bQ) → (negb b¬ Q) → reflect Q b.

Lemma iffP : (PQ) → (QP) → reflect Q b.

Lemma appP : reflect Q bPQ.

Lemma sameP : reflect P cb = c.

Lemma decPcases : if b then P else ¬ P.

Definition decP : {P} + {¬ P}.

End Reflect.

Coercion elimT : reflect >→ Funclass.

Section ReflectConnectives.

Variable b1 b2 b3 b4 b5 : bool.

Lemma idP : reflect b1 b1.

Lemma idPn : reflect (negb b1) (negb b1).

Lemma negP : reflect (¬ b1) (negb b1).

Lemma negPn : reflect b1 (negb (negb b1)).

Lemma negPf : reflect (b1 = false) (negb b1).

Lemma andP : reflect (b1 b2) (b1 && b2).

Lemma orP : reflect (b1 b2) (b1 || b2).

Lemma nandP : reflect (negb b1 negb b2) (negb (b1 && b2)).

Lemma norP : reflect (negb b1 negb b2) (negb (b1 || b2)).

End ReflectConnectives.

Equality types


These definitions are ported from ssr-eq.

Inductive phantom (T : Type) (p : T) : Type := Phantom.
Implicit Arguments phantom [].
Implicit Arguments Phantom [].
Definition phant_id T1 T2 v1 v2 := phantom T1 v1phantom T2 v2.
Definition idfun T := (fun x : Tx).

Module Equality.

Definition axiom T (e : TTbool) := x y, reflect (x = y) (e x y).

Structure mixin_of T := Mixin {op : TTbool; _ : axiom op}.
Notation class_of := mixin_of (only parsing).

Section ClassDef.

Structure type := Pack {sort; _ : class_of sort; _ : Type}.
Local Coercion sort : type >→ Sortclass.
Variables (T : Type) (cT : type).
Definition class cT' := match cT' return class_of cT' with Pack _ c _c end.

Definition pack c := @Pack T c T.
Definition clone := fun c (_ : cTT) (_ : phant_id (pack c) cT) ⇒ pack c.

End ClassDef.

Module Exports.
Coercion sort : type >→ Sortclass.
Notation eqType := type.
Notation EqMixin := Mixin.
Notation EqType T m := (@pack T m).
Notation "[ 'eqMixin' 'of' T ]" := (class _ : mixin_of T)
  (at level 0, format "[ 'eqMixin' 'of' T ]") : form_scope.
Notation "[ 'eqType' 'of' T 'for' C ]" := (@clone T C _ idfun id)
  (at level 0, format "[ 'eqType' 'of' T 'for' C ]") : form_scope.
Notation "[ 'eqType' 'of' T ]" := (@clone T _ _ id id)
  (at level 0, format "[ 'eqType' 'of' T ]") : form_scope.
End Exports.

End Equality.
Export Equality.Exports.

Definition eq_op T := Equality.op (Equality.class T).
Implicit Arguments eq_op [[T]].

Lemma eqE : T x, eq_op x = Equality.op (Equality.class T) x.

Lemma eqP : T, Equality.axiom (@eq_op T).
Implicit Arguments eqP [T].

Notation "x == y" := (eq_op x y)
  (at level 70, no associativity) : bool_scope.
Notation "x == y :> T" := ((x : T) == (y : T))
  (at level 70, y at next level) : bool_scope.
Notation "x != y" := (negb (x == y))
  (at level 70, no associativity) : bool_scope.
Notation "x != y :> T" := (negb (x == y :> T))
  (at level 70, y at next level) : bool_scope.

Lemma vlib__internal_eqP :
   (T: eqType) (x y : T), reflect (x = y) (x == y).

Lemma neqP : (T: eqType) (x y: T), reflect (x y) (x != y).

Lemma beq_refl : (T : eqType) (x : T), x == x.

Lemma beq_sym : (T : eqType) (x y : T), (x == y) = (y == x).

Hint Resolve beq_refl : vlib.
Hint Rewrite beq_refl : vlib_trivial.

Notation eqxx := beq_refl.


Basic simplification tactics


Lemma vlib__negb_rewrite : b, negb bb = false.

Lemma vlib__andb_split : b1 b2, b1 && b2b1 b2.

Lemma vlib__nandb_split : b1 b2, b1 && b2 = falseb1 = false b2 = false.

Lemma vlib__orb_split : b1 b2, b1 || b2b1 b2.

Lemma vlib__norb_split : b1 b2, b1 || b2 = falseb1 = false b2 = false.

Lemma vlib__eqb_split : b1 b2 : bool, (b1b2) → (b2b1) → b1 = b2.

Lemma vlib__beq_rewrite : (T : eqType) (x1 x2 : T), x1 == x2x1 = x2.

Set up for basic simplification: database of reflection lemmas


Hint Resolve andP orP nandP norP negP vlib__internal_eqP neqP : vlib_refl.

Ltac vlib__complaining_inj f H :=
  let X := fresh in
  (match goal with | [|- ?P ] ⇒ set (X := P) end);
  injection H;
  
  clear H; intros; subst X;
  try subst.

Ltac vlib__clarify1 :=
  try subst;
  repeat match goal with
  | [H: is_true (andb _ _) |- _] ⇒
      let H' := fresh H in case (vlib__andb_split H); clear H; intros H' H
  | [H: is_true (negb ?x) |- _] ⇒ rewrite (vlib__negb_rewrite H) in *
  | [H: is_true ?x |- _] ⇒ rewrite H in *
  | [H: ?x = true |- _] ⇒ rewrite H in *
  | [H: ?x = false |- _] ⇒ rewrite H in *
  | [H: is_true (_ == _) |- _] ⇒ generalize (vlib__beq_rewrite H); clear H; intro H
  | [H: @existT _ _ _ _ = @existT _ _ _ _ |- _] ⇒ apply inj_pair2 in H; try subst
  | [H: ?f _ = ?f _ |- _] ⇒ vlib__complaining_inj f H
  | [H: ?f _ _ = ?f _ _ |- _] ⇒ vlib__complaining_inj f H
  | [H: ?f _ _ _ = ?f _ _ _ |- _] ⇒ vlib__complaining_inj f H
  | [H: ?f _ _ _ _ = ?f _ _ _ _ |- _] ⇒ vlib__complaining_inj f H
  | [H: ?f _ _ _ _ _ = ?f _ _ _ _ _ |- _] ⇒ vlib__complaining_inj f H
  | [H: ?f _ _ _ _ _ _ = ?f _ _ _ _ _ _ |- _] ⇒ vlib__complaining_inj f H
  | [H: ?f _ _ _ _ _ _ _ = ?f _ _ _ _ _ _ _ |- _] ⇒ vlib__complaining_inj f H
  end; try done.

Perform injections & discriminations on all hypotheses

Ltac clarify :=
  vlib__clarify1;
  repeat match goal with
    | H1: ?x = Some _, H2: ?x = None |- _rewrite H2 in H1; discriminate
    | H1: ?x = Some _, H2: ?x = Some _ |- _rewrite H2 in H1; vlib__clarify1
  end; try done.

Kill simple goals that require up to two econstructor calls.

Ltac vauto :=
  (clarify; try edone;
   try (econstructor (solve [edone | econstructor (edone) ]))).

Check that the hypothesis id is defined. This is useful to make sure that an assert has been completely finished.

Ltac end_assert id :=
  let m := fresh in
  pose (m := refl_equal id); clear m.

Ltac inv x := inversion x; clarify.
Ltac simpls := simpl in *; try done.
Ltac ins := simpl in *; try done; intros.

Tactic Notation "case_eq" constr(x) := case_eq (x).

Tactic Notation "case_eq" constr(x) "as" simple_intropattern(H) :=
  destruct x as [] _eqn: H; try done.

Ltac vlib__clarsimp1 :=
  clarify; (autorewrite with vlib_trivial vlib in * );
  (autorewrite with vlib_trivial in * ); try done;
  clarify; auto 1 with vlib.

Ltac clarsimp := intros; simpl in *; vlib__clarsimp1.

Ltac autos := clarsimp; auto with vlib.

Destruct but give useful names

Definition NW (P: unitProp) : Prop := P tt.

Notation "<< x : t >>" := (NW (fun xt)) (at level 80, x ident, no associativity).
Notation "<< t >>" := (NW (fun _t)) (at level 79, no associativity).

Ltac unnw := unfold NW in *.
Ltac rednw := red; unnw.

Hint Unfold NW.

Destruct, but no case split
Ltac desc :=
  repeat match goal with
    | H: is_true (_ == _) |- _generalize (vlib__beq_rewrite H); clear H; intro H
    | H : x, NW (fun y_) |- _
      let x' := fresh x in let y' := fresh y in destruct H as [x' y']; red in y'
    | H : x, ?p |- _
      let x' := fresh x in destruct H as [x' H]
    | H : ?p ?q |- _
      let x' := match p with | NW (fun z_) ⇒ fresh z | _H end in
      let y' := match q with | NW (fun z_) ⇒ fresh z | _fresh H end in
      destruct H as [x' y'];
      match p with | NW _red in x' | _idtac end;
      match q with | NW _red in y' | _idtac end
    | H : is_true (_ && _) |- _
          let H' := fresh H in case (vlib__andb_split H); clear H; intros H H'
    | H : (_ || _) = false |- _
          let H' := fresh H in case (vlib__norb_split H); clear H; intros H H'
    | H : ?x = ?x |- _clear H


  end.

Ltac des :=
  repeat match goal with
    | H: is_true (_ == _) |- _generalize (vlib__beq_rewrite H); clear H; intro H
    | H : x, NW (fun y_) |- _
      let x' := fresh x in let y' := fresh y in destruct H as [x' y']; red in y'
    | H : x, ?p |- _
      let x' := fresh x in destruct H as [x' H]
    | H : ?p ?q |- _
      let x' := match p with | NW (fun z_) ⇒ fresh z | _H end in
      let y' := match q with | NW (fun z_) ⇒ fresh z | _fresh H end in
      destruct H as [x' y'];
      match p with | NW _red in x' | _idtac end;
      match q with | NW _red in y' | _idtac end
    | H : is_true (_ && _) |- _
        let H' := fresh H in case (vlib__andb_split H); clear H; intros H H'
    | H : (_ || _) = false |- _
        let H' := fresh H in case (vlib__norb_split H); clear H; intros H H'
    | H : ?x = ?x |- _clear H

    | H : ?p ?q |- _
      let x' := match p with | NW (fun z_) ⇒ fresh z | _H end in
      let y' := match q with | NW (fun z_) ⇒ fresh z | _fresh H end in
      destruct H as [x' y'];
      match p with | NW _unfold NW at 1 in x'; red in y' | _idtac end;
      match q with | NW _unfold NW at 1 in y'; red in x' | _idtac end
    | H : ?p ?q |- _
      let x' := match p with | NW (fun z_) ⇒ fresh z | _H end in
      let y' := match q with | NW (fun z_) ⇒ fresh z | _H end in
      destruct H as [x' | y'];
      [ match p with | NW _red in x' | _idtac end
      | match q with | NW _red in y' | _idtac end]
    | H : is_true (_ || _) |- _case (vlib__orb_split H); clear H; intro H
    | H : (_ && _) = false |- _case (vlib__nandb_split H); clear H; intro H
  end.

Ltac des_if :=
  clarify;
  repeat
    match goal with
      | |- context[match ?x with __ end] ⇒
        match (type of x) with
          | { _ } + { _ }destruct x; clarify
          | bool
            let Heq := fresh "Heq" in
            let P := fresh in
            evar(P: Prop);
            assert (Heq: reflect P x) by (subst P; trivial with vlib_refl);
            subst P; destruct Heq as [Heq|Heq]
          | _let Heq := fresh "Heq" in destruct x as [] _eqn: Heq; clarify
        end
      | H: context[ match ?x with __ end ] |- _
        match (type of x) with
          | { _ } + { _ }destruct x; clarify
          | bool
            let Heq := fresh "Heq" in
            let P := fresh in
            evar(P: Prop);
            assert (Heq: reflect P x) by (subst P; trivial with vlib_refl);
            subst P; destruct Heq as [Heq|Heq]
          | _let Heq := fresh "Heq" in destruct x as [] _eqn: Heq; clarify
        end
    end.

Ltac des_eqrefl :=
  match goal with
    | H: context[match ?X as id return (id = ?X_) with __ end Logic.eq_refl] |- _
    let EQ := fresh "EQ" in
    let id' := fresh "x" in
    revert H;
    generalize (Logic.eq_refl X); generalize X at 1 3;
    intros id' EQ; destruct id'; intros H
    | |- context[match ?X as id return (id = ?X_) with __ end Logic.eq_refl] ⇒
    let EQ := fresh "EQ" in
    let id' := fresh "x" in
    generalize (Logic.eq_refl X); generalize X at 1 3;
    intros id' EQ; destruct id'
  end.

Ltac desf := clarify; des; des_if.

Ltac clarassoc := clarsimp; autorewrite with vlib_trivial vlib vlibA in *; try done.

Ltac vlib__hacksimp1 :=
   clarsimp;
   match goal with
     | H: _ |- _solve [rewrite H; clear H; clarsimp
                         |rewrite <- H; clear H; clarsimp]
     | _solve [f_equal; clarsimp]
   end.

Ltac hacksimp :=
   clarsimp;
   try match goal with
   | H: _ |- _solve [rewrite H; clear H; clarsimp
                              |rewrite <- H; clear H; clarsimp]
   | |- context[match ?p with __ end] ⇒ solve [destruct p; vlib__hacksimp1]
   | _solve [f_equal; clarsimp]
   end.

Delineating cases in proofs


Named case tactics (taken from Libtactics)

Tactic Notation "assert_eq" ident(x) constr(v) :=
  let H := fresh in
  assert (x = v) as H by reflexivity;
  clear H.

Tactic Notation "Case_aux" ident(x) constr(name) :=
  first [
    set (x := name); move x at top
  | assert_eq x name
  | fail 1 "because we are working on a different case." ].

Ltac Case name := Case_aux case name.
Ltac SCase name := Case_aux subcase name.
Ltac SSCase name := Case_aux subsubcase name.
Ltac SSSCase name := Case_aux subsubsubcase name.
Ltac SSSSCase name := Case_aux subsubsubsubcase name.

Lightweight case tactics (without names)

Tactic Notation "--" tactic(c) :=
  first [
    assert (WithinCaseM := True); move WithinCaseM at top
  | fail 1 "because we are working on a different case." ]; c.

Tactic Notation "++" tactic(c) :=
  first [
    assert (WithinCaseP := True); move WithinCaseP at top
  | fail 1 "because we are working on a different case." ]; c.

Exploiting a hypothesis


Exploit an assumption (adapted from CompCert).

Ltac exploit x :=
    refine ((fun x yy x) (x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _ _ _ _ _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _ _ _ _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _ _ _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _ _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _ _) _)
 || refine ((fun x yy x) (x _ _ _) _)
 || refine ((fun x yy x) (x _ _) _)
 || refine ((fun x yy x) (x _) _).

Induction


Tactic Notation "induction" "[" ident_list(y) "]" ident(x) :=
  first [ try (intros until x); revert y; induction x
        | red; try (intros until x); revert y; induction x ].

Tactic Notation "induction" "[" ident_list(y) "]" ident(x) "[" ident(z) "]" :=
  first [ try (intros until x); revert y; induction x; destruct z
        | red; try (intros until x); revert y; induction x; destruct z ].

Tactic Notation "induction" "[" ident_list(y) "]" ident(x) "[" ident(z) ident (w) "]" :=
  first [ try (intros until x); revert y; induction x; destruct z, w
        | red; try (intros until x); revert y; induction x; destruct z, w ].

Versions with hacksimp

Tactic Notation "induct" ident(x) := induction x; hacksimp.

Tactic Notation "induct" ident(x) "[" ident(z) "]" :=
  induction x; destruct z; hacksimp.

Tactic Notation "induct" ident(x) "[" ident(z) ident(w) "]" :=
  induction x; destruct z, w; hacksimp.

Tactic Notation "induct" "[" ident_list(y) "]" ident(x) :=
  first [ try (intros until x); revert y; induction x; hacksimp
        | red; try (intros until x); revert y; induction x; hacksimp ].

Tactic Notation "induct" "[" ident_list(y) "]" ident(x) "[" ident(z) "]" :=
  first [ try (intros until x); revert y; induction x; destruct z; hacksimp
        | red; try (intros until x); revert y; induction x; destruct z; hacksimp ].

Tactic Notation "induct" "[" ident_list(y) "]" ident(x) "[" ident(z) ident(w) "]" :=
  first [ try (intros until x); revert y; induction x; destruct z, w; hacksimp
        | red; try (intros until x); revert y; induction x; destruct z, w; hacksimp ].

Views


Ltac vlib__apply_refl :=
  intros;
    match goal with
      | |- is_true ?peapply introT; [solve [trivial with vlib_refl]|]
      | |- ?p = trueeapply introT; [solve [trivial with vlib_refl]|]
      | |- ?p = falseeapply introFn; [solve [trivial with vlib_refl]|]
      | |- ?p = falseeapply introF; [solve [trivial with vlib_refl]|]
      | |- _red; vlib__apply_refl
    end.

Tactic Notation "apply" "/" := vlib__apply_refl.

Tactic Notation "apply" "/" constr(X) :=
  first [eapply X | eapply elimT; [eapply X; edone|]
    | eapply introT; [eapply X; edone|]
    | eapply introFn; [eapply X; edone|]
    | eapply introF; [eapply X; edone|]].

Tactic Notation "split" "/" :=
  first [split | hnf; intros; apply/ ; split
        | try red; intros; apply vlib__eqb_split].

apply in assumption

Ltac vlib__apply_refl_in H :=
  first [eapply elimT in H; [|solve [trivial with vlib_refl]]
|eapply elimFn in H; [|solve [trivial with vlib_refl]]
|eapply elimF in H; [|solve [trivial with vlib_refl]]].

Ltac vlib__apply_with_in X H :=
  first [eapply X in H
        |eapply elimT in H; [|eapply X; edone]
        |eapply elimFn in H; [|eapply X; edone]
        |eapply elimF in H; [|eapply X; edone]].

Tactic Notation "apply" "/" "in" hyp(H) := vlib__apply_refl_in H.

Tactic Notation "apply" "/" constr(X) "in" hyp(H) := vlib__apply_with_in X H.

move (apply to top of goal)

Ltac vlib__move_refl := let top := fresh in intro top; vlib__apply_refl_in top; revert top.
Ltac vlib__move_with X := let top := fresh in intro top; vlib__apply_with_in X top; revert top.

Tactic Notation "move" "⇒" simple_intropattern_list(L)
  := intros L.

Tactic Notation "move" ":" ident_list(Y)
  := revert Y.
Tactic Notation "move" ":" ident_list(Y) "⇒" simple_intropattern_list(L)
  := revert Y; intros L.

Tactic Notation "move" "/"
  := vlib__move_refl.
Tactic Notation "move" "/" ":" ident_list(Y)
  := revert Y; vlib__move_refl.
Tactic Notation "move" "/" "⇒" simple_intropattern_list(L)
  := vlib__move_refl; intros L.
Tactic Notation "move" "/" ":" ident_list(Y) "⇒" simple_intropattern_list(L)
  := revert Y; vlib__move_refl; intros L.

Tactic Notation "move" "/" constr(X) ident_list(Y)
  := revert Y; vlib__move_with X.
Tactic Notation "move" "/" constr(X) ident_list(Y) "⇒" simple_intropattern_list(L)
  := revert Y; vlib__move_with X; intros L.
Tactic Notation "move" "/" constr(X) ":" ident_list(Y)
  := revert Y; vlib__move_with X.
Tactic Notation "move" "/" constr(X) ":" ident_list(Y) "⇒" simple_intropattern_list(L)
  := revert Y; vlib__move_with X; intros L.

case

Ltac vlib__case_plain
  := let top := fresh in intro top; case top; clear top.
Ltac vlib__case_refl
  := let top := fresh in intro top; vlib__apply_refl_in top; case top; clear top.
Ltac vlib__case_with X
  := let top := fresh in intro top; vlib__apply_with_in X top; case top; clear top.

Tactic Notation "case" "⇒" simple_intropattern_list(L)
  := vlib__case_plain; intros L.

Tactic Notation "case" ":" ident_list(Y)
  := revert Y; vlib__case_plain.
Tactic Notation "case" ":" ident_list(Y) "⇒" simple_intropattern_list(L)
  := revert Y; vlib__case_plain; intros L.

Tactic Notation "case" "/"
  := vlib__case_refl.
Tactic Notation "case" "/" ":" ident_list(Y)
  := revert Y; vlib__case_refl.
Tactic Notation "case" "/" "⇒" simple_intropattern_list(L)
  := vlib__case_refl; intros L.
Tactic Notation "case" "/" ":" ident_list(Y) "⇒" simple_intropattern_list(L)
  := revert Y; vlib__case_refl; intros L.

Tactic Notation "case" "/" constr(X) ident_list(Y)
  := revert Y; vlib__case_with X.
Tactic Notation "case" "/" constr(X) ident_list(Y) "⇒" simple_intropattern_list(L)
  := revert Y; vlib__case_with X; intros L.
Tactic Notation "case" "/" constr(X) ":" ident_list(Y)
  := revert Y; vlib__case_with X.
Tactic Notation "case" "/" constr(X) ":" ident_list(Y) "⇒" simple_intropattern_list(L)
  := revert Y; vlib__case_with X; intros L.

double apply

Tactic Notation "apply" "/" constr(X1) "/" constr(X2) :=
  eapply sameP; [apply X1; edone|eapply iffP; [apply X2; edone|instantiate|instantiate]].

Function notation ported from ssrfun.v


Delimit Scope fun_scope with FUN.
Open Scope fun_scope.

Notation "f ^~ y" := (fun xf x y)
  (at level 10, y at level 8, no associativity, format "f ^~ y") : fun_scope.

Module Option.

Definition apply aT rT (f : aTrT) x u :=
  match u with
    | Some yf y
    | Nonex
  end.

Definition default T := apply (fun x : Tx).

Definition bind aT rT (f : aToption rT) := apply f None.

Definition map aT rT (f : aTrT) := bind (fun xSome (f x)).

End Option.

Notation oapp := Option.apply.
Notation odflt := Option.default.
Notation obind := Option.bind.
Notation omap := Option.map.
Notation some := (@Some _) (only parsing).

Definitions and notation for explicit functions with simplification.

Section SimplFun.

Variables aT rT : Type.

Inductive simpl_fun : Type := SimplFun (_ : aTrT).

Definition fun_of_simpl := fun f xmatch f with SimplFun lamlam x end.

Coercion fun_of_simpl : simpl_fun >→ Funclass.

End SimplFun.

Notation "[ 'fun' : T ⇒ E ]" := (SimplFun (fun _ : TE))
  (at level 0,
   format "'[hv' [ 'fun' : T ⇒ '/ ' E ] ']'") : fun_scope.

Notation "[ 'fun' x ⇒ E ]" := (SimplFun (fun xE))
  (at level 0, x ident,
   format "'[hv' [ 'fun' x ⇒ '/ ' E ] ']'") : fun_scope.

Notation "[ 'fun' x : T ⇒ E ]" := (SimplFun (fun x : TE))
  (at level 0, x ident, only parsing) : fun_scope.

Notation "[ 'fun' x y ⇒ E ]" := (fun x[fun y E])
  (at level 0, x ident, y ident,
   format "'[hv' [ 'fun' x y ⇒ '/ ' E ] ']'") : fun_scope.

Notation "[ 'fun' x y : T ⇒ E ]" := (fun x : T[fun y : T E])
  (at level 0, x ident, y ident, only parsing) : fun_scope.

Notation "[ 'fun' ( x : T ) y ⇒ E ]" := (fun x : T[fun y E])
  (at level 0, x ident, y ident, only parsing) : fun_scope.

Notation "[ 'fun' x ( y : T ) ⇒ E ]" := (fun x[fun y : T E])
  (at level 0, x ident, y ident, only parsing) : fun_scope.

Notation "[ 'fun' ( x : xT ) ( y : yT ) ⇒ E ]" :=
    (fun x : xT[fun y : yT E])
  (at level 0, x ident, y ident, only parsing) : fun_scope.

Definition erefl := @eq_refl.
Definition esym := eq_sym.
Definition nesym := sym_not_eq.
Definition etrans := eq_trans.
Definition congr1 := f_equal.
Definition congr2 := f_equal2.

A predicate for singleton types.
Definition all_equal_to T (x0 : T) := x, x = x0.

Lemma unitE : all_equal_to tt.

A generic wrapper type

Structure wrapped T := Wrap {unwrap : T}.
Canonical Structure wrap T x := @Wrap T x.


Extensional equality for unary and binary functions + syntactic sugar.

Section ExtensionalEquality.

Variables A B C : Type.

Definition eqfun (f g : BA) : Prop := x, f x = g x.

Definition eqrel (r s : CBA) : Prop := x y, r x y = s x y.

Lemma frefl : f, eqfun f f.

Lemma fsym : f g, eqfun f geqfun g f.

Lemma ftrans : f g h (EQ1: eqfun f g) (EQ2: eqfun g h), eqfun f h.

Lemma rrefl : r, eqrel r r.

End ExtensionalEquality.

Hint Resolve frefl rrefl.

Notation "f1 =1 f2" := (eqfun f1 f2)
  (at level 70, no associativity) : fun_scope.
Notation "f1 =1 f2 :> A" := (f1 =1 (f2 : A))
  (at level 70, f2 at next level, A at level 90) : fun_scope.
Notation "f1 =2 f2" := (eqrel f1 f2)
  (at level 70, no associativity) : fun_scope.
Notation "f1 =2 f2 :> A" := (f1 =2 (f2 : A))
  (at level 70, f2 at next level, A, B at level 90) : fun_scope.

Section Composition.

Variables A B C : Type.

Definition funcomp u (f : BA) (g : CB) x := match u with ttf (g x) end.
Local Notation comp := (funcomp tt).

Definition pcomp (f : Boption A) (g : Coption B) x := obind f (g x).

Lemma eq_comp : f f' g g', f =1 f'g =1 g'comp f g =1 comp f' g'.

End Composition.

Notation "[ 'eta' f ]" := (fun xf x)
  (at level 0, format "[ 'eta' f ]") : fun_scope.

Notation id := (fun xx).
Notation "@ 'id' T " := (fun x : Tx)
  (at level 10, T at level 8, only parsing) : fun_scope.

Notation comp := (funcomp tt).
Notation "@ 'comp'" := (fun A B C ⇒ @funcomp A B C tt).
Notation "f1 \o f2" := (comp f1 f2) (at level 50) : fun_scope.

Section Morphism.

Variables (aT rT sT : Type) (f : aTrT).

Definition morphism_1 aF rF := x, f (aF x) = rF (f x).
Definition morphism_2 aOp rOp := x y, f (aOp x y) = rOp (f x) (f y).

End Morphism.

Notation "{ 'morph' f : x / a >→ r }" :=
  (morphism_1 f (fun xa) (fun xr))
  (at level 0, f at level 99, x ident,
   format "{ 'morph' f : x / a >→ r }") : type_scope.

Notation "{ 'morph' f : x / a }" :=
  (morphism_1 f (fun xa) (fun xa))
  (at level 0, f at level 99, x ident,
   format "{ 'morph' f : x / a }") : type_scope.

Notation "{ 'morph' f : x y / a >→ r }" :=
  (morphism_2 f (fun x ya) (fun x yr))
  (at level 0, f at level 99, x ident, y ident,
   format "{ 'morph' f : x y / a >→ r }") : type_scope.

Notation "{ 'morph' f : x y / a }" :=
  (morphism_2 f (fun x ya) (fun x ya))
  (at level 0, f at level 99, x ident, y ident,
   format "{ 'morph' f : x y / a }") : type_scope.

Properties of relations (ported from ssrfun.v)


Section Injections.

Variables (rT aT : Type) (f : aTrT).

Definition injective := x1 x2, f x1 = f x2x1 = x2.

Definition cancel g := x, g (f x) = x.

Definition pcancel g := x, g (f x) = Some x.

Definition ocancel (g : aToption rT) h := x, oapp h x (g x) = x.

Lemma can_pcan : g, cancel gpcancel (fun ySome (g y)).

Lemma pcan_inj : g, pcancel ginjective.

Lemma can_inj : g, cancel ginjective.

Lemma canLR : g x y, cancel gx = f yg x = y.

Lemma canRL : g x y, cancel gf x = yx = g y.

End Injections.

Lemma esymK : T x y, cancel (@eq_sym T x y) (@eq_sym T y x).

Lemma etrans_id : T x y (eqxy : x = y :> T),
  eq_trans (eq_refl x) eqxy = eqxy.

Section InjectionsTheory.

Variables (A B C : Type) (f g : BA) (h : CB).

Lemma inj_id : injective (@id A).

Lemma inj_can_sym : f', cancel f f'injective f'cancel f' f.

Lemma inj_comp : injective finjective hinjective (f \o h).

Lemma can_comp : f' h',
  cancel f f'cancel h h'cancel (f \o h) (h' \o f').

Lemma pcan_pcomp : f' h',
  pcancel f f'pcancel h h'pcancel (f \o h) (pcomp h' f').

Lemma eq_inj : injective ff =1 ginjective g.

Lemma eq_can : f' g', cancel f f'f =1 gf' =1 g'cancel g g'.

Lemma inj_can_eq : f',
  cancel f f'injective f'cancel g f'f =1 g.

End InjectionsTheory.

Section Bijections.

Variables (A B : Type) (f : BA).

Inductive bijective : Prop := Bijective g (_ : cancel f g) (_ : cancel g f).

Hypothesis bijf : bijective.

Lemma bij_inj : injective f.

Lemma bij_can_sym : f', cancel f' f cancel f f'.

Lemma bij_can_eq : f' f'', cancel f f'cancel f f''f' =1 f''.

End Bijections.

Section BijectionsTheory.

Variables (A B C : Type) (f : BA) (h : CB).

Lemma eq_bij : bijective f g, f =1 gbijective g.

Lemma bij_comp : bijective fbijective hbijective (f \o h).

Lemma bij_can_bij : bijective f f', cancel f f'bijective f'.

End BijectionsTheory.

Section Involutions.

Variables (A : Type) (f : AA).

Definition involutive := cancel f f.

Hypothesis Hf : involutive.

Lemma inv_inj : injective f.

Lemma inv_bij : bijective f.

End Involutions.

Section OperationProperties.

Variables S T R : Type.

Section SopTisR.
Implicit Type op : STR.
Definition left_inverse e inv op := x, op (inv x) x = e.
Definition right_inverse e inv op := x, op x (inv x) = e.
End SopTisR.

Section SopTisS.
Implicit Type op : STS.
Definition right_id e op := x, op x e = x.
Definition left_zero z op := x, op z x = z.
Definition right_commutative op := x y z, op (op x y) z = op (op x z) y.
Definition left_distributive op add :=
   x y z, op (add x y) z = add (op x z) (op y z).
End SopTisS.

Section SopTisT.
Implicit Type op : STT.
Definition left_id e op := x, op e x = x.
Definition right_zero z op := x, op x z = z.
Definition left_commutative op := x y z, op x (op y z) = op y (op x z).
Definition right_distributive op add :=
   x y z, op x (add y z) = add (op x y) (op x z).
End SopTisT.

Section SopSisT.
Implicit Type op : SST.
Definition self_inverse e op := x, op x x = e.
Definition commutative op := x y, op x y = op y x.
End SopSisT.

Section SopSisS.
Implicit Type op : SSS.
Definition idempotent op := x, op x x = x.
Definition associative op := x y z, op x (op y z) = op (op x y) z.
End SopSisS.

End OperationProperties.

Boolean laws

Shorter, more systematic names for the boolean connectives laws.

Lemma andTb : x, true && x = x.
Lemma andFb : x, false && x = false.
Lemma andbT : x, x && true = x.
Lemma andbF : x, x && false = false.
Lemma andbb : x, x && x = x.

Lemma andbC : x y, x && y = y && x.
Lemma andbA : x y z, x && (y && z) = x && y && z.
Lemma andbCA : x y z, x && (y && z) = y && (x && z).
Lemma andbAC : x y z, x && y && z = x && z && y.

Lemma andbN : b, b && negb b = false.
Lemma andNb : b, negb b && b = false.

Lemma orTb : x, true || x = true.
Lemma orFb : x, false || x = x.
Lemma orbT : x, x || true = true.
Lemma orbF : x, x || false = x.
Lemma orbb : x, x || x = x.

Lemma orbC : x y, x || y = y || x.
Lemma orbA : x y z, x || (y || z) = x || y || z.
Lemma orbCA : x y z, x || (y || z) = y || (x || z).
Lemma orbAC : x y z, x || y || z = x || z || y.

Lemma orbN : b, b || negb b = true.
Lemma orNb : b, negb b || b = true.

Lemma andb_orl : x y z, (x || y) && z = x && z || y && z.
Lemma andb_orr : x y z, x && (y || z) = x && y || x && z.
Lemma orb_andl : x y z, (x && y) || z = (x || z) && (y || z).
Lemma orb_andr : x y z, x || (y && z) = (x || y) && (x || z).

Pseudo-cancellation -- i.e, absorbtion

Lemma andbK : b1 b2, b1 && b2 || b1 = b1.
Lemma andKb : b1 b2, b1 || b2 && b1 = b1.
Lemma orbK : b1 b2, (b1 || b2) && b1 = b1.
Lemma orKb : b1 b2, b1 && (b2 || b1) = b1.

Exclusive or -- xorb

Lemma xorFb : x, xorb false x = x.
Lemma xorbF : x, xorb x false = x.
Lemma xorTb : x, xorb true x = negb x.
Lemma xorbT : x, xorb x true = negb x.
Lemma xorbb : x, xorb x x = false.

Lemma xorbC : x y, xorb x y = xorb y x.
Lemma xorbA : x y z, xorb x (xorb y z) = xorb (xorb x y) z.
Lemma xorbCA : x y z, xorb x (xorb y z) = xorb y (xorb x z).
Lemma xorbAC : x y z, xorb (xorb x y) z = xorb (xorb x z) y.

Lemma xorbN : x y, xorb x (negb y) = negb (xorb x y).
Lemma xorNb : x y, xorb x (negb y) = negb (xorb x y).

Lemma andb_xorl : x y z, (xorb x y) && z = xorb (x && z) (y && z).
Lemma andb_xorr : x y z, x && (xorb y z) = xorb (x && y) (x && z).

Negation

Lemma negb_neg : x, negb (negb x) = x.
Lemma negb_and : x y, negb (x && y) = negb x || negb y.
Lemma negb_or : x y, negb (x || y) = negb x && negb y.
Lemma negb_xor : x y, negb (xorb x y) = xorb (negb x) y.

Automation support


Hint Rewrite
  andTb andFb andbT andbF
  orTb orFb orbT orbF
  : vlib_trivial.

Hint Rewrite
  andbb andbN andNb
  orbb orbN orNb
  andbK andKb orbK orKb
  xorbb xorFb xorbF xorTb xorbT xorbb negb_neg
  : vlib.

Hint Rewrite andbA orbA xorbA : vlibA.

Other potentially useful rewrites: negb_and negb_or negb_xor.

Views


An attempt to replicate functionality from ss-reflect.

Section ApplyIff.

Variables P Q : Prop.
Hypothesis eqPQ : P Q.

Lemma iffLR : PQ.

Lemma iffRL : QP.

Lemma iffLRn : ¬P¬Q.

Lemma iffRLn : ¬Q¬P.

End ApplyIff.

Predicates, i.e. functions to bool (ported from ssrbool.v)



Definition pred T := Tbool.

Identity Coercion fun_of_pred : pred >→ Funclass.

Definition rel T := Tpred T.

Identity Coercion fun_of_rel : rel >→ Funclass.

Notation xpred0 := (fun _false).
Notation xpredT := (fun _true).
Notation xpredI := (fun (p1 p2 : pred _) xp1 x && p2 x).
Notation xpredU := (fun (p1 p2 : pred _) xp1 x || p2 x).
Notation xpredC := (fun (p : pred _) xnegb (p x)).
Notation xpredD := (fun (p1 p2 : pred _) xnegb (p2 x) && p1 x).
Notation xpreim := (fun f (p : pred _) xp (f x)).
Notation xrelU := (fun (r1 r2 : rel _) x yr1 x y || r2 x y).

Section Predicates.

Variables T : Type.

Definition subpred (p1 p2 : pred T) := x, p1 xp2 x.

Definition subrel (r1 r2 : rel T) := x y, r1 x yr2 x y.

Definition simpl_pred := simpl_fun T bool.

Definition SimplPred (p : pred T) : simpl_pred := SimplFun p.

Coercion pred_of_simpl (p : simpl_pred) : pred T := p : Tbool.

Definition pred0 := SimplPred xpred0.
Definition predT := SimplPred xpredT.
Definition predI p1 p2 := SimplPred (xpredI p1 p2).
Definition predU p1 p2 := SimplPred (xpredU p1 p2).
Definition predC p := SimplPred (xpredC p).
Definition predD p1 p2 := SimplPred (xpredD p1 p2).
Definition preim rT f (d : pred rT) := SimplPred (xpreim f d).

Definition simpl_rel := simpl_fun T (pred T).

Definition SimplRel (r : rel T) : simpl_rel := [fun x r x].

Coercion rel_of_simpl_rel (r : simpl_rel) : rel T := fun x yr x y.

Definition relU r1 r2 := SimplRel (xrelU r1 r2).

Lemma subrelUl : r1 r2, subrel r1 (relU r1 r2).

Lemma subrelUr : r1 r2, subrel r2 (relU r1 r2).

Inductive mem_pred : Type := Mem (_ : pred T).

Definition isMem pT topred mem :=
  mem = (fun p : pTMem (fun xtopred p x)).

Structure predType : Type := PredType {
  pred_sort :> Type;
  topred : pred_sortpred T;
  _ : {mem | isMem topred mem}
}.

Definition mkPredType pT toP := PredType (exist (@isMem pT toP) _ eq_refl).

Canonical Structure predPredType := Eval hnf in @mkPredType (pred T) id.
Canonical Structure simplPredType := Eval hnf in mkPredType pred_of_simpl.

Coercion pred_of_mem mp : pred_sort predPredType :=
  match mp with Mem pfun xp x end.

Canonical Structure memPredType := Eval hnf in mkPredType pred_of_mem.

Definition clone_pred U :=
  fun pT (_ : pred_sort pTU) ⇒
  fun a mP (pT' := @PredType U a mP) (_ : phant_id pT' pT) ⇒ pT'.

End Predicates.

Implicit Arguments topred [[T] p].
Implicit Arguments pred0 [T].
Implicit Arguments predT [T].

Notation "[ 'pred' : T | E ]" := (SimplPred (fun _ : TE))
  (at level 0, format "[ 'pred' : T | E ]") : fun_scope.
Notation "[ 'pred' x | E ]" := (SimplPred (fun xE))
  (at level 0, x ident, format "[ 'pred' x | E ]") : fun_scope.
Notation "[ 'pred' x : T | E ]" := (SimplPred (fun x : TE))
  (at level 0, x ident, only parsing) : fun_scope.
Notation "[ 'rel' x y | E ]" := (SimplRel (fun x yE))
  (at level 0, x ident, y ident, format "[ 'rel' x y | E ]") : fun_scope.
Notation "[ 'rel' x y : T | E ]" := (SimplRel (fun x y : TE))
  (at level 0, x ident, y ident, only parsing) : fun_scope.

Notation "[ 'predType' 'Of' T ]" := (@clone_pred _ T _ id _ _ id)
  (at level 0, format "[ 'predType' 'Of' T ]") : form_scope.


Notation pred_class := (pred_sort (predPredType _)).
Coercion sort_of_simpl_pred T (p : simpl_pred T) : pred_class := p : pred T.

Definition predArgType := Type.
Identity Coercion sort_of_predArgType : predArgType >→ Sortclass.
Coercion pred_of_argType (T : predArgType) : simpl_pred T := predT.

Notation "{ : T }" := (T%type : predArgType)
  (at level 0, format "{ : T }") : type_scope.


Definition mem T (pT : predType T) : pTmem_pred T :=
  match tt with tt
    (match pT return pT_ with PredType _ _ (exist mem _) ⇒ mem end)
  end.

Definition in_mem T x mp :=
  match tt with tt ⇒ @pred_of_mem T mp x end.

Implicit Arguments mem [[T] pT].

Coercion pred_of_mem_pred T mp := [pred x : T | in_mem x mp].

Definition eq_mem T p1 p2 := x : T, in_mem x p1 = in_mem x p2.
Definition sub_mem T p1 p2 := x : T, in_mem x p1in_mem x p2.

Reserved Notation "x \in A" (at level 70, no associativity).
Reserved Notation "x \notin A" (at level 70, no associativity).
Reserved Notation "p1 =i p2" (at level 70, no associativity).

Notation "x \in A" := (in_mem x (mem A)) : bool_scope.
Notation "x \in A" := (in_mem x (mem A)) : bool_scope.
Notation "x \notin A" := (negb (x \in A)) : bool_scope.
Notation "A =i B" := (eq_mem (mem A) (mem B)) : type_scope.
Notation "{ 'subset' A <= B }" := (sub_mem (mem A) (mem B))
  (at level 0, A, B at level 69,
   format "{ '[hv' 'subset' A '/ ' <= B ']' }") : type_scope.
Notation "[ 'mem' A ]" := (pred_of_simpl (pred_of_mem_pred (mem A)))
  (at level 0, only parsing) : fun_scope.
Notation "[ 'rel' 'Of' fA ]" := (fun x[mem (fA x)])
  (at level 0, format "[ 'rel' 'Of' fA ]") : fun_scope.
Notation "[ 'predI' A & B ]" := (predI [mem A] [mem B])
  (at level 0, format "[ 'predI' A & B ]") : fun_scope.
Notation "[ 'predU' A & B ]" := (predU [mem A] [mem B])
  (at level 0, format "[ 'predU' A & B ]") : fun_scope.
Notation "[ 'predD' A & B ]" := (predD [mem A] [mem B])
  (at level 0, format "[ 'predD' A & B ]") : fun_scope.
Notation "[ 'predC' A ]" := (predC [mem A])
  (at level 0, format "[ 'predC' A ]") : fun_scope.
Notation "[ 'preim' f 'Of' A ]" := (preim f [mem A])
  (at level 0, format "[ 'preim' f 'Of' A ]") : fun_scope.

Notation "[ 'pred' x \in A ]" := [pred x | x \in A]
  (at level 0, x ident, format "[ 'pred' x \in A ]") : fun_scope.
Notation "[ 'pred' x \in A | E ]" := [pred x | (x \in A) && E]
  (at level 0, x ident, format "[ 'pred' x \in A | E ]") : fun_scope.
Notation "[ 'rel' x y \in A & B | E ]" :=
  [rel x y | (x \in A) && (y \in B) && E]
  (at level 0, x ident, y ident,
   format "[ 'rel' x y \in A & B | E ]") : fun_scope.
Notation "[ 'rel' x y \in A & B ]" := [rel x y | (x \in A) && (y \in B)]
  (at level 0, x ident, y ident,
   format "[ 'rel' x y \in A & B ]") : fun_scope.
Notation "[ 'rel' x y \in A | E ]" := [rel x y \in A & A | E]
  (at level 0, x ident, y ident,
   format "[ 'rel' x y \in A | E ]") : fun_scope.
Notation "[ 'rel' x y \in A ]" := [rel x y \in A & A]
  (at level 0, x ident, y ident,
   format "[ 'rel' x y \in A ]") : fun_scope.

Section simpl_mem.

Variables (T : Type) (pT : predType T).

Lemma mem_topred : (p : pT), mem (topred p) = mem p.

Lemma topredE : x (p : pT), topred p x = (x \in p).

Lemma in_simpl : x (p : simpl_pred T), (x \in p) = p x.

Lemma simpl_predE : (p : pred T), [pred x | p x] =1 p.


Lemma mem_simpl : (p : simpl_pred T), mem p = p :> pred T.

Definition memE := mem_simpl.

End simpl_mem.

Section RelationProperties.


Variable T : Type.

Variable R : rel T.

Definition total := x y, R x y || R y x.
Definition transitive := x y z, R x yR y zR x z.

Definition symmetric := x y, R x y = R y x.
Definition antisymmetric := x y, R x yR y xx = y.
Definition pre_symmetric := x y, R x yR y x.

Lemma symmetric_from_pre : pre_symmetricsymmetric.

Lemma pre_from_symmetric : symmetricpre_symmetric.

Definition reflexive := x, R x x.
Definition irreflexive := x, R x x = false.

Definition left_transitive := x y, R x yR x =1 R y.
Definition right_transitive := x y, R x yR^~ x =1 R^~ y.

End RelationProperties.

Lemma rev_trans : T (R : rel T),
  transitive Rtransitive (fun x yR y x).


Notation Local "{ 'all1' P }" := ( x, P x : Prop) (at level 0).
Notation Local "{ 'all2' P }" := ( x y, P x y : Prop) (at level 0).
Notation Local "{ 'all3' P }" := ( x y z, P x y z: Prop) (at level 0).
Notation Local ph := (phantom _).

Section LocalProperties.

Variables T1 T2 T3 : Type.

Variables (d1 : mem_pred T1) (d2 : mem_pred T2) (d3 : mem_pred T3).
Notation Local ph := (phantom Prop).

Definition prop_for (x : T1) P (_ : ph {all1 P}) := P x.

Lemma forE : x P phP, @prop_for x P phP = P x.

Definition prop_in1 P (_ : ph {all1 P}) :=
   x, in_mem x d1P x.

Definition prop_in11 P (_ : ph {all2 P}) :=
   x y, in_mem x d1in_mem y d2P x y.

Definition prop_in2 P (_ : ph {all2 P}) :=
   x y, in_mem x d1in_mem y d1P x y.

Definition prop_in111 P (_ : ph {all3 P}) :=
   x y z, in_mem x d1in_mem y d2in_mem z d3P x y z.

Definition prop_in12 P (_ : ph {all3 P}) :=
   x y z, in_mem x d1in_mem y d2in_mem z d2P x y z.

Definition prop_in21 P (_ : ph {all3 P}) :=
   x y z, in_mem x d1in_mem y d1in_mem z d2P x y z.

Definition prop_in3 P (_ : ph {all3 P}) :=
   x y z, in_mem x d1in_mem y d1in_mem z d1P x y z.

Variable f : T1T2.

Definition prop_on1 Pf P (_ : phantom T3 (Pf f)) (_ : ph {all1 P}) :=
   x, in_mem (f x) d2P x.

Definition prop_on2 Pf P (_ : phantom T3 (Pf f)) (_ : ph {all2 P}) :=
   x y, in_mem (f x) d2in_mem (f y) d2P x y.

End LocalProperties.

Implicit Arguments prop_in1 [T1 P].
Implicit Arguments prop_in11 [T1 T2 P].
Implicit Arguments prop_in2 [T1 P].
Implicit Arguments prop_in111 [T1 T2 T3 P].
Implicit Arguments prop_in12 [T1 T2 P].
Implicit Arguments prop_in21 [T1 T2 P].
Implicit Arguments prop_in3 [T1 P].
Implicit Arguments prop_on1 [T1 T2 T3 f Pf P].
Implicit Arguments prop_on2 [T1 T2 T3 f Pf P].

Definition inPhantom := Phantom Prop.
Definition onPhantom T P (x : T) := Phantom Prop (P x).

Definition bijective_in aT rT (d : mem_pred aT) (f : aTrT) :=
  exists2 g, prop_in1 d (inPhantom (cancel f g))
           & prop_on1 d (Phantom _ (cancel g)) (onPhantom (cancel g) f).

Definition bijective_on aT rT (cd : mem_pred rT) (f : aTrT) :=
  exists2 g, prop_on1 cd (Phantom _ (cancel f)) (onPhantom (cancel f) g)
           & prop_in1 cd (inPhantom (cancel g f)).

Notation "{ 'for' x , P }" :=
  (prop_for x (inPhantom P))
  (at level 0, format "{ 'for' x , P }") : type_scope.

Notation "{ 'in' d , P }" :=
  (prop_in1 (mem d) (inPhantom P))
  (at level 0, format "{ 'in' d , P }") : type_scope.

Notation "{ 'in' d1 & d2 , P }" :=
  (prop_in11 (mem d1) (mem d2) (inPhantom P))
  (at level 0, format "{ 'in' d1 & d2 , P }") : type_scope.

Notation "{ 'in' d & , P }" :=
  (prop_in2 (mem d) (inPhantom P))
  (at level 0, format "{ 'in' d & , P }") : type_scope.

Notation "{ 'in' d1 & d2 & d3 , P }" :=
  (prop_in111 (mem d1) (mem d2) (mem d3) (inPhantom P))
  (at level 0, format "{ 'in' d1 & d2 & d3 , P }") : type_scope.

Notation "{ 'in' d1 & & d3 , P }" :=
  (prop_in21 (mem d1) (mem d3) (inPhantom P))
  (at level 0, format "{ 'in' d1 & & d3 , P }") : type_scope.

Notation "{ 'in' d1 & d2 & , P }" :=
  (prop_in12 (mem d1) (mem d2) (inPhantom P))
  (at level 0, format "{ 'in' d1 & d2 & , P }") : type_scope.

Notation "{ 'in' d & & , P }" :=
  (prop_in3 (mem d) (inPhantom P))
  (at level 0, format "{ 'in' d & & , P }") : type_scope.

Notation "{ 'on' cd , P }" :=
  (prop_on1 (mem cd) (inPhantom P) (inPhantom P))
  (at level 0, format "{ 'on' cd , P }") : type_scope.

Notation "{ 'on' cd & , P }" :=
  (prop_on2 (mem cd) (inPhantom P) (inPhantom P))
  (at level 0, format "{ 'on' cd & , P }") : type_scope.

Notation "{ 'on' cd , P & g }" :=
  (prop_on1 (mem cd) (Phantom (_Prop) P) (onPhantom P g))
  (at level 0, format "{ 'on' cd , P & g }") : type_scope.

Notation "{ 'in' d , 'bijective' f }" := (bijective_in (mem d) f)
  (at level 0, f at level 8,
   format "{ 'in' d , 'bijective' f }") : type_scope.

Notation "{ 'on' cd , 'bijective' f }" := (bijective_on (mem cd) f)
  (at level 0, f at level 8,
   format "{ 'on' cd , 'bijective' f }") : type_scope.


Section LocalGlobal.

Variables T1 T2 T3 : predArgType.
Variables (D1 : pred T1) (D2 : pred T2) (D3 : pred T3).
Variables (d1 d1' : mem_pred T1) (d2 d2' : mem_pred T2) (d3 d3' : mem_pred T3).
Variables (f f' : T1T2) (g : T2T1) (h : T3).
Variables (P1 : T1Prop) (P2 : T1T2Prop).
Variable P3 : T1T2T3Prop.
Variable Q1 : (T1T2) → T1Prop.
Variable Q1l : (T1T2) → T3T1Prop.
Variable Q2 : (T1T2) → T1T1Prop.

Hypothesis sub1 : sub_mem d1 d1'.
Hypothesis sub2 : sub_mem d2 d2'.
Hypothesis sub3 : sub_mem d3 d3'.

Lemma in1W : {all1 P1}{in D1, {all1 P1}}.
Lemma in2W : {all2 P2}{in D1 & D2, {all2 P2}}.
Lemma in3W : {all3 P3}{in D1 & D2 & D3, {all3 P3}}.

Lemma in1T : {in T1, {all1 P1}}{all1 P1}.
Lemma in2T : {in T1 & T2, {all2 P2}}{all2 P2}.
Lemma in3T : {in T1 & T2 & T3, {all3 P3}}{all3 P3}.

Lemma sub_in1 : Ph : ph {all1 P1},
  prop_in1 d1' Phprop_in1 d1 Ph.

Lemma sub_in11 : Ph : ph {all2 P2},
  prop_in11 d1' d2' Phprop_in11 d1 d2 Ph.

Lemma sub_in111 : Ph : ph {all3 P3},
  prop_in111 d1' d2' d3' Phprop_in111 d1 d2 d3 Ph.

Let allQ1 f'' := {all1 Q1 f''}.
Let allQ1l f'' h' := {all1 Q1l f'' h'}.
Let allQ2 f'' := {all2 Q2 f''}.

Lemma on1W : allQ1 f{on D2, allQ1 f}.
Lemma on1lW : allQ1l f h{on D2, allQ1l f & h}.
Lemma on2W : allQ2 f{on D2 &, allQ2 f}.

Lemma on1T : {on T2, allQ1 f}allQ1 f.
Lemma on1lT : {on T2, allQ1l f & h}allQ1l f h.
Lemma on2T : {on T2 &, allQ2 f}allQ2 f.

Lemma subon1 : (Phf : ph (allQ1 f)) (Ph : ph (allQ1 f)),
  prop_on1 d2' Phf Phprop_on1 d2 Phf Ph.

Lemma subon1l : (Phf : ph (allQ1l f)) (Ph : ph (allQ1l f h)),
  prop_on1 d2' Phf Phprop_on1 d2 Phf Ph.

Lemma subon2 : (Phf : ph (allQ2 f)) (Ph : ph (allQ2 f)),
  prop_on2 d2' Phf Phprop_on2 d2 Phf Ph.

Lemma can_in_inj : {in D1, cancel f g}{in D1 &, injective f}.

Lemma canLR_in : x y,
  {in D1, cancel f g}y \in D1x = f yg x = y.

Lemma canRL_in : x y,
  {in D1, cancel f g}x \in D1f x = yx = g y.

Lemma on_can_inj : {on D2, cancel f & g}{on D2 &, injective f}.

Lemma canLR_on : x y,
  {on D2, cancel f & g}f y \in D2x = f yg x = y.

Lemma canRL_on : x y,
  {on D2, cancel f & g}f x \in D2f x = yx = g y.

Lemma inW_bij : bijective f{in D1, bijective f}.

Lemma onW_bij : bijective f{on D2, bijective f}.

Lemma inT_bij : {in T1, bijective f}bijective f.

Lemma onT_bij : {on T2, bijective f}bijective f.

Lemma sub_in_bij : D1' : pred T1,
  {subset D1 D1'}{in D1', bijective f}{in D1, bijective f}.

Lemma subon_bij : D2' : pred T2,
 {subset D2 D2'}{on D2', bijective f}{on D2, bijective f}.

End LocalGlobal.

Lemma sub_in2 : T d d' (P : TTProp),
  sub_mem d d' Ph : ph {all2 P}, prop_in2 d' Phprop_in2 d Ph.

Lemma sub_in3 : T d d' (P : TTTProp),
  sub_mem d d' Ph : ph {all3 P}, prop_in3 d' Phprop_in3 d Ph.

Lemma sub_in12 : T1 T d1 d1' d d' (P : T1TTProp),
  sub_mem d1 d1'sub_mem d d'
   Ph : ph {all3 P}, prop_in12 d1' d' Phprop_in12 d1 d Ph.

Lemma sub_in21 : T T3 d d' d3 d3' (P : TTT3Prop),
  sub_mem d d'sub_mem d3 d3'
   Ph : ph {all3 P}, prop_in21 d' d3' Phprop_in21 d d3 Ph.

Comparison for nat

Fixpoint eqn_rec (x y: nat) {struct x} :=
   match x, y with
     | O, Otrue
     | S x, S yeqn_rec x y
     | _, _false
   end.

Definition eqn := match tt with tteqn_rec end.

Lemma eqnP: x y, reflect (x = y) (eqn x y).

Canonical Structure nat_eqMixin := EqMixin eqnP.
Canonical Structure nat_eqType := Eval hnf in EqType nat nat_eqMixin.

Lemma eqnE : eqn = (@eq_op _).

Comparison for option

Definition eq_option {A: eqType} (x y: option A) :=
  match x, y with None, Nonetrue
    | Some x, Some yx == y
    | _ , _false
  end.

Lemma eq_optionP: (A: eqType) (x y: option A), reflect (x = y) (eq_option x y).

Canonical Structure option_eqMixin A := EqMixin (@eq_optionP A).
Canonical Structure option_eqType (A: eqType) := Eval hnf in EqType (option A) (@option_eqMixin A).


This page has been generated by coqdoc