(** * Proofs and definitions obtained from external sources  This file contains proofs and definitions from external sources. Specifically from thr base library used in IC by Prof. Gert Smolka in the version from 15. February 2016. Some other definitions are taken from the preliminary file of then development of Heriditarily finite sets by Prof. Gert Smolka and Kathrin Stark. Mainly these are newer versions of the definitions from the base library from ICL. *)
Global Set Implicit Arguments.
Global Unset Strict Implicit.
Global Unset Printing Records.
Global Unset Printing Implicit Defensive.
Global Set Regular Subst Tactic.
Hint Extern 4 => exact _.  (* make auto use type class inference *)
Require Export Setoid Morphisms.
Require Export Omega List Morphisms.
Set Implicit Arguments.
(* Set Universe Polymorphism. *)
(* exists-style notation for Sigma-types *)
Notation "'Sigma' x .. y , p" :=
(sigT (fun x => .. (sigT (fun y => p)) ..))
(at level 200, x binder, right associativity,
format "'[' 'Sigma'  '/  ' x  ..  y ,  '/  ' p ']'")
: type_scope.
Ltac inv A := inversion A; subst; try clear A.
(** * De Morgan laws *)
(** Decidable propositions *)
Definition dec (P : Prop) := {P} + {~ P}.
Existing Class dec.
Definition decision (P : Prop) (d : dec P) : dec P := d.
Arguments decision P {d}.
Tactic Notation "decide" constr(p) :=
destruct (decision p).
Tactic Notation "decide" constr(p) "as" simple_intropattern(i) :=
destruct (decision p) as i.
Fact dec_trans P Q :
dec P -> P <-> Q -> dec Q.
Instance True_dec :
dec True.
Instance False_dec :
dec False.
Instance impl_dec (P Q : Prop) :
dec P -> dec Q -> dec (P -> Q).
Instance and_dec (P Q : Prop) :
dec P -> dec Q -> dec (P /\ Q).
Instance or_dec (P Q : Prop) :
dec P -> dec Q -> dec (P \/ Q).
Instance not_dec (P : Prop) :
dec P -> dec (~P).
Instance iff_dec (P Q : Prop) :
dec P -> dec Q -> dec (P <-> Q).
Notation "'eq_dec' X" := (forall x y : X, dec (x=y)) (at level 70).
(** Discrete types and decidable predicates *)
Structure eqType := EqType {
eqtype :> Type;
decide_eq : eq_dec eqtype }.
Arguments EqType eqtype {decide_eq}.
(** This is like defined and not like Qed *)
Existing Instance decide_eq.
Structure decPred X := DecPred {
predicate :> X -> Prop;
decide_pred x : dec (predicate x) }.
Arguments DecPred {X} predicate {decide_pred}.
Existing Instance decide_pred.
Instance decp_dec X (p : decPred X) x :
dec (p x).
(** Decidable relations *)
Structure decRel X := DecRel {
relation :> X -> X -> Prop;
decide_rel x y : dec (relation x y) }.
Arguments DecRel {X} relation {decide_rel}.
Instance decRel_dec X (R : decRel X) x y :
dec (R x y).
Instance bool_eq_dec :
eq_dec bool.
Instance nat_eq_dec :
eq_dec nat.
Hint Resolve dec_prop_iff.
Instance nat_le_dec (x y : nat) : dec (x <= y) :=
le_dec x y.
Instance list_eq_dec X :
eq_dec X -> eq_dec (list X).
Instance list_in_dec (X : Type) (x : X) (A : list X) :
eq_dec X -> dec (In x A).
(** * Lists *)
Definition equi X (A B : list X) : Prop :=
incl A B /\ incl B A.
Hint Unfold equi.
Export ListNotations.
Notation "| A |" := (length A) (at level 65).
Notation "x 'el' A" := (In x A) (at level 70).
Notation "A <<= B" := (incl A B) (at level 70).
Notation "A === B" := (equi A B) (at level 70).
(* The following comments are for coqdoc *)
(** printing el #∊# *)
(** printing <<= #⊆# *)
(** printing === #≡# *)
(** Register additional simplification rules with autorewrite / simpl_list *)
Hint Rewrite <- app_assoc : list.
Hint Rewrite rev_app_distr map_app prod_length : list.
(* Print Rewrite HintDb list. *)
(** * Decidability laws for lists *)
Instance list_exists_dec X A (p : X -> Prop) :
(forall x, dec (p x)) -> dec (exists x, x el A /\ p x).

Lemma list_exists_DM X A  (p : X -> Prop) :
(forall x, dec (p x)) ->
~ (forall x, x el A -> ~ p x) -> exists x, x el A /\ p x.