proarrow-0.1.0.0: src/Proarrow/Profunctor/Instance/Cocone.hs
-- | A 'Cocone' is a list of arrows sharing a single target (the coapex), as a profunctor from lists of
-- objects to objects; a 'Sink' is a cocone with the coapex hidden existentially.
module Proarrow.Profunctor.Instance.Cocone where
import Proarrow.Category.Monoidal (MonoidalProfunctor (..))
import Proarrow.Colimit.BinaryCoproduct (COPROD (..), Coprod (..), HasBinaryCoproducts (..), HasCoproducts)
import Proarrow.Core (CategoryOf (..), Profunctor (..), Promonad (..), UN, rmap, type (+->))
import Proarrow.Profunctor.Instance.List (LIST (..), List (..))
-- | A cocone is a bunch of arrows with a shared target.
data Cocone (bs :: LIST k) (a :: COPROD k) where
Coapex :: (Ob a) => Cocone (L '[]) (COPR a)
Coleg :: b ~> a -> Cocone (L bs) (COPR a) -> Cocone (L (b : bs)) (COPR a)
instance (CategoryOf k) => Profunctor (Cocone :: COPROD k +-> LIST k) where
dimap Nil r Coapex = Coapex \\ r
dimap (Cons l ls) r@(Coprod r') (Coleg f fs) = Coleg (r' . f . l) (dimap ls r fs)
r \\ Coapex = r
r \\ Coleg l Coapex = r \\ l
r \\ Coleg l c@(Coleg _ c1) = r \\ l \\ c \\ c1
instance (HasCoproducts k) => MonoidalProfunctor (Cocone :: COPROD k +-> LIST k) where
one = Coapex
Coapex @l ** rs = rmap (Coprod (rgt @_ @l)) rs \\ rs
Coleg l ls ** (rs :: Cocone rs r) = Coleg (lft @_ @_ @(UN COPR r) . l) (ls ** rs) \\ l \\ rs
-- | A sink is a cocone, but with the apex type hidden by an existential.
data Sink (as :: [k]) where
Cocone :: Cocone (L as) (COPR a) -> Sink as