packages feed

FiniteCategories-0.1.0.0: src/Adjunction/Adjunction.hs

{-# LANGUAGE MultiParamTypeClasses  #-}
{-| Module  : FiniteCategories
Description : Adjoint functors.
Copyright   : Guillaume Sabbagh 2021
License     : GPL-3
Maintainer  : guillaumesabbagh@protonmail.com
Stability   : experimental
Portability : portable

Adjunctions are all over the place in mathematics.
-}

module Adjunction.Adjunction 
(
    leftAdjoint,
    rightAdjoint,
)
where
    import              FiniteCategory.FiniteCategory
    import              Diagram.Diagram
    import              CommaCategory.CommaCategory
    import              Data.Maybe                          (fromJust)
    import              Utils.AssociationList
    
    -- | Returns the left adjoint of a functor, if the left adjoint does not exist, returns a partial Diagram being the best ajoint we could construct.
    leftAdjoint :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1,
                     FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2) =>
                     Diagram c1 m1 o1 c2 m2 o2 -> Diagram c2 m2 o2 c1 m1 o1
    leftAdjoint g = Diagram {
                        src = tgt g,
                        tgt = src g,
                        omap = [(y, indexTgt.head.universalMorphisms $ y) | y <- ob (tgt g), not (null (universalMorphisms y))],
                        mmap = [(m, head (binding m)) | m <- arrows (tgt g), not (null (binding m))]
                    }
        where
            universalMorphisms y = initialObjects (CommaCategory {rightDiag = g, leftDiag = fromJust (mkSelect1 (tgt g) y)})
            binding m = [a | a <- arrows (src g), (not (null (universalMorphisms (source m)))) && (not (null (universalMorphisms (target m)))) && ((target ((mmap g) !-! a)) == (source (arrow.head.universalMorphisms $ target m))) && (((arrow.head.universalMorphisms $ target m) @ m) == ((mmap g) !-! a) @ (arrow.head.universalMorphisms $ source m))]
    
    -- | Returns the right adjoint of a functor, if the right adjoint does not exist, returns a partial Diagram being the best ajoint we could construct.
    rightAdjoint :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1,
                     FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2) =>
                     Diagram c2 m2 o2 c1 m1 o1 -> Diagram c1 m1 o1 c2 m2 o2
    rightAdjoint f = Diagram {
                        src = tgt f,
                        tgt = src f,
                        omap = [(x, indexSrc.head.universalMorphisms $ x) | x <- ob (tgt f), not (null (universalMorphisms x))],
                        mmap = [(m, head (binding m)) | m <- arrows (tgt f), (not (null (universalMorphisms (source m)))) && (not (null (universalMorphisms (target m)))) && not (null (binding m))]
                    }
        where
            universalMorphisms x = terminalObjects (CommaCategory {leftDiag = f, rightDiag = fromJust (mkSelect1 (tgt f) x)})
            binding m = [a | a <- ar (src f) (indexSrc.head.universalMorphisms $ (source m)) (indexSrc.head.universalMorphisms $ (target m)), ((arrow.head.universalMorphisms $ target m) @ ((mmap f) !-! a)) == (m @ (arrow.head.universalMorphisms $ source m))]