(************************************************************************)
(*         *   The Coq Proof Assistant / The Coq Development Team       *)
(*  v      *   INRIA, CNRS and contributors - Copyright 1999-2018       *)
(* <O___,, *       (see CREDITS file for the list of authors)           *)
(*   \VV/  **************************************************************)
(*    //   *    This file is distributed under the terms of the         *)
(*         *     GNU Lesser General Public License Version 2.1          *)
(*         *     (see LICENSE file for the text of the license)         *)
(************************************************************************)
Set Implicit Arguments.
(********************************************************************)
(** * Datatypes with zero and one element *)
(** [Empty_set] is a datatype with no inhabitant *)
Inductive Empty_set : Set :=.
(** [unit] is a singleton datatype with sole inhabitant [tt] *)
Inductive unit : Set :=
tt : unit.
(********************************************************************)
(** * The boolean datatype *)
(** [bool] is the datatype of the boolean values [true] and [false] *)
Inductive bool : Set :=
| true : bool
| false : bool.
Add Printing If bool.
Declare Scope bool_scope.
Delimit Scope bool_scope with bool.
Bind Scope bool_scope with bool.
Register bool as core.bool.type.
Register true as core.bool.true.
Register false as core.bool.false.
(** Basic boolean operators *)
Definition andb (b1 b2:bool) : bool := if b1 then b2 else false.
Definition orb (b1 b2:bool) : bool := if b1 then true else b2.
Definition implb (b1 b2:bool) : bool := if b1 then b2 else true.
Definition xorb (b1 b2:bool) : bool :=
match b1, b2 with
| true, true => false
| true, false => true
| false, true => true
| false, false => false
end.
Definition negb (b:bool) := if b then false else true.
Infix "||" := orb : bool_scope.
Infix "&&" := andb : bool_scope.
Register andb as core.bool.andb.
Register orb as core.bool.orb.
Register xorb as core.bool.xorb.
Register negb as core.bool.negb.
(** Basic properties of [andb] *)
Hint Resolve andb_prop: bool.
Register andb_prop as core.bool.andb_prop.
Hint Resolve andb_true_intro: bool.
Register andb_true_intro as core.bool.andb_true_intro.
(** Interpretation of booleans as propositions *)
Inductive eq_true : bool -> Prop := is_eq_true : eq_true true.
Hint Constructors eq_true : eq_true.
Register eq_true as core.eq_true.type.
(** Another way of interpreting booleans as propositions *)
Definition is_true b := b = true.
(** [is_true] can be activated as a coercion by ([Local]) [Coercion is_true : bool >-> Sortclass]. *)
(** Additional rewriting lemmas about [eq_true] *)
Proof with auto.
split; intros.
- split.
+ replace a1 with (fst (a1, b1)); replace a2 with (fst (a2, b2))...
rewrite H...
+ replace b1 with (snd (a1, b1)); replace b2 with (snd (a2, b2))...
rewrite H...
- destruct H; subst...
Qed.
Definition prod_uncurry (A B C:Type) (f:A * B -> C)
(x:A) (y:B) : C := f (x,y).
Definition prod_curry (A B C:Type) (f:A -> B -> C)
(p:A * B) : C := match p with (x, y) => f x y end.

Lemma rew_pair : forall A (P Q : A->Type) x1 x2 (y1:P x1) (y2:Q x1) (H:x1=x2),
(rew H in y1, rew H in y2) = rew [fun x => (P x * Q x)%type] H in (y1,y2).