Top source

Module mathcomp.classical.boolp

From HB Require Import structures.
From mathcomp Require Import boot order.
#[warning="-warn-library-file-internal-analysis"]
From mathcomp Require Import unstable.
From mathcomp Require Import mathcomp_extra.
From mathcomp Require internal_Eqdep_dec.

# Classical Logic This file provides the axioms of classical logic and tools to perform classical reasoning in the Mathematical Component framework. The three axioms are taken from the standard library of Coq, more details can be found in Section 5 of - R. Affeldt, C. Cohen, D. Rouhling. Formalization Techniques for Asymptotic Reasoning in Classical Analysis. JFR 2018 ## Axioms ``` functional_extensionality_dep == functional extensionality (on dependently typed functions), i.e., functions that are pointwise equal are equal propositional_extensionality == propositional extensionality, i.e., iff and equality are the same on Prop constructive_indefinite_description == existential in Prop (ex) implies existential in Type (sig) cid := constructive_indefinite_description (shortcut) ``` A number of properties are derived below from these axioms and are often more pratical to use than directly using the axioms. For instance propext, funext, the excluded middle (EM),... ## Boolean View of Prop ``` `[< P >] == boolean view of P : Prop, see all lemmas about asbool ``` ## Mathematical Components Structures - A decidable equality is defined for any type. It is thus possible to define an eqType structure for any type using the mixin `gen_eqMixin`. - This file adds the possibility to define a choiceType structure for any type thanks to an axiom `gen_choiceMixin` giving a choice mixin. - We chose to have generic mixins and no global instances of the eqType and choiceType structures to let the user choose which definition of equality to use and to avoid conflict with already declared instances. ``` {classic T} == Endow T : Type with a canonical eqType/choiceType. This is intended for local use. E.g., T : Type |- A : {fset {classic T}} Alternatively one may use elim/Pchoice: T => T in H *. to substitute T with T : choiceType once and for all. {eclassic T} == Endow T : eqType with a canonical choiceType. On the model of {classic _}. See also the lemmas Peq and eqPchoice. ``` Functions onto a porderType (resp. latticeType) are equipped with a porderType (resp. latticeType), so that the generic notation (_ <= _)%O (resp. `&`, `|`) from `order.v` can be used. ``` FunOrder.lef f g == pointwise large inequality between two functions FunOrder.ltf f g == pointwise strict inequality between two functions FunLattice.meetf f g == pointwise meet between two functions FunLattice.joinf f g == pointwise join between two functions ```

Unset SsrOldRewriteGoalsOrder.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.

Declare Scope box_scope.
Declare Scope quant_scope.

Axiom
functional_extensionality_dep
Source code
:
       forall ( : Type) ( : A -> Type) ( : forall : A, B x),
       (forall : A, f x = g x) -> f = g.
Axiom
propositional_extensionality
Source code
:
       forall : Prop, P <-> Q -> P = Q.

Axiom
constructive_indefinite_description
Source code
:
  forall ( : Type) ( : A -> Prop),
  (exists : A, P x) -> { : A | P x}.
Notation := constructive_indefinite_description.

Lemma ( : Type) ( : A -> Prop) :
  (exists2 : A, P x & Q x) -> { : A | P x & Q x}.
Proof.
move=> PQA; suff: { | P x /\ Q x} by move=> [a [*]]; exists a.
by apply: cid; case: PQA => x; exists x.
Qed.

Lemma
existT_inj1
Source code
( : Type) ( : T -> Type) ( : T) ( : P x) ( : P y) :
  existT P x Px = existT P y Py -> x = y.
Proof.
by case. Qed.

Lemma
existT_inj2
Source code
( : eqType) ( : T -> Type) ( : T) ( : P x) :
  existT P x Px1 = existT P x Px2 -> Px1 = Px2.
Proof.
apply: internal_Eqdep_dec.inj_pair2_eq_dec => y z.
by have [|/eqP] := eqVneq y z; [left|right].
Qed.

Lemma
surjective_existT
Source code
( : Type) ( : T -> Type) ( : { : T & P x}):
  existT [eta P] (projT1 p) (projT2 p) = p.
Proof.
by case: p. Qed.

Record
mextensionality
Source code
:= {
  _ : forall ( : Prop), (P <-> Q) -> (P = Q);
  _ : forall { : Type} ( : T -> U),
        (forall , f x = g x) -> f = g;
}.

Fact
extensionality
Source code
: mextensionality.
Proof.
split.
- exact: propositional_extensionality.
- by move=> T U f g; apply: functional_extensionality_dep.
Qed.

Lemma ( : Prop) : (P <-> Q) -> (P = Q).
Proof.
by have [propext _] := extensionality; apply: propext. Qed.

Ltac eqProp := apply: propext; split.

Lemma { : Type} ( : T -> U) : (f =1 g) -> f = g.
Proof.
by case: extensionality=> _; apply. Qed.

Lemma ( : Prop) : (P = Q) = (P <-> Q).
Proof.
by apply: propext; split=> [->|/propext]. Qed.

Lemma ( : Prop) : (P = Q) <-> (P <-> Q).
Proof.
by rewrite propeqE. Qed.

Lemma { : Type} ( : T -> U) : (f = g) = (f =1 g).
Proof.
by rewrite propeqE; split=> [->//|/funext]. Qed.

Lemma { : Type} ( : T -> U -> V) : (f = g) = (f =2 g).
Proof.
by rewrite propeqE; split=> [->//|?]; rewrite funeqE=> x; rewrite funeqE.
Qed.

Lemma { : Type} ( : T -> U -> V -> W) :
  (f = g) = (forall , f x y z = g x y z).
Proof.
by rewrite propeqE; split=> [->//|?]; rewrite funeq2E=> x y; rewrite funeqE.
Qed.

Lemma { : Type} ( : T -> U) : (f = g) <-> (f =1 g).
Proof.
by rewrite funeqE. Qed.

Lemma { : Type} ( : T -> U -> V) : (f = g) <-> (f =2 g).
Proof.
by rewrite funeq2E. Qed.

Lemma { : Type} ( : T -> U -> V -> W) :
  (f = g) <-> (forall , f x y z = g x y z).
Proof.
by rewrite funeq3E. Qed.

Lemma {} ( : T -> Prop) : (P = Q) = (forall , P x <-> Q x).
Proof.
by rewrite propeqE; split=> [->//|?]; rewrite funeqE=> x; rewrite propeqE.
Qed.

Lemma
predeq2E
Source code
{ } ( : T -> U -> Prop) :
   (P = Q) = (forall , P x y <-> Q x y).
Proof.
by rewrite propeqE; split=> [->//|?]; rewrite funeq2E=> ??; rewrite propeqE.
Qed.

Lemma
predeq3E
Source code
{ } ( : T -> U -> V -> Prop) :
   (P = Q) = (forall , P x y z <-> Q x y z).
Proof.
by rewrite propeqE; split=> [->//|?]; rewrite funeq3E=> ???; rewrite propeqE.
Qed.

Lemma {} ( : T -> Prop) : (A = B) <-> (forall , A x <-> B x).
Proof.
by rewrite predeqE. Qed.

Lemma
predeq2P
Source code
{ } ( : T -> U -> Prop) :
   (P = Q) <-> (forall , P x y <-> Q x y).
Proof.
by rewrite predeq2E. Qed.

Lemma
predeq3P
Source code
{ } ( : T -> U -> V -> Prop) :
   (P = Q) <-> (forall , P x y z <-> Q x y z).
Proof.
by rewrite predeq3E. Qed.

Lemma { : Prop} : P -> P = True.
Proof.
by move=> p; rewrite propeqE. Qed.

Lemma
Prop_irrelevance
Source code
( : Prop) ( : P) : x = y.
Proof.
by move: x (x) y => /propT-> [] []. Qed.
#[global] Hint Resolve Prop_irrelevance : core.

Record
mclassic
Source code
:= {
  _ : forall ( : Prop), {P} + {~P};
  _ : forall , hasChoice T
}.

Lemma ( : X -> Y -> Prop) :
  (forall , exists , P x y) -> { & forall , P x (f x)}.
Proof.

Theorem : P \/ ~ P.
Proof.
pose U := fun : bool => Q = val \/ P.
have Uex val : exists , U val b by exists val; left.
pose f := projT1 (cid (Uex val)).
pose Uf : U val (f val) := projT2 (cid (Uex val)).
have : f true != f false \/ P.
  have [] := (Uf true, Uf false); rewrite /U.
  by move=> [->|?] [->|?] ; do ?[by right]; left.
move=> [/eqP fTFN|]; [right=> p|by left]; apply: fTFN.
have UTF : U true = U false by rewrite predeqE /U => b; split=> _; right.
rewrite /f; move: (Uex true) (Uex false); rewrite UTF => p1 p2.
by congr (projT1 (cid _)).
Qed.

Lemma ( : Prop): {P} + {~P}.
Proof.
have : exists , if b then P else ~ P.
  by case: (EM P); [exists true|exists false].
by move=> /cid [[]]; [left|right].
Qed.

Lemma
pselectT
Source code
: (T -> False) + T.
Proof.
have [/cid[]//|NT] := pselect (exists : T, True); first by right.
by left=> t; case: NT; exists t.
Qed.

Lemma : mclassic.
Proof.
split=> [|T]; first exact: pselect.
exists (fun ( : pred T) ( : nat) =>
  if pselect (exists , P x) isn't left ex then None
  else Some (projT1 (cid ex)))
  => [P n x|P [x Px]|P Q /funext -> //].
  by case: pselect => // ex [<- ]; case: cid.
by exists 0; case: pselect => // -[]; exists x.
Qed.

Lemma
gen_choiceMixin
Source code
( : Type) : hasChoice T.
Proof.
by case: classic. Qed.

Lemma ( : Prop): P \/ ~P.
Proof.
by case: (pselect P); tauto. Qed.

Lemma : true = True :> Prop.
Proof.
by rewrite propeqE; split. Qed.

Lemma : false = False :> Prop.
Proof.
by rewrite propeqE; split. Qed.

Lemma ( : Prop) : ~ P -> P = False.
Proof.
by move=> p; rewrite propeqE; tauto. Qed.

Lemma ( : T -> rT) :
  (forall : T, U x = V x) -> (fun => U x) = (fun => V x).
Proof.
by move=> /funext->. Qed.

Lemma ( : T1 -> T2 -> rT) :
  (forall , U x y = V x y) -> (fun => U x y) = (fun => V x y).
Proof.
by move=> UV; rewrite funeq2E => x y; rewrite UV. Qed.
#[deprecated(since="mathcomp-analysis 1.10.0", note="renamed to `eq2_fun`.")]
Notation := eq2_fun (only parsing).

Lemma ( : T1 -> T2 -> T3 -> rT) :
  (forall , U x y z = V x y z) ->
  (fun => U x y z) = (fun => V x y z).
Proof.
by move=> UV; rewrite funeq3E => x y z; rewrite UV. Qed.
#[deprecated(since="mathcomp-analysis 1.10.0", note="renamed to `eq3_fun`.")]
Notation := eq3_fun (only parsing).

Lemma
eq_forall
Source code
( : T -> Prop) :
  (forall : T, U x = V x) -> (forall , U x) = (forall , V x).
Proof.
by move=> e; rewrite propeqE; split=> ??; rewrite (e,=^~e). Qed.

Lemma
eq2_forall
Source code
( : forall : T, S x -> Prop) :
  (forall , U x y = V x y) -> (forall , U x y) = (forall , V x y).
Proof.
by move=> UV; apply/eq_forall => x; exact/eq_forall. Qed.
#[deprecated(since="mathcomp-analysis 1.10.0", note="renamed to `eq2_forall`.")]
Notation
eq_forall2
Source code
:= eq2_forall (only parsing).

Lemma
eq3_forall
Source code
( : forall ( : T) ( : S x), R x y -> Prop) :
  (forall , U x y z = V x y z) ->
  (forall , U x y z) = (forall , V x y z).
Proof.
by move=> UV; apply/eq2_forall => x y; exact/eq_forall. Qed.
#[deprecated(since="mathcomp-analysis 1.10.0", note="renamed to `eq3_forall`.")]
Notation
eq_forall3
Source code
:= eq3_forall (only parsing).

Lemma
eq_exists
Source code
( : T -> Prop) :
  (forall : T, U x = V x) -> (exists , U x) = (exists , V x).
Proof.
by move=> e; rewrite propeqE; split=> - [] x ?; exists x; rewrite (e,=^~e).
Qed.

Lemma
eq2_exists
Source code
( : forall : T, S x -> Prop) :
  (forall , U x y = V x y) -> (exists , U x y) = (exists , V x y).
Proof.
by move=> UV; apply/eq_exists => x; exact/eq_exists. Qed.

Lemma
eq3_exists
Source code
( : forall ( : T) ( : S x), R x y -> Prop) :
  (forall , U x y z = V x y z) ->
  (exists , U x y z) = (exists , V x y z).
Proof.
by move=> UV; apply/eq2_exists => x y; exact/eq_exists. Qed.
#[deprecated(since="mathcomp-analysis 1.10.0", note="renamed to `eq3_exists`.")]
Notation
eq_exists3
Source code
:= eq3_exists (only parsing).

Lemma
eq_exist
Source code
( : T -> Prop) ( : T) ( : P s) ( : P t) :
  s = t -> exist P s p = exist P t q.
Proof.
by move=> st; case: _ / st in q *; apply/congr1. Qed.

Lemma
forall_swap
Source code
( : forall ( : T) ( : S), Prop) :
   (forall , U x y) = (forall , U x y).
Proof.
by rewrite propeqE; split. Qed.

Lemma
exists_swap
Source code
( : forall ( : T) ( : S), Prop) :
   (exists , U x y) = (exists , U x y).
Proof.
by rewrite propeqE; split => -[x [y]]; exists y, x. Qed.

Lemma
reflect_eq
Source code
( : Prop) ( : bool) : reflect P b -> P = b.
Proof.
by rewrite propeqE; exact: rwP. Qed.

Definition
asbool

asbool : Prop -> bool asbool is not universe polymorphic Arguments asbool P%_type_scope asbool is transparent Expands to: Constant mathcomp.classical.boolp.asbool Declared in library mathcomp.classical.boolp, line 335, characters 11-17


Source code
( : Prop) := if pselect P then true else false.

Notation
"`[< P >]"
Source code
:= (asbool P) : bool_scope.

Lemma ( : Prop) : `[<P>] = P :> Prop.
Proof.
by rewrite propeqE /asbool; case: pselect; split. Qed.

Lemma ( : Prop) : reflect P `[<P>].
Proof.
by apply: (equivP idP); rewrite asboolE. Qed.

Lemma ( : bool) : `[< b >] = b.
Proof.
by apply/asboolP/idP. Qed.

Lemma
asboolPn
Source code
( : Prop) : reflect (~ P) (~~ `[<P>]).
Proof.
by rewrite /asbool; case: pselect=> h; constructor. Qed.

Lemma ( : Prop) : `[<P>] -> P.
Proof.
by case: asboolP. Qed.

Lemma : A \/ B -> A + B.
Proof.
have [|NA] := asboolP A; first by left.
have [|NB] := asboolP B; first by right.
by move=> AB; exfalso; case: AB.
Qed.

Lemma : [\/ A, B | C] -> A + B + C.
Proof.
have [|NA] := asboolP A; first by left; left.
have [|NB] := asboolP B; first by left; right.
have [|NC] := asboolP C; first by right.
by move=> ABC; exfalso; case: ABC.
Qed.

Lemma : [\/ A, B, C | D] -> A + B + C + D.
Proof.
have [|NA] := asboolP A; first by left; left; left.
have [|NB] := asboolP B; first by left; left; right.
have [|NC] := asboolP C; first by left; right.
have [|ND] := asboolP D; first by right.
by move=> ABCD; exfalso; case: ABCD.
Qed.

Lemma ( : Prop) : P -> `[<P>].
Proof.
by case: asboolP. Qed.

Lemma ( : Prop) : ~ P -> `[<P>] = false.
Proof.
by apply/introF/asboolP. Qed.

Lemma ( : eqType) ( : T) : (x == y : Prop) = (x = y).
Proof.
by apply/propext; split=> /eqP. Qed.

Lemma
is_true_inj
Source code
: injective is_true.
Proof.
by move=> [] []; rewrite ?(trueE, falseE) ?propeqE; tauto. Qed.

Definition
gen_eq

gen_eq : forall [T : Type], T -> T -> bool gen_eq is not universe polymorphic Arguments gen_eq [T]%_type_scope u v gen_eq is transparent Expands to: Constant mathcomp.classical.boolp.gen_eq Declared in library mathcomp.classical.boolp, line 391, characters 11-17


Source code
( : Type) ( : T) := `[<u = v>].
Lemma ( : Type) : Equality.axiom (@gen_eq T).
Proof.
by move=> x y; apply: (iffP (asboolP _)). Qed.
Definition
gen_eqMixin

gen_eqMixin : forall T : Type, hasDecEq.phant_axioms T gen_eqMixin is not universe polymorphic Arguments gen_eqMixin T%_type_scope gen_eqMixin is transparent Expands to: Constant mathcomp.classical.boolp.gen_eqMixin Declared in library mathcomp.classical.boolp, line 394, characters 11-22


Source code
( : Type) : hasDecEq T :=
  hasDecEq.Build T (@gen_eqP T).

.
instance
Source code
Definition
Source code
() ( -> eqType) :=
  gen_eqMixin (forall : T, T' t).

.
instance
Source code
Definition
Source code
() ( -> choiceType) :=
  gen_choiceMixin (forall : T, T' t).

.
instance
Source code
Definition
Source code
gen_eqMixin
Source code
Prop.
.
instance
Source code
Definition
Source code
gen_choiceMixin
Source code
Prop.

Section classicType.
Variable : Type.
Definition
classicType

classicType : Type -> Type classicType is not universe polymorphic Arguments classicType T%_type_scope classicType is transparent Expands to: Constant mathcomp.classical.boolp.classicType Declared in library mathcomp.classical.boolp, line 408, characters 11-22


Source code
:= T.
.
instance
Source code
Definition
Source code
gen_eqMixin
Source code
classicType.
.
instance
Source code
Definition
Source code
gen_choiceMixin
Source code
classicType.
End classicType.
Notation
"'{classic' T }"
Source code
:= (classicType T)
 (format "'{classic' T }") : type_scope.

Section eclassicType.
Variable : eqType.
Definition
eclassicType

eclassicType : eqType -> Type eclassicType is not universe polymorphic Arguments eclassicType T eclassicType is transparent Expands to: Constant mathcomp.classical.boolp.eclassicType Declared in library mathcomp.classical.boolp, line 417, characters 11-23


Source code
: Type := T.
.
instance
Source code
Definition
Source code
Equality
Source code
.copy eclassicType T.
.
instance
Source code
Definition
Source code
gen_choiceMixin
Source code
eclassicType.
End eclassicType.
Notation
"'{eclassic' T }"
Source code
:= (eclassicType T)
 (format "'{eclassic' T }") : type_scope.

Definition
canonical_of

canonical_of : forall [T U : Type], (U -> T) -> Type canonical_of is not universe polymorphic Arguments canonical_of [T U]%_type_scope sort%_function_scope canonical_of is transparent Expands to: Constant mathcomp.classical.boolp.canonical_of Declared in library mathcomp.classical.boolp, line 424, characters 11-23


Source code
( : U -> T) := forall ( : T -> Type),
  (forall , G (sort x')) -> forall , G x.
Notation
canonical_
Source code
sort := (@canonical_of _ _ sort).
Notation
canonical
Source code
T E := (@canonical_of T E id).

Lemma ( : U -> T) :
  (forall , exists , sort y = x) -> canonical_ sort.
Proof.
by move=> + G Gs x => /(_ x)/cid[x' <-]. Qed.
Arguments canon {T U sort} x.

Lemma : canonical Type eqType.
Proof.
by apply: canon => T; exists {classic T}. Qed.
Lemma : canonical Type choiceType.
Proof.
by apply: canon => T; exists {classic T}. Qed.
Lemma
eqPchoice
Source code
: canonical eqType choiceType.
Proof.
by apply: canon => T; exists {eclassic T}; case: T => //= T [?]//. Qed.

Lemma
not_True
Source code
: (~ True) = False
Proof.
exact/propext. Qed.
Lemma
not_False
Source code
: (~ False) = True
Proof.
by apply/propext; split=> _. Qed.

Lemma
asbool_equiv_eq
Source code
{ : Prop} : (P <-> Q) -> `[<P>] = `[<Q>].
Proof.
by rewrite -propeqE => ->. Qed.

Lemma
asbool_equiv_eqP
Source code
{ : Prop} : reflect Q b -> (P <-> Q) -> `[<P>] = b.
Proof.
by move=> Q_b [PQ QP]; apply/asboolP/Q_b. Qed.

Lemma
asbool_equiv
Source code
{ : Prop} : (P <-> Q) -> (`[<P>] <-> `[<Q>]).
Proof.
by move/asbool_equiv_eq->. Qed.

Lemma
asbool_eq_equiv
Source code
{ : Prop} : `[<P>] = `[<Q>] -> (P <-> Q).
Proof.
by move=> eq; split=> /asboolP; rewrite (eq, =^~ eq) => /asboolP. Qed.

Lemma
and_asboolP
Source code
( : Prop) : reflect (P /\ Q) (`[< P >] && `[< Q >]).
Proof.
apply: (iffP idP); first by case/andP => /asboolP p /asboolP q.
by case=> /asboolP-> /asboolP->.
Qed.

Lemma
and3_asboolP
Source code
( : Prop) :
  reflect [/\ P, Q & R] [&& `[< P >], `[< Q >] & `[< R >]].
Proof.
apply: (iffP idP); first by case/and3P => /asboolP p /asboolP q /asboolP r.
by case => /asboolP -> /asboolP -> /asboolP ->.
Qed.

Lemma
or_asboolP
Source code
( : Prop) : reflect (P \/ Q) (`[< P >] || `[< Q >]).
Proof.
apply: (iffP idP); first by case/orP=> /asboolP; [left | right].
by case=> /asboolP-> //=; rewrite orbT.
Qed.

Lemma
or3_asboolP
Source code
( : Prop) :
  reflect [\/ P, Q | R] [|| `[< P >], `[< Q >] | `[< R >]].
Proof.
apply: (iffP idP); last by case=> [| |] /asboolP -> //=; rewrite !orbT.
by case/orP=> [/asboolP p|/orP[]/asboolP]; [exact:Or31|exact:Or32|exact:Or33].
Qed.

Lemma
asbool_neg
Source code
{ : Prop} : `[<~ P>] = ~~ `[<P>].
Proof.
by apply/idP/asboolPn=> [/asboolP|/asboolT]. Qed.

Lemma
asbool_or
Source code
{ : Prop} : `[<P \/ Q>] = `[<P>] || `[<Q>].
Proof.
exact: (asbool_equiv_eqP (or_asboolP _ _)). Qed.

Lemma
asbool_and
Source code
{ : Prop} : `[<P /\ Q>] = `[<P>] && `[<Q>].
Proof.
exact: (asbool_equiv_eqP (and_asboolP _ _)). Qed.

Lemma
imply_asboolP
Source code
{ : Prop} : reflect (P -> Q) (`[<P>] ==> `[<Q>]).
Proof.
apply: (iffP implyP)=> [PQb /asboolP/PQb/asboolW //|].
by move=> PQ /asboolP/PQ/asboolT.
Qed.

Lemma
asbool_imply
Source code
{ : Prop} : `[<P -> Q>] = `[<P>] ==> `[<Q>].
Proof.

Lemma
imply_asboolPn
Source code
( : Prop) : reflect (P /\ ~ Q) (~~ `[<P -> Q>]).
Proof.

Lemma
forall_asboolP
Source code
{ : Type} ( : T -> Prop) :
  reflect (forall , `[<P x>]) (`[<forall , P x>]).
Proof.
apply: (iffP idP); first by move/asboolP=> Px x; apply/asboolP.
by move=> Px; apply/asboolP=> x; apply/asboolP.
Qed.

Lemma
exists_asboolP
Source code
{ : Type} ( : T -> Prop) :
  reflect (exists , `[<P x>]) (`[<exists , P x>]).
Proof.
apply: (iffP idP); first by case/asboolP=> x Px; exists x; apply/asboolP.
by case=> x bPx; apply/asboolP; exists x; apply/asboolP.
Qed.


Variant
BoolProp
Source code
: Prop -> Type :=
 |
TrueProp
Source code
: BoolProp True
 |
FalseProp
Source code
: BoolProp False.

Lemma : BoolProp P.
Proof.
by case: (asboolP P) => [/propT-> | /propF->]; [left | right]. Qed.

Lemma : ((~ True) = False) * ((~ False) = True).
Proof.
by rewrite /not; split; eqProp. Qed.

Lemma : left_id True and * right_id True and
          * (left_zero False and * right_zero False and * idempotent_op and).
Proof.
by do ![split] => /PropB[]; eqProp=> // -[]. Qed.

Lemma : left_id False or * right_id False or
          * (left_zero True or * right_zero True or * idempotent_op or).
Proof.
do ![split] => /PropB[]; eqProp=> -[] //; by [left | right]. Qed.

Lemma : let ( : Prop) := P -> Q in
    (imply False =1 fun=> True) * (imply^~ False =1 not)
  * (left_id True imply * right_zero True imply * self_inverse True imply).
Proof.
by do ![split] => /PropB[]; eqProp=> //; apply. Qed.

Lemma
decide_or
Source code
: P \/ Q -> {P} + {Q}.
Proof.
by case/PropB: P; [left | rewrite orB; right]. Qed.


Lemma ( : Prop) : P = False -> ~ P.
Proof.
by move->. Qed.

Lemma
contrapT
Source code
: ~ ~ P -> P.
Proof.
by case: (PropB P) => //; rewrite not_False. Qed.

Lemma ( : Prop) : (~ P) -> P = False
Proof.
by case: (PropB P). Qed.

Lemma ( : Prop) : (~ P) = False -> P.
Proof.
by move/notT; exact: contrapT. Qed.

Lemma : involutive not.
Proof.
by case/PropB; rewrite !(not_False,not_True). Qed.

Lemma
contra_notP
Source code
( : Prop) : (~ Q -> P) -> ~ P -> Q.
Proof.
by move: Q P => /PropB[] /PropB[]. Qed.

Lemma
contraPP
Source code
( : Prop) : (~ Q -> ~ P) -> P -> Q.
Proof.
by move: Q P => /PropB[] /PropB[]//; rewrite not_False not_True. Qed.

Lemma
contra_notT
Source code
( : Prop) : (~~ b -> P) -> ~ P -> b.
Proof.
by move=> bP; apply: contra_notP => /negP. Qed.

Lemma
contraPT
Source code
( : Prop) : (~~ b -> ~ P) -> P -> b.
Proof.
by move=> /contra_notT; rewrite notK. Qed.

Lemma
contraTP
Source code
( : Prop) : (~ Q -> ~~ b) -> b -> Q.
Proof.
by move=> QB; apply: contraPP => /QB/negP. Qed.

Lemma
contraNP
Source code
( : Prop) ( : bool) : (~ P -> b) -> ~~ b -> P.
Proof.
by move=> /contra_notP + /negP => /[apply]. Qed.

Lemma
contra_neqP
Source code
( : eqType) ( : T) : (~ P -> x = y) -> x != y -> P.
Proof.
by move=> Pxy; apply: contraNP => /Pxy/eqP. Qed.

Lemma
contra_eqP
Source code
( : eqType) ( : T) : (~ Q -> x != y) -> x = y -> Q.
Proof.
by move=> Qxy /eqP; apply: contraTP. Qed.

Lemma
contra_leP
Source code
{} { : porderType disp1} [ : Prop] [ : T1] :
  (~ P -> (x < y)%O) -> (y <= x)%O -> P.
Proof.
move=> Pxy yx; apply/asboolP.
by apply: Order.POrderTheory.contra_leT yx => /asboolPn.
Qed.

Lemma
contra_ltP
Source code
{} { : porderType disp1} [ : Prop] [ : T1] :
  (~ P -> (x <= y)%O) -> (y < x)%O -> P.
Proof.
move=> Pxy yx; apply/asboolP.
by apply: Order.POrderTheory.contra_ltT yx => /asboolPn.
Qed.

Lemma
wlog_neg
Source code
: (~ P -> P) -> P.
Proof.
by case: (PropB P); exact. Qed.

Lemma : injective not
Proof.
exact: can_inj notK. Qed.

Lemma : (P = (~ Q)) -> (~ P) = Q
Proof.
exact: canLR notK. Qed.

Lemma : (~ P) = Q -> P = (~ Q)
Proof.
exact: canRL notK. Qed.

Lemma
iff_notr
Source code
( : Prop) : (P <-> ~ Q) <-> (~ P <-> Q).
Proof.
by split=> [/propext ->|/propext <-]; rewrite notK. Qed.

Lemma
iff_not2
Source code
( : Prop) : (~ P <-> ~ Q) <-> (P <-> Q).
Proof.
by split=> [/iff_notr|PQ]; [|apply/iff_notr]; rewrite notK. Qed.


Definition
predp

predp : Type -> Type predp is not universe polymorphic Arguments predp T%_type_scope predp is transparent Expands to: Constant mathcomp.classical.boolp.predp Declared in library mathcomp.classical.boolp, line 622, characters 11-16


Source code
:= T -> Prop.

Identity Coercion fun_of_pred : predp >-> Funclass.

Definition
relp

relp : Type -> Type relp is not universe polymorphic Arguments relp T%_type_scope relp is transparent Expands to: Constant mathcomp.classical.boolp.relp Declared in library mathcomp.classical.boolp, line 626, characters 11-15


Source code
:= T -> predp T.

Identity Coercion fun_of_rel : rel >-> Funclass.

Notation := (fun _ => False).
Notation := (fun _ => True).
Notation := (fun ( : predp _) => p1 x /\ p2 x).
Notation := (fun ( : predp _) => p1 x \/ p2 x).
Notation := (fun ( : predp _) => ~ p x).
Notation := (fun ( : predp _) => ~ p2 x /\ p1 x).
Notation := (fun ( : predp _) => p (f x)).
Notation := (fun ( : relp _) => r1 x y \/ r2 x y).

Definition
pred0p

pred0p : forall {T : Type}, predp T -> bool pred0p is not universe polymorphic Arguments pred0p {T}%_type_scope P pred0p is transparent Expands to: Constant mathcomp.classical.boolp.pred0p Declared in library mathcomp.classical.boolp, line 639, characters 11-17


Source code
( : Type) ( : predp T) : bool := `[<P =1 xpredp0>].
Prenex Implicits pred0p.

Lemma ( : Type) ( : predp T) : reflect (P =1 xpredp0) (pred0p P).
Proof.
by apply: (iffP (asboolP _)). Qed.

Lemma
forallp_asboolPn
Source code
{} { : T -> Prop} :
  reflect (forall : T, ~ P x) (~~ `[<exists : T, P x>]).
Proof.
apply: (iffP idP)=> [/asboolPn NP x Px|NP].
by apply/NP; exists x. by apply/asboolP=> -[x]; apply/NP.
Qed.

Lemma
existsp_asboolPn
Source code
{} { : T -> Prop} :
  reflect (exists : T, ~ P x) (~~ `[<forall : T, P x>]).
Proof.
apply: (iffP idP); last by case=> x NPx; apply/asboolPn=> /(_ x).
move/asboolPn=> NP; apply/asboolP/negbNE/asboolPn=> h.
by apply/NP=> x; apply/asboolP/negbNE/asboolPn=> NPx; apply/h; exists x.
Qed.

Lemma
asbool_forallNb
Source code
{ : Type} ( : pred T) :
  `[< forall : T, ~~ (P x) >] = ~~ `[< exists : T, P x >].
Proof.
apply: (asbool_equiv_eqP forallp_asboolPn);
  by split=> h x; apply/negP/h.
Qed.

Lemma
asbool_existsNb
Source code
{ : Type} ( : pred T) :
  `[< exists : T, ~~ (P x) >] = ~~ `[< forall : T, P x >].
Proof.
apply: (asbool_equiv_eqP existsp_asboolPn);
  by split=> -[x h]; exists x; apply/negP.
Qed.

Lemma
not_implyP
Source code
( : Prop) : ~ (P -> Q) <-> P /\ ~ Q.
Proof.
split=> [/asboolP|[p nq pq]]; [|exact/nq/pq].
by rewrite asbool_neg => /imply_asboolPn.
Qed.

Lemma
not_andE
Source code
( : Prop) : (~ (P /\ Q)) = (~ P \/ ~ Q).
Proof.
eqProp=> [/asboolPn|[|]]; try by apply: contra_not => -[].
by rewrite asbool_and negb_and => /orP[]/asboolPn; [left|right].
Qed.

Lemma
not_andP
Source code
( : Prop) : ~ (P /\ Q) <-> ~ P \/ ~ Q.
Proof.
by rewrite not_andE. Qed.

Lemma
not_and3P
Source code
( : Prop) : ~ [/\ P, Q & R] <-> [\/ ~ P, ~ Q | ~ R].
Proof.
split=> [/and3_asboolP|/or3_asboolP].
by rewrite 2!negb_and -3!asbool_neg => /or3_asboolP.
by rewrite 3!asbool_neg -2!negb_and => /and3_asboolP.
Qed.

Lemma
not_notP
Source code
( : Prop) : ~ ~ P <-> P.
Proof.
by split => [|p]; [exact: contrapT|exact]. Qed.
#[deprecated(since="mathcomp-analysis 1.15.0", note="Renamed to `not_notP`. Warning: a different `notP` is provided by `contra.v`.")]
Notation := not_notP (only parsing).

Lemma
not_notE
Source code
( : Prop) : (~ ~ P) = P.
Proof.
by rewrite propeqE not_notP. Qed.
#[deprecated(since="mathcomp-analysis 1.15.0", note="Renamed to `not_notE`. Warning: a different `notE` is provided by `contra.v`.")]
Notation := not_notE (only parsing).

Lemma ( : Prop) : (~ (P \/ Q)) = (~ P /\ ~ Q).
Proof.
by rewrite -[_ /\ _]not_notE not_andE 2!not_notE. Qed.

Lemma ( : Prop) : ~ (P \/ Q) <-> ~ P /\ ~ Q.
Proof.
by rewrite not_orE. Qed.

Lemma
not_implyE
Source code
( : Prop) : (~ (P -> Q)) = (P /\ ~ Q).
Proof.
by rewrite propeqE not_implyP. Qed.

Lemma ( : Prop) : (P -> Q) = (~ P \/ Q).
Proof.

Lemma : commutative or.
Proof.
by move=> /PropB[] /PropB[] => //; rewrite !orB. Qed.

Lemma : associative or.
Proof.
by move=> P Q R; rewrite propeqE; split=> [|]; tauto. Qed.

Lemma : left_commutative or.
Proof.
by move=> P Q R; rewrite !orA (orC P). Qed.

Lemma : right_commutative or.
Proof.
by move=> P Q R; rewrite -!orA (orC Q). Qed.

Lemma : interchange or or.
Proof.
by move=> P Q R S; rewrite !orA (orAC P). Qed.

Lemma : (~ P \/ Q) = (P -> Q).
Proof.
by case/PropB: P; rewrite notB orB implyB. Qed.

Lemma : (P \/ ~ Q) = (Q -> P)
Proof.
by rewrite orC orNp. Qed.

Lemma : [\/ P, Q | R] = (P \/ Q \/ R).
Proof.
rewrite -(asboolE P) -(asboolE Q) -(asboolE R) (reflect_eq or3P).
by rewrite -2!(reflect_eq orP).
Qed.

Lemma : [\/ P, Q, R | S] = (P \/ Q \/ R \/ S).
Proof.
rewrite -(asboolE P) -(asboolE Q) -(asboolE R) -(asboolE S) (reflect_eq or4P).
by rewrite -3!(reflect_eq orP).
Qed.

Lemma : commutative and.
Proof.
by move=> /PropB[] /PropB[]; rewrite !andB. Qed.

Lemma : associative and.
Proof.
by move=> P Q R; rewrite propeqE; split=> [|]; tauto. Qed.

Lemma : left_commutative and.
Proof.
by move=> P Q R; rewrite !andA (andC P). Qed.

Lemma : right_commutative and.
Proof.
by move=> P Q R; rewrite -!andA (andC Q). Qed.

Lemma : interchange and and.
Proof.
by move=> P Q R S; rewrite !andA (andAC P). Qed.

Lemma : [/\ P, Q & R] = (P /\ Q /\ R).
Proof.
by eqProp=> [[] | [? []]]. Qed.

Lemma : [/\ P, Q, R & S] = (P /\ Q /\ R /\ S).
Proof.
by eqProp=> [[] | [? [? []]]]. Qed.

Lemma : [/\ P, Q, R, S & T] = (P /\ Q /\ R /\ S /\ T).
Proof.
by eqProp=> [[] | [? [? [? []]]]]. Qed.

Lemma : (~ P -> Q : Prop) = (P \/ Q).
Proof.
by rewrite -orNp notK. Qed.

Lemma ( : Prop) : (P -> ~ Q) = (~ (P /\ Q)).
Proof.
by case/PropB: P; rewrite implyB andB ?notB. Qed.

Lemma : (~ P -> ~ Q) = (Q -> P).
Proof.
by rewrite implyNp orpN. Qed.

Lemma : right_distributive or and.
Proof.
by case/PropB=> Q R; rewrite !orB ?andB. Qed.

Lemma : left_distributive or and.
Proof.
by move=> P Q R; rewrite -!(orC R) or_andr. Qed.

Lemma : right_distributive and or.
Proof.
by move=> P Q R; apply/not_inj; rewrite !(not_andE, not_orE) or_andr. Qed.

Lemma : left_distributive and or.
Proof.
by move=> P Q R; apply/not_inj; rewrite !(not_andE, not_orE) or_andl. Qed.

Lemma
forallNE
Source code
{} ( : T -> Prop) : (forall , ~ P x) = (~ exists , P x).
Proof.
by rewrite propeqE; split => [fP [x /fP]//|nexP x Px]; apply: nexP; exists x.
Qed.

Lemma
existsNE
Source code
{} ( : T -> Prop) : (exists , ~ P x) = (~ forall , P x).
Proof.
rewrite propeqE; split=> [[x Px] aP //|NaP].
by apply: contrapT; rewrite -forallNE => aP; apply: NaP => x; apply: contrapT.
Qed.

Lemma
existsNP
Source code
( : T -> Prop) : (exists , ~ P x) <-> ~ forall , P x.
Proof.
by rewrite existsNE. Qed.

Lemma
not_existsP
Source code
( : T -> Prop) : (exists , P x) <-> ~ forall , ~ P x.
Proof.
by rewrite forallNE notK. Qed.

Lemma
forallNP
Source code
( : T -> Prop) : (forall , ~ P x) <-> ~ exists , P x.
Proof.
by rewrite forallNE. Qed.

Lemma
not_forallP
Source code
( : T -> Prop) : (forall , P x) <-> ~ exists , ~ P x.
Proof.
by rewrite existsNE notK. Qed.

Lemma
exists2E
Source code
: (exists2 : A, P x & Q x) = (exists , P x /\ Q x).
Proof.
by eqProp=> -[x]; last case; exists x. Qed.

Lemma
exists2P
Source code
( : T -> Prop) :
  (exists2 , P x & Q x) <-> exists , P x /\ Q x.
Proof.
by rewrite exists2E. Qed.

Lemma
not_exists2P
Source code
( : T -> Prop) :
  (exists2 , P x & Q x) <-> ~ forall , ~ P x \/ ~ Q x.
Proof.
rewrite exists2P not_existsP.
by split; apply: contra_not => PQx x; apply/not_andP; apply: PQx.
Qed.

Lemma
forall2NP
Source code
( : T -> Prop) :
  (forall , ~ P x \/ ~ Q x) <-> ~ (exists2 , P x & Q x).
Proof.
split=> [PQ [t Pt Qt]|PQ t]; first by have [] := PQ t.
by rewrite -not_andP => -[Pt Qt]; apply PQ; exists t.
Qed.

Lemma
forallPNP
Source code
( : T -> Prop) :
  (forall , P x -> ~ Q x) <-> ~ (exists2 , P x & Q x).
Proof.
split=> [PQ [t Pt Qt]|PQ t]; first by have [] := PQ t.
by move=> Pt Qt; apply: PQ; exists t.
Qed.

Lemma
existsPNP
Source code
( : T -> Prop) :
  (exists2 , P x & ~ Q x) <-> ~ (forall , P x -> Q x).
Proof.
split=> [[x Px NQx] /(_ x Px)//|]; apply: contra_notP => + x Px.
by apply: contra_notP => NQx; exists x.
Qed.

Lemma
forallp_asboolPn2
Source code
{} { : T -> Prop} :
  reflect (forall : T, ~ P x \/ ~ Q x) (~~ `[<exists2 : T, P x & Q x>]).
Proof.
apply: (iffP idP)=> [/asboolPn NP x|NP].
  by move/forallPNP : NP => /(_ x)/and_rec/not_andP.
by apply/asboolP=> -[x Px Qx]; have /not_andP := NP x; exact.
Qed.

Section bigmaxmin.
Local Notation := Order.max.
Local Notation := Order.min.
Local Open Scope order_scope.
Variables ( : Order.disp_t) ( : orderType d).
Variables ( : T) ( : finType) ( : pred I) ( : T) ( : I -> T).

Import Order.TTheory.

Lemma
bigmax_geP
Source code
: reflect (m <= x \/ exists2 , P i & m <= F i)
                           (m <= \big[max/x]_( | P i) F i).
Proof.
apply: (iffP idP) => [|[mx|[i Pi mFi]]].
- rewrite leNgt => /bigmax_ltP /not_andP[/negP|]; first by rewrite -leNgt; left.
  by move=> /existsNP[i /not_implyP[Pi /negP]]; rewrite -leNgt; right; exists i.
- by rewrite bigmax_idl le_max mx.
- by rewrite (bigmaxD1 i)// le_max mFi.
Qed.

Lemma
bigmax_gtP
Source code
: reflect (m < x \/ exists2 , P i & m < F i)
                           (m < \big[max/x]_( | P i) F i).
Proof.
apply: (iffP idP) => [|[mx|[i Pi mFi]]].
- rewrite ltNge => /bigmax_leP /not_andP[/negP|]; first by rewrite -ltNge; left.
  by move=> /existsNP[i /not_implyP[Pi /negP]]; rewrite -ltNge; right; exists i.
- by rewrite bigmax_idl lt_max mx.
- by rewrite (bigmaxD1 i)// lt_max mFi.
Qed.

Lemma
bigmin_leP
Source code
: reflect (x <= m \/ exists2 , P i & F i <= m)
                           (\big[min/x]_( | P i) F i <= m).
Proof.
apply: (iffP idP) => [|[xm|[i Pi Fim]]].
- rewrite leNgt => /bigmin_gtP /not_andP[/negP|]; first by rewrite -leNgt; left.
  by move=> /existsNP[i /not_implyP[Pi /negP]]; rewrite -leNgt; right; exists i.
- by rewrite bigmin_idl ge_min xm.
- by rewrite (bigminD1 i)// ge_min Fim.
Qed.

Lemma
bigmin_ltP
Source code
: reflect (x < m \/ exists2 , P i & F i < m)
                           (\big[min/x]_( | P i) F i < m).
Proof.
apply: (iffP idP) => [|[xm|[i Pi Fim]]].
- rewrite ltNge => /bigmin_geP /not_andP[/negP|]; first by rewrite -ltNge; left.
  by move=> /existsNP[i /not_implyP[Pi /negP]]; rewrite -ltNge; right; exists i.
- by rewrite bigmin_idl gt_min xm.
- by rewrite (bigminD1 _ _ _ Pi) gt_min Fim.
Qed.

End bigmaxmin.

Module
FunOrder
Source code
.
Section FunOrder.
Import Order.TTheory.
Variables ( : Type) ( : Order.disp_t) ( : porderType d).
Implicit Types f g h : aT -> T.

Lemma
fun_display
Source code
: Order.disp_t
Proof.
exact: Order.default_display. Qed.

Definition
lef

FunOrder.lef : forall [aT : Type] [d : disp_t] [T : porderType d], (aT -> T) -> (aT -> T) -> bool FunOrder.lef is not universe polymorphic Arguments FunOrder.lef [aT]%_type_scope [d T] (f g)%_function_scope FunOrder.lef is transparent Expands to: Constant mathcomp.classical.boolp.FunOrder.lef Declared in library mathcomp.classical.boolp, line 920, characters 11-14


Source code
:= `[< forall , (f x <= g x)%O >].
Local Notation
"f <= g"
Source code
:= (lef f g).

Definition
ltf

FunOrder.ltf : forall [aT : Type] [d : disp_t] [T : porderType d], (aT -> T) -> (aT -> T) -> bool FunOrder.ltf is not universe polymorphic Arguments FunOrder.ltf [aT]%_type_scope [d T] (f g)%_function_scope FunOrder.ltf is transparent Expands to: Constant mathcomp.classical.boolp.FunOrder.ltf Declared in library mathcomp.classical.boolp, line 923, characters 11-14


Source code
:= `[< (forall , (f x <= g x)%O) /\ exists , f x != g x >].
Local Notation := (ltf f g).

Lemma : (f < g) = (g != f) && (f <= g).
Proof.
apply/idP/andP => [fg|[gf fg]]; [split|apply/asboolP; split; [exact/asboolP|]].
- by apply/eqP => gf; move: fg => /asboolP[fg] [x /eqP]; apply; rewrite gf.
- apply/asboolP => x; rewrite le_eqVlt; move/asboolP : fg => [fg [y gfy]].
  by have [//|gfx /=] := boolP (f x == g x); rewrite lt_neqAle gfx /= fg.
- apply/not_existsP => h.
  have : f =1 g by move=> x; have /negP/negPn/eqP := h x.
  by rewrite -funeqE; apply/nesym/eqP.
Qed.

Fact
lef_refl
Source code
: reflexive lef
Proof.
by move=> f; apply/asboolP => x. Qed.

Fact
lef_anti
Source code
: antisymmetric lef.
Proof.
move=> f g => /andP[/asboolP fg /asboolP gf]; rewrite funeqE => x.
by apply/eqP; rewrite eq_le fg gf.
Qed.

Fact
lef_trans
Source code
: transitive lef.
Proof.
move=> g f h /asboolP fg /asboolP gh; apply/asboolP => x.
by rewrite (le_trans (fg x)).
Qed.

#[export]
Source code

.
instance
Source code
Definition
Source code
.isPOrder.Build
  fun_display (aT -> T) lef ltf ltf_def lef_refl lef_anti lef_trans.

End FunOrder.

Section FunLattice.
Import Order.TTheory.
Variables ( : Type) ( : Order.disp_t) ( : latticeType d).
Implicit Types f g h : aT -> T.

Definition
meetf

FunOrder.meetf : forall [aT : Type] [d : disp_t] [T : latticeType d], (aT -> T) -> (aT -> T) -> aT -> T FunOrder.meetf is not universe polymorphic Arguments FunOrder.meetf [aT]%_type_scope [d T] (f g)%_function_scope x FunOrder.meetf is transparent Expands to: Constant mathcomp.classical.boolp.FunOrder.meetf Declared in library mathcomp.classical.boolp, line 962, characters 11-16


Source code
:= fun => Order.meet (f x) (g x).
Definition
joinf

FunOrder.joinf : forall [aT : Type] [d : disp_t] [T : latticeType d], (aT -> T) -> (aT -> T) -> aT -> T FunOrder.joinf is not universe polymorphic Arguments FunOrder.joinf [aT]%_type_scope [d T] (f g)%_function_scope x FunOrder.joinf is transparent Expands to: Constant mathcomp.classical.boolp.FunOrder.joinf Declared in library mathcomp.classical.boolp, line 963, characters 11-16


Source code
:= fun => Order.join (f x) (g x).

Lemma : commutative meetf.
Proof.
move=> f g; apply/funext => x; exact: meetC. Qed.

Lemma : commutative joinf.
Proof.
move=> f g; apply/funext => x; exact: joinC. Qed.

Lemma : associative meetf.
Proof.
move=> f g h; apply/funext => x; exact: meetA. Qed.

Lemma : associative joinf.
Proof.
move=> f g h; apply/funext => x; exact: joinA. Qed.

Lemma : meetf f (joinf f g) = f.
Proof.
apply/funext => x; exact: joinKI. Qed.

Lemma : joinf f (meetf f g) = f.
Proof.
apply/funext => x; exact: meetKU. Qed.

Lemma
lef_meet
Source code
: (f <= g)%O = (meetf f g == f).
Proof.
apply/idP/idP => [/asboolP f_le_g|/eqP <-].
- apply/eqP/funext => x; exact/meet_l/f_le_g.
- apply/asboolP => x; exact: leIr.
Qed.

#[export]
Source code

.
instance
Source code
Definition
Source code
.POrder_isLattice.Build _ (aT -> T)
  meetfC joinfC meetfA joinfA joinfKI meetfKU lef_meet.

End FunLattice.
Module .
HB.reexport.
End Exports.
End FunOrder.
Export FunOrder.Exports.

Lemma ( : Type) ( : porderType d) ( : aT -> T) :
  reflect (forall , (f x <= g x)%O) (f <= g)%O.
Proof.
by apply: (iffP idP) => [fg|fg]; [exact/asboolP | exact/asboolP]. Qed.

Lemma ( : Type) ( : latticeType d) ( : aT -> T) :
  ((f `&` g) x = f x `&` g x)%O.
Proof.
by []. Qed.

Lemma ( : Type) ( : latticeType d) ( : aT -> T) :
  ((f `|` g) x = f x `|` g x)%O.
Proof.
by []. Qed.

Lemma {} ( : T -> T) ( : nat) : iter n.+1 f = f \o iter n f.
Proof.
by []. Qed.

Lemma {} ( : T -> T) ( : nat) : iter n.+1 f = iter n f \o f.
Proof.
by apply/funeqP => ?; rewrite iterSr. Qed.

Lemma {} ( : T -> T) : iter 0 f = id.
Proof.
by []. Qed.

Section Inhabited.
Variable ( : Type).

Lemma
inhabitedE
Source code
: inhabited T = exists : T, True.
Proof.
by eqProp; case. Qed.

Lemma
inhabited_witness
Source code
: inhabited T -> T.
Proof.
by rewrite inhabitedE => /cid[]. Qed.

End Inhabited.

Lemma
uncurryK
Source code
{ : Type} : cancel (@uncurry X Y Z) curry.
Proof.
by move=> f; rewrite funeq2E. Qed.

Lemma { : Type} : cancel curry (@uncurry X Y Z).
Proof.
by move=> f; rewrite funeqE=> -[]. Qed.