{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies  #-}
module Math.Category
(
    
    Morphism(..),
    
    compose,
    
    Category(..),
    arWithoutId,
    
    isIdentity,
    isNotIdentity,
    isIso,
    isSection,
    isRetraction,
    areIsomorphic,
    
    genArWithoutId,
    isGenerator,
    isComposite,
    
    findInverse,
    findIsomorphism,
    findRightInverses,
    findLeftInverses,
)
where
    import              Data.WeakSet             (Set)
    import qualified    Data.WeakSet           as Set
    import              Data.WeakSet.Safe
    
    
    
    
    
    
    
    
    class Morphism m o | m -> o where        
        
        
        
        
        
        
        
        (@) :: m -> m -> m
        
        
        
        
        
        
        
        (@?) :: (Eq o) => m -> m -> Maybe m
        (@?) m
g m
f
            | m -> o
forall m o. Morphism m o => m -> o
source m
g o -> o -> Bool
forall a. Eq a => a -> a -> Bool
== m -> o
forall m o. Morphism m o => m -> o
target m
f = m -> Maybe m
forall a. a -> Maybe a
Just (m -> Maybe m) -> m -> Maybe m
forall a b. (a -> b) -> a -> b
$ m
g m -> m -> m
forall m o. Morphism m o => m -> m -> m
@ m
g
            | Bool
otherwise = Maybe m
forall a. Maybe a
Nothing
        
        
        source :: m -> o
        
        
        target :: m -> o
    
    
    
    
    
    
    
    compose :: (Morphism m o) => [m] -> m
    compose :: forall m o. Morphism m o => [m] -> m
compose [] = [Char] -> m
forall a. HasCallStack => [Char] -> a
error [Char]
"Category.compose: empty list to compose"
    compose [m]
l = (m -> m -> m) -> [m] -> m
forall a. (a -> a -> a) -> [a] -> a
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 m -> m -> m
forall m o. Morphism m o => m -> m -> m
(@) [m]
l
        
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    class Category c m o | c -> m, m -> o where
        
        
        
        
        
        
        identity :: (Morphism m o) => c -> o -> m
        
        
        
        
        ar :: (Morphism m o) => c 
            -> o 
            -> o 
            -> Set m 
            
        
            
        
        
        
        
        
        genAr :: (Morphism m o) => c -> o -> o -> Set m
        genAr = c -> o -> o -> Set m
forall c m o.
(Category c m o, Morphism m o) =>
c -> o -> o -> Set m
ar
        
        
        
        
        
        
        
        
        decompose :: (Morphism m o) => c -> m -> [m]
        decompose c
_ = (m -> [m] -> [m]
forall a. a -> [a] -> [a]
:[])
      
    
    arWithoutId :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> o -> o -> Set m
    arWithoutId :: forall c m o.
(Category c m o, Morphism m o, Eq m, Eq o) =>
c -> o -> o -> Set m
arWithoutId c
c o
s o
t = (m -> Bool) -> Set m -> Set m
forall a. (a -> Bool) -> Set a -> Set a
Set.filter (c -> m -> Bool
forall c m o.
(Category c m o, Morphism m o, Eq m, Eq o) =>
c -> m -> Bool
isNotIdentity c
c) (Set m -> Set m) -> Set m -> Set m
forall a b. (a -> b) -> a -> b
$ c -> o -> o -> Set m
forall c m o.
(Category c m o, Morphism m o) =>
c -> o -> o -> Set m
ar c
c o
s o
t
      
    
    genArWithoutId :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> o -> o -> Set m
    genArWithoutId :: forall c m o.
(Category c m o, Morphism m o, Eq m, Eq o) =>
c -> o -> o -> Set m
genArWithoutId c
c o
s o
t = (m -> Bool) -> Set m -> Set m
forall a. (a -> Bool) -> Set a -> Set a
Set.filter (c -> m -> Bool
forall c m o.
(Category c m o, Morphism m o, Eq m, Eq o) =>
c -> m -> Bool
isNotIdentity c
c) (Set m -> Set m) -> Set m -> Set m
forall a b. (a -> b) -> a -> b
$ c -> o -> o -> Set m
forall c m o.
(Category c m o, Morphism m o) =>
c -> o -> o -> Set m
genAr c
c o
s o
t
            
    
    isIdentity :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> m -> Bool
    isIdentity :: forall c m o.
(Category c m o, Morphism m o, Eq m, Eq o) =>
c -> m -> Bool
isIdentity c
c m
m = c -> o -> m
forall c m o. (Category c m o, Morphism m o) => c -> o -> m
identity c
c (m -> o
forall m o. Morphism m o => m -> o
source m
m) m -> m -> Bool
forall a. Eq a => a -> a -> Bool
== m
m
    
    
    isNotIdentity :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> m -> Bool
    isNotIdentity :: forall c m o.
(Category c m o, Morphism m o, Eq m, Eq o) =>
c -> m -> Bool
isNotIdentity c
c m
m = Bool -> Bool
not (c -> m -> Bool
forall c m o.
(Category c m o, Morphism m o, Eq m, Eq o) =>
c -> m -> Bool
isIdentity c
c m
m)
    
    findInverse :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> m -> Maybe m
    findInverse :: forall c m o.
(Category c m o, Morphism m o, Eq m, Eq o) =>
c -> m -> Maybe m
findInverse c
c m
m = (forall a. Set a -> Maybe a
Set.setToMaybe) (Set m -> Maybe m) -> Set m -> Maybe m
forall a b. (a -> b) -> a -> b
$ (m -> Bool) -> Set m -> Set m
forall a. (a -> Bool) -> Set a -> Set a
Set.filter (\m
f -> c -> m -> Bool
forall c m o.
(Category c m o, Morphism m o, Eq m, Eq o) =>
c -> m -> Bool
isIdentity c
c (m
m m -> m -> m
forall m o. Morphism m o => m -> m -> m
@ m
f) Bool -> Bool -> Bool
&& c -> m -> Bool
forall c m o.
(Category c m o, Morphism m o, Eq m, Eq o) =>
c -> m -> Bool
isIdentity c
c (m
f m -> m -> m
forall m o. Morphism m o => m -> m -> m
@ m
m)) (c -> o -> o -> Set m
forall c m o.
(Category c m o, Morphism m o) =>
c -> o -> o -> Set m
ar c
c (m -> o
forall m o. Morphism m o => m -> o
target m
m) (m -> o
forall m o. Morphism m o => m -> o
source m
m))
    
    
    findIsomorphism :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> o -> o -> Maybe m
    findIsomorphism :: forall c m o.
(Category c m o, Morphism m o, Eq m, Eq o) =>
c -> o -> o -> Maybe m
findIsomorphism c
c o
s o
t = (Set m -> Maybe m
forall a. Set a -> Maybe a
Set.setToMaybe)(Set m -> Maybe m)
-> (Set (Maybe m) -> Set m) -> Set (Maybe m) -> Maybe m
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Set (Maybe m) -> Set m
forall a. Set (Maybe a) -> Set a
Set.catMaybes) (Set (Maybe m) -> Maybe m) -> Set (Maybe m) -> Maybe m
forall a b. (a -> b) -> a -> b
$ c -> m -> Maybe m
forall c m o.
(Category c m o, Morphism m o, Eq m, Eq o) =>
c -> m -> Maybe m
findInverse c
c (m -> Maybe m) -> Set m -> Set (Maybe m)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> c -> o -> o -> Set m
forall c m o.
(Category c m o, Morphism m o) =>
c -> o -> o -> Set m
ar c
c o
s o
t
    
    
    areIsomorphic :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> o -> o -> Bool
    areIsomorphic :: forall c m o.
(Category c m o, Morphism m o, Eq m, Eq o) =>
c -> o -> o -> Bool
areIsomorphic c
c o
s o
t = Bool -> Bool
not(Bool -> Bool) -> (Maybe m -> Bool) -> Maybe m -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Maybe m -> Bool
forall a. Maybe a -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (Maybe m -> Bool) -> Maybe m -> Bool
forall a b. (a -> b) -> a -> b
$ c -> o -> o -> Maybe m
forall c m o.
(Category c m o, Morphism m o, Eq m, Eq o) =>
c -> o -> o -> Maybe m
findIsomorphism c
c o
s o
t
        
    
    isIso :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> m -> Bool
    isIso :: forall c m o.
(Category c m o, Morphism m o, Eq m, Eq o) =>
c -> m -> Bool
isIso c
c m
m = Bool -> Bool
not(Bool -> Bool) -> (Maybe m -> Bool) -> Maybe m -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Maybe m -> Bool
forall a. Maybe a -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (Maybe m -> Bool) -> Maybe m -> Bool
forall a b. (a -> b) -> a -> b
$ c -> m -> Maybe m
forall c m o.
(Category c m o, Morphism m o, Eq m, Eq o) =>
c -> m -> Maybe m
findInverse c
c m
m
    
    findRightInverses :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> m -> Set m
    findRightInverses :: forall c m o.
(Category c m o, Morphism m o, Eq m, Eq o) =>
c -> m -> Set m
findRightInverses c
c m
f = (m -> Bool) -> Set m -> Set m
forall a. (a -> Bool) -> Set a -> Set a
Set.filter (\m
g -> c -> m -> Bool
forall c m o.
(Category c m o, Morphism m o, Eq m, Eq o) =>
c -> m -> Bool
isIdentity c
c (m
f m -> m -> m
forall m o. Morphism m o => m -> m -> m
@ m
g)) (Set m -> Set m) -> Set m -> Set m
forall a b. (a -> b) -> a -> b
$ c -> o -> o -> Set m
forall c m o.
(Category c m o, Morphism m o) =>
c -> o -> o -> Set m
ar c
c (m -> o
forall m o. Morphism m o => m -> o
target m
f) (m -> o
forall m o. Morphism m o => m -> o
source m
f)
    
    
    isSection :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> m -> Bool
    isSection :: forall c m o.
(Category c m o, Morphism m o, Eq m, Eq o) =>
c -> m -> Bool
isSection c
c m
f = Bool -> Bool
not(Bool -> Bool) -> (Set m -> Bool) -> Set m -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Set m -> Bool
forall a. Set a -> Bool
Set.null) (Set m -> Bool) -> Set m -> Bool
forall a b. (a -> b) -> a -> b
$ c -> m -> Set m
forall c m o.
(Category c m o, Morphism m o, Eq m, Eq o) =>
c -> m -> Set m
findRightInverses c
c m
f
    
    
    findLeftInverses :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> m -> Set m
    findLeftInverses :: forall c m o.
(Category c m o, Morphism m o, Eq m, Eq o) =>
c -> m -> Set m
findLeftInverses c
c m
f = (m -> Bool) -> Set m -> Set m
forall a. (a -> Bool) -> Set a -> Set a
Set.filter (\m
g ->  c -> m -> Bool
forall c m o.
(Category c m o, Morphism m o, Eq m, Eq o) =>
c -> m -> Bool
isIdentity c
c (m
g m -> m -> m
forall m o. Morphism m o => m -> m -> m
@ m
f)) (Set m -> Set m) -> Set m -> Set m
forall a b. (a -> b) -> a -> b
$ c -> o -> o -> Set m
forall c m o.
(Category c m o, Morphism m o) =>
c -> o -> o -> Set m
ar c
c (m -> o
forall m o. Morphism m o => m -> o
target m
f) (m -> o
forall m o. Morphism m o => m -> o
source m
f)
    
    
    isRetraction :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> m -> Bool
    isRetraction :: forall c m o.
(Category c m o, Morphism m o, Eq m, Eq o) =>
c -> m -> Bool
isRetraction c
c m
f = Bool -> Bool
not(Bool -> Bool) -> (Set m -> Bool) -> Set m -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Set m -> Bool
forall a. Set a -> Bool
Set.null) (Set m -> Bool) -> Set m -> Bool
forall a b. (a -> b) -> a -> b
$ c -> m -> Set m
forall c m o.
(Category c m o, Morphism m o, Eq m, Eq o) =>
c -> m -> Set m
findLeftInverses c
c m
f
        
    
    isGenerator :: (Category c m o, Morphism m o, Eq m) => c -> m -> Bool
    isGenerator :: forall c m o.
(Category c m o, Morphism m o, Eq m) =>
c -> m -> Bool
isGenerator c
c m
f = m
f m -> Set m -> Bool
forall a. Eq a => a -> Set a -> Bool
`isIn` (c -> o -> o -> Set m
forall c m o.
(Category c m o, Morphism m o) =>
c -> o -> o -> Set m
genAr c
c (m -> o
forall m o. Morphism m o => m -> o
source m
f) (m -> o
forall m o. Morphism m o => m -> o
target m
f))
    
    
    isComposite :: (Category c m o, Morphism m o, Eq m) => c -> m -> Bool
    isComposite :: forall c m o.
(Category c m o, Morphism m o, Eq m) =>
c -> m -> Bool
isComposite c
c m
f = Bool -> Bool
not (c -> m -> Bool
forall c m o.
(Category c m o, Morphism m o, Eq m) =>
c -> m -> Bool
isGenerator c
c m
f)