open import Chapter2.Desc
open import Chapter2.Desc.Tagged
open import Chapter2.Desc.Fixpoint

module Chapter4.NoConfusion (D : tagDesc) where

open import Function

open import Data.Empty
open import Data.Unit hiding (_≟_)
open import Data.Nat hiding (compare ; pred ; _≟_)
open import Data.Fin
open import Data.Sum
open import Data.Product

open import Relation.Nullary
open import Relation.Binary
open import Relation.Binary.PropositionalEquality

Eq : (D : Desc){X : Set}   D  X   D  X  Set
Eq `1 tt tt = 
Eq `var xs ys = xs  ys
Eq (D₁  D₂) (xs₁ , xs₂) (ys₁ , ys₂) = Eq D₁ xs₁ ys₁ × Eq D₂ xs₂ ys₂
Eq (D₁ `+ D₂) (inj₁ xs₁) (inj₁ ys₁) = Eq D₁ xs₁ ys₁
Eq (D₁ `+ D₂) (inj₁ xs₁) (inj₂ ys₂) = 
Eq (D₁ `+ D₂) (inj₂ xs₁) (inj₁ ys₂) = 
Eq (D₁ `+ D₂) (inj₂ xs₂) (inj₂ ys₂) = Eq D₂ xs₂ ys₂
Eq ( S T) (s₁ , xs) (s₂ , ys) = Σ[ q  s₁  s₂ ] Eq (T s₁) xs (subst  s   T s  _) (sym q) ys)
Eq ( S T) xs ys =  s  Eq (T s) (xs s) (ys s)


infix 4 _≟_

_≟_ : {n : }  Decidable {A = Fin n} _≡_
zero   zero   = yes refl
suc m  suc n  with m  n
suc m  suc .m | yes refl = yes refl
suc m  suc n  | no prf = no  q  prf (help q)) 
  where help : ∀{k}{m n : Fin k}  _≡_ {A = Fin ((suc k))} (suc m) (suc n)  m  n
        help refl = refl
zero   suc n  = no λ()
suc m  zero   = no λ()


NoConfusion : (x y : μ (toDesc D))  Set₁
NoConfusion  x , args₁   y , args₂  with x  y
NoConfusion  .y , args₁   y , args₂ 
    | yes refl =  P  (args₁  args₂  P)  P
NoConfusion  x , args₁   y , args₂ 
    | no q =  P  P

noConfusion : (x y :  toDesc D  (μ (toDesc D)))  x  y  NoConfusion ( x ) ( y )
noConfusion (x , args₁) (y , args₂) q with x  y
noConfusion (.y , .args₁) (y , args₁) refl | yes refl = λ P rec  rec refl
noConfusion (.y , .args₂) (y , args₂) refl | no notEq = ⊥-elim (notEq refl)