module oc-Sets where

open import Prelude
open import Unfinite

----------------------------------------------------------------------
-- oc-Sets [Section 2.2]
----------------------------------------------------------------------
record oc (X : Set) : Set where
  constructor mkoc
  infix 5 _~>_ _<~_
  field
    _~>_ :   𝔸  X  X
    _<~_ :   𝔸  X  X
    -- [Figure 1]
    oc₁ :
      (i : )
      (a b : 𝔸)
      (x : X)
       -----------------------------
      (i ~> a)((i ~> b)x)  (i ~> b)x
    oc₂ :
      (i j : )
      (a : 𝔸)
      (x : X)
       -----------------------------
      (i <~ a)((j <~ a)x)  (j <~ a)x
    oc₃ :
      (i : )
      (a : 𝔸)
      (x : X)
       -----------------------------
      (i <~ a)((i ~> a)x)  (i <~ a)x
    oc₄ :
      (i : )
      (a : 𝔸)
      (x : X)
       -----------------------------
      (i ~> a)((i <~ a)x)  (i ~> a)x
    oc₅ :
      (i j : )
      (a b : 𝔸)
      (x : X)
      {{_ : i  j}}
       ---------------------------------------
      (i ~> a)((j ~> b)x)  (j ~> b)((i ~> a)x)
    oc₆ :
      (i j : )
      (a b : 𝔸)
      (x : X)
      {{_ : a  b}}
       ---------------------------------------
      (i <~ a)((j <~ b)x)  (j <~ b)((i <~ a)x)
    oc₇ :
      (i j : )
      (a b : 𝔸)
      (x : X)
      {{_ : i  j}}
      {{_ : a  b}}
       ---------------------------------------
      (i ~> a)((j <~ b)x)  (j <~ b)((i ~> a)x)
    oc₈ :
      (i j : )
      (a b : 𝔸)
      (x : X)
       -----------------------------------------------------------
      (i ~> b)((i <~ a)((j ~> b)x))  (j ~> b)((j <~ a)((i ~> a)x))
    oc₉ :
      (i j : )
      (a b : 𝔸)
      (x : X)
       -----------------------------------------------------------
      (j <~ a)((i ~> a)((j <~ b)x))  (j <~ b)((i ~> b)((i <~ a)x))

open oc{{...}} public

{-# DISPLAY oc._~>_ _ i a = i ~> a #-}
{-# DISPLAY oc._<~_ _ i a = i <~ a #-}

----------------------------------------------------------------------
-- Example: oc-set of indices and atoms [Example 2.2]
----------------------------------------------------------------------
ℕ𝔸 : Set
ℕ𝔸 =   𝔸

private
  opn :   𝔸  ℕ𝔸  ℕ𝔸
  opn i a (ι₁ j) = if does(i  j) then ι₂ a else ι₁ j
  opn i a (ι₂ b) = ι₂ b

  cls :   𝔸  ℕ𝔸  ℕ𝔸
  cls i a (ι₁ j) = ι₁ j
  cls i a (ι₂ b) = if does(a  b) then ι₁ i else ι₂ b

  ax₁ :
    (i : )
    (a b : 𝔸)
    (x : ℕ𝔸)
     -----------------------------
    opn i a (opn i b x)  opn i b x
  ax₁ i _ _ (ι₁ j) with i  j
  ... | neq f rewrite dec-neq i j f = refl
  ... | equ = refl
  ax₁ i _ _ (ι₂ _) = refl

  ax₂ :
    (i j : )
    (a : 𝔸)
    (x : ℕ𝔸)
     -----------------------------
    cls i a (cls j a x)  cls j a x
  ax₂ _ _ _ (ι₁ _) = refl
  ax₂ _ _ a (ι₂ b) with  a  b
  ... | neq f rewrite dec-neq a b f = refl
  ... | equ = refl

  ax₃ :
    (i : )
    (a : 𝔸)
    (x : ℕ𝔸)
     -----------------------------
    cls i a (opn i a x)  cls i a x
  ax₃ i a (ι₁ j) with i  j
  ... | neq _ = refl
  ... | equ rewrite dec-equ a = refl
  ax₃ _ _ (ι₂ _) = refl

  ax₄ :
    (i : )
    (a : 𝔸)
    (x : ℕ𝔸)
     -----------------------------
    opn i a (cls i a x)  opn i a x
  ax₄ i a (ι₁ j) = refl
  ax₄ i a (ι₂ b) with a  b
  ... | neq _ = refl
  ... | equ rewrite dec-equ i = refl

  ax₅ :
    (i j : )
    (a b : 𝔸)
    (x : ℕ𝔸)
    {{p : i  j}}
     ---------------------------------------
    opn i a (opn j b x)  opn j b (opn i a x)
  ax₅ _ j _ _ (ι₁ k)       with j  k
  ax₅ i _ _ _ (ι₁ k)       | neq _ with  i  k
  ax₅ _ j _ _ (ι₁ k)       | neq f | neq _ rewrite dec-neq j k f = refl
  ax₅ _ _ _ _ (ι₁ _)       | neq _ | equ                         = refl
  ax₅ _ j _ _ (ι₁ _) {{p}} | equ rewrite p | dec-equ j           = refl
  ax₅ _ _ _ _ (ι₂ _)                                             = refl

  ax₆ :
    (i j : )
    (a b : 𝔸)
    (x : ℕ𝔸)
    {{p : a  b}}
     ---------------------------------------
    cls i a (cls j b x)  cls j b (cls i a x)
  ax₆ _ _ _ _ (ι₁ _)                                             = refl
  ax₆ _ _ _ b (ι₂ c)       with  b  c
  ax₆ _ _ a _ (ι₂ c)       | neq _ with a  c
  ax₆ _ _ _ b (ι₂ c)       | neq f | neq _ rewrite dec-neq b c f = refl
  ax₆ _ _ _ _ (ι₂ _)       | neq _ | equ                         = refl
  ax₆ _ _ _ b (ι₂ _) {{p}} | equ rewrite p | dec-equ b           = refl

  ax₇ :
    (i j : )
    (a b : 𝔸)
    (x : ℕ𝔸)
    {{p : i  j}}
    {{q : a  b}}
     ---------------------------------------
    opn i a (cls j b x)  cls j b (opn i a x)
  ax₇ i _ _ _ (ι₁ k)           with i  k
  ax₇ _ _ _ _ (ι₁ _)           | neq _                   = refl
  ax₇ _ _ a b (ι₁ _) {{q = q}} | equ rewrite symm≠ a b q = refl
  ax₇ _ _ _ b (ι₂ c)           with b  c
  ax₇ _ _ _ _ (ι₂ _)           | neq _                   = refl
  ax₇ _ _ _ _ (ι₂ _) {{p}}     | equ rewrite p           = refl

  ax₈ :
    (i j : )
    (a b : 𝔸)
    (x : ℕ𝔸)
     -----------------------------------------------------------
    opn i b (cls i a (opn j b x))  opn j b (cls j a (opn i a x))
  ax₈ _ j _ _ (ι₁ k) with j  k
  ax₈ i _ _ _ (ι₁ k) | neq _ with i  k
  ax₈ _ j _ _ (ι₁ k) | neq f | neq _
      rewrite dec-neq j k f         = refl
  ax₈ _ j a _ (ι₁ _) | neq _ | equ
      rewrite dec-equ a | dec-equ j = refl
  ax₈ _ _ a b (ι₁ _) | equ   with a  b
  ax₈ i j _ _ (ι₁ _) | equ   | neq _ with i  j
  ax₈ _ j _ _ (ι₁ -) | equ   | neq _ | neq _
      rewrite dec-equ j = refl
  ax₈ _ j a _ (ι₁ _) | equ   | neq _ | equ
      rewrite dec-equ a | dec-equ j = refl
  ax₈ i j _ _ (ι₁ _) | equ   | equ   with i  j
  ax₈ i j _ _ (ι₁ _) | equ   | equ   | neq _
      rewrite dec-equ i | dec-equ j = refl
  ax₈ _ j a _ (ι₁ _) | equ   | equ   | equ
      rewrite dec-equ a | dec-equ j = refl
  ax₈ _ _ a _ (ι₂ c) with a  c
  ax₈ _ _ _ _ (ι₂ _) | neq _      = refl
  ax₈ i j _ _ (ι₂ _) | equ
      rewrite dec-equ i | dec-equ j = refl

  ax₉ :
    (i j : )
    (a b : 𝔸)
    (x : ℕ𝔸)
     -----------------------------------------------------------
    cls j a (opn i a (cls j b x))  cls j b (opn i b (cls i a x))
  ax₉ i _ _ _ (ι₁ k) with i  k
  ax₉ _ _ _ _ (ι₁ _) | neq _ = refl
  ax₉ _ _ a b (ι₁ _) | equ
      rewrite dec-equ a | dec-equ b = refl
  ax₉ _ _ _ b (ι₂ c) with  b  c
  ax₉ _ _ a _ (ι₂ c) | neq _ with a  c
  ax₉ _ _ _ b (ι₂ c) | neq f | neq _
      rewrite dec-neq b c f = refl
  ax₉ i _ _ b (ι₂ _) | neq _ | equ
      rewrite dec-equ i | dec-equ b = refl
  ax₉ i j _ _ (ι₂ _) | equ   with i  j
  ax₉ _ _ a b (ι₂ _) | equ   | neq _ with a  b
  ax₉ _ _ _ b (ι₂ _) | equ   | neq _ | neq _
      rewrite dec-equ b = refl
  ax₉ i _ _ b (ι₂ _) | equ   | neq _ | equ
      rewrite dec-equ i | dec-equ b = refl
  ax₉ _ _ a b (ι₂ _) | equ   | equ   with a  b
  ax₉ _ _ a b (ι₂ _) | equ   | equ   | neq _
      rewrite dec-equ a | dec-equ b = refl
  ax₉ i _ _ b (ι₂ _) | equ   | equ   | equ
      rewrite dec-equ i | dec-equ b = refl

instance
  ocℕ𝔸 : oc ℕ𝔸
  ocℕ𝔸 = mkoc opn cls ax₁ ax₂ ax₃ ax₄ ax₅ ax₆ ax₇ ax₈ ax₉

-- ℕ𝔸 is unfinite
instance
  Unfiniteℕ𝔸 : Unfinite ℕ𝔸
  Unfiniteℕ𝔸 = Unfinite⊎

----------------------------------------------------------------------
-- Product of oc-sets
----------------------------------------------------------------------
oc× :
  {X Y : Set}
  {{_ : oc X}}
  {{_ : oc Y}}
   ----------
  oc (X × Y)
_~>_ {{oc×}} i a (x , y) = ((i ~> a)x  , ((i ~> a)y))
_<~_ {{oc×}} i a (x , y) = ((i <~ a)x  , ((i <~ a)y))
oc₁ {{oc×}} i a b (x , y)
  rewrite oc₁ i a b x | oc₁ i a b y = refl
oc₂ {{oc×}} i j a (x , y)
  rewrite oc₂ i j a x | oc₂ i j a y = refl
oc₃ {{oc×}} i a (x , y)
  rewrite oc₃ i a x | oc₃ i a y = refl
oc₄ {{oc×}} i a (x , y)
  rewrite oc₄ i a x | oc₄ i a y = refl
oc₅ {{oc×}} i j a b (x , y)
  rewrite oc₅ i j a b x {{it}} | oc₅ i j a b y {{it}} = refl
oc₆ {{oc×}} i j a b (x , y)
  rewrite oc₆ i j a b x {{it}} | oc₆ i j a b y {{it}} = refl
oc₇ {{oc×}} i j a b (x , y)
  rewrite oc₇ i j a b x {{it}} {{it}} | oc₇ i j a b y {{it}} {{it}} = refl
oc₈ {{oc×}} i j a b (x , y)
  rewrite oc₈ i j a b x | oc₈ i j a b y = refl
oc.oc₉ oc× i j a b (x , y)
  rewrite oc₉ i j a b x | oc₉ i j a b y = refl