Jon Sterling, started 16th Dec 2022
A deductive system is a category-like structure in that omits the associativity
law; associativity of pre-and-post-composition then begins a *property* of
certain morphisms. This captures the behavior of *effectful* programs, whose
composition is not also associative; this perspective of effectful programs
arises from an analysis of the dynamics of cut elimination in polarized sequent
calculus. For this reason, we denote morphisms by `A ⊢ B` and write `cut` for
the (non-associative) composition operation.
\begin{code}
{-# OPTIONS --safe --without-K #-}
open import UF.FunExt
module Duploids.DeductiveSystem (fe : Fun-Ext) where
open import UF.Equiv
open import MLTT.Spartan
open import UF.Subsingletons
open import UF.Subsingletons-FunExt
open import Categories.Category fe
deductive-system-structure : (𝓤 𝓥 : Universe) → (𝓤 ⊔ 𝓥)⁺ ̇
deductive-system-structure 𝓤 𝓥 = category-structure 𝓤 𝓥
module deductive-system-structure (𝓓 : deductive-system-structure 𝓤 𝓥) where
ob : 𝓤 ̇
ob = pr₁ 𝓓
_⊢_ : ob → ob → 𝓥 ̇
A ⊢ B = pr₁ (pr₂ 𝓓) A B
idn : (A : ob) → A ⊢ A
idn A = pr₁ (pr₂ (pr₂ 𝓓)) A
cut : {A B C : ob} (f : A ⊢ B) (g : B ⊢ C) → A ⊢ C
cut f g = pr₂ (pr₂ (pr₂ 𝓓)) _ _ _ f g
module _ (𝓓 : deductive-system-structure 𝓤 𝓥) where
open deductive-system-structure 𝓓
open category-axiom-statements 𝓓
deductive-system-axioms : 𝓤 ⊔ 𝓥 ̇
deductive-system-axioms =
statement-hom-is-set
× statement-idn-L
× statement-idn-R
module deductive-system-axioms (ax : deductive-system-axioms) where
⊢-is-set : statement-hom-is-set
⊢-is-set = pr₁ ax
idn-L : statement-idn-L
idn-L = pr₁ (pr₂ ax)
idn-R : statement-idn-R
idn-R = pr₂ (pr₂ ax)
record deductive-system (𝓤 𝓥 : Universe) : (𝓤 ⊔ 𝓥)⁺ ̇ where
constructor make
field
str : deductive-system-structure 𝓤 𝓥
ax : deductive-system-axioms str
open deductive-system-structure str public
open deductive-system-axioms str ax public
module deductive-system-as-sum {𝓤 𝓥 : Universe} where
to-sum
: deductive-system 𝓤 𝓥
→ Σ str ꞉ deductive-system-structure 𝓤 𝓥 , deductive-system-axioms str
to-sum 𝓓 = let open deductive-system 𝓓 in str , ax
from-sum
: (Σ str ꞉ deductive-system-structure 𝓤 𝓥 , deductive-system-axioms str)
→ deductive-system 𝓤 𝓥
from-sum 𝓓 = make (pr₁ 𝓓) (pr₂ 𝓓)
to-sum-is-equiv : is-equiv to-sum
pr₁ (pr₁ to-sum-is-equiv) = from-sum
pr₂ (pr₁ to-sum-is-equiv) _ = refl
pr₁ (pr₂ to-sum-is-equiv) = from-sum
pr₂ (pr₂ to-sum-is-equiv) _ = refl
equiv
: deductive-system 𝓤 𝓥
≃ (Σ str ꞉ deductive-system-structure 𝓤 𝓥 , deductive-system-axioms str)
equiv = to-sum , to-sum-is-equiv
\end{code}
We now begin to state the associativity properties that hold of certain
morphisms. A morphism `f` is "thunkable" when precomposing by it is associative
in the sense that `f; (g; h) = (f; g); h`; such morphisms correspond to
"values" in programming languages. On the other hand, a morphism `f` is "linear"
when postcomposing by it is associative; such morphisms correspond to "stacks" in
programming languages.
\begin{code}
module ⊢-properties (𝓓 : deductive-system 𝓤 𝓥) where
open deductive-system 𝓓
module _ {A B : ob} (f : A ⊢ B) where
is-thunkable : 𝓤 ⊔ 𝓥 ̇
is-thunkable =
(C D : ob) (g : B ⊢ C) (h : C ⊢ D)
→ cut (cut f g) h = cut f (cut g h)
is-linear : 𝓤 ⊔ 𝓥 ̇
is-linear =
(U V : ob) (g : V ⊢ A) (h : U ⊢ V)
→ cut (cut h g) f = (cut h (cut g f))
\end{code}
Just as in a category, we can speak of a map being inverse to another map. Note
however that without additional assumptions, inverses do not seem to be unique.
\begin{code}
is-inverse : (g : B ⊢ A) → 𝓥 ̇
is-inverse g =
(cut f g = idn _)
× (cut g f = idn _)
being-inverse-is-prop
: {g : B ⊢ A}
→ is-prop (is-inverse g)
being-inverse-is-prop =
×-is-prop
(⊢-is-set _ _)
(⊢-is-set _ _)
\end{code}
Because the identity laws hold, identity morphisms are both linear and
thunkable. Furthermore, the composition of (linear, thunkable) morphisms is
(linear, thunkable).
\begin{code}
module _ (A : ob) where
abstract
idn-linear : is-linear (idn A)
idn-linear U V g h =
cut (cut h g) (idn A) =⟨ idn-R _ _ _ ⟩
cut h g =⟨ ap (cut h) (idn-R _ _ _ ⁻¹) ⟩
cut h (cut g (idn A)) ∎
idn-thunkable : is-thunkable (idn A)
idn-thunkable C D g h =
cut (cut (idn A) g) h =⟨ ap (λ x → cut x h) (idn-L A C g) ⟩
cut g h =⟨ idn-L A D (cut g h) ⁻¹ ⟩
cut (idn A) (cut g h) ∎
module _ {A B C : ob} (f : A ⊢ B) (g : B ⊢ C) where
abstract
cut-linear
: is-linear f
→ is-linear g
→ is-linear (cut f g)
cut-linear f-lin g-lin U V h k =
cut (cut k h) (cut f g) =⟨ g-lin U A f (cut k h) ⁻¹ ⟩
cut (cut (cut k h) f) g =⟨ ap (λ x → cut x g) (f-lin U V h k) ⟩
cut (cut k (cut h f)) g =⟨ g-lin U V (cut h f) k ⟩
cut k (cut (cut h f) g) =⟨ ap (cut k) (g-lin V A f h) ⟩
cut k (cut h (cut f g)) ∎
cut-thunkable
: is-thunkable f
→ is-thunkable g
→ is-thunkable (cut f g)
cut-thunkable f-th g-th D E h k =
cut (cut (cut f g) h) k =⟨ ap (λ x → cut x k) (f-th C D g h) ⟩
cut (cut f (cut g h)) k =⟨ f-th D E (cut g h) k ⟩
cut f (cut (cut g h) k) =⟨ ap (cut f) (g-th D E h k) ⟩
cut f (cut g (cut h k)) =⟨ f-th C E g (cut h k) ⁻¹ ⟩
cut (cut f g) (cut h k) ∎
module _ {A B} {f : A ⊢ B} where
being-thunkable-is-prop : is-prop (is-thunkable f)
being-thunkable-is-prop =
Π-is-prop fe λ _ →
Π-is-prop fe λ _ →
Π-is-prop fe λ _ →
Π-is-prop fe λ _ →
⊢-is-set _ _
being-linear-is-prop : is-prop (is-linear f)
being-linear-is-prop =
Π-is-prop fe λ _ →
Π-is-prop fe λ _ →
Π-is-prop fe λ _ →
Π-is-prop fe λ _ →
⊢-is-set _ _
\end{code}
Although inverses need not in general be unique, an inverse *is* unique if it is
either linear or thunkable.
\begin{code}
module _ {A B} {f : A ⊢ B} {g g'} (fg : is-inverse f g) (fg' : is-inverse f g') where
linear-inverse-is-unique
: is-linear g
→ g' = g
linear-inverse-is-unique g-lin =
g' =⟨ idn-R B A _ ⁻¹ ⟩
cut _ (idn _) =⟨ ap (cut _) (pr₁ fg ⁻¹) ⟩
cut _ (cut f _) =⟨ g-lin B A f _ ⁻¹ ⟩
cut (cut _ f) _ =⟨ ap (λ x → cut x g) (pr₂ fg') ⟩
cut (idn _) g =⟨ idn-L B A g ⟩
g ∎
thunkable-inverse-is-unique
: is-thunkable g
→ g' = g
thunkable-inverse-is-unique g-th =
g' =⟨ idn-L B A g' ⁻¹ ⟩
cut (idn _) g' =⟨ ap (λ x → cut x g') (pr₂ fg ⁻¹) ⟩
cut (cut g f) g' =⟨ g-th B A f g' ⟩
cut g (cut f g') =⟨ ap (cut g) (pr₁ fg') ⟩
cut g (idn _) =⟨ idn-R B A g ⟩
g ∎
\end{code}
An object `A` in a deductive system such that every morphism out of `A` is
linear is called "positive"; conversely, when every morphism into `A` is
thunkable we call `A` "negative". This is an extensional / objective account of
the syntactical phenomenon of polarity in structural proof theory.
\begin{code}
module polarities (𝓓 : deductive-system 𝓤 𝓥) where
open deductive-system 𝓓
open ⊢-properties 𝓓
module _ (A : ob) where
is-positive : 𝓤 ⊔ 𝓥 ̇
is-positive =
(B : ob) (f : A ⊢ B)
→ is-linear f
is-negative : 𝓤 ⊔ 𝓥 ̇
is-negative =
(B : ob) (f : B ⊢ A)
→ is-thunkable f
module _ {A} where
being-positive-is-prop : is-prop (is-positive A)
being-positive-is-prop =
Π-is-prop fe λ _ →
Π-is-prop fe λ _ →
being-linear-is-prop
being-negative-is-prop : is-prop (is-negative A)
being-negative-is-prop =
Π-is-prop fe λ _ →
Π-is-prop fe λ _ →
being-thunkable-is-prop
\end{code}