packages feed

proarrow-0.1.0.0: src/Proarrow/Category/Monoidal/Rev.hs

-- | The reversed monoidal category: 'REV' wraps a kind so that @'R' a '**' 'R' b = 'R' (b ** a)@,
-- swapping the tensor's arguments while keeping the same objects and morphisms.
module Proarrow.Category.Monoidal.Rev where

import Proarrow.Category.Monoidal (Monoidal (..), MonoidalProfunctor (..), SymMonoidal (..))
import Proarrow.Category.Monoidal.CopyDiscard (CopyDiscard (..))
import Proarrow.Core (CategoryOf (..), Profunctor (..), Promonad (..), WrappedOb, type (+->))
import Proarrow.Monoid (CocommutativeComonoid, Comonoid (..), Monoid (..))

type data REV k = R k

-- | Wraps a profunctor between the 'REV'-wrapped kinds: the same values, but the monoidal
-- structure on 'REV' tensors in reverse order.
type Rev :: j +-> k -> REV j +-> REV k
data Rev p a b where
  Rev :: p a b -> Rev p (R a) (R b)

instance (Profunctor p) => Profunctor (Rev p) where
  dimap (Rev l) (Rev r) (Rev p) = Rev (dimap l r p)
  r \\ Rev p = r \\ p

instance (Promonad p) => Promonad (Rev p) where
  id = Rev id
  Rev f . Rev g = Rev (f . g)

-- | The reverse of the category of @k@, i.e. with the tensor flipped.
instance (CategoryOf k) => CategoryOf (REV k) where
  type (~>) = Rev (~>)
  type Ob a = WrappedOb R a

instance (MonoidalProfunctor p) => MonoidalProfunctor (Rev p) where
  one = Rev one
  Rev f ** Rev g = Rev (g ** f)

-- | The flipped tensor.
instance (Monoidal k) => Monoidal (REV k) where
  type Unit = R Unit
  type R a ** R b = R (b ** a)
  withOb2 @(R a) @(R b) r = withOb2 @k @b @a r
  leftUnitor = Rev rightUnitor
  leftUnitorInv = Rev rightUnitorInv
  rightUnitor = Rev leftUnitor
  rightUnitorInv = Rev leftUnitorInv
  associator @(R a) @(R b) @(R c) = Rev (associatorInv @k @c @b @a)
  associatorInv @(R a) @(R b) @(R c) = Rev (associator @k @c @b @a)

instance (SymMonoidal k) => SymMonoidal (REV k) where
  swap @(R a) @(R b) = Rev (swap @k @b @a)

instance (Monoid a) => Monoid (R a) where
  mempty = Rev mempty
  mappend = Rev mappend

instance (Comonoid a) => Comonoid (R a) where
  counit = Rev counit
  comult = Rev comult
instance (CocommutativeComonoid a) => CocommutativeComonoid (R a)

instance (CopyDiscard k) => CopyDiscard (REV k) where
  copy = Rev copy
  discard = Rev discard