(************************************************************************)
(*         *   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] *)

Lemma injective_projections :
forall (A B:Type) (p1 p2:A * B),
fst p1 = fst p2 -> snd p1 = snd p2 -> p1 = p2.