{-# LANGUAGE
PolyKinds
, RankNTypes
#-}
module Data.Quiver.Functor
( QFunctor (..)
, QPointed (..)
, QFoldable (..)
, QTraversable (..)
, QMonad (..)
) where
import Control.Category
import Data.Quiver
import Prelude hiding (id, (.))
class QFunctor c where
qmap :: (forall x y. p x y -> q x y) -> c p x y -> c q x y
instance QFunctor (ProductQ p) where qmap f (ProductQ p q) = ProductQ p (f q)
instance QFunctor (HomQ p) where qmap g (HomQ f) = HomQ (g . f)
instance Functor t => QFunctor (ApQ t) where qmap f (ApQ t) = ApQ (f <$> t)
instance QFunctor OpQ where qmap f = OpQ . f . getOpQ
instance QFunctor IsoQ where qmap f (IsoQ u d) = IsoQ (f u) (f d)
instance QFunctor IQ where qmap f = IQ . f . getIQ
instance QFunctor (ComposeQ p) where qmap f (ComposeQ p q) = ComposeQ p (f q)
instance QFunctor (LeftQ p) where qmap g (LeftQ f) = LeftQ (g . f)
instance QFunctor (RightQ p) where qmap g (RightQ f) = RightQ (g . f)
class QFunctor c => QPointed c where qsingle :: p x y -> c p x y
instance QPointed (HomQ p) where qsingle q = HomQ (const q)
instance Applicative t => QPointed (ApQ t) where qsingle = ApQ . pure
instance QPointed IQ where qsingle = IQ
instance Category p => QPointed (ComposeQ p) where qsingle = ComposeQ id
class QFunctor c => QFoldable c where
qfoldMap :: Category q => (forall x y. p x y -> q x y) -> c p x y -> q x y
qfold :: Category q => c q x y -> q x y
qfold = qfoldMap id
qfoldr :: (forall x y z . p x y -> q y z -> q x z) -> q y z -> c p x y -> q x z
qfoldr (?) q c = getRightQ (qfoldMap (\ x -> RightQ (\ y -> x ? y)) c) q
qfoldl :: (forall x y z . q x y -> p y z -> q x z) -> q x y -> c p y z -> q x z
qfoldl (?) q c = getLeftQ (qfoldMap (\ x -> LeftQ (\ y -> y ? x)) c) q
qtoMonoid :: Monoid m => (forall x y. p x y -> m) -> c p x y -> m
qtoMonoid f = getKQ . qfoldMap (KQ . f)
qtoList :: (forall x y. p x y -> a) -> c p x y -> [a]
qtoList f = qtoMonoid (pure . f)
qtraverse_
:: (Applicative m, Category q)
=> (forall x y. p x y -> m (q x y)) -> c p x y -> m (q x y)
qtraverse_ f = getApQ . qfoldMap (ApQ . f)
instance QFoldable (ProductQ p) where qfoldMap f (ProductQ _ q) = f q
instance QFoldable IQ where qfoldMap f (IQ c) = f c
class QFoldable c => QTraversable c where
qtraverse
:: Applicative m
=> (forall x y. p x y -> m (q x y)) -> c p x y -> m (c q x y)
instance QTraversable (ProductQ p) where
qtraverse f (ProductQ p q) = ProductQ p <$> f q
instance QTraversable IQ where qtraverse f (IQ c) = IQ <$> f c
class (QFunctor c, QPointed c) => QMonad c where
qjoin :: c (c p) x y -> c p x y
qjoin = qbind id
qbind :: (forall x y. p x y -> c q x y) -> c p x y -> c q x y
qbind f p = qjoin (qmap f p)
{-# MINIMAL qjoin | qbind #-}
instance QMonad (HomQ p) where
qjoin (HomQ q) = HomQ (\p -> getHomQ (q p) p)
instance Monad t => QMonad (ApQ t) where
qbind f (ApQ t) = ApQ $ do
p <- t
getApQ $ f p
instance QMonad IQ where qjoin = getIQ
instance Category p => QMonad (ComposeQ p) where
qjoin (ComposeQ yz (ComposeQ xy q)) = ComposeQ (yz . xy) q