module NCILL.Examples.Equivalences where
open import NCILL
record _o-o_ (A B : Ty) : Set where
field
lfwd : [ A ] ⊢ B
lbwd : [ B ] ⊢ A
infix 6 _o-o_
o-o-refl : ∀ A → A o-o A
o-o-refl _ = record { lfwd = var ; lbwd = var }
o-o-trans : ∀ A B C → A o-o B → B o-o C → A o-o C
o-o-trans _ _ _ record { lfwd = ab ; lbwd = ba } record { lfwd = bc ; lbwd = cb } = record
{ lfwd = cut [] ab bc
; lbwd = cut [] cb ba
}
⊗-left-identity : ∀ A → ♯1 ⊗ A o-o A
⊗-left-identity _ = record
{ lfwd = times-L [] (unit-L [] var)
; lbwd = times-R unit-R var
}
⊗-right-identity : ∀ A → A ⊗ ♯1 o-o A
⊗-right-identity _ = record
{ lfwd = times-L [] (unit-L [ _ ] var)
; lbwd = times-R var unit-R
}
⊗-assoc : ∀ A B C → (A ⊗ B) ⊗ C o-o A ⊗ B ⊗ C
⊗-assoc _ _ _ = record
{ lfwd = times-L [] (times-L [] (times-R var (times-R var var)))
; lbwd = times-L [] (times-L [ _ ] (times-R (times-R var var) var))
}
⊕-left-identity : ∀ A → ♯0 ⊕ A o-o A
⊕-left-identity _ = record
{ lfwd = plus-L [] (zero-L []) var
; lbwd = plus-R₂ var
}
⊕-right-identity : ∀ A → A ⊕ ♯0 o-o A
⊕-right-identity _ = record
{ lfwd = plus-L [] var (zero-L [])
; lbwd = plus-R₁ var
}
⊕-assoc : ∀ A B C → (A ⊕ B) ⊕ C o-o A ⊕ B ⊕ C
⊕-assoc _ _ _ = record
{ lfwd = plus-L [] (plus-L [] (plus-R₁ var) (plus-R₂ (plus-R₁ var))) (plus-R₂ (plus-R₂ var))
; lbwd = plus-L [] (plus-R₁ (plus-R₁ var)) (plus-L [] (plus-R₁ (plus-R₂ var)) (plus-R₂ var))
}
⊕-comm : ∀ A B → A ⊕ B o-o B ⊕ A
⊕-comm _ _ = record
{ lfwd = plus-L [] (plus-R₂ var) (plus-R₁ var)
; lbwd = plus-L [] (plus-R₂ var) (plus-R₁ var)
}
⊕-idemp : ∀ A → A ⊕ A o-o A
⊕-idemp _ = record
{ lfwd = plus-L [] var var
; lbwd = plus-R₁ var
}
&-left-identity : ∀ A → ♯⊤ & A o-o A
&-left-identity _ = record
{ lfwd = with-L₂ [] var
; lbwd = with-R top-R var
}
&-right-identity : ∀ A → A & ♯⊤ o-o A
&-right-identity _ = record
{ lfwd = with-L₁ [] var
; lbwd = with-R var top-R
}
&-assoc : ∀ A B C → (A & B) & C o-o A & B & C
&-assoc _ _ _ = record
{ lfwd = with-R
(with-L₁ [] (with-L₁ [] var))
(with-R
(with-L₁ [] (with-L₂ [] var))
(with-L₂ [] var))
; lbwd = with-R
(with-R
(with-L₁ [] var)
(with-L₂ [] (with-L₁ [] var)))
(with-L₂ [] (with-L₂ [] var))
}
&-comm : ∀ A B → A & B o-o B & A
&-comm _ _ = record
{ lfwd = with-R (with-L₂ [] var) (with-L₁ [] var)
; lbwd = with-R (with-L₂ [] var) (with-L₁ [] var)
}
&-idemp : ∀ A → A & A o-o A
&-idemp _ = record
{ lfwd = with-L₁ [] var
; lbwd = with-R var var
}
⊗-⊕-left-distr : ∀ A B C → A ⊗ (B ⊕ C) o-o (A ⊗ B) ⊕ (A ⊗ C)
⊗-⊕-left-distr _ _ _ = record
{ lfwd = times-L [] (plus-L [ _ ]
(plus-R₁ (times-R var var))
(plus-R₂ (times-R var var)))
; lbwd = plus-L []
(times-L [] (times-R var (plus-R₁ var)))
(times-L [] (times-R var (plus-R₂ var)))
}
⊗-⊕-right-distr : ∀ A B C → (A ⊕ B) ⊗ C o-o (A ⊗ C) ⊕ (B ⊗ C)
⊗-⊕-right-distr _ _ _ = record
{ lfwd = times-L [] (plus-L []
(plus-R₁ (times-R var var))
(plus-R₂ (times-R var var)))
; lbwd = plus-L []
(times-L [] (times-R (plus-R₁ var) var))
(times-L [] (times-R (plus-R₂ var) var))
}
left-zero : ∀ A → ♯0 ⊗ A o-o ♯0
left-zero _ = record
{ lfwd = times-L [] (zero-L [])
; lbwd = zero-L []
}
right-zero : ∀ A → A ⊗ ♯0 o-o ♯0
right-zero _ = record
{ lfwd = times-L [] (zero-L [ _ ])
; lbwd = zero-L []
}
absurd : ∀ A → ♯0 ⊸ʳ A o-o ♯⊤
absurd _ = record
{ lfwd = top-R
; lbwd = lam (zero-L (♯⊤ ∷ []))
}
boring : ∀ A → A ⊸ʳ ♯⊤ o-o ♯⊤
boring _ = record
{ lfwd = top-R
; lbwd = lam top-R
}
distr-1 : ∀ A B C → A ⊕ B ⊸ʳ C o-o (A ⊸ʳ C) & (B ⊸ʳ C)
distr-1 _ _ _ = record
{ lfwd = with-R
(lam (app [] (plus-R₁ var) var))
(lam (app [] (plus-R₂ var) var))
; lbwd = lam (plus-L [ _ ]
(with-L₁ [] (app [] var var))
(with-L₂ [] (app [] var var)))
}
distr-2 : ∀ A B C → A ⊸ʳ B & C o-o (A ⊸ʳ B) & (A ⊸ʳ C)
distr-2 _ _ _ = record
{ lfwd = with-R
(lam (app [] var (with-L₁ [] var)))
(lam (app [] var (with-L₂ [] var)))
; lbwd = lam (with-R
(with-L₁ [] (app [] var var))
(with-L₂ [] (app [] var var)))
}
half-distr-1 : ∀ A B C → [ A ⊗ (B & C) ] ⊢ (A ⊗ B) & (A ⊗ C)
half-distr-1 _ _ _ = with-R
(times-L [] (times-R var (with-L₁ [] var)))
(times-L [] (times-R var (with-L₂ [] var)))
half-distr-2 : ∀ A B C → [ (A ⊸ʳ C) ⊕ (B ⊸ʳ C) ] ⊢ A & B ⊸ʳ C
half-distr-2 _ _ _ = lam (plus-L []
(app [] (with-L₁ [] var) var)
(app [] (with-L₂ [] var) var))
half-distr-3 : ∀ A B C → [ (A ⊸ʳ B) ⊕ (A ⊸ʳ C) ] ⊢ A ⊸ʳ B ⊕ C
half-distr-3 _ _ _ = lam (plus-L []
(app [] var (plus-R₁ var))
(app [] var (plus-R₂ var)) )
curry : ∀ A B C → B ⊗ A ⊸ C o-o A ⊸ B ⊸ C
curry _ _ _ = record
{ lfwd = impl-R (impl-R (cut [] (times-R var var) (impl-L [] var var)))
; lbwd = impl-R (times-L [] (impl-L [ _ ] var (impl-L [] var var)))
}
curryʳ : ∀ A B C → A ⊗ B ⊸ʳ C o-o A ⊸ʳ B ⊸ʳ C
curryʳ _ _ _ = record
{ lfwd = impl-Rʳ (impl-Rʳ (cut [ _ ] (times-R var var) (impl-Lʳ [] var var)))
; lbwd = impl-Rʳ (times-L [ _ ] (impl-Lʳ [] var (impl-Lʳ [] var var)))
}
lin-equiv₁ : ∀ A B → [] ⊢ A ⊸ B → [] ⊢ A ⊸ʳ B
lin-equiv₁ _ _ f = impl-Rʳ (cut [ _ ] f (impl-L [] var var))
lin-equiv₂ : ∀ A B → [] ⊢ A ⊸ʳ B → [] ⊢ A ⊸ B
lin-equiv₂ _ _ f = impl-R (cut [] f (impl-Lʳ [] var var))