{-# LANGUAGE
FlexibleInstances
, FunctionalDependencies
, GADTs
, PolyKinds
, QuantifiedConstraints
, RankNTypes
#-}
module Data.Quiver.Bifunctor
( QBifunctor (..)
, QProfunctor (..)
, QMonoidal (..)
, QClosed (..)
) where
import Data.Quiver
import Data.Quiver.Functor
class (forall q. QFunctor (prod q)) => QBifunctor prod where
qbimap
:: (forall x y. p x y -> p' x y)
-> (forall x y. q x y -> q' x y)
-> prod p q x y -> prod p' q' x y
instance QBifunctor ProductQ where
qbimap f g (ProductQ p q) = ProductQ (f p) (g q)
instance QBifunctor ComposeQ where
qbimap f g (ComposeQ p q) = ComposeQ (f p) (g q)
class (forall q. QFunctor (hom q)) => QProfunctor hom where
qdimap
:: (forall x y. p' x y -> p x y)
-> (forall x y. q x y -> q' x y)
-> hom p q x y -> hom p' q' x y
instance QProfunctor HomQ where qdimap f h (HomQ g) = HomQ (h . g . f)
instance QProfunctor LeftQ where qdimap f h (LeftQ g) = LeftQ (h . g . f)
instance QProfunctor RightQ where qdimap f h (RightQ g) = RightQ (h . g . f)
class QBifunctor prod => QMonoidal prod unit | prod -> unit where
qintro1 :: p x y -> prod unit p x y
qintro2 :: p x y -> prod p unit x y
qelim1 :: prod unit p x y -> p x y
qelim2 :: prod p unit x y -> p x y
qassoc :: prod (prod p q) r x y -> prod p (prod q r) x y
qdisassoc :: prod p (prod q r) x y -> prod (prod p q) r x y
instance QMonoidal ProductQ (KQ ()) where
qintro1 p = ProductQ (KQ ()) p
qintro2 p = ProductQ p (KQ ())
qelim1 (ProductQ _ p) = p
qelim2 (ProductQ p _) = p
qassoc (ProductQ (ProductQ p q) r) = ProductQ p (ProductQ q r)
qdisassoc (ProductQ p (ProductQ q r)) = ProductQ (ProductQ p q) r
instance QMonoidal ComposeQ (ReflQ ()) where
qintro1 p = ComposeQ (ReflQ ()) p
qintro2 p = ComposeQ p (ReflQ ())
qelim1 (ComposeQ (ReflQ ()) p) = p
qelim2 (ComposeQ p (ReflQ ())) = p
qassoc (ComposeQ (ComposeQ p q) r) = ComposeQ p (ComposeQ q r)
qdisassoc (ComposeQ p (ComposeQ q r)) = ComposeQ (ComposeQ p q) r
class (QBifunctor prod, QProfunctor lhom, QProfunctor rhom)
=> QClosed prod lhom rhom | prod -> lhom, prod -> rhom where
qlev :: prod (lhom p q) p x y -> q x y
qrev :: prod p (rhom p q) x y -> q x y
qcurry :: (forall x y. prod p q x y -> r x y) -> p x y -> lhom q r x y
quncurry :: (forall x y. p x y -> lhom q r x y) -> prod p q x y -> r x y
qflurry :: (forall x y. prod p q x y -> r x y) -> q x y -> rhom p r x y
qunflurry :: (forall x y. q x y -> rhom p r x y) -> prod p q x y -> r x y
instance QClosed ProductQ HomQ HomQ where
qlev (ProductQ (HomQ pq) p) = pq p
qrev (ProductQ p (HomQ pq)) = pq p
qcurry f p = HomQ (\q -> f (ProductQ p q))
quncurry f (ProductQ p q) = getHomQ (f p) q
qflurry f q = HomQ (\p -> f (ProductQ p q))
qunflurry f (ProductQ p q) = getHomQ (f q) p
instance QClosed ComposeQ LeftQ RightQ where
qlev (ComposeQ (LeftQ pq) p) = pq p
qrev (ComposeQ p (RightQ pq)) = pq p
qcurry f p = LeftQ (\q -> f (ComposeQ p q))
quncurry f (ComposeQ p q) = getLeftQ (f p) q
qflurry f q = RightQ (\p -> f (ComposeQ p q))
qunflurry f (ComposeQ p q) = getRightQ (f q) p