{-# OPTIONS --cubical --allow-unsolved-metas #-}
module AFF2024.AgdaTutorial.Session2 where

data  : Set where  -- \bN \alpha \to
  zero : 
  succ :   
-- Inhabitants of ℕ:
-- zero, succ zero, succ (succ zero), ...

--{-# BUILTIN NATURAL ℕ #-} 

data Bool : Set where
  false : Bool
  true  : Bool

-- in blackboard mathematics: f(x,y)
-- in Agda:                   f x y

one : 
one = succ zero

-- For instance, pred of 7 should be 6.
pred :   
pred zero     = zero
pred (succ x) = x

-- For instance, double 7 should be 14.
double :   
double zero     = zero
double (succ x) = succ (succ (double x))   -- 2*(1+x) = 2+2x = 1+(1+2x) = 1+(1+double(x))

_·2 :   
x ·2 = double x

-- for instance, 3 ! should be 6.
_! :   
_! = {!!}

!_ : (b : Bool)  Bool
! false = true
! true  = false

{-
_foo_bar_ : X → Y → Z → A
x foo y bar z = ?

0 + x + y ≡⟨ comm x y ⟩ 0 + y + x ≡⟨ neutr ⟩ y + x
-}

fun : Bool  Set
fun false = 
fun true  = Bool

bar : (b : Bool)  fun b
bar false = succ (succ (succ (succ (succ (succ zero)))))
bar true  = false

-- The following declaration sets up a type/set called "x ≡ y", for each x : ℕ, y : ℕ.
data _≡_ {X : Set} : X  X  Set where
  -- logical reading: for every x : ℕ, x equals x.
  -- computational reading: "refl" is a function which inputs a number x : ℕ
  -- and outputs a witness that x equals x.
  refl : {x : X}  x  x
  -- bailout : {x y : ℕ} → x ≡ y
  -- bogus : {x : ℕ} → x ≡ succ (succ x)

-- In Agda, for every two numbers "x" and "y", there is a type/set "x ≡ y".
-- The inhabitants of this type are witnesses that "x" and "y" are equal.
-- For instance, the type "zero ≡ one" is empty.
-- In constrast, the type "one ≡ one" is inhabited (namely by "refl").
tem : zero  zero   -- \==
tem = refl

tem' : bar false  succ (succ (succ (succ (succ (succ zero)))))
tem' = refl

_+_ :     
zero   + y = y
succ x + y = succ (x + y)

-- logical reading: for every y : ℕ, zero + y equals y.
-- computational reading: "lemma" is a function which inputs a number y : ℕ
-- and outputs a witness that zero + y equals y.
lemma : (y : )  (zero + y)  y
lemma y = refl

-- logical reading: for every set A, for every set B, for every function f : A → B,
-- for every elements x, y : A, if x equals y, then f x equals f y.
-- computational reading: "cong" is a function which takes 6 inputs, namely
-- 1. a set A
-- 2. a set B
-- 3. a function f : A → B
-- 4. a value/element/inhabitant x : A
-- 5. a value y : A
-- 6. a witness that x equals y
-- and outputs a witness that f x equals f y.
cong : {A B : Set} (f : A  B) {x y : A}  x  y  f x  f y
cong f refl = refl

data  : Set where

¬_ : Set  Set
¬ A = A  
-- "¬ A" means (by definition): The assumption that A implies a contradiction.

postulate
  double-negation-elimination : {A : Set}  ¬ ¬ A  A

lemma' : (x : )  (x + zero)  x
lemma' zero     = refl
lemma' (succ a) = cong succ (lemma' a)

-- induction on a blackboard = recursion in Agda

symm : {X : Set} {a b : X}  a  b  b  a
symm refl = refl

trans : {X : Set} {a b c : X}  a  b  b  c  a  c
trans refl q = q

---------------------------------------------------------------------------------
-- syntax for equational proofs, please ignore these definitions on first reading
infix  3 _∎
infixr 2 _≡⟨_⟩_ _≡⟨⟩_
infix  1 begin_

_≡⟨_⟩_ : {A : Set} {y z : A}  (x : A)  x  y  y  z  x  z
x ≡⟨ p  q = trans p q

_≡⟨⟩_ : {A : Set} {y : A}  (x : A)  (q : x  y)  x  y
x ≡⟨⟩ q = q

_∎ : {A : Set}  (x : A)  x  x
x  = refl

begin_ : {A : Set} {x y : A}  x  y  x  y
begin p = p
-- end of syntax for equational proof
---------------------------------------------------------------------------------

lemma-succ : (a b : )  (a + succ b)  succ (a + b)
lemma-succ zero     b = refl
lemma-succ (succ a) b = cong succ (lemma-succ a b)

-- logical reading: for every x : ℕ, for every y : ℕ, x + y equals y + x.
-- computational reading: "comm" is a function which inputs a number x : ℕ
-- and a number y : ℕ and outputs a witness that x + y equals y + x.
comm : (x : )  (y : )  (x + y)  (y + x)
comm zero     y = symm (lemma' y)
-- comm (succ x) y = trans (symm (lemma-succ x y)) (trans (comm x (succ y)) (symm (lemma-succ y x)))
comm (succ x) y = begin
  succ x + y   ≡⟨⟩          -- \==\<\>
  succ (x + y) ≡⟨ symm (lemma-succ x y) 
  x + succ y   ≡⟨ comm x (succ y) 
  succ y + x   ≡⟨ symm (lemma-succ y x) 
  y + succ x     -- \qed

lemma'' : (x : )  (x + zero)  x
lemma'' x = double-negation-elimination {!!}