module A201801.S4ExperimentalDerivations3x where

open import A201801.Prelude
open import A201801.Category
open import A201801.List
open import A201801.ListLemmas
open import A201801.AllList
open import A201801.S4Propositions
import A201801.S4StandardDerivations as S4


--------------------------------------------------------------------------------


mutual
  infix 3 _⨾_⊢_true
  data _⨾_⊢_true : List Assert  List Form  Form  Set
    where
      vz :  {A Δ Γ}  Δ  Γ , A  A true

      wk :  {A B Δ Γ}  Δ  Γ  A true
                        Δ  Γ , B  A true

      cut :  {A B Δ Γ}  Δ  Γ  A true  Δ  Γ , A  B true
                         Δ  Γ  B true

      lam :  {A B Δ Γ}  Δ  Γ , A  B true
                         Δ  Γ  A  B true

      unlam :  {A B Δ Γ}  Δ  Γ  A  B true
                           Δ  Γ , A  B true

      vau :  {A B Δ Γ}  Δ , ⟪⊫ A   Γ  B true
                         Δ  Γ ,  A  B true

      unvau :  {A B Δ Γ}  Δ  Γ ,  A  B true
                           Δ , ⟪⊫ A   Γ  B true

      v→t :  {A Δ Γ}  Δ  A valid
                        Δ  Γ  A true

  infix 3 _⊢_valid
  data _⊢_valid : List Assert  Form  Set
    where
      mvz :  {A Δ}  Δ , ⟪⊫ A   A valid

      mwk :  {A B Δ}  Δ  A valid
                       Δ , B  A valid

      mcut :  {A B Δ}  Δ  A valid  Δ , ⟪⊫ A   B valid
                        Δ  B valid

      t→v :  {A Δ}  Δ    A true
                      Δ  A valid


infix 3 _⨾_⊢_alltrue
_⨾_⊢_alltrue : List Assert  List Form  List Form  Set
Δ  Γ  Ξ alltrue = All (Δ  Γ ⊢_true) Ξ


infix 3 _⊢_allvalid
_⊢_allvalid : List Assert  List Assert  Set
Δ  Ξ allvalid = All (\ { ⟪⊫ A   Δ  A valid }) Ξ


--------------------------------------------------------------------------------


wks :  {A Δ Γ Ξ}  Δ  Γ  Ξ alltrue
                   Δ  Γ , A  Ξ alltrue
wks ξ = maps wk ξ


lifts :  {A Δ Γ Ξ}  Δ  Γ  Ξ alltrue
                     Δ  Γ , A  Ξ , A alltrue
lifts ξ = wks ξ , vz


vars :  {Δ Γ Γ′}  Γ′  Γ
                   Δ  Γ′  Γ alltrue
vars done     = 
vars (drop η) = wks (vars η)
vars (keep η) = lifts (vars η)


ids :  {Δ Γ}  Δ  Γ  Γ alltrue
ids = vars id


--------------------------------------------------------------------------------


mwks :  {A Δ Ξ}  Δ  Ξ allvalid
                  Δ , A  Ξ allvalid
mwks ξ = maps mwk ξ


mlifts :  {A Δ Ξ}  Δ  Ξ allvalid
                    Δ , ⟪⊫ A   Ξ , ⟪⊫ A  allvalid
mlifts ξ = mwks ξ , mvz


mvars :  {Δ Δ′}  Δ′  Δ
                  Δ′  Δ allvalid
mvars done     = 
mvars (drop η) = mwks (mvars η)
mvars (keep η) = mlifts (mvars η)


mids :  {Δ}  Δ  Δ allvalid
mids = mvars id


--------------------------------------------------------------------------------


mwk′ :  {A B Δ Γ}  Δ  Γ  A true
                    Δ , B  Γ  A true
mwk′ 𝒟 = unvau (wk 𝒟)


mwks′ :  {A Δ Γ Ξ}  Δ  Γ  Ξ alltrue
                     Δ , ⟪⊫ A   Γ  Ξ alltrue
mwks′ ξ = maps mwk′ ξ


vaus :  {Δ Γ A Ξ}  Δ , ⟪⊫ A   Γ  Ξ alltrue
                    Δ  Γ ,  A  Ξ alltrue
vaus 𝒟 = maps vau 𝒟


-- NOTE: Similar shape to lift or cut

unnamed :  {Δ Γ A Ξ}  Δ , ⟪⊫ A   Γ  Ξ alltrue
                       Δ  Γ ,  A  Ξ ,  A alltrue
unnamed 𝒟 = vaus 𝒟 , vz


sub :  {Δ Γ Ξ A}  Δ  Γ  Ξ alltrue  Δ  Ξ  A true
                   Δ  Γ  A true
sub (ξ , 𝒞) vz        = 𝒞
sub (ξ , 𝒞) (wk 𝒟)    = sub ξ 𝒟
sub ξ       (cut 𝒟 ) = cut (sub ξ 𝒟) (sub (lifts ξ) )
sub ξ       (lam 𝒟)   = lam (sub (lifts ξ) 𝒟)
sub (ξ , 𝒞) (unlam 𝒟) = cut 𝒞 (unlam (sub ξ 𝒟))
sub (ξ , 𝒞) (vau 𝒟)   = cut 𝒞 (vau (sub (mwks′ ξ) 𝒟))
sub ξ       (unvau 𝒟) = unvau (sub (unnamed ξ) 𝒟)  -- NOTE: Interesting
sub ξ       (v→t 𝒟)  = v→t 𝒟


--------------------------------------------------------------------------------


box :  {A Δ Γ}  Δ    A true
                 Δ  Γ   A true
box 𝒟 = v→t (mcut (t→v 𝒟) (t→v (unvau vz)))


letbox :  {A B Δ Γ}  Δ  Γ   A true  Δ , ⟪⊫ A   Γ  B true
                      Δ  Γ  B true
letbox 𝒟  = cut 𝒟 (vau )


mcut′ :  {Δ Γ A B}  Δ    A true  Δ , ⟪⊫ A   Γ  B true
                     Δ  Γ  B true
mcut′ 𝒟  = cut (box 𝒟) (vau )


mutual
  msub :  {Δ Γ Ξ A}  Δ  Ξ allvalid  Ξ  Γ  A true
                      Δ  Γ  A true
  msub ξ       vz        = vz
  msub ξ       (wk 𝒟)    = wk (msub ξ 𝒟)
  msub ξ       (cut 𝒟 ) = cut (msub ξ 𝒟) (msub ξ )
  msub ξ       (lam 𝒟)   = lam (msub ξ 𝒟)
  msub ξ       (unlam 𝒟) = unlam (msub ξ 𝒟)
  msub ξ       (vau 𝒟)   = vau (msub (mlifts ξ) 𝒟)
  msub (ξ , 𝒞) (unvau 𝒟) = mcut′ (v→t 𝒞) (unvau (msub ξ 𝒟))  -- NOTE: Interesting
  msub ξ       (v→t 𝒟)  = v→t (msub₁ ξ 𝒟)

  msub₁ :  {Δ Ξ A}  Δ  Ξ allvalid  Ξ  A valid
                     Δ  A valid
  msub₁ ξ       (t→v 𝒟)   = t→v (msub ξ 𝒟)
  msub₁ (ξ , 𝒞) mvz        = 𝒞
  msub₁ (ξ , 𝒞) (mwk 𝒟)    = msub₁ ξ 𝒟
  msub₁ ξ       (mcut 𝒟 ) = mcut (msub₁ ξ 𝒟) (msub₁ (mlifts ξ) )


--------------------------------------------------------------------------------


var :  {A Δ Γ}  Γ  A
                 Δ  Γ  A true
var zero    = vz
var (suc i) = wk (var i)


app :  {A B Δ Γ}  Δ  Γ  A  B true  Δ  Γ  A true
                   Δ  Γ  B true
app 𝒟  = cut  (unlam 𝒟)


--------------------------------------------------------------------------------


mvz′ :  {A Δ Γ}  Δ , ⟪⊫ A   Γ  A true
mvz′ = v→t mvz


mvar :  {A Δ Γ}  Δ  ⟪⊫ A 
                  Δ  Γ  A true
mvar zero    = mvz′
mvar (suc i) = mwk′ (mvar i)


--------------------------------------------------------------------------------


module S4′
  where
    _⨾_⊢_true′ : List Assert  List Form  Form  Set
    Δ  Γ  A true′ = Δ S4.⊢ A valid[ Γ ]

    _⊢_valid′ : List Assert  Assert  Set
    Δ  ⟪⊫ A  valid′ = Δ S4.⊢ A valid[  ]


-- v→t : ∀ {A Δ Γ} → Δ ⊢ A valid
--                  → Δ ⨾ Γ ⊢ A true

S4′v→t :  {A Δ Γ}  Δ S4′.⊢ ⟪⊫ A  valid′
                    Δ S4′.⨾ Γ  A true′
S4′v→t 𝒟 = S4.sub  𝒟


-- t→v : ∀ {A Δ} → Δ ⨾ ∙ ⊢ A true
--                → Δ ⊢ A valid

S4′t→v :  {A Δ}  Δ S4′.⨾   A true′
                  Δ S4′.⊢ ⟪⊫ A  valid′
S4′t→v 𝒟 = 𝒟


mutual
   :  {Δ Γ A}  Δ  Γ  A true
                 Δ S4.⊢ A valid[ Γ ]
   vz           = S4.vz
   (wk 𝒟)       = S4.wk ( 𝒟)
   (cut 𝒟 )    = S4.cut ( 𝒟) ( )
   (lam 𝒟)      = S4.lam ( 𝒟)
   (unlam 𝒟)    = S4.unlam ( 𝒟)
   (vau 𝒟)      = S4.vau ( 𝒟)
   (unvau 𝒟)    = S4.unvau ( 𝒟)
   (v→t 𝒟)     = S4′v→t (↓₁ 𝒟)

  ↓₁ :  {Δ A}  Δ  A valid
                Δ S4.⊢ A valid[  ]
  ↓₁ (t→v 𝒟)   = S4′t→v ( 𝒟)
  ↓₁ mvz        = S4.mvz
  ↓₁ (mwk 𝒟)    = S4.mwk (↓₁ 𝒟)
  ↓₁ (mcut 𝒟 ) = S4.mcut (↓₁ 𝒟) (↓₁ )


 :  {Δ Γ A}  Δ S4.⊢ A valid[ Γ ]
               Δ  Γ  A true
 (S4.var i)      = var i
 (S4.lam 𝒟)      = lam ( 𝒟)
 (S4.app 𝒟 )    = app ( 𝒟) ( )
 (S4.mvar i)     = mvar i
 (S4.box 𝒟)      = box ( 𝒟)
 (S4.letbox 𝒟 ) = letbox ( 𝒟) ( )


--------------------------------------------------------------------------------