monoidal-functors-0.1.0.0: src/Data/Bifunctor/Monoidal.hs
module Data.Bifunctor.Monoidal where
import Prelude hiding ((.), id)
import Control.Applicative
import Control.Category
import Control.Category.Tensor
import Data.Biapplicative
import Data.Bifunctor.Clown
import Data.Bifunctor.Joker
import Data.Profunctor
import Data.Semigroupoid
import Data.These
import Data.Void
class (Associative t1 cat, Associative t2 cat, Associative to cat) => Semigroupal cat t1 t2 to f where
combine :: cat (to (f x y) (f x' y')) (f (t1 x x') (t2 y y'))
instance Profunctor p => Semigroupal (->) (,) Either Either p where
combine :: Either (p x y) (p x' y') -> p (x, x') (Either y y')
combine = either (dimap fst Left) (dimap snd Right)
instance Semigroupal (->) (,) (,) (,) (,) where
combine :: ((x, y), (x', y')) -> ((x, x'), (y, y'))
combine ((x, y), (x', y')) = ((x, x'), (y, y'))
-- NOTE: This version could be used for a more general abstraction
-- of products in a category:
-- combine =
-- let fwd' = fwd assoc
-- bwd' = bwd assoc
-- in second swap . swap . fwd' . swap . first (bwd' . first swap) . fwd'
instance Semigroupal (->) Either Either Either (,) where
combine :: Either (x, y) (x', y') -> (Either x x', Either y y')
combine = either (bimap Left Left) (bimap Right Right)
instance Semigroupal (->) Either Either Either Either where
combine :: Either (Either x y) (Either x' y') -> Either (Either x x') (Either y y')
combine = either (bimap Left Left) (bimap Right Right)
instance Semigroupal (->) Either (,) (,) Either where
combine :: (Either x y, Either x' y') -> Either (Either x x') (y, y')
combine = \case
(Left x, Left _) -> Left $ Left x
(Left x, Right _) -> Left $ Left x
(Right _, Left x') -> Left $ Right x'
(Right y, Right y') -> Right (y, y')
instance Semigroupal (->) These (,) (,) Either where
combine :: (Either x y, Either x' y') -> Either (These x x') (y, y')
combine = \case
(Left x, Left x') -> Left $ These x x'
(Left x, Right _) -> Left $ This x
(Right _, Left x') -> Left $ That x'
(Right y, Right y') -> Right (y, y')
instance Semigroupal (->) (,) (,) (,) (->) where
combine :: (x -> y, x' -> y') -> (x, x') -> (y, y')
combine fs = uncurry bimap fs
instance Semigroupal (->) Either Either (,) (->) where
combine :: (x -> y, x' -> y') -> Either x x' -> Either y y'
combine fs = either (Left . fst fs) (Right . snd fs)
instance Applicative f => Semigroupal (->) (,) (,) (,) (Joker f) where
combine :: (Joker f x y, Joker f x' y') -> Joker f (x, x') (y, y')
combine = uncurry $ biliftA2 (,) (,)
instance Alternative f => Semigroupal (->) Either Either (,) (Joker f) where
combine :: (Joker f x y, Joker f x' y') -> Joker f (Either x x') (Either y y')
combine = uncurry $ biliftA2 (\_ x' -> Right x') (\_ y' -> Right y')
instance Functor f => Semigroupal (->) Either Either Either (Joker f) where
combine :: Either (Joker f x y) (Joker f x' y') -> Joker f (Either x x') (Either y y')
combine = either (Joker . fmap Left . runJoker ) (Joker . fmap Right . runJoker)
instance Applicative f => Semigroupal (->) (,) (,) (,) (Clown f) where
combine :: (Clown f x y, Clown f x' y') -> Clown f (x, x') (y, y')
combine = uncurry $ biliftA2 (,) (,)
instance Alternative f => Semigroupal (->) Either Either (,) (Clown f) where
combine :: (Clown f x y, Clown f x' y') -> Clown f (Either x x') (Either y y')
combine = uncurry $ biliftA2 (\_ x' -> Right x') (\_ y' -> Right y')
instance Applicative f => Semigroupal (->) (,) (,) (,) (Star f) where
combine :: (Star f x y, Star f x' y') -> Star f (x, x') (y, y')
combine (Star fxy, Star fxy') = Star $ \(x, x') -> liftA2 (,) (fxy x) (fxy' x')
instance Functor f => Semigroupal (->) Either Either (,) (Star f) where
combine :: (Star f x y, Star f x' y') -> Star f (Either x x') (Either y y')
combine (Star fxy, Star fxy') = Star $ either (fmap Left . fxy) (fmap Right . fxy')
instance Alternative f => Semigroupal (->) Either Either Either (Star f) where
combine :: Either (Star f x y) (Star f x' y') -> Star f (Either x x') (Either y y')
combine = \case
Left (Star fxy) -> Star $ either (fmap Left . fxy) (const empty)
Right (Star fxy') -> Star $ either (const empty) (fmap Right . fxy')
instance Alternative f => Semigroupal (->) (,) Either (,) (Star f) where
combine :: (Star f x y, Star f x' y') -> Star f (x, x') (Either y y')
combine (Star f, Star g) = Star $ \(x, x') -> (Left <$> f x) <|> (Right <$> g x')
instance Alternative f => Semigroupal (->) (,) (,) (,) (Forget (f r)) where
combine :: (Forget (f r) x y, Forget (f r) x' y') -> Forget (f r) (x, x') (y, y')
combine (Forget f, Forget g) = Forget $ \(x, x') -> f x <|> g x'
instance Semigroupal (->) Either Either (,) (Forget (f r)) where
combine :: (Forget (f r) x y, Forget (f r) x' y') -> Forget (f r) (Either x x') (Either y y')
combine (Forget f, Forget g) = Forget $ either f g
instance Alternative f => Semigroupal (->) Either Either Either (Forget (f r)) where
combine :: Either (Forget (f r) x y) (Forget (f r) x' y') -> Forget (f r) (Either x x') (Either y y')
combine = \case
Left (Forget f) -> Forget $ either f (const empty)
Right (Forget g) -> Forget $ either (const empty) g
instance Alternative f => Semigroupal (->) (,) Either (,) (Forget (f r)) where
combine :: (Forget (f r) x y, Forget (f r) x' y') -> Forget (f r) (x, x') (Either y y')
combine (Forget f, Forget g) = Forget $ \(x, x') -> f x <|> g x'
class Unital cat i1 i2 io f where
introduce :: cat io (f i1 i2)
instance (Profunctor p, Category p) => Unital (->) () () () (StrongCategory p) where
introduce :: () -> StrongCategory p () ()
introduce () = StrongCategory id
instance Unital (->) () () () (,) where
introduce :: () -> ((), ())
introduce = dup
instance Unital (->) Void Void Void (,) where
introduce :: Void -> (Void, Void)
introduce = absurd
instance Unital (->) Void Void Void Either where
introduce :: Void -> Either Void Void
introduce = bwd runit
instance Unital (->) Void () () Either where
introduce :: () -> Either Void ()
introduce = Right
instance Unital (->) () () () (->) where
introduce :: () -> () -> ()
introduce () () = ()
instance Unital (->) Void Void Void (->) where
introduce :: Void -> Void -> Void
introduce = absurd
instance (Unital (->) Void Void () (->)) where
introduce :: () -> Void -> Void
introduce () = absurd
instance Applicative f => Unital (->) () () () (Joker f) where
introduce :: () -> Joker f () ()
introduce = Joker . pure
instance Alternative f => Unital (->) Void Void () (Joker f) where
introduce :: () -> Joker f Void Void
introduce () = Joker empty
instance Unital (->) Void Void Void (Joker f) where
introduce :: Void -> Joker f Void Void
introduce = absurd
instance Applicative f => Unital (->) () () () (Star f) where
introduce :: () -> Star f () ()
introduce () = Star pure
instance Unital (->) Void Void () (Star f) where
introduce :: () -> Star f Void Void
introduce () = Star absurd
instance Alternative f => Unital (->) Void Void Void (Star f) where
introduce :: Void -> Star f Void Void
introduce = absurd
instance Alternative f => Unital (->) () Void () (Star f) where
introduce :: () -> Star f () Void
introduce () = Star $ const empty
class (Tensor t1 i1 cat
, Tensor t2 i2 cat
, Tensor to io cat
, Semigroupal cat t1 t2 to f
, Unital cat i1 i2 io f
) => Monoidal cat t1 i1 t2 i2 to io f
instance (Strong p, Semigroupoid p, Category p) => Monoidal (->) (,) () (,) () (,) () (StrongCategory p)
instance Monoidal (->) (,) () (,) () (,) () (,)
instance Monoidal (->) Either Void Either Void Either Void (,)
instance Monoidal (->) Either Void Either Void Either Void Either
instance Monoidal (->) Either Void (,) () (,) () Either
instance Monoidal (->) These Void (,) () (,) () Either
instance Monoidal (->) (,) () (,) () (,) () (->)
instance Monoidal (->) Either Void Either Void (,) () (->)
instance Applicative f => Monoidal (->) (,) () (,) () (,) () (Joker f)
instance Alternative f => Monoidal (->) Either Void Either Void (,) () (Joker f)
instance Functor f => Monoidal (->) Either Void Either Void Either Void (Joker f)
instance Applicative f => Monoidal (->) (,) () (,) () (,) () (Star f)
instance Functor f => Monoidal (->) Either Void Either Void (,) () (Star f)
instance Alternative f => Monoidal (->) Either Void Either Void Either Void (Star f)
instance Alternative f => Monoidal (->) (,) () Either Void (,) () (Star f)
newtype StrongCategory p a b = StrongCategory (p a b)
deriving (Functor, Applicative, Monad, Profunctor, Category)
instance Semigroupoid p => Semigroupoid (StrongCategory p) where
o :: StrongCategory p b c -> StrongCategory p a b -> StrongCategory p a c
o (StrongCategory f) (StrongCategory g) = StrongCategory (f `o` g)
instance (Strong p, Semigroupoid p) => Semigroupal (->) (,) (,) (,) (StrongCategory p) where
combine :: (StrongCategory p x y, StrongCategory p x' y') -> StrongCategory p (x, x') (y, y')
combine (StrongCategory pxy, StrongCategory pxy') = StrongCategory $ first' pxy `o` second' pxy'