Martin Escardo 2011.

\begin{code}
module CurryHoward where
\end{code}

The universe of propositions is denoted by Prp. By the
Curry-Howard isomorphism, it is the universe of types,
sometimes called sets in Agda.

\begin{code}

open import SetsAndFunctions

Prp = Set

\end{code}

We also need this, where Set₁ is the second universe:

\begin{code}

Prp₁ = Set₁

\end{code}

The false proposition (empty set) is inductively
defined with no cases:

\begin{code}

⊥ : Prp
⊥ = ∅

⊥-elim : {A : Prp} → ⊥ → A
⊥-elim = unique-from-∅

infix  50 ¬_
infixr 10 _∧_
infixr 20 _∨_

¬_ : Prp → Prp
¬ A = (A → ⊥)

_∧_ : Prp → Prp → Prp
A ∧ B = A × B

∧-elim₀ : {A₀ A₁ : Prp} → A₀ ∧ A₁ → A₀
∧-elim₀ = π₀

∧-elim₁ : {A₀ A₁ : Prp} → A₀ ∧ A₁ → A₁
∧-elim₁ = π₁

∧-intro : {A₀ A₁ : Prp} → A₀ → A₁ → A₀ ∧ A₁
∧-intro a₀ a₁ = (a₀ , a₁)

_∨_ : Prp → Prp → Prp
A ∨ B = A + B

∨-intro₀ : {A₀ A₁ : Prp} → A₀ → A₀ ∨ A₁
∨-intro₀ = in₀

∨-intro₁ : {A₀ A₁ : Prp} → A₁ → A₀ ∨ A₁
∨-intro₁ = in₁

∨-elim : {A₀ A₁ B : Prp} →

  (A₀ → B) → (A₁ → B) → A₀ ∨ A₁ → B

∨-elim = cases

∨-commutative : {A B : Prp} → A ∨ B → B ∨ A
∨-commutative = ∨-elim ∨-intro₁ ∨-intro₀


∃ : {X : Set} → (A : X → Prp) → Prp
∃ = Σ


∃-intro : {X : Set} → {A : X → Prp} →

  (x₀ : X) → A x₀ → ∃ \(x : X) → A x

∃-intro x a = (x , a)


∃-witness : {X : Set} {A : X → Prp} →

   (∃ \(x : X) → A x) → X

∃-witness = π₀


∃-elim : {X : Set} {A : X → Prp} →

   (proof : ∃ \(x : X) → A x) → A (∃-witness proof)

∃-elim = π₁


infixr 1 _↔_

_↔_ : Prp → Prp → Prp
A ↔ B = (A → B) ∧ (B → A)

\end{code}

A set X is inhabited if it has an element, if and only if,
when the set X, considered as a proposition, holds. So the
statement that X is inhabited is X itself! In fact, notice
that X is isomorphic to ∃ \(x : X) → ⊤, where ⊤ is the unit
proposition (assuming extensionality).

\begin{code}

inhabited : Set → Prp
inhabited X = X

\end{code}

Some basic logical facts. 

\begin{code}

contra-positive : {A B : Prp} → (A → B) → ¬ B → ¬ A
contra-positive = contra-variant

\end{code}

Double-negation monad:

\begin{code}

¬¬ : Prp → Prp
¬¬ A = ¬(¬ A)

¬¬-functor : {A B : Prp} → (A → B) → ¬¬ A → ¬¬ B
¬¬-functor = K-functor

double-negation-intro : {A : Prp} → A → ¬¬ A
double-negation-intro = ηK


three-negations-imply-one : {A : Prp} → ¬(¬¬ A) → ¬ A
three-negations-imply-one =
  contra-positive double-negation-intro


not-exists-implies-forall-not : {X : Set} → {A : X → Prp} →

 ¬(∃ \(x : X) → A x) → ∀(x : X) → ¬(A x)

not-exists-implies-forall-not = curry


forall-not-implies-not-exists : {X : Set} → {A : X → Prp} →

 (∀(x : X) → ¬(A x)) → ¬(∃ \(x : X) → A x)

forall-not-implies-not-exists = uncurry

\end{code}

Double-negation unshift:

\begin{code}

DNU : {X : Set} {A : X → Prp} →

 ¬¬(∀ x → A x) → ∀ x → ¬¬(A x)

DNU = KU

\end{code}

Special case, if you like:

\begin{code}

dnu : {A B : Prp} → ¬¬(A ∧ B) → ¬¬ A ∧ ¬¬ B
dnu = ku

\end{code}