data-category-0.11: Data/Category/Enriched.hs
{-# LANGUAGE
TypeOperators
, TypeFamilies
, GADTs
, RankNTypes
, PatternSynonyms
, FlexibleContexts
, FlexibleInstances
, NoImplicitPrelude
, UndecidableInstances
, ScopedTypeVariables
, ConstraintKinds
, MultiParamTypeClasses
#-}
-----------------------------------------------------------------------------
-- |
-- Module : Data.Category.Enriched
-- License : BSD-style (see the file LICENSE)
--
-- Maintainer : sjoerd@w3future.com
-- Stability : experimental
-- Portability : non-portable
-----------------------------------------------------------------------------
module Data.Category.Enriched where
import Data.Kind (Type)
import Data.Category (Category(..), Obj, Op(..))
import Data.Category.Product
import Data.Category.Functor (Functor(..), Hom(..))
import Data.Category.Limit (HasBinaryProducts(..), HasTerminalObject(..))
import Data.Category.CartesianClosed (CartesianClosed(..), ExpFunctor(..), curry, uncurry)
-- | An enriched category
class CartesianClosed (V k) => ECategory (k :: Type -> Type -> Type) where
-- | The category V which k is enriched in
type V k :: Type -> Type -> Type
-- | The hom object in V from a to b
type k $ ab :: Type
hom :: Obj k a -> Obj k b -> Obj (V k) (k $ (a, b))
id :: Obj k a -> Arr k a a
comp :: Obj k a -> Obj k b -> Obj k c -> V k (BinaryProduct (V k) (k $ (b, c)) (k $ (a, b))) (k $ (a, c))
-- | Arrows as elements of @k@
type Arr k a b = V k (TerminalObject (V k)) (k $ (a, b))
compArr :: ECategory k => Obj k a -> Obj k b -> Obj k c -> Arr k b c -> Arr k a b -> Arr k a c
compArr a b c f g = comp a b c . (f &&& g)
data Underlying k a b = Underlying (Obj k a) (Arr k a b) (Obj k b)
-- | The underlying category of an enriched category
instance ECategory k => Category (Underlying k) where
src (Underlying a _ _) = Underlying a (id a) a
tgt (Underlying _ _ b) = Underlying b (id b) b
Underlying b f c . Underlying a g _ = Underlying a (compArr a b c f g) c
newtype EOp k a b = EOp (k b a)
-- | The opposite of an enriched category
instance ECategory k => ECategory (EOp k) where
type V (EOp k) = V k
type EOp k $ (a, b) = k $ (b, a)
hom (EOp a) (EOp b) = hom b a
id (EOp a) = id a
comp (EOp a) (EOp b) (EOp c) = comp c b a . (proj2 (hom c b) (hom b a) &&& proj1 (hom c b) (hom b a))
data (:<>:) :: (Type -> Type -> Type) -> (Type -> Type -> Type) -> Type -> Type -> Type where
(:<>:) :: (V k1 ~ V k2) => Obj k1 a1 -> Obj k2 a2 -> (:<>:) k1 k2 (a1, a2) (a1, a2)
-- | The enriched product category of enriched categories @c1@ and @c2@.
instance (ECategory k1, ECategory k2, V k1 ~ V k2) => ECategory (k1 :<>: k2) where
type V (k1 :<>: k2) = V k1
type (k1 :<>: k2) $ ((a1, a2), (b1, b2)) = BinaryProduct (V k1) (k1 $ (a1, b1)) (k2 $ (a2, b2))
hom (a1 :<>: a2) (b1 :<>: b2) = hom a1 b1 *** hom a2 b2
id (a1 :<>: a2) = id a1 &&& id a2
comp (a1 :<>: a2) (b1 :<>: b2) (c1 :<>: c2) =
comp a1 b1 c1 . (proj1 bc1 bc2 . proj1 l r &&& proj1 ab1 ab2 . proj2 l r) &&&
comp a2 b2 c2 . (proj2 bc1 bc2 . proj1 l r &&& proj2 ab1 ab2 . proj2 l r)
where
ab1 = hom a1 b1
ab2 = hom a2 b2
bc1 = hom b1 c1
bc2 = hom b2 c2
l = bc1 *** bc2
r = ab1 *** ab2
newtype Self v a b = Self { getSelf :: v a b }
-- | Self enrichment
instance CartesianClosed v => ECategory (Self v) where
type V (Self v) = v
type Self v $ (a, b) = Exponential v a b
hom (Self a) (Self b) = ExpFunctor % (Op a :**: b)
id (Self a) = toSelf a
comp (Self a) (Self b) (Self c) = curry (bc *** ab) a c (apply b c . (proj1 bc ab *** apply a b) . shuffle)
where
bc = c ^^^ b
ab = b ^^^ a
shuffle = proj1 (bc *** ab) a &&& (proj2 bc ab *** a)
toSelf :: CartesianClosed v => v a b -> Arr (Self v) a b
toSelf v = curry terminalObject (src v) (tgt v) (v . proj2 terminalObject (src v))
fromSelf :: forall v a b. CartesianClosed v => Obj v a -> Obj v b -> Arr (Self v) a b -> v a b
fromSelf a b arr = uncurry terminalObject a b arr . (terminate a &&& a)
newtype InHask k a b = InHask (k a b)
-- | Any regular category is enriched in (->), aka Hask
instance Category k => ECategory (InHask k) where
type V (InHask k) = (->)
type InHask k $ (a, b) = k a b
hom (InHask a) (InHask b) = Hom % (Op a :**: b)
id (InHask f) () = f
comp _ _ _ (f, g) = f . g