packages feed

proarrow-0.1.0.0: src/Proarrow/Profunctor/Instance/Terminal.hs

-- | The terminal profunctor, with exactly one value between any two objects: the terminal object of the
-- category of profunctors @j +-> k@.
module Proarrow.Profunctor.Instance.Terminal (TerminalProfunctor (.., TerminalProfunctor)) where

import Proarrow.Category.Enriched.Dagger (Dagger, DaggerProfunctor (..))
import Proarrow.Category.Enriched.Thin (DecidableProfunctor (..), Decision (..), ThinProfunctor (..))
import Proarrow.Category.Instance.Bool (BOOL (..))
import Proarrow.Category.Monoidal (Monoidal, MonoidalProfunctor (..))
import Proarrow.Core (CategoryOf (..), Profunctor (..), Promonad (..), type (+->))
import Proarrow.Object (pattern Obj, type Obj)

-- | The profunctor with exactly one value between any two objects: the terminal object of the
-- category of profunctors @j +-> k@.
type TerminalProfunctor :: j +-> k
data TerminalProfunctor a b where
  TerminalProfunctor' :: Obj a -> Obj b -> TerminalProfunctor (a :: j) (b :: k)

instance (CategoryOf j, CategoryOf k) => Profunctor (TerminalProfunctor :: j +-> k) where
  dimap l r TerminalProfunctor = TerminalProfunctor \\ l \\ r
  r \\ TerminalProfunctor = r

instance (CategoryOf k) => Promonad (TerminalProfunctor :: k +-> k) where
  id = TerminalProfunctor
  TerminalProfunctor . TerminalProfunctor = TerminalProfunctor

instance (Monoidal j, Monoidal k) => MonoidalProfunctor (TerminalProfunctor :: j +-> k) where
  one = TerminalProfunctor' one one
  TerminalProfunctor' a1 b1 ** TerminalProfunctor' a2 b2 = TerminalProfunctor' (a1 ** a2) (b1 ** b2)

instance (Dagger k) => DaggerProfunctor (TerminalProfunctor :: k +-> k) where
  dagger TerminalProfunctor = TerminalProfunctor

pattern TerminalProfunctor
  :: forall {j} {k} a b. (CategoryOf j, CategoryOf k) => (Ob (a :: j), Ob (b :: k)) => TerminalProfunctor a b
pattern TerminalProfunctor = TerminalProfunctor' Obj Obj

{-# COMPLETE TerminalProfunctor #-}

instance (CategoryOf j, CategoryOf k) => ThinProfunctor (TerminalProfunctor :: j +-> k)

instance (CategoryOf j, CategoryOf k) => DecidableProfunctor (TerminalProfunctor :: j +-> k) where
  type Holds TerminalProfunctor a b = TRU
  decide = Yes TerminalProfunctor
  toHolds TerminalProfunctor r = r