data  : Set where
  zero : 
  succ :   

data  : Set where

one : 
one = succ zero

two : 
two = succ (succ zero)

four : 
four = succ (succ (succ (succ zero)))

-- We will now define, for any natural number n, "Even n".
-- More precisely, "Even n" is a certain type.
-- Namely the type of *witnesses that n is even*.

-- For instance, the type "Even one" (where one = succ zero) should be an empty type.
-- In contrast, the types "Even zero" and "Even four" should each be inhabited.

data Even :   Set where
  Base : Even zero                                 -- "the number zero is even"
  Step : (n : )  Even n  Even (succ (succ n))   -- "for every number n, if n is even, so is succ (succ n)"

-- "Odd" is a function which maps natural numbers to (newly created) types.
-- Namely, "Odd n" is the type of witnesses that n is odd.
-- For instance, the type "Odd zero" is empty and the type "Odd one" is inhabited.
data Odd :   Set where
  Base' : Odd one
  Step' : (n : )  Odd n  Odd (succ (succ n))

lemma-even-odd : (n : )  Even n  Odd (succ n)
lemma-even-odd .zero            Base       = Base'
lemma-even-odd .(succ (succ n)) (Step n p) = Step' (succ n) (lemma-even-odd n p)
{-
  in English:

  By induction on n.
  Base case n = 0: In this case we have to verify that 1 is odd. This is trivial (by Base').
  Induction step m → 2 + m: In this case we have to verify that, if m is even, then succ m is odd.
  Because m is even, m is of the form succ (succ n) for some even number n.
  Hence by the inductive hypothesis, the number succ n is odd.
  Hence by Step', the number succ (succ (succ n)) is odd.
-}

data _⊎_ (A B : Set) : Set where  -- in Haskell, this type is called "Either"
  left  : A  A  B
  right : B  A  B
-- The type "ℕ ⊎ Bool" contains the following values:
-- left zero, left (succ zero), left (succ (succ zero)), ...
-- right false, right true

-- "Every natural number is even or odd."
theorem : (n : )  Even n  Odd n
theorem zero     = left Base
theorem (succ n) with theorem n
... | left  p = right (lemma-even-odd n p)
... | right q = {!!}

fun-fact : Even zero
fun-fact = Base

fun-fact' : Even two
fun-fact' = Step zero Base

fun-fact'' : Even four
-- fun-fact'' = Step (succ (succ zero)) (Step zero Base)
fun-fact'' = Step two fun-fact'

fun-fact''' : Odd (succ (succ (succ zero)))
fun-fact''' = Step' (succ zero) Base'

lemma : (n : )  Even n  Even n   -- "for every number n, if n is even, then n is even"
lemma n p = p

lemma' : (n : )  Odd n  Odd n   -- "for every number n, if n is odd, then n is odd
lemma' n p = p

lemma'' : {A : Set}  A  A   -- "A implies A"   "if A, then A"
lemma'' x = x

{-
  ROSETTA STONE BETWEEN COMPUTING AND LOGIC

  programming                  logic/type theory
  ----------------------------------------------
  type A → A of functions      statement that A implies A
  identity function            proof of the statement that A implies A
-}




{-
-- CLAIM: There is no function from ℕ → ∅.
claim : (ℕ → ∅) → ∅
claim f = f zero
-- "There are no function f : ℕ → ∅, just have a look at what f(zero) would be!"

claim' : (ℕ → ∅) → ∅
claim' f = f (succ zero)
-- "There are no function f : ℕ → ∅, just have a look at what f(1) would be!"

data Bool : Set where
  false true : Bool

Set-of-decidable-subsets : Set → Set
Set-of-decidable-subsets X = X → Bool

Powerset : Set → Set₁
Powerset X = X → Set
-- the empty subset of X is given by the function λ x → ∅

truer-Powerset : Set → Set₂
truer-Powerset X = X → Set₁

{-
even-truer-Powerset : Set → Set
even-truer-Powerset X = X → Set₂
-}

-- Prop is the type of all those small types which contain at most one inhabitant.
-- Prop itself is not a small type, but a large type.

is-prop : Set → Set
is-prop X = {!(a : X) → (b : X) → a ≡ b!}    -- "is-prop X" means: "X contains at most one inhabitant"

{-
Prop : Set₁
Prop = ?  -- (the type of pairs (X,p) where X is a small type and p is an element of is-prop X)
-}

data Σ (A : Set) (B : A → Set) : Set where
  ⟨_,_⟩ : (x : A) → B x → Σ A B

is-decidable : Set → Set
is-decidable X = X ⊎ (X → ∅)

is-semidecidable-oracle : {X : Set} → (X → Bool ⊎ ∅) → Set
is-semidecidable-oracle f = ?

-- Prop₁ is the type of all those large types which contain at most one inhabitant.
-- Prop₁ itself is not a large type, but a very large type.

-- Prop₂ is the type of all those very large types which contain at most one inhabitant.
-- Prop₂ itself is not a very large type, but a very very large type.

{-


Powerset' : Set → Set₁
Powerset' X = X → Prop
-- the empty subset of X is given by the function λ x → ∅

truer-Powerset' : Set → Set₂
truer-Powerset' X = X → Prop₁

even-truer-Powerset' : Set → Set₃
even-truer-Powerset' X = X → Prop₂

-- Set is the type of small types, but Set itself is not a small type.
-- zero : ℕ : Set : Set₁ : Set₂ : Set₃ : ...

-- For most types X, there is no procedure for checking whether any
-- given predicate f : X → Bool has a zero (attains false).
-- But for some types, there is.
-- For instance, for finite types there is.
-- Amazing wonder: Also for some infinite types there is such a checking procedure.
-- Approximately: There is such a checking procedure if and only if X is compact (when thought of as a space).

-- CLAIM: The number one is not even.
-- RECALL: In logic, "¬ φ" is a shorthand for "φ ⇒ ⊥".
{-
lemma-one-not-even : Even one → ∅
lemma-one-not-even = ?
-}

-}
-}