(** ** Constructive choice and description *)

(** AC_rel = relational form of the (non extensional) axiom of choice
             (a "set-theoretic" axiom of choice) *)

Definition RelationalChoice_on :=
  forall R:A->B->Prop,
    (forall x : A, exists y : B, R x y) ->
    (exists R' : A->B->Prop, subrelation R' R /\ forall x, exists! y, R' x y).(** AC_fun = functional form of the (non extensional) axiom of choice
             (a "type-theoretic" axiom of choice) *)

(* Note: This is called Type-Theoretic Description Axiom (TTDA) in
   [[Werner97]] (using a non-standard meaning of "description"). This
   is called intensional axiom of choice (AC_int) in [[Carlström04]] *)

Definition FunctionalChoice_on_rel (R:A->B->Prop) :=
  (forall x:A, exists y : B, R x y) ->
  exists f : A -> B, (forall x:A, R x (f x)).Definition FunctionalChoice_on :=
  forall R:A->B->Prop,
    (forall x : A, exists y : B, R x y) ->
    (exists f : A->B, forall x : A, R x (f x)).(** AC_fun_dep = functional form of the (non extensional) axiom of
                 choice, with dependent functions *)
Definition DependentFunctionalChoice_on (A:Type) (B:A -> Type) :=
  forall R:forall x:A, B x -> Prop,
    (forall x:A, exists y : B x, R x y) ->
    (exists f : (forall x:A, B x), forall x:A, R x (f x)).(** AC_trunc = axiom of choice for propositional truncations
               (truncation and quantification commute) *)
Definition InhabitedForallCommute_on (A : Type) (B : A -> Type) :=
  (forall x, inhabited (B x)) -> inhabited (forall x, B x).(** DC_fun = functional form of the dependent axiom of choice *)

Definition FunctionalDependentChoice_on :=
  forall (R:A->A->Prop),
    (forall x, exists y, R x y) -> forall x0,
    (exists f : nat -> A, f 0 = x0 /\ forall n, R (f n) (f (S n))).(** ACw_fun = functional form of the countable axiom of choice *)

Definition FunctionalCountableChoice_on :=
  forall (R:nat->A->Prop),
    (forall n, exists y, R n y) ->
    (exists f : nat -> A, forall n, R n (f n)).(** AC! = functional relation reification
          (known as axiom of unique choice in topos theory,
           sometimes called principle of definite description in
           the context of constructive type theory, sometimes
           called axiom of no choice) *)

Definition FunctionalRelReification_on :=
  forall R:A->B->Prop,
    (forall x : A, exists! y : B, R x y) ->
    (exists f : A->B, forall x : A, R x (f x)).(** AC_dep! = functional relation reification, with dependent functions
              see AC! *)
Definition DependentFunctionalRelReification_on (A:Type) (B:A -> Type) :=
  forall (R:forall x:A, B x -> Prop),
    (forall x:A, exists! y : B x, R x y) ->
    (exists f : (forall x:A, B x), forall x:A, R x (f x)).(** AC_fun_repr = functional choice of a representative in an equivalence class *)

(* Note: This is called Type-Theoretic Choice Axiom (TTCA) in
   [[Werner97]] (by reference to the extensional set-theoretic
   formulation of choice); Note also a typo in its intended
   formulation in [[Werner97]]. *)

Definition RepresentativeFunctionalChoice_on :=
  forall R:A->A->Prop,
    (Equivalence R) ->
    (exists f : A->A, forall x : A, (R x (f x)) /\ forall x', R x x' -> f x = f x').(** AC_fun_setoid = functional form of the (so-called extensional) axiom of
                    choice from setoids *)

Definition SetoidFunctionalChoice_on :=
  forall R : A -> A -> Prop,
  forall T : A -> B -> Prop,
  Equivalence R ->
  (forall x x' y, R x x' -> T x y -> T x' y) ->
  (forall x, exists y, T x y) ->
  exists f : A -> B, forall x : A, T x (f x) /\ (forall x' : A, R x x' -> f x = f x').(** AC_fun_setoid_gen = functional form of the general form of the (so-called
                        extensional) axiom of choice over setoids *)

(* Note: This is called extensional axiom of choice (AC_ext) in
   [[Carlström04]]. *)

Definition GeneralizedSetoidFunctionalChoice_on :=
  forall R : A -> A -> Prop,
  forall S : B -> B -> Prop,
  forall T : A -> B -> Prop,
  Equivalence R ->
  Equivalence S ->
  (forall x x' y y', R x x' -> S y y' -> T x y -> T x' y') ->
  (forall x, exists y, T x y) ->
  exists f : A -> B,
    forall x : A, T x (f x) /\ (forall x' : A, R x x' -> S (f x) (f x')).(** AC_fun_setoid_simple = functional form of the (so-called extensional) axiom of
                           choice from setoids on locally compatible relations *)

Definition SimpleSetoidFunctionalChoice_on A B :=
  forall R : A -> A -> Prop,
  forall T : A -> B -> Prop,
  Equivalence R ->
  (forall x, exists y, forall x', R x x' -> T x' y) ->
  exists f : A -> B, forall x : A, T x (f x) /\ (forall x' : A, R x x' -> f x = f x').(** ID_epsilon = constructive version of indefinite description;
                 combined with proof-irrelevance, it may be connected to
                 Carlström's type theory with a constructive indefinite description
                 operator *)

Definition ConstructiveIndefiniteDescription_on :=
  forall P:A->Prop,
    (exists x, P x) -> { x:A | P x }.(** ID_iota = constructive version of definite description;
              combined with proof-irrelevance, it may be connected to
              Carlström's and Stenlund's type theory with a
              constructive definite description operator) *)

Definition ConstructiveDefiniteDescription_on :=
  forall P:A->Prop,
    (exists! x, P x) -> { x:A | P x }.(** ** Weakly classical choice and description *)

(** GAC_rel = guarded relational form of the (non extensional) axiom of choice *)

Definition GuardedRelationalChoice_on :=
  forall P : A->Prop, forall R : A->B->Prop,
    (forall x : A, P x -> exists y : B, R x y) ->
    (exists R' : A->B->Prop,
      subrelation R' R /\ forall x, P x -> exists! y, R' x y).(** GAC_fun = guarded functional form of the (non extensional) axiom of choice *)

Definition GuardedFunctionalChoice_on :=
  forall P : A->Prop, forall R : A->B->Prop,
    inhabited B ->
    (forall x : A, P x -> exists y : B, R x y) ->
    (exists f : A->B, forall x, P x -> R x (f x)).(** GAC! = guarded functional relation reification *)

Definition GuardedFunctionalRelReification_on :=
  forall P : A->Prop, forall R : A->B->Prop,
    inhabited B ->
    (forall x : A, P x -> exists! y : B, R x y) ->
    (exists f : A->B, forall x : A, P x -> R x (f x)).(** OAC_rel = "omniscient" relational form of the (non extensional) axiom of choice *)

Definition OmniscientRelationalChoice_on :=
  forall R : A->B->Prop,
    exists R' : A->B->Prop,
      subrelation R' R /\ forall x : A, (exists y : B, R x y) -> exists! y, R' x y.(** OAC_fun = "omniscient" functional form of the (non extensional) axiom of choice
              (called AC* in Bell [[Bell]]) *)

Definition OmniscientFunctionalChoice_on :=
  forall R : A->B->Prop,
    inhabited B ->
    exists f : A->B, forall x : A, (exists y : B, R x y) -> R x (f x).(** D_epsilon = (weakly classical) indefinite description principle *)

Definition EpsilonStatement_on :=
  forall P:A->Prop,
    inhabited A -> { x:A | (exists x, P x) -> P x }.(** D_iota = (weakly classical) definite description principle *)

Definition IotaStatement_on :=
  forall P:A->Prop,
    inhabited A -> { x:A | (exists! x, P x) -> P x }.(** Generalized schemes *)

Notation RelationalChoice :=
  (forall A B : Type, RelationalChoice_on A B).Notation FunctionalChoice :=
  (forall A B : Type, FunctionalChoice_on A B).Notation DependentFunctionalChoice :=
  (forall A (B:A->Type), DependentFunctionalChoice_on B).Notation InhabitedForallCommute :=
  (forall A (B : A -> Type), InhabitedForallCommute_on B).Notation FunctionalDependentChoice :=
  (forall A : Type, FunctionalDependentChoice_on A).Notation FunctionalCountableChoice :=
  (forall A : Type, FunctionalCountableChoice_on A).Notation FunctionalChoiceOnInhabitedSet :=
  (forall A B : Type, inhabited B -> FunctionalChoice_on A B).Notation FunctionalRelReification :=
  (forall A B : Type, FunctionalRelReification_on A B).Notation DependentFunctionalRelReification :=
  (forall A (B:A->Type), DependentFunctionalRelReification_on B).Notation RepresentativeFunctionalChoice :=
  (forall A : Type, RepresentativeFunctionalChoice_on A).Notation SetoidFunctionalChoice :=
  (forall A  B: Type, SetoidFunctionalChoice_on A B).Notation GeneralizedSetoidFunctionalChoice :=
  (forall A B : Type, GeneralizedSetoidFunctionalChoice_on A B).Notation SimpleSetoidFunctionalChoice :=
  (forall A B : Type, SimpleSetoidFunctionalChoice_on A B).Notation GuardedRelationalChoice :=
  (forall A B : Type, GuardedRelationalChoice_on A B).Notation GuardedFunctionalChoice :=
  (forall A B : Type, GuardedFunctionalChoice_on A B).Notation GuardedFunctionalRelReification :=
  (forall A B : Type, GuardedFunctionalRelReification_on A B).Notation OmniscientRelationalChoice :=
  (forall A B : Type, OmniscientRelationalChoice_on A B).Notation OmniscientFunctionalChoice :=
  (forall A B : Type, OmniscientFunctionalChoice_on A B).Notation ConstructiveDefiniteDescription :=
  (forall A : Type, ConstructiveDefiniteDescription_on A).Notation ConstructiveIndefiniteDescription :=
  (forall A : Type, ConstructiveIndefiniteDescription_on A).Notation IotaStatement :=
  (forall A : Type, IotaStatement_on A).Notation EpsilonStatement :=
  (forall A : Type, EpsilonStatement_on A).(** Subclassical schemes *)

(** PI = proof irrelevance *)
Definition ProofIrrelevance :=
  forall (A:Prop) (a1 a2:A), a1 = a2.(** IGP = independence of general premises
          (an unconstrained generalisation of the constructive principle of
           independence of premises) *)
Definition IndependenceOfGeneralPremises :=
  forall (A:Type) (P:A -> Prop) (Q:Prop),
    inhabited A ->
    (Q -> exists x, P x) -> exists x, Q -> P x.(** Drinker = drinker's paradox (small form)
              (called Ex in Bell [[Bell]]) *)
Definition SmallDrinker'sParadox :=
  forall (A:Type) (P:A -> Prop), inhabited A ->
    exists x, (exists x, P x) -> P x.(** EM = excluded-middle *)
Definition ExcludedMiddle :=
  forall P:Prop, P \/ ~ P.(** Extensional schemes *)

(** Ext_prop_repr = choice of a representative among extensional propositions *)
Local Notation ExtensionalPropositionRepresentative :=
  (forall (A:Type),
   exists h : Prop -> Prop,
   forall P : Prop, (P <-> h P) /\ forall Q, (P <-> Q) -> h P = h Q).(** Ext_pred_repr = choice of a representative among extensional predicates *)
Local Notation ExtensionalPredicateRepresentative :=
  (forall (A:Type),
   exists h : (A->Prop) -> (A->Prop),
   forall (P : A -> Prop), (forall x, P x <-> h P x) /\ forall Q, (forall x, P x <-> Q x) -> h P = h Q).(** Ext_fun_repr = choice of a representative among extensional functions *)
Local Notation ExtensionalFunctionRepresentative :=
  (forall (A B:Type),
   exists h : (A->B) -> (A->B),
   forall (f : A -> B), (forall x, f x = h f x) /\ forall g, (forall x, f x = g x) -> h f = h g).

(* Specifications: *)
Lemma functional_rel_reification_and_rel_choice_imp_fun_choice : forall A B : Type, FunctionalRelReification_on A B -> RelationalChoice_on A B -> FunctionalChoice_on A B.
Lemma fun_choice_imp_rel_choice : forall A B : Type, FunctionalChoice_on A B -> RelationalChoice_on A B.
Lemma fun_choice_imp_functional_rel_reification : forall A B : Type, FunctionalChoice_on A B -> FunctionalRelReification_on A B.