module SizedFunctor where

open import AlgebraicSignature public
open import Colimit public
open import InflationaryIteration public
open import InitialAlgebra public
open import InitialAlgebraViaInflationaryIteration public
open import Prelude public
open import Size

----------------------------------------------------------------------
-- Sized functors between cocomplete categories
----------------------------------------------------------------------
module _
  {𝓒 𝓓 : Set₁}
  {{_ : CAT 𝓒}}
  {{_ : Cocomplete 𝓒}}
  {{_ : CAT 𝓓}}
  {{_ : Cocomplete 𝓓}}
  (F : 𝓒 → 𝓓)
  {{_ : Functor F}}
  where
  infix 4 _hasSize_
  _hasSize_ : Sig → Prop₁
  -- F hasSize Σ if it preserves colimits indexed by any Σ-filtered size
  _hasSize_ Σ =
    (κ : Set)
    {{sz : Size κ}}
    {{fi : Filtered Σ κ}}
    → ------------------
    Cocontinuous κ F

  -- F is sized if it hasSize Σ for some Σ
  Sized : Prop₁
  Sized = ∃ Sig _hasSize_

  -- Behaviour of sizing on signature sums
  Sized⨁ :
    (A : Set)
    (Σ : A → Sig)
    (x : A)
    → ---------------------------------
    _hasSize_ (Σ x) → _hasSize_ (⨁ A Σ)
  Sized⨁ A Σ x hsx κ = hsx κ {{fi = Filtered⨁ κ A Σ x}}

  Sized⊕l :
    (Σ Σ' : Sig)
    → ------------------------------
    _hasSize_ Σ → _hasSize_ (Σ ⊕ Σ')
  Sized⊕l Σ Σ' hs κ = hs κ {{fi = Filtered⊕l κ Σ Σ'}}

  Sized⊕r :
    (Σ Σ' : Sig)
    → -------------------------------
    _hasSize_ Σ' → _hasSize_ (Σ ⊕ Σ')
  Sized⊕r Σ Σ' hs κ = hs κ {{fi = Filtered⊕r κ Σ Σ'}}

----------------------------------------------------------------------
-- Theorem 4.4: Sized endofunctors have initial algebras
----------------------------------------------------------------------
SizedInitialAlg :
  {𝓒 : Set₁}
  {{_ : CAT 𝓒}}
  {{_ : Cocomplete 𝓒}}
  (F : 𝓒 → 𝓒)
  {{_ : Functor F}}
  (Σ : Sig)
  → ------------------------
  F hasSize Σ → InitialAlg F
SizedInitialAlg F Σ sizedΣF = InitialAlgebraTheorem κ F (sizedΣF κ)
  where
  κ : Set
  κ = plump Σ
  instance
   _ : Size (plump Σ)
   _ = SizePlump
   _ : Filtered Σ κ
   _ = FilteredPlump

----------------------------------------------------------------------
-- Any cocontinuous functor is sized
----------------------------------------------------------------------
CocontinuousSized :
  {𝓒 𝓓 : Set₁}
  {{_ : CAT 𝓒}}
  {{_ : Cocomplete 𝓒}}
  {{_ : CAT 𝓓}}
  {{_ : Cocomplete 𝓓}}
  (F : 𝓒 → 𝓓)
  {{_ : Functor F}}
  (_ : (κ : Set){{_ : Thin κ}} → Cocontinuous κ F)
  → ----------------------------------------------
  Sized F
CocontinuousSized F c = ∃i emp λ κ → c κ

----------------------------------------------------------------------
-- Identity functors are sized
----------------------------------------------------------------------
-- IdSized :
--   {𝓒 : Set₁}
--   {{_ : CAT 𝓒}}
--   {{_ : Cocomplete 𝓒}}
--   → -------------------------------
--   Sized (λ(X : 𝓒) → X){{FunctorId}}
-- IdSized = {!!}