module Jueves where
open import Data.Nat hiding (_≤_ ; module _≤_ ; _≤?_ ; _<_)
open import Relation.Binary.PropositionalEquality
open import Relation.Nullary
open import Data.String
data _≤_ : ℕ → ℕ → Set where
z≤n : ∀ {n} → zero ≤ n
s≤s : ∀ {m n} (m≤n : m ≤ n) → suc m ≤ suc n
2≤4 : 2 ≤ 4
2≤4 = s≤s (s≤s z≤n)
¬4≤2 : ¬ 4 ≤ 2
¬4≤2 (s≤s (s≤s ()))
≤-refl : ∀ {n} → n ≤ n
≤-refl {zero} = z≤n
≤-refl {suc n} = s≤s (≤-refl {n})
≤-trans : ∀ {l m n} → l ≤ m → m ≤ n → l ≤ n
≤-trans z≤n m≤n = z≤n
≤-trans (s≤s m≤n) (s≤s n≤n') = s≤s (≤-trans m≤n n≤n')
≤-asym : ∀ {m n} → m ≤ n → n ≤ m → m ≡ n
≤-asym z≤n z≤n = refl
≤-asym (s≤s m≤n) (s≤s m≤n') = cong suc (≤-asym m≤n m≤n')
≤-unique : {m n : ℕ} → (p q : m ≤ n) → p ≡ q
≤-unique z≤n z≤n = refl
≤-unique (s≤s m≤n) (s≤s m≤n') = cong s≤s (≤-unique m≤n m≤n')
s≤s-inv : ∀ {m n} → suc m ≤ suc n → m ≤ n
s≤s-inv (s≤s m≤n) = m≤n
_≤?_ : (m n : ℕ) → Dec (m ≤ n)
zero ≤? n = yes z≤n
suc n ≤? zero = no (λ ())
suc n ≤? suc n' with n ≤? n'
suc n ≤? suc n' | yes p = yes (s≤s p)
suc n ≤? suc n' | no ¬p = no (λ x → ¬p (s≤s-inv x))
data _≤'_ : ℕ → ℕ → Set where
n≤'n : ∀ {n} → n ≤' n
m≤'s : ∀ {m n} (m≤n : m ≤' n) → m ≤' suc n
m≤s : ∀ {m n} (m≤n : m ≤ n) → m ≤ suc n
m≤s z≤n = z≤n
m≤s (s≤s m≤n) = s≤s (m≤s m≤n)
≤'→≤ : ∀ {m}{n} → m ≤' n → m ≤ n
≤'→≤ n≤'n = ≤-refl
≤'→≤ (m≤'s m≤n) = m≤s (≤'→≤ m≤n)
z≤'n : ∀ {n} → zero ≤' n
z≤'n {zero} = n≤'n
z≤'n {suc n} = m≤'s (z≤'n {n})
s≤'s : ∀ {m n} (m≤n : m ≤' n) → suc m ≤' suc n
s≤'s n≤'n = n≤'n
s≤'s (m≤'s m≤n) = m≤'s (s≤'s m≤n)
≤→≤' : ∀ {m}{n} → m ≤ n → m ≤' n
≤→≤' z≤n = z≤'n
≤→≤' (s≤s m≤n) = s≤'s (≤→≤' m≤n)
data Even : ℕ → Set where
zero : Even zero
sucsuc : ∀ {n} → Even n → Even (suc (suc n))
even4 : Even 4
even4 = sucsuc (sucsuc zero)
¬even3 : ¬ (Even 3)
¬even3 (sucsuc ())
inv-sucsuc : ∀ {n} → Even (suc (suc n)) → Even n
inv-sucsuc (sucsuc evenn) = evenn
even-unique : ∀ {m} → (p q : Even m) → p ≡ q
even-unique zero zero = refl
even-unique (sucsuc p) (sucsuc q) = cong sucsuc (even-unique p q)
even? : (n : ℕ) → Dec (Even n)
even? zero = yes zero
even? (suc zero) = no (λ ())
even? (suc (suc n)) with even? n
even? (suc (suc n)) | yes p = yes (sucsuc p)
even? (suc (suc n)) | no ¬p = no (λ x → ¬p (inv-sucsuc x))
data Formula : Set where
Atom : String → Formula
_⇒_ : (A B : Formula) → Formula
_∧_ : (A B : Formula) → Formula
_∨_ : (A B : Formula) → Formula
example : Formula
example = ((Atom "P") ⇒ (Atom "Q")) ⇒ Atom "P"
data Context : Set where
ε : Context
_·_ : (Γ : Context) → (A : Formula) → Context
infixl 7 _∧_
infixr 6 _⇒_
infix 4 _⊢sk_
infix 4 _⊢_
infixl 5 _·_
infixl 7 _∨_
data _⊢_ : Context → Formula → Set where
ass : ∀ {Γ A} → Γ · A ⊢ A
weak : ∀ {Γ A B} → Γ ⊢ A → Γ · B ⊢ A
app : ∀ {Γ A B} → Γ ⊢ A ⇒ B → Γ ⊢ A → Γ ⊢ B
abs : ∀ {Γ A B} → Γ · A ⊢ B → Γ ⊢ A ⇒ B
pair : ∀ {Γ A B} → Γ ⊢ A → Γ ⊢ B → Γ ⊢ A ∧ B
elim : ∀ {Γ A B C} → Γ · A · B ⊢ C → Γ · A ∧ B ⊢ C
left : ∀ {Γ A B} → Γ ⊢ A → Γ ⊢ A ∨ B
right : ∀ {Γ A B} → Γ ⊢ B → Γ ⊢ A ∨ B
case : ∀ {Γ A B C} → Γ · A ⊢ C → Γ · B ⊢ C → Γ · A ∨ B ⊢ C
data _⊢sk_ : Context → Formula → Set where
ass : ∀ {Γ A} → Γ · A ⊢sk A
weak : ∀ {Γ A B} → Γ ⊢sk A → Γ · B ⊢sk A
app : ∀ {Γ A B} → Γ ⊢sk A ⇒ B → Γ ⊢sk A → Γ ⊢sk B
K : ∀ {Γ A B} → Γ ⊢sk A ⇒ B ⇒ A
S : ∀ {Γ A B C} → Γ ⊢sk (A ⇒ B ⇒ C) ⇒ (A ⇒ B) ⇒ A ⇒ C
pair : ∀ {Γ A B} → Γ ⊢sk A ⇒ B ⇒ A ∧ B
fst : ∀ {Γ A B} → Γ ⊢sk A ∧ B ⇒ A
snd : ∀ {Γ A B} → Γ ⊢sk A ∧ B ⇒ B
left : ∀ {Γ A B} → Γ ⊢sk A ⇒ A ∨ B
right : ∀ {Γ A B} → Γ ⊢sk B ⇒ A ∨ B
case : ∀ {Γ A B C} → Γ ⊢sk (A ⇒ C) ⇒ (B ⇒ C) ⇒ A ∨ B ⇒ C
pair' : ∀ {Γ A B} → Γ ⊢ A ⇒ B ⇒ A ∧ B
pair' = abs (abs (pair (weak ass) ass))
fst' : ∀ {Γ A B} → Γ ⊢ A ∧ B ⇒ A
fst' = abs (elim (weak ass))
snd' : ∀ {Γ A B} → Γ ⊢ A ∧ B ⇒ B
snd' = abs (elim ass)
I : ∀ {Γ A} → Γ ⊢sk A ⇒ A
I {Γ} {A} = app (app S K) (K {B = A})
K' : ∀ {Γ A B} → Γ ⊢ A ⇒ B ⇒ A
K' = abs (abs (weak ass))
S' : ∀ {Γ A B C} → Γ ⊢ (A ⇒ B ⇒ C) ⇒ (A ⇒ B) ⇒ A ⇒ C
S' = abs (abs (abs (app (app (weak (weak ass)) ass)
(app (weak ass) ass))))
abs' : ∀ {Γ A B} → Γ · A ⊢sk B → Γ ⊢sk A ⇒ B
abs' ass = I
abs' (weak d) = app K d
abs' (app d d') = app (app S (abs' d)) (abs' d')
abs' K = app K K
abs' S = app K S
abs' pair = app K pair
abs' fst = app K fst
abs' snd = app K snd
abs' left = app K left
abs' right = app K right
abs' case = app K case
left' : ∀ {Γ A B} → Γ ⊢sk A → Γ ⊢sk A ∨ B
left' d = app left d
right' : ∀ {Γ A B} → Γ ⊢sk B → Γ ⊢sk A ∨ B
right' d = app right d
case' : ∀ {Γ A B C} → Γ · A ⊢sk C → Γ · B ⊢sk C → Γ · A ∨ B ⊢sk C
case' d d' = app (app (app case (weak (abs' d))) (weak (abs' d'))) ass
elim' : ∀ {Γ A B C} → Γ · A · B ⊢sk C → Γ · A ∧ B ⊢sk C
elim' d = app (app (weak (abs' (abs' d))) (app fst ass)) (app snd ass)
⊢sk→⊢ : ∀ {Γ A} → Γ ⊢sk A → Γ ⊢ A
⊢sk→⊢ ass = ass
⊢sk→⊢ (weak d) = weak (⊢sk→⊢ d)
⊢sk→⊢ (app d d') = app (⊢sk→⊢ d) (⊢sk→⊢ d')
⊢sk→⊢ K = K'
⊢sk→⊢ S = S'
⊢sk→⊢ pair = pair'
⊢sk→⊢ fst = fst'
⊢sk→⊢ snd = snd'
⊢sk→⊢ left = abs (left ass)
⊢sk→⊢ right = abs (right ass)
⊢sk→⊢ case = abs (abs (abs (case (app (weak (weak ass)) ass) (app (weak ass) ass)) ))
⊢→⊢sk : ∀ {Γ A} → Γ ⊢ A → Γ ⊢sk A
⊢→⊢sk ass = ass
⊢→⊢sk (weak d) = weak (⊢→⊢sk d)
⊢→⊢sk (app d d') = app (⊢→⊢sk d) (⊢→⊢sk d')
⊢→⊢sk (abs d) = abs' (⊢→⊢sk d)
⊢→⊢sk (pair d d') = app (app pair (⊢→⊢sk d)) (⊢→⊢sk d')
⊢→⊢sk (elim d) = elim' (⊢→⊢sk d)
⊢→⊢sk (left d) = left' (⊢→⊢sk d)
⊢→⊢sk (right d) = right' (⊢→⊢sk d)
⊢→⊢sk (case d d') = case' (⊢→⊢sk d) (⊢→⊢sk d')
B : ∀ {Γ P Q R} → Γ ⊢ (P ⇒ Q) ⇒ (Q ⇒ R) ⇒ (P ⇒ R)
B = abs (abs (abs (app (weak ass) (app (weak (weak ass)) ass))))
B' : ∀ {Γ P Q R} → Γ ⊢sk (P ⇒ Q) ⇒ (Q ⇒ R) ⇒ (P ⇒ R)
B' = ⊢→⊢sk B
C : ∀ {Γ P Q R} → Γ ⊢ (P ⇒ Q ⇒ R) ⇒ Q ⇒ P ⇒ R
C = abs (abs (abs (app (app (weak (weak ass)) ass) (weak ass))))
C' : ∀ {Γ P Q R} → Γ ⊢sk (P ⇒ Q ⇒ R) ⇒ Q ⇒ P ⇒ R
C' = ⊢→⊢sk C
distrib : ∀ {Γ P Q R} → Γ ⊢ P ∧ (Q ∨ R) ⇒ (P ∧ Q) ∨ (P ∧ R)
distrib = abs (elim (case (left (pair (weak ass) ass)) (right (pair (weak ass) ass))))
distrib' : ∀ {Γ P Q R} → Γ ⊢sk P ∧ (Q ∨ R) ⇒ (P ∧ Q) ∨ (P ∧ R)
distrib' = ⊢→⊢sk distrib