packages feed

FiniteCategories-0.2.0.0: src/Math/Categories/FinSet.hs

{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}

{-| Module  : FiniteCategories
Description : The __'FinSet'__ category has finite sets as objects and functions as morphisms.
Copyright   : Guillaume Sabbagh 2022
License     : GPL-3
Maintainer  : guillaumesabbagh@protonmail.com
Stability   : experimental
Portability : portable

The __'FinSet'__ category has finite sets as objects and functions as morphisms.

Finite sets are represented by weak sets from Data.WeakSet and functions by enriched weak maps from Data.WeakMap.

These structures are homogeneous, meaning you can only have sets containing one type of objects in a given 'FinSet' category.

See the category __'PureSet'__ for the category of sets which can be arbitrarily nested.
-}

module Math.Categories.FinSet
(
    -- * Function
    Function(..),
    (||!||),
    -- * __FinSet__
    FinSet(..),
)
where
    import              Math.Category
    import              Math.Categories.ConeCategory
    import              Math.Categories.FunctorCategory
    import              Math.FiniteCategories.DiscreteCategory
    import              Math.IO.PrettyPrint
    
    import              Data.WeakSet        (Set)
    import qualified    Data.WeakSet    as  Set
    import              Data.WeakSet.Safe
    import              Data.WeakMap        (Map)
    import qualified    Data.WeakMap    as  Map
    import              Data.WeakMap.Safe
    import              Data.List           (nub)
    import              Data.Maybe          (fromJust)

    
    -- | A 'Function' (finite function) is a weak map enriched with a codomain.
    --
    -- We have to store the codomain to retrieve the target set of a morphism in __'FinSet'__.
    data Function a = Function 
                            {
                                function :: Map a a,
                                codomain :: Set a
                            }
                        deriving
                            (Eq, Show)
    
    instance (Eq a) => Morphism (Function a) (Set a) where
        source = domain.function
        target = codomain
        (@?) f2 f1
            | target f1 == source f2 = Just Function{function = (function f2) |.| (function f1), codomain = codomain f2}
            | otherwise = Nothing
            
    -- | A function to apply a 'Function' to an object in the domain of the 'Function'.
    (||!||) :: (Eq a) => Function a -> a -> a
    (||!||) f x = (function f) |!| x
    
    -- | __'FinSet'__ is the category of finite sets.
    data FinSet a = FinSet deriving (Eq, Show)
    
    instance (Eq a) => Category (FinSet a) (Function a) (Set a) where
        identity _ s = Function {function = idFromSet s, codomain = s}
        
        ar _ s t
            | Set.null s = set [Function{function = weakMap [], codomain = t}]
            | Set.null t = set []
            | otherwise = (\x -> Function{function = x, codomain = t}) <$> functions where
                domain = setToList s
                images = (t |^| (length domain))
                functions = weakMap <$> zip domain <$> images
                
    -- instance (Eq a) => HasFiniteProducts (FinSet a) (Set a) (Function [a]) (Set [a]) where
        -- product _ diag2 = result
            -- where
                -- prod = cartesianProductOfSets (elems (omap diag2))
                -- diag1 = constantDiagram (source diag2) FinSet prod
                -- mapping i = memorizeFunction (\_ -> (!! i) <$> prod) prod
                -- Just result = naturalTransformationToCone $ unsafeNaturalTransformation diag1 diag2 (weakMap [(i,Function {function=mapping i, codomain = image (mapping i)}) | i <- [0..((Map.size (omap diag2))-1)]])
       
    instance (PrettyPrint a, Eq a) => PrettyPrint (Function a) where
        pprint = pprint.function
        
    instance (PrettyPrint a, Eq a) => PrettyPrint (FinSet a) where
        pprint = show