(************************************************************************)
(*         *   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.
Definition CompOpp (r:comparison) :=
match r with
| Eq => Eq
| Lt => Gt
| Gt => Lt
end.
(** The [CompareSpec] inductive relates a [comparison] value with three propositions, one for each possible case. Typically, it can be used to specify a comparison function via some equality and order predicates. Interest: [CompareSpec] behave nicely with [case] and [destruct]. *)
Inductive CompareSpec (Peq Plt Pgt : Prop) : comparison -> Prop :=
| CompEq : Peq -> CompareSpec Peq Plt Pgt Eq
| CompLt : Plt -> CompareSpec Peq Plt Pgt Lt
| CompGt : Pgt -> CompareSpec Peq Plt Pgt Gt.
Hint Constructors CompareSpec : core.
(** For having clean interfaces after extraction, [CompareSpec] is declared in Prop. For some situations, it is nonetheless useful to have a version in Type. Interestingly, these two versions are equivalent. *)
Inductive CompareSpecT (Peq Plt Pgt : Prop) : comparison -> Type :=
| CompEqT : Peq -> CompareSpecT Peq Plt Pgt Eq
| CompLtT : Plt -> CompareSpecT Peq Plt Pgt Lt
| CompGtT : Pgt -> CompareSpecT Peq Plt Pgt Gt.
Hint Constructors CompareSpecT : core.

Lemma CompareSpec2Type : forall Peq Plt Pgt c,
CompareSpec Peq Plt Pgt c -> CompareSpecT Peq Plt Pgt c.