packages feed

FiniteCategories-0.6.5.1: src/Math/Categories/TotalOrder.hs

{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MonadComprehensions #-}
{-# LANGUAGE MultiParamTypeClasses #-}

{-| Module  : FiniteCategories
Description : Any total (or linear) order induces a preorder category where elements are objects, there is an arrow between two objects iff the relation is satisfied.
Copyright   : Guillaume Sabbagh 2022
License     : GPL-3
Maintainer  : guillaumesabbagh@protonmail.com
Stability   : experimental
Portability : portable

Any total (or linear) order induces a preorder category where elements are objects, there is an arrow between two objects iff the relation is satisfied.

(See Categories for the working mathematican. Saunders Mac Lane. p.11)
-}

module Math.Categories.TotalOrder
(
    IsSmallerThan(..),
    TotalOrder(..),
    
)
where
    import              Math.FiniteCategory
    import              Math.Category
    import              Math.Categories.FunctorCategory
    import              Math.Categories.ConeCategory
    import              Math.CompleteCategory
    import              Math.CocompleteCategory
    import              Math.FiniteCategories.Parallel
    import              Math.IO.PrettyPrint
    
    import qualified    Data.WeakSet          as Set
    import              Data.WeakSet.Safe
    import qualified    Data.WeakMap          as Map
    import              Data.WeakMap.Safe
    import              Data.Simplifiable
    
    import              GHC.Generics
    
    -- | 'IsSmallerThan' is the type of morphisms in a linear order, it reminds the fact that there is a morphism from a source to a target iff the source is smaller than the target.
    data IsSmallerThan a = IsSmallerThan a a deriving (Eq, Show, Generic, Simplifiable)
    
    instance (Eq a) => Morphism (IsSmallerThan a) a where
        (IsSmallerThan m1 t) @ (IsSmallerThan s m2) = IsSmallerThan s t
        source (IsSmallerThan s _) = s
        target (IsSmallerThan _ t) = t
    
    -- | A 'TotalOrder' category is the category induced by a total order.
    --
    -- (See Categories for the working mathematican. Saunders Mac Lane. p.11)
    data TotalOrder a = TotalOrder deriving (Eq, Show, Generic, PrettyPrint, Simplifiable)
    
    instance (Eq a, Ord a) => Category (TotalOrder a) (IsSmallerThan a) a where
        identity _ x = IsSmallerThan x x
        ar _ x y
            | x <= y = set [IsSmallerThan x y]
            | otherwise = set []
    
    instance (PrettyPrint a) => PrettyPrint (IsSmallerThan a) where
        pprint 0 (IsSmallerThan x y) = pprint 0 x ++ " <= " ++ pprint 0 y
        pprint v (IsSmallerThan x y) = pprint (v-1) x ++ " <= " ++ pprint (v-1) y
        
        -- pprintWithIndentations 0 ov indent (IsSmallerThan x y) = indentation ov indent ++ pprint 0 x++" <= "++pprint 0 y ++ "\n"
        -- pprintWithIndentations cv ov indent (IsSmallerThan x y) = indentation (ov - cv) indent ++ pprint (cv-1) x++" <= "++pprint (cv-1) y ++ "\n"
        
    instance (Ord a, Eq oIndex) => HasProducts (TotalOrder a) (IsSmallerThan a) a (TotalOrder a) (IsSmallerThan a) a oIndex where
        product diag = unsafeCone apexProduct nat
            where
                apexProduct = Set.minimum $ Map.values $ omap diag
                nat = unsafeNaturalTransformation (constantDiagram (src diag) TotalOrder apexProduct) diag $ Map.weakMapFromSet [(i,IsSmallerThan apexProduct (diag ->$ i)) | i <- ob $ src diag]
                
    instance (Ord a) => HasEqualizers (TotalOrder a) (IsSmallerThan a) a where
        equalize parallelDiag = unsafeCone apexEq nat
            where
                apexEq = parallelDiag ->$ ParallelA
                nat = unsafeNaturalTransformation (constantDiagram Parallel TotalOrder apexEq) parallelDiag (weakMap [(ParallelA, IsSmallerThan apexEq apexEq),(ParallelB, IsSmallerThan (parallelDiag ->$ ParallelB) (parallelDiag ->$ ParallelB))])
                
    instance (Ord a, Eq mIndex, Eq oIndex) => CompleteCategory (TotalOrder a) (IsSmallerThan a) a (TotalOrder a) (IsSmallerThan a) a cIndex mIndex oIndex where
        limit diag = unsafeCone apexProduct nat
            where
                apexProduct = Set.minimum $ Map.values $ omap diag
                nat = unsafeNaturalTransformation (constantDiagram (src diag) TotalOrder apexProduct) diag $ Map.weakMapFromSet [(i,IsSmallerThan apexProduct (diag ->$ i)) | i <- ob $ src diag]
                
        projectBase diag = Diagram{src = tgt diag, tgt = tgt diag, omap = memorizeFunction id (Map.values (omap diag)), mmap = memorizeFunction id (Map.values (mmap diag))}
                
    instance (Ord a, Eq oIndex) => HasCoproducts (TotalOrder a) (IsSmallerThan a) a (TotalOrder a) (IsSmallerThan a) a oIndex where
        coproduct diag = unsafeCocone nadirCoproduct nat
            where
                nadirCoproduct = Set.maximum $ Map.values $ omap diag
                nat = unsafeNaturalTransformation diag (constantDiagram (src diag) TotalOrder nadirCoproduct) $ Map.weakMapFromSet [(i,IsSmallerThan (diag ->$ i) nadirCoproduct) | i <- ob $ src diag]
                
    instance (Ord a) => HasCoequalizers (TotalOrder a) (IsSmallerThan a) a where
        coequalize parallelDiag = unsafeCocone nadirCoeq nat
            where
                nadirCoeq = parallelDiag ->$ ParallelB
                nat = unsafeNaturalTransformation parallelDiag (constantDiagram Parallel TotalOrder nadirCoeq) (weakMap [(ParallelA, IsSmallerThan (parallelDiag ->$ ParallelA) (parallelDiag ->$ ParallelA)),(ParallelB, IsSmallerThan nadirCoeq nadirCoeq)])
                
    instance (Ord a, Eq mIndex, Eq oIndex) => CocompleteCategory (TotalOrder a) (IsSmallerThan a) a (TotalOrder a) (IsSmallerThan a) a cIndex mIndex oIndex where
        colimit diag = unsafeCocone nadirColimit nat
            where
                nadirColimit = Set.maximum $ Map.values $ omap diag
                nat = unsafeNaturalTransformation diag (constantDiagram (src diag) TotalOrder nadirColimit) $ Map.weakMapFromSet [(i,IsSmallerThan (diag ->$ i) nadirColimit) | i <- ob $ src diag]
                
        coprojectBase diag = Diagram{src = tgt diag, tgt = tgt diag, omap = memorizeFunction id (Map.values (omap diag)), mmap = memorizeFunction id (Map.values (mmap diag))}