ATBR.BoolView
(**************************************************************************)
(* This is part of ATBR, it is distributed under the terms of the *)
(* GNU Lesser General Public License version 3 *)
(* (see file LICENSE for more details) *)
(* *)
(* Copyright 2009-2011: Thomas Braibant, Damien Pous. *)
(**************************************************************************)
(* This is part of ATBR, it is distributed under the terms of the *)
(* GNU Lesser General Public License version 3 *)
(* (see file LICENSE for more details) *)
(* *)
(* Copyright 2009-2011: Thomas Braibant, Damien Pous. *)
(**************************************************************************)
This file builds some machinery to deal with reflection and
views.
Through the development, we define several efficient comparison
functions that produce results in bool or comparison. For
example, eq_nat_bool efficiently computes the equality on nat,
but is not easy to manipulate.
We provide some tools to deal with these kind of functions:
- *_analyse tactics: using a "view" mechanism, we associate to
- *_prop tactics: Through the development, we declare several
- bool_simpl tactic: Through the development, we declare several
Require Import Common.
Require Export Bool.
Require Import Equality Program Sumbool Peano.
(***********)
(* analyse *)
(***********)
Class Type_View {A} (f : A) := {
type_view_ty : Type;
type_view : type_view_ty
}.
(* TOTHINK: a-t'on vraiment besoin de passer par les instances, puisqu'on a toujours le lemme dans la main !? *)
Ltac type_view f :=
Tactics.on_call f
ltac:(fun c =>
match c with
| context args[f] =>
let ind_app := context args [type_view (f:=f)] in
let t := type of ind_app in
destruct ind_app
end).
Inductive compare_spec {A} eq lt (x y : A) : comparison -> Prop :=
| compare_spec_lt : lt x y -> compare_spec eq lt x y Lt
| compare_spec_eq : eq x y -> compare_spec eq lt x y Eq
| compare_spec_gt : lt y x -> compare_spec eq lt x y Gt.
computationally efficient equality and comparison of natural numbers
Fixpoint eq_nat_bool a b :=
match (a,b) with
| (S n, S p) => eq_nat_bool n p
| (O , O) => true
| _ => false
end.
Fixpoint le_lt_bool a b :=
match (a,b) with
| (O , _) => true
| (S n, S p) => le_lt_bool n p
| _ => false
end.
Lemma eq_nat_spec: forall a b, reflect (a=b) (eq_nat_bool a b).
Proof.
induction a; intros [|b]; simpl; try constructor; auto.
case (IHa ( b)); intros H; subst; constructor; auto.
Qed.
Lemma le_nat_spec : forall a b, reflect (le a b) (le_lt_bool a b).
Proof.
induction a; intros [|b]; simpl; try constructor; auto with arith.
case (IHa ( b)); intros H; subst; constructor; auto with arith.
Qed.
Instance eq_nat_view : Type_View eq_nat_bool := { type_view := eq_nat_spec }.
Instance le_nat_view : Type_View le_lt_bool := { type_view := le_nat_spec }.
Ltac nat_analyse :=
repeat (
try (type_view eq_nat_bool; try subst; try omega_false);
try (type_view le_lt_bool; try subst; try omega_false)
).
match (a,b) with
| (S n, S p) => eq_nat_bool n p
| (O , O) => true
| _ => false
end.
Fixpoint le_lt_bool a b :=
match (a,b) with
| (O , _) => true
| (S n, S p) => le_lt_bool n p
| _ => false
end.
Lemma eq_nat_spec: forall a b, reflect (a=b) (eq_nat_bool a b).
Proof.
induction a; intros [|b]; simpl; try constructor; auto.
case (IHa ( b)); intros H; subst; constructor; auto.
Qed.
Lemma le_nat_spec : forall a b, reflect (le a b) (le_lt_bool a b).
Proof.
induction a; intros [|b]; simpl; try constructor; auto with arith.
case (IHa ( b)); intros H; subst; constructor; auto with arith.
Qed.
Instance eq_nat_view : Type_View eq_nat_bool := { type_view := eq_nat_spec }.
Instance le_nat_view : Type_View le_lt_bool := { type_view := le_nat_spec }.
Ltac nat_analyse :=
repeat (
try (type_view eq_nat_bool; try subst; try omega_false);
try (type_view le_lt_bool; try subst; try omega_false)
).
same thing for positive numbers
Fixpoint eq_pos_bool x y :=
match x,y with
| xH, xH => true
| xO a, xO b => eq_pos_bool a b
| xI a, xI b => eq_pos_bool a b
| _, _ => false
end.
Lemma eq_pos_spec : forall n m, reflect (n=m) (eq_pos_bool n m).
Proof.
induction n; intros [m|m|]; simpl; try constructor; try congruence.
case (IHn m); intro; subst; constructor; congruence.
case (IHn m); intro; subst; constructor; congruence.
Qed.
Instance eq_pos_view : Type_View eq_pos_bool := { type_view := eq_pos_spec }.
Ltac pos_analyse := repeat type_view eq_pos_bool.
match x,y with
| xH, xH => true
| xO a, xO b => eq_pos_bool a b
| xI a, xI b => eq_pos_bool a b
| _, _ => false
end.
Lemma eq_pos_spec : forall n m, reflect (n=m) (eq_pos_bool n m).
Proof.
induction n; intros [m|m|]; simpl; try constructor; try congruence.
case (IHn m); intro; subst; constructor; congruence.
case (IHn m); intro; subst; constructor; congruence.
Qed.
Instance eq_pos_view : Type_View eq_pos_bool := { type_view := eq_pos_spec }.
Ltac pos_analyse := repeat type_view eq_pos_bool.
same thing for booleans
Definition eq_bool_bool := Bool.eqb.
Lemma eq_bool_spec : forall a b, reflect (a=b) (eq_bool_bool a b).
Proof.
intros [|] [|]; simpl; constructor; firstorder.
Qed.
Instance eq_bool_view : Type_View eq_bool_bool := { type_view := eq_bool_spec }.
Ltac bool_analyse := repeat type_view eq_bool_bool.
(************)
(* nat_prop *)
(************)
Lemma eq_nat_bool_true : forall x y, eq_nat_bool x y = true <-> x = y.
Proof. intros. nat_analyse; intuition discriminate. Qed.
Lemma eq_nat_bool_false : forall x y, eq_nat_bool x y = false <-> x <> y.
Proof. intros. nat_analyse; intuition discriminate. Qed.
Lemma le_lt_bool_true : forall x y, le_lt_bool x y = true <-> x <= y.
Proof. intros. nat_analyse; intuition. Qed.
Lemma le_lt_bool_false : forall x y, le_lt_bool x y = false <-> y < x.
Proof. intros. nat_analyse; intuition. Qed.
Hint Rewrite eq_nat_bool_true eq_nat_bool_false le_lt_bool_true le_lt_bool_false : nat_prop.
Ltac nat_prop := autorewrite with nat_prop in *.
(**************)
(* bool_simpl *)
(**************)
Lemma eq_bool_spec : forall a b, reflect (a=b) (eq_bool_bool a b).
Proof.
intros [|] [|]; simpl; constructor; firstorder.
Qed.
Instance eq_bool_view : Type_View eq_bool_bool := { type_view := eq_bool_spec }.
Ltac bool_analyse := repeat type_view eq_bool_bool.
(************)
(* nat_prop *)
(************)
Lemma eq_nat_bool_true : forall x y, eq_nat_bool x y = true <-> x = y.
Proof. intros. nat_analyse; intuition discriminate. Qed.
Lemma eq_nat_bool_false : forall x y, eq_nat_bool x y = false <-> x <> y.
Proof. intros. nat_analyse; intuition discriminate. Qed.
Lemma le_lt_bool_true : forall x y, le_lt_bool x y = true <-> x <= y.
Proof. intros. nat_analyse; intuition. Qed.
Lemma le_lt_bool_false : forall x y, le_lt_bool x y = false <-> y < x.
Proof. intros. nat_analyse; intuition. Qed.
Hint Rewrite eq_nat_bool_true eq_nat_bool_false le_lt_bool_true le_lt_bool_false : nat_prop.
Ltac nat_prop := autorewrite with nat_prop in *.
(**************)
(* bool_simpl *)
(**************)
bool_simpl is a tactic that simplifies boolean operations in the context and in the goal
The database bool_simpl should be enriched with lemmas such as forall x, eqb x x = true, which is done in Numbers.v
b || false -> b
false || b -> b
b || true -> true
true || b -> true
b && false -> false
false && b -> false
b && true -> b
true && b -> b
negb (b || c) -> negb b && negb c
negb (b && c) -> negb b || negb c
negb (negb b) -> b
a &&& b -> a && b
a ||| b -> a || b
Ltac bool_simpl := autorewrite with bool_simpl in *.
Lemma eq_nat_bool_refl: forall x, eq_nat_bool x x = true.
Proof. intro. nat_prop. reflexivity. Qed.
Lemma le_lt_bool_refl: forall x, le_lt_bool x x = true.
Proof. intro. nat_prop. auto with arith. Qed.
Hint Rewrite eq_nat_bool_refl le_lt_bool_refl: bool_simpl.
(*******************)
(* bool_connectors *)
(*******************)
bool_connectors takes hypothesis like ((x && y) || negb z) = true and transforms them into
? : (x = true /\ y = true) \/ (~ z = true).Lemma andb_false_iff : forall b1 b2:bool, b1 && b2 = false <-> (b1 = false \/ b2 = false).
Proof. intros [|] [|]; firstorder. Qed.
Lemma andb_true_iff : forall b1 b2:bool, b1 && b2 = true <-> (b1 = true /\ b2 = true).
Proof. intros [|] [|]; firstorder. Qed.
Lemma orb_false_iff : forall b1 b2:bool, b1 || b2 = false <-> (b1 = false /\ b2 = false).
Proof. intros [|] [|]; firstorder. Qed.
Lemma orb_true_iff : forall b1 b2:bool, b1 || b2 = true <-> (b1 = true \/ b2 = true).
Proof. intros [|] [|]; firstorder. Qed.
Lemma negb_true : forall b, negb b = true <-> b = false.
Proof. intros [|]; firstorder. Qed.
Lemma negb_false : forall b, negb b = false <-> b = true.
Proof. intros [|]; firstorder. Qed.
Lemma eq_not_negb : forall b c, b = c <-> ~ (b = negb c).
Proof. intros [|] [|]; firstorder. Qed.
Hint Rewrite andb_false_iff andb_true_iff orb_false_iff orb_true_iff negb_true negb_false : bool_connectors.
Ltac bool_connectors := autorewrite with bool_connectors in *.
Lemma bool_prop_iff : forall b1 b2, b1 = b2 <-> (b1 = true <-> b2 = true).
Proof. intros [|] [|]; firstorder. Qed.
(*************)
(* decompose *)
(*************)
completer tac simplfies the layout of the hypothesis, and try to
saturate the context with hypothesis. It is adapted from A. Chlipala
Ltac notHyp P :=
match goal with
[ _ : P |- _ ] => fail 1
| _ => match P with
| ?P1 /\ ?P2 => first [notHyp P1 | notHyp P2 | fail 2]
| _ => idtac
end
end.
Ltac extend pf :=
let t := type of pf in notHyp t; generalize pf; intro.
Ltac completer tac:=
repeat match goal with
| H : False |- _ => apply False_ind; exact H
| H : ?P \/ ?Q |- _ => destruct H as [?|?]
| [ |- _ /\ _ ] => constructor
| [ |- _ <-> _ ] => constructor
| [ |- _ -> _] => intro
| [H : _ /\ _ |- _] => destruct H
| [H : ?P -> ?Q, H' : ?P |- _] => generalize (H H'); clear H; intro H
| [ |- forall x, _] => intro
| [H : forall x, ?P x -> _ , H' : ?P ?X |- _ ]=> extend (H X H')
| [H : exists x, _ |- _ ] => destruct H
| [H : ?x = ?y |- _ ] => subst H
| _ => tac
end.