Top source

Module mathcomp.classical.contra

From mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq.
From mathcomp Require Import boolp.

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

# Contraposition This file provides tactics to reason by contraposition and contradiction. ## Tactics ``` assume_not == add a goal negation assumption. The tactic also works for goals in Type, simplifies the added assumption, and exposes its top-level constructive content. absurd_not == proof by contradiction. Same as assume_not, but the goal is erased and replaced by False. Caveat: absurd_not cannot be used as a move/ view because its conclusion is indeterminate. The more general notP can be used instead. contra == proof by contraposition. Change a goal of the form assumption -> conclusion to ~ conclusion -> ~ assumption. As with assume_not, contra allows both assumption and conclusion to be in Type, simplifies the negation of both assumption and conclusion, and exposes the constructive contents of the negated conclusion. The contra tactic also supports a limited form of the ':' discharge pseudo tactical, whereby contra: <d-items> means move: <d-items>; contra. The only <d-items> allowed are one term, possibly preceded by a clear switch. absurd == proof by contradiction. The defective form of the tactic simply replaces the entire goal with False (just as the Ltac exfalso), leaving the user to derive a contradiction from the assumptions. The ':' form absurd: <d-items> replaces the goal with the negation of the (single) <d-item> (as with contra:, a clear switch is also allowed. Finally the Ltac absurd term form is also supported. ```

Hiding module for the internal definitions and lemmas used by the tactics defined here.
Module
Internals
Source code
.

A wrapper for view lemmas with an indeterminate conclusion (of the form forall ... T ..., pattern -> T), and for which the intended view pattern may fail to match some assumptions. This wrapper ensures that such views are only used in the forward direction (as in move/), and only with the appropriate move_viewP hint, preventing its application to an arbitrary assumption A by the instatiation to A -> T' of its indeterminate conclusion T. This is similar to the implies wrapper, except move_viewP is *NOT* declared as a coercion---it must be used explicitly to apply the view manually to an assumption (as in, move_viewP my_view some_assumption).

Variant
move_view
Source code
:=
MoveView
Source code
of S -> T.
Definition
move_viewP

supremums : forall [d : Order.disp_t] [T : porderType d], set T -> set T supremums is not universe polymorphic Arguments supremums [d T] A%_classical_set_scope _ supremums is transparent Expands to: Constant mathcomp.classical.classical_sets.supremums Declared in library mathcomp.classical.classical_sets, line 3146, characters 11-20


Source code
{ } : S -> T := let: MoveView v := mv in v.
Hint View for move/ move_viewP|2.

## Type-level equivalence

Variant := of S -> T & T -> S.

Definition
equivT_refl

supremum : forall [d : Order.disp_t] [T : porderType d], T -> set T -> T supremum is not universe polymorphic Arguments supremum [d T] x0 A%_classical_set_scope supremum is transparent Expands to: Constant mathcomp.classical.classical_sets.supremum Declared in library mathcomp.classical.classical_sets, line 3161, characters 11-19


Source code
: equivT S S := EquivT id id.
Definition
equivT_transl

infimums : forall [d : Order.disp_t] [T : porderType d], set T -> set T infimums is not universe polymorphic Arguments infimums [d T] A%_classical_set_scope _ infimums is transparent Expands to: Constant mathcomp.classical.classical_sets.infimums Declared in library mathcomp.classical.classical_sets, line 3180, characters 11-19


Source code
{ } : equivT S T -> equivT S U -> equivT T U :=
  fun ( : equivT S T) ( : equivT S U) =>
    let: EquivT S_T T_S := st in
    let: EquivT S_U U_S := su in
    EquivT (S_U \o T_S) (S_T \o U_S).
Definition
equivT_sym

infimum : forall [d : Order.disp_t] [T : porderType d], T -> set T -> T infimum is not universe polymorphic Arguments infimum [d T] x0 A%_classical_set_scope infimum is transparent Expands to: Constant mathcomp.classical.classical_sets.infimum Declared in library mathcomp.classical.classical_sets, line 3195, characters 11-18


Source code
{ } : equivT S T -> equivT T S :=
   equivT_transl^~ (equivT_refl S).
Definition
equivT_trans

meets : forall [T : Type], set_system T -> set_system T -> Prop meets is not universe polymorphic Arguments meets [T]%_type_scope F G meets is transparent Expands to: Constant mathcomp.classical.classical_sets.meets Declared in library mathcomp.classical.classical_sets, line 3229, characters 11-16


Source code
{ } : equivT S T -> equivT T U -> equivT S U :=
   equivT_transl \o equivT_sym.
Definition
equivT_transr

seqDU : forall [T : Type], (set T) ^nat -> nat -> set T seqDU is not universe polymorphic Arguments seqDU [T]%_type_scope F n%_nat_scope _ seqDU is transparent Expands to: Constant mathcomp.classical.classical_sets.seqDU Declared in library mathcomp.classical.classical_sets, line 3360, characters 11-16


Source code
{ } : equivT U S -> equivT U T :=
   equivT_trans^~ eqST.
Definition
equivT_Prop

seqD : forall [T : Type], (set T) ^nat -> nat -> set T seqD is not universe polymorphic Arguments seqD [T]%_type_scope F n%_nat_scope _ seqD is transparent Expands to: Constant mathcomp.classical.classical_sets.seqD Declared in library mathcomp.classical.classical_sets, line 3371, characters 11-15


Source code
( : Prop) : (equivT P Q) <-> (equivT P Q).
Proof.
split; destruct 1; split; assumption. Defined.
Definition
equivT_LR

xsection : forall [T1 T2 : Type], set (T1 * T2) -> T1 -> set T2 xsection is not universe polymorphic Arguments xsection [T1 T2]%_type_scope A%_classical_set_scope x _ xsection is transparent Expands to: Constant mathcomp.classical.classical_sets.xsection Declared in library mathcomp.classical.classical_sets, line 3440, characters 11-19


Source code
{ } ( : equivT S T) : S -> T :=
  let: EquivT S_T _ := eq in S_T.
Definition
equivT_RL

ysection : forall [T1 T2 : Type], set (T1 * T2) -> T2 -> set T1 ysection is not universe polymorphic Arguments ysection [T1 T2]%_type_scope A%_classical_set_scope y _ ysection is transparent Expands to: Constant mathcomp.classical.classical_sets.ysection Declared in library mathcomp.classical.classical_sets, line 3442, characters 11-19


Source code
{ } ( : equivT S T) : T -> S :=
  let: EquivT _ T_S := eq in T_S.

Hint View for move/ equivT_LR|2 equivT_RL|2.
Hint View for apply/ equivT_RL|2 equivT_LR|2.

A generic Forall "constructor" for the Gallina forall quantifier, i.e., ``` \Forall x, P := Forall (fun x => P) := forall x, P. ``` The main use of Forall is to apply congruence to a forall equality: ``` congr1 Forall : forall P Q, P = Q -> Forall P = Forall Q. ``` in particular in a classical setting with function extensionality, where we can have (forall x, P x = Q x) -> (forall x, P x) = (forall x, Q x). We use a forallSort structure to factor the ad hoc PTS product formation rules; forallSort is keyed on the type of the entire forall expression, or (up to subsumption) the type of the forall body---this is always a sort. This implementation has two important limitations: 1. It cannot handle the SProp sort and its typing rules. However, its main application is extensionality, which is not compatible with SProp because an (A : SProp) -> B "function" is not a generic (A : Type) -> B function as SProp is not included in Type. 2. The Forall constructor can't be inserted by a straightforward unfold (as in, rewrite -[forall x, _]/(Forall _)) because of the way Coq unification handles Type constraints. The ForallI tactic mitigates this issue, but there are additional issues with its implementation---see below.

Structure
forallSort
Source code
:=
  ForallSort {
forall_sort
Source code
:> Type; _ : (A -> forall_sort) -> forall_sort}.

Notation
mkForallSort
Source code
A S := (@ForallSort A S (fun => forall , T x)).
Polymorphic Definition
TypeForall

diagonal : forall {T : Type}, set (T * T) diagonal is not universe polymorphic Arguments diagonal {T}%_type_scope _ diagonal is transparent Expands to: Constant mathcomp.classical.classical_sets.diagonal Declared in library mathcomp.classical.classical_sets, line 3582, characters 11-19


Source code
( := Type) ( : S) := mkForallSort A S.
Canonical TypeForall.

Canonical
PropForall
Source code
:= mkForallSort A Prop.

Canonical
SetForall
Source code
( : Set) := mkForallSort A Set.

Definition {} { : forallSort A} :=
  let: ForallSort _ F := S return (A -> S) -> S in F.

Notation
"\Forall x .. z , T"
Source code
:=
   (Forall (fun => .. (Forall (fun => T)) ..))
  (at level 200, x binder, z binder, T at level 200,
   format "'[hv' '\Forall' '[' x .. z , ']' '/ ' T ']'") : type_scope.

Tactic Notation "ForallI" ssrpatternarg(pat) :=
  let F := fresh "F" in ssrmatching.ssrpattern pat => F;
  case: F / (@erefl _ F : Forall _ = _).
Tactic Notation "ForallI" := ForallI (forall , _).

We define specialized copies of the wrapped structure of ssrfun for Prop and Type, as we need more than two alternative rules (indeed, 3 for Prop and 4 for Type). We need separate copies for Prop and Type as universe polymorphism cannot instantiate Type with Prop.

Structure
wrappedProp
Source code
:= WrapProp {
unwrap_Prop
Source code
:> Prop}.
Definition
wrap4Prop
Source code
:= WrapProp.
Definition
wrap3Prop
Source code
:= wrap4Prop.
Definition
wrap2Prop
Source code
:= wrap3Prop.
Canonical
wrap1Prop
Source code
:= wrap2Prop P.

Polymorphic Structure
wrappedType
Source code
@{i} := WrapType {
unwrap_Type
Source code
:> Type@{i}}.
Polymorphic Definition
wrap4Type
Source code
@{i} := WrapType@{i}.
Polymorphic Definition
wrap3Type
Source code
@{i} := wrap4Type@{i}.
Polymorphic Definition
wrap2Type
Source code
@{i} := wrap3Type@{i}.
Polymorphic Definition
wrap1Type
Source code
@{i} ( : Type@{i}) := wrap2Type T.
Canonical wrap1Type.

Lemma
generic_forall_extensionality
Source code
{} { : forallSort A} { : A -> S} :
  P =1 Q -> Forall P = Forall Q.
Proof.
by move/funext->. Qed.

A set of tools (tactics, views, and rewrite rules) to facilitate the handling of classical negation. The core functionality of these tools is implemented by three sets of canonical structures that provide for the simplification of negation statements (e.g., using de Morgan laws), the conversion from constructive statements in Type to purely logical ones in Prop (equivalently, expansion rules for the statement inhabited T), and conversely extraction of constructive contents from logical statements. Except for bool predicates and operators, all definitions are treated transparently when matching statements for either simplification or conversion; this is achieved by using the wrapper telescope pattern, first delegating the matching of specific logical connectives, predicates, or type constructors to an auxiliary structure that *FAILS* to match unknown operators, thus triggers the expansion of defined constants. If this ultimately fails then the wrapper is expanded, and the primary structure instance for the expanded wrapper provides an alternative default rule: not simplifying ~ P, not expanding inhabited T, or not extracting any contents from a proposition P, respectively. Additional rules, for intermediate wrapper instances, are used to handle forall statements (for which canonical instances are not yet supported), as well as addiitonal simplifications, such as inhabited P = P :> Prop. Finally various tertiary structures are used to match deeper patterns, such as bounded forall statements of the form forall x, P x -> Q x, or inequalites x != y (i.e., is_true (~~ (x == y))). As mentioned above, tertiary rules for bool subexpressions do not try to expand definitions, as this would lead to the undesirable expansion of some standard definitions. This is simply achieved by *NOT* using the wrapper telescope pattern, and just having a default instance alongside those for specific predicates and connectives.

The negatedProp structure provides simplification of the Prop negation (~ _) for standard connectives and predicates. The instances below cover the pervasive and ssrbool Prop connectives, decidable equality, as well as bool propositions (i.e., the is_true predicate), together with a few bool connectives and predicates: negation ~~, equality ==, and nat <= and <. Others can be added (e.g., Order.le/lt) by declaring appropriate instances of bool_negation and bool_affirmation, while other Prop connectives and predicates can be added by declaring instances of proper_negatedProp.

The implementation follows the wrapper telescope pattern outlined above: negatedProp instances match on the wrappedProp wrapper to try three generic matching rules, in succession: - Rule 1: match a specific connective or predicate with an instance of the properNegatedProp secondary structure, expanding definitions if needed, but failing if no proper match is found. - Rule 2: match a forall statement (including (T : Type) -> P statements). - Rule 3: match any Prop but return the trivial simplification. The simplified proposition is returned as a projection parameter nP rather than a Structure member, so that applying the corresponding views or rewrite rules doesn't expose the inferred structures; properNegatedProp does similarly. Also, negatedProp similarly returns a 'trivial' bool flag that is set when Rule 3 is used, but this is actually used in the reverse direction: views notP and rewrite rule notE force trivial := false, thus excluding trivial instances.

Structure
negatedProp
Source code
( : bool) :=
  NegatedProp {
negated_Prop
Source code
:> wrappedProp; _ : (~ negated_Prop) = nP}.

Structure
properNegatedProp
Source code
:= ProperNegatedProp {
  
proper_negated_Prop
Source code
:> Prop; _ : (~ proper_negated_Prop) = nP}.

Local Notation t nP P := (unwrap_Prop (@negated_Prop t nP P)).
Local Notation t nP P x := (nProp t (nP x) (P x)).
Local Notation nP P := (@proper_negated_Prop nP P).

User views and rewrite rules. The plain versions (notP, notE and notI) do not match trivial instances; lax_XXX versions allow them. In addition, the negation introduction rewrite rule notI does not match forall or -> statements---lax_notI must be used for these.

Lemma
lax_notE
Source code
{ } : (~ nProp t nP P) = nP
Proof.
by case: P. Qed.
Lemma
lax_notP
Source code
{ } : ~ nProp t nP P -> nP
Proof.
by rewrite lax_notE. Qed.
Definition
lax_notI

Order.default_display : disp_t Order.default_display is not universe polymorphic Order.default_display is transparent Expands to: Constant mathcomp.classical.unstable.Order.default_display Declared in library mathcomp.classical.unstable, line 58, characters 11-26


Source code
{ } : nProp t nP P = (~ nP) := canRL notK (lax_notE P).

#[warn(note="A different `notE` used to be provided by `boolp.v` before MathComp-Analysis 1.15.0.")]
Definition
notE

proj : forall {I : Type} {T : I -> Type} (i : I), (forall i0 : I, T i0) -> T i proj is not universe polymorphic Arguments proj {I}%_type_scope {T}%_function_scope i f%_function_scope proj is transparent Expands to: Constant mathcomp.classical.unstable.proj Declared in library mathcomp.classical.unstable, line 63, characters 11-15


Source code
{} : (~ nProp false nP P) = nP := lax_notE P.
#[warn(note="A different `notP` used to be provided by `boolp.v` before MathComp-Analysis 1.15.0.")]
Definition
notP

monotonic : forall [d : disp_t] [T : porderType d] [d' : disp_t] [T' : porderType d'] [pT : predType T], pT -> (T -> T') -> Prop monotonic is not universe polymorphic Arguments monotonic [d T d' T' pT] A f%_function_scope monotonic is transparent Expands to: Constant mathcomp.classical.unstable.monotonic Declared in library mathcomp.classical.unstable, line 194, characters 11-20


Source code
{ } := MoveView (@lax_notP false nP P).

Fact
proper_nPropP
Source code
: (~ pnProp nP P) = nP
Proof.
by case: P. Qed.
Definition
notI

strict_monotonic : forall [d : disp_t] [T : porderType d] [d' : disp_t] [T' : porderType d'] [pT : predType T], pT -> (T -> T') -> Prop strict_monotonic is not universe polymorphic Arguments strict_monotonic [d T d' T' pT] A f%_function_scope strict_monotonic is transparent Expands to: Constant mathcomp.classical.unstable.strict_monotonic Declared in library mathcomp.classical.unstable, line 198, characters 11-27


Source code
{} : pnProp nP P = (~ nP) := canRL notK (proper_nPropP P).

Rule 1: proper negation simplification, delegated to properNegatedProp.
Canonical
proper_nProp

onem : forall {R : pzRingType}, R -> R onem is not universe polymorphic Arguments onem {R} r%_ring_scope onem is transparent Expands to: Constant mathcomp.classical.unstable.onem Declared in library mathcomp.classical.unstable, line 302, characters 11-15


Source code
:=
  @NegatedProp false nP (wrap1Prop (pnProp nP P)) (proper_nPropP P).

Rule 2: forall_nProp is defined below as it uses exists_nProp.

Rule 3: trivial negation.
Canonical
trivial_nProp

inv_fun : forall {T : Type} {R : unitRingType}, (T -> R) -> T -> R inv_fun is not universe polymorphic Arguments inv_fun {T}%_type_scope {R} f%_function_scope x / The reduction tactics unfold inv_fun when applied to 4 arguments inv_fun is transparent Expands to: Constant mathcomp.classical.unstable.inv_fun Declared in library mathcomp.classical.unstable, line 392, characters 11-18


Source code
:= @NegatedProp true (~ P) (wrap3Prop P) erefl.

properNegatedProp instances.

Canonical
True_nProp

bound_side : forall [d : disp_t] [T : porderType d], bool -> itv_bound T -> bool bound_side is not universe polymorphic Arguments bound_side [d T] c%_bool_scope x bound_side is transparent Expands to: Constant mathcomp.classical.unstable.bound_side Declared in library mathcomp.classical.unstable, line 396, characters 11-21


Source code
:= @ProperNegatedProp False True notB.1.
Canonical
False_nProp

swap : forall {T1 T2 : Type}, T1 * T2 -> T2 * T1 swap is not universe polymorphic Arguments swap {T1 T2}%_type_scope x swap is transparent Expands to: Constant mathcomp.classical.unstable.swap Declared in library mathcomp.classical.unstable, line 403, characters 11-15


Source code
:= @ProperNegatedProp True False notB.2.
Canonical
not_nProp

prodA : forall {X Y Z : Type}, X * Y * Z -> X * (Y * Z) prodA is not universe polymorphic Arguments prodA {X Y Z}%_type_scope xyz prodA is transparent Expands to: Constant mathcomp.classical.unstable.prodA Declared in library mathcomp.classical.unstable, line 408, characters 11-16


Source code
:= @ProperNegatedProp P (~ P) (notK P).

Fact
and_nPropP
Source code
: (~ (P /\ nProp tQ nQ Q)) = (P -> nQ).
Proof.
by rewrite -implypN lax_notE. Qed.
Canonical
and_nProp

prodAr : forall {X Y Z : Type}, X * (Y * Z) -> X * Y * Z prodAr is not universe polymorphic Arguments prodAr {X Y Z}%_type_scope xyz prodAr is transparent Expands to: Constant mathcomp.classical.unstable.prodAr Declared in library mathcomp.classical.unstable, line 411, characters 11-17


Source code
:=
  ProperNegatedProp (@and_nPropP P tQ nQ Q).

Fact
and3_nPropP
Source code
: (~ [/\ P, Q & nProp tR nR R]) = (P -> Q -> nR).
Proof.
#[warnings="-user-warn"] by hnf; rewrite and3E notE. Qed.
Canonical
and3_nProp

map_pair : forall {S U : Type}, (S -> U) -> S * S -> U * U map_pair is not universe polymorphic Arguments map_pair {S U}%_type_scope f%_function_scope x map_pair is transparent Expands to: Constant mathcomp.classical.unstable.map_pair Declared in library mathcomp.classical.unstable, line 425, characters 11-19


Source code
:=
  ProperNegatedProp (@and3_nPropP P Q tR nR R).

Fact
and4_nPropP
Source code
:
  (~ [/\ P, Q, R & nProp tS nS S]) = (P -> Q -> R -> nS).
Proof.
#[warnings="-user-warn"] by hnf; rewrite and4E notE. Qed.
Canonical
and4_nProp

sigT_fun : forall {I : Type} {X : I -> Type} {T : Type}, (forall i : I, X i -> T) -> {i : I & X i} -> T sigT_fun is not universe polymorphic Arguments sigT_fun {I}%_type_scope {X}%_function_scope {T}%_type_scope f%_function_scope x sigT_fun is transparent Expands to: Constant mathcomp.classical.unstable.sigT_fun Declared in library mathcomp.classical.unstable, line 474, characters 11-19


Source code
:=
  ProperNegatedProp (@and4_nPropP P Q R tS nS S).

Fact
and5_nPropP
Source code
:
  (~ [/\ P, Q, R, S & nProp tT nT T]) = (P -> Q -> R -> S -> nT).
Proof.
#[warnings="-user-warn"] by hnf; rewrite and5E notE. Qed.
Canonical
and5_nProp
Source code
:=
  ProperNegatedProp (@and5_nPropP P Q R S tT nT T).

Fact
or_nPropP
Source code
:
  (~ (nProp tP nP P \/ nProp tQ nQ Q)) = (nP /\ nQ).
Proof.
by rewrite not_orE !lax_notE. Qed.
Canonical
or_nProp
Source code
:=
  ProperNegatedProp (@or_nPropP tP nP P tQ nQ Q).

Fact
or3_nPropP
Source code
:
  (~ [\/ nProp tP nP P, nProp tQ nQ Q | nProp tR nR R]) = [/\ nP, nQ & nR].
Proof.
#[warnings="-user-warn"] by rewrite or3E notE and3E. Qed.
Canonical
or3_nProp
Source code
:=
  ProperNegatedProp (@or3_nPropP tP nP P tQ nQ Q tR nR R).

Fact
or4_nPropP
Source code
:
  (~ [\/ nProp tP nP P, nProp tQ nQ Q, nProp tR nR R | nProp tS nS S])
     = [/\ nP, nQ, nR & nS].
Proof.
#[warnings="-user-warn"] by rewrite or4E notE and4E. Qed.
Canonical
or4_nProp
Source code
:=
  ProperNegatedProp (@or4_nPropP tP nP P tQ nQ Q tR nR R tS nS S).

The andRHS tertiary structure used to simplify (~ (P -> False)) to P, both here for the imply_nProp instance and for bounded_forall_nProp below. Because the andRHS instances match the Prop RETURNED by negatedProp they do not need to expand definitions, hence do not need to use the wrapper telescope pattern.

Notation binary P Q PQ := (PQ = if binary then P /\ Q else Q)%type.
Structure :=
  AndRHS { :> Prop; _ : (P /\ and_RHS) = PQ; _ : and_def binary P Q PQ}.
Canonical
unary_and_rhs
Source code
:= @AndRHS false P P P True (andB.1.2 P) erefl.
Canonical
binary_and_rhs
Source code
:= @AndRHS true P Q (P /\ Q) Q erefl erefl.

Fact
imply_nPropP
Source code
( : andRHS b P nQ PnQ) :
  (~ (P -> nProp tR nR R)) = PnQ.
Proof.
by rewrite -orNp {R}lax_notE; case: nR. Qed.
Canonical
imply_nProp
Source code
:=
  ProperNegatedProp (@imply_nPropP b P nQ PnQ tR nR R).

Fact
exists_nPropP
Source code
:
  (~ exists : A, nPred tP nP P x) = (forall : A, nP x).
Proof.
eqProp=> [nEP x | AnP [x]]; last by rewrite -/(~ _) lax_notE.
by rewrite -(lax_notE (P x)) => Px; case: nEP; exists x.
Qed.
Canonical
exists_nProp
Source code
:=
  ProperNegatedProp (@exists_nPropP A tP nP P).

Fact
exists2_nPropP
Source code
:
  (~ exists2 : A, P x & nPred tQ nQ Q x) = (forall : A, P x -> nQ x).
Proof.
#[warnings="-user-warn"] by rewrite exists2E notE. Qed.
Canonical
exists2_nProp

card_le : forall [T U : Type], set T -> set U -> bool card_le is not universe polymorphic Arguments card_le [T U]%_type_scope (A B)%_classical_set_scope card_le is transparent Expands to: Constant mathcomp.classical.cardinality.card_le Declared in library mathcomp.classical.cardinality, line 61, characters 11-18


Source code
:=
  ProperNegatedProp (@exists2_nPropP A P tQ nQ Q).

Fact
inhabited_nPropP
Source code
: (~ inhabited T) = (T -> False).
Proof.
#[warnings="-user-warn"] by rewrite inhabitedE notE. Qed.
Canonical
inhabited_nProp

card_eq : forall [T U : Type], set T -> set U -> bool card_eq is not universe polymorphic Arguments card_eq [T U]%_type_scope (A B)%_classical_set_scope card_eq is transparent Expands to: Constant mathcomp.classical.cardinality.card_eq Declared in library mathcomp.classical.cardinality, line 66, characters 11-18


Source code
:= ProperNegatedProp (inhabited_nPropP T).

Rule 2: forall negation, including (T : Type) -> P statements. We use tertiary structures to recognize bounded foralls and simplify, e.g., ~ forall x, P -> Q to exists2 x, P & ~ Q, or even exists x, P when Q := False (as above for imply). As forall_body_nProp and forall_body_proper_nProp are telescopes over negatedProp and properNegatedProp, respectively, their instances match instances declared above without the need to expand definitions, hence do not need to use the wrapper telescope idiom.

Structure
negatedForallBody
Source code
:= NegatedForallBody {
  
negated_forall_body
Source code
:> negatedProp tR nR; _ : and_def bounded P nQ nR}.
Structure
properNegatedForallBody
Source code
:= ProperNegatedForallBody {
  
proper_negated_forall_body
Source code
:> properNegatedProp nR; _ : and_def b P nQ nR}.
Notation b P nQ t nR x := (negatedForallBody b (P x) (nQ x) t (nR x)).

The explicit argument to fun_if is a workaround for a bug in the Coq unification code that prevents default instances from ever matching match constructs. Furthermore rewriting with ifE would not work here, because the if_expr definition would be expanded by the eta expansion needed to match the exists_nProp rule.

Fact
forall_nPropP
Source code
( : forall , nBody b P nQ tR nR x) :
  (~ forall : A, R x) = if b then exists2 , P x & nQ x else exists , nQ x.
Proof.
rewrite exists2E -(fun_if (fun => exists , idfun P x)) notI /=; congr not.
apply/generic_forall_extensionality=> x; rewrite if_arg lax_notI.
by case: (R x) => _ <-.
Qed.
Canonical
forall_nProp

finite_set : forall {T : Type}, set T -> Prop finite_set is not universe polymorphic Arguments finite_set {T}%_type_scope A%_classical_set_scope finite_set is transparent Expands to: Constant mathcomp.classical.cardinality.finite_set Declared in library mathcomp.classical.cardinality, line 71, characters 11-21


Source code
( : forall , nBody b P nQ tR nR x) :=
  @NegatedProp false _ (wrap2Prop (forall : A, R x)) (forall_nPropP R).

Fact
proper_nBodyP
Source code
:
  properNegatedForallBody b P nQ nR -> and_def b P nQ nR.
Proof.
by case. Qed.
Canonical
proper_nBody

emptyE_subdef : (forall T : emptyType, all_equal_to (set0 : set T)) * (forall (T : emptyType) (U : Type) (A : set T) (B : set U), (A #<= B)%card) * (forall (T : emptyType) (U : Type) (A : set T) (B : set U), (B #<= A)%card = (B == set0)) * (forall (T : eqType) (x y : T), (x == y : Prop) = (x = y)) emptyE_subdef is not universe polymorphic emptyE_subdef is transparent Expands to: Constant mathcomp.classical.cardinality.emptyE_subdef Declared in library mathcomp.classical.cardinality, line 191, characters 11-24


Source code
:=
  let := @proper_nBodyP b P nQ nR R in
  @NegatedForallBody b P nQ false nR (proper_nProp R) def_nR.
Canonical
nonproper_nBody

emptyE : (forall T : emptyType, all_equal_to (set0 : set T)) * (forall (T : emptyType) (U : Type) (A : set T) (B : set U), (A #<= B)%card) * (forall (T : emptyType) (U : Type) (A : set T) (B : set U), (B #<= A)%card = (B == set0)) * (forall (T : eqType) (x y : T), (x == y : Prop) = (x = y)) * (forall (T : emptyType) (U : Type) (A : set T) (B : set U), (B #= A)%card = (B == set0)) * (forall (T : emptyType) (U : Type) (A : set T) (B : set U), (A #= B)%card = (B == set0)) emptyE is not universe polymorphic emptyE is transparent Expands to: Constant mathcomp.classical.cardinality.emptyE Declared in library mathcomp.classical.cardinality, line 363, characters 11-17


Source code
:=
  @NegatedForallBody false True nP tP nP P erefl.

Fact
andRHS_def
Source code
: andRHS b P Q PQ -> and_def b P Q PQ.
Proof.
by case. Qed.
Canonical
bounded_nBody

countable : forall [T : Type], set T -> bool countable is not universe polymorphic Arguments countable [T]%_type_scope A%_classical_set_scope countable is transparent Expands to: Constant mathcomp.classical.cardinality.countable Declared in library mathcomp.classical.cardinality, line 459, characters 11-20


Source code
:=
  ProperNegatedForallBody (@imply_nProp b P nQ PnQ tR nR R) (andRHS_def nR).
Canonical
unbounded_nBody

fset_set : forall [T : choiceType], set T -> {fset T} fset_set is not universe polymorphic Arguments fset_set [T] A%_classical_set_scope fset_set is transparent Expands to: Constant mathcomp.classical.cardinality.fset_set Declared in library mathcomp.classical.cardinality, line 761, characters 11-19


Source code
:=
  @ProperNegatedForallBody false True nQ nQ Q erefl.

The properNegatedProp instance that handles boolean statements. We use two tertiary structures to handle positive and negative boolean statements so that the contra tactic below will mostly subsume the collection of contraXX lemmas in ssrbool and eqtype. We only match manifest ~~ connectives, the true and false constants, and the ==, <=%N, and <%N predicates. In particular we do not use de Morgan laws to push boolean negation into connectives, as we did above for Prop connectives. It will be up to the user to use rewriting to put the negated statement in its desired shape.

Structure
negatedBool
Source code
:=
  NegatedBool {
negated_bool
Source code
:> bool; _ : (~ negated_bool) = nP}.
Structure
positedBool
Source code
:=
  PositedBool {
posited_bool
Source code
:> bool; _ : is_true posited_bool = P}.

Local Fact
is_true_nPropP
Source code
( : negatedBool nP) : (~ b) = nP.
Proof.
by case: b. Qed.
Canonical
is_true_nProp

fst_fset : forall [T1 T2 : choiceType], {fset T1 * T2} -> {fset T1} fst_fset is not universe polymorphic Arguments fst_fset [T1 T2] A fst_fset is transparent Expands to: Constant mathcomp.classical.cardinality.fst_fset Declared in library mathcomp.classical.cardinality, line 846, characters 11-19


Source code
:= ProperNegatedProp (@is_true_nPropP nP b).

Local Fact
true_negP
Source code
: (~ true) = False
Proof.
by eqProp. Qed.
Local Fact
true_posP
Source code
: (true : Prop) = True
Proof.
by eqProp. Qed.
Local Fact
false_negP
Source code
: (~ false) = True
Proof.
by eqProp. Qed.
Local Fact
false_posP
Source code
: (false : Prop) = False
Proof.
by eqProp. Qed.
Canonical
true_neg

snd_fset : forall [T1 T2 : choiceType], {fset T1 * T2} -> {fset T2} snd_fset is not universe polymorphic Arguments snd_fset [T1 T2] A snd_fset is transparent Expands to: Constant mathcomp.classical.cardinality.snd_fset Declared in library mathcomp.classical.cardinality, line 848, characters 11-19


Source code
:= NegatedBool true_negP.
Canonical
true_pos

fimfun : forall {aT rT : Type}, {pred aT -> rT} fimfun is not universe polymorphic Arguments fimfun {aT rT}%_type_scope _ fimfun is transparent Expands to: Constant mathcomp.classical.cardinality.fimfun Declared in library mathcomp.classical.cardinality, line 1340, characters 11-17


Source code
:= PositedBool true_posP.
Canonical
false_neg

fimfun_key : forall {aT rT : Type}, pred_key (T:=aT -> rT) fimfun fimfun_key is not universe polymorphic Arguments fimfun_key {aT rT}%_type_scope fimfun_key is opaque Expands to: Constant mathcomp.classical.cardinality.fimfun_key Declared in library mathcomp.classical.cardinality, line 1341, characters 11-21


Source code
:= NegatedBool false_negP.
Canonical
false_pos

fimfun_keyed : forall {aT rT : Type}, keyed_pred fimfun_key fimfun_keyed is not universe polymorphic Arguments fimfun_keyed {aT rT}%_type_scope fimfun_keyed is transparent Expands to: Constant mathcomp.classical.cardinality.fimfun_keyed Declared in library mathcomp.classical.cardinality, line 1343, characters 10-22


Source code
:= PositedBool false_posP.

Local Fact ( : bool) : (~ b) = ~~ b
Proof.
exact/reflect_eq/negP. Qed.
Canonical
id_neg

fimfun_Sub_subproof : forall {aT rT : Type} [f : aT -> rT], f \in fimfun -> FiniteImage.axioms_ aT rT f fimfun_Sub_subproof is not universe polymorphic Arguments fimfun_Sub_subproof {aT rT}%_type_scope [f]%_function_scope fP fimfun_Sub_subproof is transparent Expands to: Constant mathcomp.classical.cardinality.fimfun_Sub_subproof Declared in library mathcomp.classical.cardinality, line 1352, characters 11-30


Source code
:= NegatedBool (id_negP b).
Canonical
id_pos

fimfun_Sub : forall {aT rT : Type} [f : aT -> rT], f \in fimfun -> {fimfun aT >-> rT} fimfun_Sub is not universe polymorphic Arguments fimfun_Sub {aT rT}%_type_scope [f]%_function_scope fP fimfun_Sub is transparent Expands to: Constant mathcomp.classical.cardinality.fimfun_Sub Declared in library mathcomp.classical.cardinality, line 1354, characters 11-21


Source code
( : bool) := @PositedBool b b erefl.

Local Fact
negb_negP
Source code
( : positedBool P) : (~ ~~ b) = P.
Proof.
by rewrite (reflect_eq negP) negbK; case: b. Qed.
Canonical
negb_neg

cst_fimfun : forall {aT rT : Type}, rT -> {fimfun aT >-> rT} cst_fimfun is not universe polymorphic Arguments cst_fimfun {aT rT}%_type_scope x cst_fimfun is transparent Expands to: Constant mathcomp.classical.cardinality.cst_fimfun Declared in library mathcomp.classical.cardinality, line 1391, characters 11-21


Source code
:= NegatedBool (@negb_negP P b).
Local Fact
negb_posP
Source code
( : negatedBool nP) : (~~ b = nP :> Prop).
Proof.
#[warnings="-user-warn"] by rewrite -(reflect_eq negP) notE. Qed.
Canonical
negb_pos

Internals.move_viewP : forall {S T : Type}, Internals.move_view S T -> S -> T Internals.move_viewP is not universe polymorphic Arguments Internals.move_viewP {S T}%_type_scope mv _ Internals.move_viewP is transparent Expands to: Constant mathcomp.classical.contra.Internals.move_viewP Declared in library mathcomp.classical.contra, line 64, characters 11-21


Source code
:= PositedBool (@negb_posP nP b).

We use a tertiary structure to handle the negation of nat comparisons, and simplify ~ m <= n to n < m, and ~ m < n to n <= m. As m < n is merely notation for m.+1 <= n, we need to dispatch on the left hand side of the comparison to perform the latter simplification.

Structure
negatedLeqLHS
Source code
:=
  NegatedLeqLHS {
negated_leq_LHS
Source code
:> nat; _ : (n < negated_leq_LHS) = lt_nm}.
Canonical
neg_ltn_LHS

Internals.equivT_refl : forall S : Type, Internals.equivT S S Internals.equivT_refl is not universe polymorphic Arguments Internals.equivT_refl S%_type_scope Internals.equivT_refl is transparent Expands to: Constant mathcomp.classical.contra.Internals.equivT_refl Declared in library mathcomp.classical.contra, line 73, characters 11-22


Source code
:= @NegatedLeqLHS n (n <= m) m.+1 erefl.
Canonical
neg_leq_LHS

Internals.equivT_transl : forall {S T U : Type}, Internals.equivT S T -> Internals.equivT S U -> Internals.equivT T U Internals.equivT_transl is not universe polymorphic Arguments Internals.equivT_transl {S T U}%_type_scope _ _ Internals.equivT_transl is transparent Expands to: Constant mathcomp.classical.contra.Internals.equivT_transl Declared in library mathcomp.classical.contra, line 74, characters 11-24


Source code
:= @NegatedLeqLHS n (n < m) m erefl.

Local Fact
leq_negP
Source code
( : negatedLeqLHS n lt_nm) : (~ m <= n) = lt_nm.
Proof.
#[warnings="-user-warn"] by rewrite notE -ltnNge; case: m => /= m ->. Qed.
Canonical
leq_neg

Internals.equivT_sym : forall {S T : Type}, Internals.equivT S T -> Internals.equivT T S Internals.equivT_sym is not universe polymorphic Arguments Internals.equivT_sym {S T}%_type_scope _ Internals.equivT_sym is transparent Expands to: Constant mathcomp.classical.contra.Internals.equivT_sym Declared in library mathcomp.classical.contra, line 79, characters 11-21


Source code
:= NegatedBool (@leq_negP n lt_nm m).

We use two tertiary structures to simplify negation of boolean constant and decidable equalities, simplifying b <> true to ~~ b, b <> false to b, x <> y to x != y, and ~ x != y to x = y. We do need to use the wrapper telescope pattern here, as we want to simplify instances of x <> y when y evaluates to true or false. Since we only need two rules (true/false RHS or generic eqType RHS) we can use the generic wrapped type from ssrfun. The actual matching of the true and false RHS is delegated to a fourth level bool_eq_negation_rhs structure. Finally observe that the ~ x != y to x = y simplification can be handled by a bool_affirmation instance.

Structure :=
  NeqRHS { :> wrapped T; _ : (x <> unwrap neq_RHS) = nP}.
Structure
boolNeqRHS
Source code
( : bool) :=
  BoolNeqRHS {
bool_neq_RHS
Source code
; _ : (x <> bool_neq_RHS) = nP}.

Local Fact
eq_nPropP
Source code
( : neqRHS nP x) : (x <> unwrap y :> T) = nP.
Proof.
by case: y. Qed.
Canonical
eq_nProp

Internals.equivT_trans : forall {S T U : Type}, Internals.equivT S T -> Internals.equivT T U -> Internals.equivT S U Internals.equivT_trans is not universe polymorphic Arguments Internals.equivT_trans {S T U}%_type_scope _ _ Internals.equivT_trans is transparent Expands to: Constant mathcomp.classical.contra.Internals.equivT_trans Declared in library mathcomp.classical.contra, line 81, characters 11-23


Source code
:= ProperNegatedProp (@eq_nPropP nP T x y).

Local Fact
bool_neqP
Source code
: (x <> @bool_neq_RHS nP x y) = nP.
Proof.
by case: y. Qed.
Canonical
bool_neq

Internals.equivT_transr : forall {S T U : Type}, Internals.equivT S T -> Internals.equivT U S -> Internals.equivT U T Internals.equivT_transr is not universe polymorphic Arguments Internals.equivT_transr {S T U}%_type_scope eqST _ Internals.equivT_transr is transparent Expands to: Constant mathcomp.classical.contra.Internals.equivT_transr Declared in library mathcomp.classical.contra, line 83, characters 11-24


Source code
:= @NeqRHS nP bool x (wrap _) (@bool_neqP nP x y).
Canonical
true_neq

Internals.equivT_Prop : forall P Q : Prop, Internals.equivT P Q <-> Internals.equivT P Q Internals.equivT_Prop is not universe polymorphic Arguments Internals.equivT_Prop (P Q)%_type_scope Internals.equivT_Prop is transparent Expands to: Constant mathcomp.classical.contra.Internals.equivT_Prop Declared in library mathcomp.classical.contra, line 85, characters 11-22


Source code
:= BoolNeqRHS (@is_true_nPropP nP b).
Local Fact
false_neqP
Source code
( : positedBool P) : (b <> false :> bool) = P.
Proof.
by move: b => [] [] /= <-; exact/propext. Qed.
Canonical
false_neq

Internals.equivT_LR : forall {S T : Type}, Internals.equivT S T -> S -> T Internals.equivT_LR is not universe polymorphic Arguments Internals.equivT_LR {S T}%_type_scope eq _ Internals.equivT_LR is transparent Expands to: Constant mathcomp.classical.contra.Internals.equivT_LR Declared in library mathcomp.classical.contra, line 87, characters 11-20


Source code
:= BoolNeqRHS (@false_neqP P b).

Local Fact
eqType_neqP
Source code
( : eqType) ( : T) : (x <> y) = (x != y).
Proof.
by rewrite [in LHS](reflect_eq eqP) (reflect_eq negP). Qed.
Canonical
eqType_neq

Internals.equivT_RL : forall {S T : Type}, Internals.equivT S T -> T -> S Internals.equivT_RL is not universe polymorphic Arguments Internals.equivT_RL {S T}%_type_scope eq _ Internals.equivT_RL is transparent Expands to: Constant mathcomp.classical.contra.Internals.equivT_RL Declared in library mathcomp.classical.contra, line 89, characters 11-20


Source code
( : eqType) :=
  @NeqRHS (x != y) T x (Wrap y) (eqType_neqP x y).
Local Fact
eq_op_posP
Source code
( : eqType) : (x == y :> T : Prop) = (x = y).
Proof.
exact/esym/reflect_eq/eqP. Qed.
Canonical
eq_op_pos

Internals.TypeForall@{u u0} : forall A : Type, Internals.forallSort A Internals.TypeForall is universe polymorphic Arguments Internals.TypeForall A%_type_scope Internals.TypeForall is transparent Expands to: Constant mathcomp.classical.contra.Internals.TypeForall Declared in library mathcomp.classical.contra, line 127, characters 23-33


Source code
:= PositedBool (@eq_op_posP T x y).

The witnessedType structure provides conversion between Type and Prop in goals; the conversion is mostly used in the Type-to-Prop direction, e.g., as a preprocessing step preceding proof by contradiction (see absurd_not below), but the Prop-to-Type direction is required for contraposition. Thus witnessedType associates to a type T a "witness" proposition P equivalent to the existence of an x of type T. As in a `{classical_logic} context inhabited T is such a proposition, witnessedType can be understood as providing simplification for inhabited T, much like negatedProp provides simplification for ~ P for standard connectives and predicates.

Similarly to negatedProp, witnessedType returns the witness proposition via a projection argument P, but does not need to signal "trivial" instances as the default value for P is nontrivial (namely, inhabited T), while the "trivial" case where P = T is actually desireable and handled by an extra top-priority rule.

Structure
witnessedType
Source code
:= WitnessedType {
 
witnessed_Type
Source code
:> wrappedType; _ : inhabited witnessed_Type = P}.
Structure
properWitnessedType
Source code
:= ProperWitnessedType {
  
proper_witnessed_Type
Source code
:> Type; _ : inhabited proper_witnessed_Type = P}.
Local Notation P T := (unwrap_Type (@witnessed_Type P T)).
Local Notation P T x := (wType (P x) (T x)).


Lemma
witnessedType_intro
Source code
{ : Prop} : P -> wType P T.
Proof.
by case: T => /= T <- /inhabited_witness. Qed.
Local Coercion witnessedType_intro : witnessedType >-> Funclass.

Lemma
witnessedType_elim
Source code
{} : wType P T -> P.
Proof.
by case: T => /= T <-. Qed.
Local Notation := witnessedType_elim.


Local Fact
eq_inhabited
Source code
( : Prop) : (T -> P) -> (P -> T) -> inhabited T = P.
Proof.
by move=> T_P P_T; eqProp=> [[/T_P] | /P_T]. Qed.
Ltac eqInh := apply: eq_inhabited.

Rule 1: Prop goals are left as is.
Canonical
Prop_wType

Internals.PropForall : forall A : Type, Internals.forallSort A Internals.PropForall is not universe polymorphic Arguments Internals.PropForall A%_type_scope Internals.PropForall is transparent Expands to: Constant mathcomp.classical.contra.Internals.PropForall Declared in library mathcomp.classical.contra, line 130, characters 10-20


Source code
:=
  @WitnessedType P (wrap1Type P) (eq_inhabited (@id P) id).

Rule 2: Specific type constructors (sigs, sums, and pairs) are delegated to the secondary properWitnessedType structure.
Lemma
proper_wTypeP
Source code
( : properWitnessedType P) : inhabited T = P.
Proof.
by case: T. Qed.
Canonical
proper_wType

Internals.SetForall : forall A : Set, Internals.forallSort A Internals.SetForall is not universe polymorphic Arguments Internals.SetForall A%_type_scope Internals.SetForall is transparent Expands to: Constant mathcomp.classical.contra.Internals.SetForall Declared in library mathcomp.classical.contra, line 134, characters 10-19


Source code
:=
  @WitnessedType P (wrap2Type _) (@proper_wTypeP P T).

Rule 3: Forall (and -> as a special case).
Local Fact
forall_wTypeP
Source code
:
  inhabited (forall : A, wTycon P T x) = (forall : A, P x) .
Proof.
by do [eqInh=> allP x; have:= allP x] => [/wTypeP | /T]. Qed.
Canonical
forall_wType

Internals.Forall : forall {A : Type} {S : Internals.forallSort A}, (A -> Internals.forall_sort S) -> Internals.forall_sort S Internals.Forall is not universe polymorphic Arguments Internals.Forall {A}%_type_scope {S} _%_function_scope Internals.Forall is transparent Expands to: Constant mathcomp.classical.contra.Internals.Forall Declared in library mathcomp.classical.contra, line 136, characters 11-17


Source code
:=
  @WitnessedType _ (wrap3Type _) (@forall_wTypeP A P T).

Rule 4: Default to inhabited if all else fails.
Canonical
inhabited_wType

Internals.wrap4Prop : Prop -> Internals.wrappedProp Internals.wrap4Prop is not universe polymorphic Arguments Internals.wrap4Prop unwrap_Prop%_type_scope Internals.wrap4Prop is transparent Expands to: Constant mathcomp.classical.contra.Internals.wrap4Prop Declared in library mathcomp.classical.contra, line 172, characters 11-20


Source code
:= @WitnessedType (inhabited T) (wrap4Type T) erefl.

Specific proper_witnessedType instances.

Local Fact
void_wTypeP
Source code
: inhabited void = False
Proof.
by eqInh. Qed.
Canonical
void_wType

Internals.wrap3Prop : Prop -> Internals.wrappedProp Internals.wrap3Prop is not universe polymorphic Arguments Internals.wrap3Prop unwrap_Prop%_type_scope Internals.wrap3Prop is transparent Expands to: Constant mathcomp.classical.contra.Internals.wrap3Prop Declared in library mathcomp.classical.contra, line 173, characters 11-20


Source code
:= ProperWitnessedType void_wTypeP.

Local Fact
unit_wTypeP
Source code
: inhabited unit = True
Proof.
by eqInh. Qed.
Canonical
unit_wType

Internals.wrap2Prop : Prop -> Internals.wrappedProp Internals.wrap2Prop is not universe polymorphic Arguments Internals.wrap2Prop unwrap_Prop%_type_scope Internals.wrap2Prop is transparent Expands to: Constant mathcomp.classical.contra.Internals.wrap2Prop Declared in library mathcomp.classical.contra, line 174, characters 11-20


Source code
:= ProperWitnessedType unit_wTypeP.

Local Fact
pair_wTypeP
Source code
: inhabited (wType P S * wType Q T) = (P /\ Q).
Proof.
by eqInh=> [[/wTypeP-isP /wTypeP] | [/S-x /T]]. Qed.
Canonical
pair_wType

Internals.wrap1Prop : Prop -> Internals.wrappedProp Internals.wrap1Prop is not universe polymorphic Arguments Internals.wrap1Prop P%_type_scope Internals.wrap1Prop is transparent Expands to: Constant mathcomp.classical.contra.Internals.wrap1Prop Declared in library mathcomp.classical.contra, line 175, characters 10-19


Source code
:= ProperWitnessedType (@pair_wTypeP P Q S T).

Local Fact
sum_wTypeP
Source code
: inhabited (wType P S + wType Q T) = (P \/ Q).
Proof.
by eqInh=> [[] /wTypeP | /decide_or[/S | /T]]; by [left | right]. Qed.
Canonical
sum_wType

Internals.wrap4Type@{i} : Type -> Internals.wrappedType Internals.wrap4Type is universe polymorphic Arguments Internals.wrap4Type unwrap_Type%_type_scope Internals.wrap4Type is transparent Expands to: Constant mathcomp.classical.contra.Internals.wrap4Type Declared in library mathcomp.classical.contra, line 178, characters 23-32


Source code
:= ProperWitnessedType (@sum_wTypeP P Q S T).

Local Fact
sumbool_wTypeP
Source code
: inhabited ({P} + {Q}) = (P \/ Q).
Proof.
by eqInh=> [[] | /decide_or[]]; by [left | right]. Qed.
Canonical
sumbool_wType

Internals.wrap3Type@{i} : Type -> Internals.wrappedType Internals.wrap3Type is universe polymorphic Arguments Internals.wrap3Type unwrap_Type%_type_scope Internals.wrap3Type is transparent Expands to: Constant mathcomp.classical.contra.Internals.wrap3Type Declared in library mathcomp.classical.contra, line 179, characters 23-32


Source code
:= ProperWitnessedType (@sumbool_wTypeP P Q).

Local Fact
sumor_wTypeP
Source code
: inhabited (wType P T + {Q}) = (P \/ Q).
Proof.
by eqInh=> [[/wTypeP|] | /decide_or[/T|]]; by [left | right]. Qed.
Canonical
sumor_wType

Internals.wrap2Type@{i} : Type -> Internals.wrappedType Internals.wrap2Type is universe polymorphic Arguments Internals.wrap2Type unwrap_Type%_type_scope Internals.wrap2Type is transparent Expands to: Constant mathcomp.classical.contra.Internals.wrap2Type Declared in library mathcomp.classical.contra, line 180, characters 23-32


Source code
:= ProperWitnessedType (@sumor_wTypeP P Q T).

Local Fact
sig1_wTypeP
Source code
: inhabited { : T | P x} = (exists : T, P x).
Proof.
by eqInh=> [[x Px] | /cid//]; exists x. Qed.
Canonical
sig1_wType

Internals.wrap1Type@{i} : Type -> Internals.wrappedType Internals.wrap1Type is universe polymorphic Arguments Internals.wrap1Type T%_type_scope Internals.wrap1Type is transparent Expands to: Constant mathcomp.classical.contra.Internals.wrap1Type Declared in library mathcomp.classical.contra, line 181, characters 23-32


Source code
:= ProperWitnessedType (@sig1_wTypeP T P).

Local Fact
sig2_wTypeP
Source code
:
  inhabited { : T | P x & Q x} = exists2 : T, P x & Q x.
Proof.
by eqInh=> [[x Px Qx] | /cid2//]; exists x. Qed.
Canonical
sig2_wType

Internals.lax_notI : forall {t : bool} {nP : Prop} (P : Internals.negatedProp t nP), Internals.unwrap_Prop (Internals.negated_Prop P) = (~ nP) Internals.lax_notI is not universe polymorphic Arguments Internals.lax_notI {t}%_bool_scope {nP}%_type_scope P Internals.lax_notI is transparent Expands to: Constant mathcomp.classical.contra.Internals.lax_notI Declared in library mathcomp.classical.contra, line 270, characters 11-19


Source code
:= ProperWitnessedType (@sig2_wTypeP T P Q).

Local Fact
sigT_wTypeP
Source code
:
  inhabited { : A & wTycon P T x} = (exists : A, P x).
Proof.
by eqInh=> [[x /wTypeP] | /cid[x /T]]; exists x. Qed.
Canonical
sigT_wType

Internals.notE : forall {nP : Prop} (P : Internals.negatedProp false nP), (~ Internals.unwrap_Prop (Internals.negated_Prop P)) = nP Internals.notE is not universe polymorphic Arguments Internals.notE {nP}%_type_scope P Internals.notE is transparent Expands to: Constant mathcomp.classical.contra.Internals.notE Declared in library mathcomp.classical.contra, line 273, characters 11-15


Source code
:= ProperWitnessedType (@sigT_wTypeP A P T).

Local Fact
sigT2_wTypeP
Source code
:
  inhabited { : A & wTycon P S x & wTycon Q T x} = (exists2 : A, P x & Q x).
Proof.
by eqInh=> [[x /wTypeP-Px /wTypeP] | /cid2[x /S-y /T]]; exists x. Qed.
Canonical
sigT2_wType

Internals.notP : forall {nP : Prop} {P : Internals.negatedProp false nP}, Internals.move_view (~ Internals.unwrap_Prop (Internals.negated_Prop P)) nP Internals.notP is not universe polymorphic Arguments Internals.notP {nP}%_type_scope {P} Internals.notP is transparent Expands to: Constant mathcomp.classical.contra.Internals.notP Declared in library mathcomp.classical.contra, line 275, characters 11-15


Source code
:=
  ProperWitnessedType (@sigT2_wTypeP A P Q S T).

The witnessProp structure provides for conversion of some Prop assumptions to Type values with some constructive contents, e.g., convert a P \/ Q assumption to a {P} + {Q} sumbool value. This is not the same as the forward direction of witnessedType, because instances here match the Prop statement: witness_Prop find a T such that P -> T while witnessedType finds a P such that P -> T (and T -> P for the converse direction).

The implementation follows the wrapper telescope pattern similarly to negatedProp, with three rules, one for Prop constructors with proper constructive contents, one for forall propositions (also with proper constructive contents) and one default rule that just returns P : Prop as is (thus, with no other contents except the provability of P). The witnessProp structure also uses projection parameters to return the inferred Type T together with a bool 'trivial' flag that is set when the trivial rule is used. Here, however, this flag is used in both directions: the 'witness' view forces it to false to prevent trivial instances, but the flag is also used to fine tune the choice of T, selecting between sum, sumor, and sumbool, between sig and sigT, and sig2 and sigT2. This relies on the fact that the tactic engine will eagerly iota reduce the returned type, so that the user will never see the conditionals specified in the proper_witness_Prop instances. However, it would not be possible to construct the specialised types for trivial witnesses (e.g., {P} + {Q}) using the types returned by witnessProp instances, since thes are in Type, and the information that they are actully in Prop has been lost. This is solved by returning an additional Prop P0 that is a copy of the matched Prop P when trivial = true. (We put P0 = True when trivial = false, as we only need to ensure P -> P0.) Caveat: although P0 should in principle be the last parameter of witness_Prop, and we use this order for the wProp and wPred projector local notation, it is important to put P0 _BEFORE_ T, to circumvent an incompleteness in Coq's implementation of higher-order pattern unification that would cause the trivial rule to fail for the body of an exists. In such a case the rule needs to unify (1) ?P0 x ~ ?P and (2) ?T x ~ ?P for some type A some x : A in the context of ?P, but not ?P0 nor ?T. This succeeds easily if (1) is performed before (2), setting ?P := ?P0 x and ?T := ?P0, but if (2) is attempted first Coq tries to perform ?P := ?T x, which fails Type/Prop universe constraints, and then fails outright, instead of using pattern unification to solve (2) as ?P := ?Q x, ?T := ?Q for a fresh ?Q : A -> Prop.

Structure
witnessProp
Source code
( : bool) ( : Prop) ( : Type) :=
  WitnessProp {
witness_Prop
Source code
:> wrappedProp; _ : witness_Prop -> T * P0}.
Structure
properWitnessProp
Source code
:=
  ProperWitnessProp {
proper_witness_Prop
Source code
:> Prop; _ : proper_witness_Prop -> T}.

Local Notation t T P0 P := (unwrap_Prop (@witness_Prop t P0 T P)).
Local Notation t T P0 P x := (wProp t (T x) (P0 x) (P x)).

Local Fact : wProp t T P0 P -> T * P0
Proof.
by case: P. Qed.
Lemma
lax_witness
Source code
{ } : move_view (wProp t T P0 P) T.
Proof.
by split=> /wPropP[]. Qed.
Definition
witness

Internals.notI : forall {nP : Prop} (P : Internals.properNegatedProp nP), Internals.proper_negated_Prop P = (~ nP) Internals.notI is not universe polymorphic Arguments Internals.notI {nP}%_type_scope P Internals.notI is transparent Expands to: Constant mathcomp.classical.contra.Internals.notI Declared in library mathcomp.classical.contra, line 278, characters 11-15


Source code
{ } := @lax_witness false T P0 P.

Rule 1: proper instances (except forall), delegated to an auxiliary structures.
Local Fact
proper_wPropP
Source code
: wrap1Prop (@proper_witness_Prop T P) -> T * True.
Proof.
by case: P => _ P_T {}/P_T. Qed.
Canonical
proper_wProp

Internals.proper_nProp : forall [nP : Prop], Internals.properNegatedProp nP -> Internals.negatedProp false nP Internals.proper_nProp is not universe polymorphic Arguments Internals.proper_nProp [nP]%_type_scope P Internals.proper_nProp is transparent Expands to: Constant mathcomp.classical.contra.Internals.proper_nProp Declared in library mathcomp.classical.contra, line 281, characters 10-22


Source code
:= WitnessProp false (@proper_wPropP T P).

Rule 2: forall types (including implication); as only proper instances are allowed, we set trivial = false for the recursive body instance.
Local Fact
forall_wPropP
Source code
:
  wrap2Prop (forall : A, wPred false T P0 P x) -> (forall , T x) * True.
Proof.
by move=> P_A; split=> // x; have /witness := P_A x. Qed.
Canonical
forall_wProp

Internals.trivial_nProp : forall P : Prop, Internals.negatedProp true (~ P) Internals.trivial_nProp is not universe polymorphic Arguments Internals.trivial_nProp P%_type_scope Internals.trivial_nProp is transparent Expands to: Constant mathcomp.classical.contra.Internals.trivial_nProp Declared in library mathcomp.classical.contra, line 287, characters 10-23


Source code
:= WitnessProp false (@forall_wPropP A T P0 P).

Rule 3: trivial (proof) self-witness.
Canonical
trivial_wProp

Internals.True_nProp : Internals.properNegatedProp False Internals.True_nProp is not universe polymorphic Internals.True_nProp is transparent Expands to: Constant mathcomp.classical.contra.Internals.True_nProp Declared in library mathcomp.classical.contra, line 291, characters 10-20


Source code
:=
  WitnessProp true (fun : wrap3Prop P => (p, p) : P * P).

Specific proper_witnesss_Prop instances.

Canonical
inhabited_wProp

Internals.False_nProp : Internals.properNegatedProp True Internals.False_nProp is not universe polymorphic Internals.False_nProp is transparent Expands to: Constant mathcomp.classical.contra.Internals.False_nProp Declared in library mathcomp.classical.contra, line 292, characters 10-21


Source code
:= ProperWitnessProp (@inhabited_witness T).

Conjunctions P /\ Q are a little delicate to handle, as we should not produce a proper instance (and thus fail) if neither P nor Q is proper. We use a tertiary structure for this : nand_bool b, which has instances only for booleans b0 such that ~~ (b0 && b). We allow the witness_Prop instance for P to return an arbitrary 'trivial' flag s, but then force the 'trivial' flag for Q to be an instance of nand_bool s.

Structure
nandBool
Source code
:= NandBool {
nand_bool
Source code
:> bool; _ : ~~ (nand_bool && b)}.
Canonical
nand_false_bool

Internals.not_nProp : forall P : Prop, Internals.properNegatedProp P Internals.not_nProp is not universe polymorphic Arguments Internals.not_nProp P%_type_scope Internals.not_nProp is transparent Expands to: Constant mathcomp.classical.contra.Internals.not_nProp Declared in library mathcomp.classical.contra, line 293, characters 10-19


Source code
:= @NandBool b false isT.
Canonical
nand_true_bool

Internals.and_nProp : forall (P : Prop) [tQ : bool] [nQ : Prop], Internals.negatedProp tQ nQ -> Internals.properNegatedProp (P -> nQ) Internals.and_nProp is not universe polymorphic Arguments Internals.and_nProp P%_type_scope [tQ]%_bool_scope [nQ]%_type_scope Q Internals.and_nProp is transparent Expands to: Constant mathcomp.classical.contra.Internals.and_nProp Declared in library mathcomp.classical.contra, line 297, characters 10-19


Source code
:= @NandBool false true isT.

Local Fact
and_wPropP
Source code
( : nandBool s) :
  wProp s S P0 P /\ wProp t T Q0 Q -> S * T.
Proof.
by case=> /lax_witness-x /lax_witness. Qed.
Canonical
and_wProp

Internals.and3_nProp : forall (P Q : Prop) [tR : bool] [nR : Prop], Internals.negatedProp tR nR -> Internals.properNegatedProp (P -> Q -> nR) Internals.and3_nProp is not universe polymorphic Arguments Internals.and3_nProp (P Q)%_type_scope [tR]%_bool_scope [nR]%_type_scope R Internals.and3_nProp is transparent Expands to: Constant mathcomp.classical.contra.Internals.and3_nProp Declared in library mathcomp.classical.contra, line 302, characters 10-20


Source code
:=
  ProperWitnessProp (@and_wPropP s S P0 P t T Q0 Q).

Local Fact
or_wPropP
Source code
:
    wProp s S P0 P \/ wProp t T Q0 Q ->
  if t then if s then {P0} + {Q0} : Type else S + {Q0} else S + T : Type.
Proof.
by case: s t => -[] in P Q *; (case/decide_or=> /wPropP[]; [left | right]).
Qed.
Canonical
or_wProp

Internals.and4_nProp : forall (P Q R : Prop) [tS : bool] [nS : Prop], Internals.negatedProp tS nS -> Internals.properNegatedProp (P -> Q -> R -> nS) Internals.and4_nProp is not universe polymorphic Arguments Internals.and4_nProp (P Q R)%_type_scope [tS]%_bool_scope [nS]%_type_scope S Internals.and4_nProp is transparent Expands to: Constant mathcomp.classical.contra.Internals.and4_nProp Declared in library mathcomp.classical.contra, line 308, characters 10-20


Source code
:=
  ProperWitnessProp (@or_wPropP s S P0 P t T Q0 Q).

Local Fact
exists_wPropP
Source code
:
  (exists : A, wPred t T P0 P x) -> if t then { | P0 x} else { & T x}.
Proof.
by case/cid => x /wPropP[]; case t; exists x. Qed.
Canonical
exists_wProp

Internals.and5_nProp : forall (P Q R S : Prop) [tT : bool] [nT : Prop], Internals.negatedProp tT nT -> Internals.properNegatedProp (P -> Q -> R -> S -> nT) Internals.and5_nProp is not universe polymorphic Arguments Internals.and5_nProp (P Q R S)%_type_scope [tT]%_bool_scope [nT]%_type_scope T Internals.and5_nProp is transparent Expands to: Constant mathcomp.classical.contra.Internals.and5_nProp Declared in library mathcomp.classical.contra, line 314, characters 10-20


Source code
:=
  ProperWitnessProp (@exists_wPropP A t T P0 P).

Local Fact
exists2_wPropP
Source code
( := if s then t else false) :
    (exists2 : A, wPred s S P0 P x & wPred t T Q0 Q x) ->
  if st then { | P0 x & Q0 x} else { : A & S x & T x}.
Proof.
by case/cid2=> x /wPropP[P0x y] /wPropP[]; case: ifP; exists x. Qed.
Canonical
exists2_wProp

Internals.or_nProp : forall [tP : bool] [nP : Prop], Internals.negatedProp tP nP -> forall [tQ : bool] [nQ : Prop], Internals.negatedProp tQ nQ -> Internals.properNegatedProp (nP /\ nQ) Internals.or_nProp is not universe polymorphic Arguments Internals.or_nProp [tP]%_bool_scope [nP]%_type_scope P [tQ]%_bool_scope [nQ]%_type_scope Q Internals.or_nProp is transparent Expands to: Constant mathcomp.classical.contra.Internals.or_nProp Declared in library mathcomp.classical.contra, line 320, characters 10-18


Source code
:=
  ProperWitnessProp (@exists2_wPropP A s S P0 P t T Q0 Q).

## User lemmas and tactics for proof by contradiction and contraposition.

Helper lemmas: - push_goal_copy makes a copy of the goal that can then be matched with witnessedType and negatedProp instances to generate a contradiction assuption, without disturbing the original form of the goal. - assume_not_with turns the copy generated by push_identity into an equivalent negative assumption, which can then be simplified using the lax_notP and lax_witness views. - absurd and absurdW replace the goal with False; absurdW does this under an assumption, and is used to weaken proof-by-assuming-negation to proof-by-contradiction. - contra_Type converts an arbitrary function goal (with assumption and conclusion in Type) to an equivalent contrapositive Prop implication. - contra_notP simplifies a contrapositive ~ Q -> ~ P goal using negatedProp instances.

Local Fact
push_goal_copy
Source code
{} : ((T -> T) -> T) -> T
Proof.
exact. Qed.
Local Fact
assume_not_with
Source code
{ } : (~ P -> R) -> (wType P T -> R) -> R.
Proof.
by move=> nP_T T_R; have [/T|] := asboolP P. Qed.

Local Fact { } : (S -> False) -> S -> T
Proof.
by []. Qed.

Local Fact
contra_Type
Source code
{ } : (~ Q -> ~ P) -> wType P S -> wType Q T.
Proof.
by rewrite implyNN => P_Q /wTypeP/P_Q/T. Qed.

Local Fact
contra_notP
Source code
( : Prop) :
  (nP -> nQ) -> (~ nProp tP nP P -> ~ nProp tQ nQ Q).
Proof.
by rewrite 2!lax_notE. Qed.

End Internals.
Import Internals.
#[warnings="-user-warn"] Definition
notP

Internals.or4_nProp : forall [tP : bool] [nP : Prop], Internals.negatedProp tP nP -> forall [tQ : bool] [nQ : Prop], Internals.negatedProp tQ nQ -> forall [tR : bool] [nR : Prop], Internals.negatedProp tR nR -> forall [tS : bool] [nS : Prop], Internals.negatedProp tS nS -> Internals.properNegatedProp [/\ nP, nQ, nR & nS] Internals.or4_nProp is not universe polymorphic Arguments Internals.or4_nProp [tP]%_bool_scope [nP]%_type_scope P [tQ]%_bool_scope [nQ]%_type_scope Q [tR]%_bool_scope [nR]%_type_scope R [tS]%_bool_scope [nS]%_type_scope S Internals.or4_nProp is transparent Expands to: Constant mathcomp.classical.contra.Internals.or4_nProp Declared in library mathcomp.classical.contra, line 333, characters 10-19


Source code
:= @Internals.notP.
Hint View for move/ move_viewP|2.
Hint View for move/ Internals.equivT_LR|2 Internals.equivT_RL|2.
Hint View for apply/ Internals.equivT_RL|2 Internals.equivT_LR|2.
Export (canonicals) Internals.

Lemma and tactic assume_not: add a goal negation assumption. The tactic also works for goals in Type, simplifies the added assumption, and exposes its top-level constructive content.

Lemma
assume_not
Source code
{} : (~ P -> P) -> P
Proof.
by rewrite implyNp orB. Qed.
Ltac assume_not :=
  apply: Internals.push_goal_copy; apply: Internals.assume_not_with
    => /Internals.lax_notP-/Internals.lax_witness.

Lemma and tactic absurd_not: proof by contradiction. Same as assume_not, but the goal is erased and replaced by False. Caveat: absurd_not cannot be used as a move/ view because its conclusion is indeterminate. The more general notP defined above can be used instead.
Lemma
absurd_not
Source code
{} : (~ P -> False) -> P
Proof.
#[warnings="-user-warn"] by move/Internals.notP. Qed.
Ltac absurd_not := assume_not; apply: Internals.absurdW.

Tactic contra: proof by contraposition. Assume the negation of the goal conclusion, and prove the negation of a given assumption. The defective form contra (which can also be written contrapose) expects the assumption to be pushed on the goal which thus has the form assumption -> conclusion. As with assume_not, contra allows both assumption and conclusion to be in Type, simplifies the negation of both assumption and conclusion, and exposes the constructive contents of the negated conclusion. The contra tactic also supports a limited form of the ':' discharge pseudo tactical, whereby contra: <d-items> means move: <d-items>; contra. The only <d-items> allowed are one term, possibly preceded by a clear switch.

Ltac contrapose :=
  apply: Internals.contra_Type;
  apply: Internals.contra_notP => /Internals.lax_witness.
Tactic Notation "contra" := contrapose.
Tactic Notation "contra" ":" constr(H) := move: (H); contra.
Tactic Notation "contra" ":" ident(H) := move: H; contra.
Tactic Notation "contra" ":" "{" hyp_list(Hs) "}" constr(H) :=
  contra: (H); clear Hs.
Tactic Notation "contra" ":" "{" hyp_list(Hs) "}" ident(H) :=
  contra: H; clear Hs.
Tactic Notation "contra" ":" "{" "-" "}" constr(H) := contra: (H).

Lemma and tactic absurd: proof by contradiction. The defective form of the lemma simply replaces the entire goal with False (just as the Ltac exfalso), leaving the user to derive a contradiction from the assumptions. The ':' form absurd: <d-items> replaces the goal with the negation of the (single) <d-item> (as with contra:, a clear switch is also allowed. Finally the Ltac absurd term form is also supported.

Lemma : False -> T
Proof.
by []. Qed.
Tactic Notation (at level 0) "absurd" := apply absurd.
Tactic Notation (at level 0) "absurd" constr(P) := have []: ~ P.
Tactic Notation "absurd" ":" constr(H) := absurd; contra: (H) => _.
Tactic Notation "absurd" ":" ident(H) := absurd; contra: H => _.
Tactic Notation "absurd" ":" "{" hyp_list(Hs) "}" constr(H) :=
  absurd: (H) => _; clear Hs.
Tactic Notation "absurd" ":" "{" hyp_list(Hs) "}" ident(H) :=
  absurd: H => _; clear Hs.