FiniteCategories 0.1.0.0 → 0.2.0.0
raw patch · 169 files changed
+6457/−7145 lines, 169 filesdep +WeakSetsPVP ok
version bump matches the API change (PVP)
Dependencies added: WeakSets
API changes (from Hackage documentation)
- Adjunction.Adjunction: 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
- Adjunction.Adjunction: 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
- Cat.FinCat: FinCat :: [c] -> FinCat c m o
- Cat.FinCat: FinFunctor :: c -> c -> AssociationList o o -> AssociationList m m -> FinFunctor c m o
- Cat.FinCat: [mmapF] :: FinFunctor c m o -> AssociationList m m
- Cat.FinCat: [omapF] :: FinFunctor c m o -> AssociationList o o
- Cat.FinCat: [srcF] :: FinFunctor c m o -> c
- Cat.FinCat: [tgtF] :: FinFunctor c m o -> c
- Cat.FinCat: data FinFunctor c m o
- Cat.FinCat: instance (FiniteCategory.FiniteCategory.FiniteCategory c m o, FiniteCategory.FiniteCategory.Morphism m o, GHC.Classes.Eq c, GHC.Classes.Eq m, GHC.Classes.Eq o) => FiniteCategory.FiniteCategory.FiniteCategory (Cat.FinCat.FinCat c m o) (Cat.FinCat.FinFunctor c m o) c
- Cat.FinCat: instance (FiniteCategory.FiniteCategory.FiniteCategory c m o, FiniteCategory.FiniteCategory.Morphism m o, GHC.Classes.Eq c, GHC.Classes.Eq m, GHC.Classes.Eq o) => FiniteCategory.FiniteCategory.GeneratedFiniteCategory (Cat.FinCat.FinCat c m o) (Cat.FinCat.FinFunctor c m o) c
- Cat.FinCat: instance (FiniteCategory.FiniteCategory.FiniteCategory c m o, FiniteCategory.FiniteCategory.Morphism m o, IO.PrettyPrint.PrettyPrintable c, IO.PrettyPrint.PrettyPrintable m, IO.PrettyPrint.PrettyPrintable o, GHC.Classes.Eq m, GHC.Classes.Eq o) => IO.PrettyPrint.PrettyPrintable (Cat.FinCat.FinFunctor c m o)
- Cat.FinCat: instance (GHC.Classes.Eq c, GHC.Classes.Eq m, GHC.Classes.Eq o) => FiniteCategory.FiniteCategory.Morphism (Cat.FinCat.FinFunctor c m o) c
- Cat.FinCat: instance (GHC.Classes.Eq c, GHC.Classes.Eq o, GHC.Classes.Eq m) => GHC.Classes.Eq (Cat.FinCat.FinFunctor c m o)
- Cat.FinCat: instance (GHC.Show.Show c, GHC.Show.Show o, GHC.Show.Show m) => GHC.Show.Show (Cat.FinCat.FinFunctor c m o)
- Cat.FinCat: newtype FinCat c m o
- Cat.PartialFinCat: PartialFinCat :: [c] -> PartialFinCat c m o
- Cat.PartialFinCat: PartialFunctor :: c -> c -> AssociationList o o -> AssociationList m m -> PartialFunctor c m o
- Cat.PartialFinCat: [mmapPF] :: PartialFunctor c m o -> AssociationList m m
- Cat.PartialFinCat: [omapPF] :: PartialFunctor c m o -> AssociationList o o
- Cat.PartialFinCat: [srcPF] :: PartialFunctor c m o -> c
- Cat.PartialFinCat: [tgtPF] :: PartialFunctor c m o -> c
- Cat.PartialFinCat: arrowsNotMapped :: (FiniteCategory c m o, Morphism m o, Eq c, Eq m, Eq o) => PartialFunctor c m o -> [m]
- Cat.PartialFinCat: arrowsNotMappedTo :: (FiniteCategory c m o, Morphism m o, Eq c, Eq m, Eq o) => PartialFunctor c m o -> [m]
- Cat.PartialFinCat: codomainArrows :: (FiniteCategory c m o, Morphism m o, Eq c, Eq m, Eq o) => PartialFunctor c m o -> [m]
- Cat.PartialFinCat: codomainObjects :: (FiniteCategory c m o, Morphism m o, Eq c, Eq m, Eq o) => PartialFunctor c m o -> [o]
- Cat.PartialFinCat: data PartialFunctor c m o
- Cat.PartialFinCat: domainArrows :: (FiniteCategory c m o, Morphism m o, Eq c, Eq m, Eq o) => PartialFunctor c m o -> [m]
- Cat.PartialFinCat: domainObjects :: (FiniteCategory c m o, Morphism m o, Eq c, Eq m, Eq o) => PartialFunctor c m o -> [o]
- Cat.PartialFinCat: instance (FiniteCategory.FiniteCategory.FiniteCategory c m o, FiniteCategory.FiniteCategory.Morphism m o, GHC.Classes.Eq c, GHC.Classes.Eq m, GHC.Classes.Eq o) => FiniteCategory.FiniteCategory.FiniteCategory (Cat.PartialFinCat.PartialFinCat c m o) (Cat.PartialFinCat.PartialFunctor c m o) c
- Cat.PartialFinCat: instance (FiniteCategory.FiniteCategory.FiniteCategory c m o, FiniteCategory.FiniteCategory.Morphism m o, GHC.Classes.Eq c, GHC.Classes.Eq m, GHC.Classes.Eq o) => FiniteCategory.FiniteCategory.GeneratedFiniteCategory (Cat.PartialFinCat.PartialFinCat c m o) (Cat.PartialFinCat.PartialFunctor c m o) c
- Cat.PartialFinCat: instance (FiniteCategory.FiniteCategory.FiniteCategory c m o, FiniteCategory.FiniteCategory.Morphism m o, IO.PrettyPrint.PrettyPrintable c, IO.PrettyPrint.PrettyPrintable m, IO.PrettyPrint.PrettyPrintable o, GHC.Classes.Eq m, GHC.Classes.Eq o) => IO.PrettyPrint.PrettyPrintable (Cat.PartialFinCat.PartialFunctor c m o)
- Cat.PartialFinCat: instance (GHC.Classes.Eq c, GHC.Classes.Eq m, GHC.Classes.Eq o) => FiniteCategory.FiniteCategory.Morphism (Cat.PartialFinCat.PartialFunctor c m o) c
- Cat.PartialFinCat: instance (GHC.Classes.Eq c, GHC.Classes.Eq o, GHC.Classes.Eq m) => GHC.Classes.Eq (Cat.PartialFinCat.PartialFunctor c m o)
- Cat.PartialFinCat: instance (GHC.Show.Show c, GHC.Show.Show o, GHC.Show.Show m) => GHC.Show.Show (Cat.PartialFinCat.PartialFunctor c m o)
- Cat.PartialFinCat: newtype PartialFinCat c m o
- Cat.PartialFinCat: objectsNotMapped :: (FiniteCategory c m o, Morphism m o, Eq c, Eq m, Eq o) => PartialFunctor c m o -> [o]
- Cat.PartialFinCat: objectsNotMappedTo :: (FiniteCategory c m o, Morphism m o, Eq c, Eq m, Eq o) => PartialFunctor c m o -> [o]
- CommaCategory.CommaCategory: CommaCategory :: Diagram c1 m1 o1 c3 m3 o3 -> Diagram c2 m2 o2 c3 m3 o3 -> CommaCategory c1 m1 o1 c2 m2 o2 c3 m3 o3
- CommaCategory.CommaCategory: CommaMorphism :: CommaObject o1 o2 m3 -> CommaObject o1 o2 m3 -> m1 -> m2 -> CommaMorphism o1 o2 m1 m2 m3
- CommaCategory.CommaCategory: CommaObject :: o1 -> o2 -> m3 -> CommaObject o1 o2 m3
- CommaCategory.CommaCategory: [arrow] :: CommaObject o1 o2 m3 -> m3
- CommaCategory.CommaCategory: [indexAr1] :: CommaMorphism o1 o2 m1 m2 m3 -> m1
- CommaCategory.CommaCategory: [indexAr2] :: CommaMorphism o1 o2 m1 m2 m3 -> m2
- CommaCategory.CommaCategory: [indexSrc] :: CommaObject o1 o2 m3 -> o1
- CommaCategory.CommaCategory: [indexTgt] :: CommaObject o1 o2 m3 -> o2
- CommaCategory.CommaCategory: [leftDiag] :: CommaCategory c1 m1 o1 c2 m2 o2 c3 m3 o3 -> Diagram c1 m1 o1 c3 m3 o3
- CommaCategory.CommaCategory: [rightDiag] :: CommaCategory c1 m1 o1 c2 m2 o2 c3 m3 o3 -> Diagram c2 m2 o2 c3 m3 o3
- CommaCategory.CommaCategory: [srcCM] :: CommaMorphism o1 o2 m1 m2 m3 -> CommaObject o1 o2 m3
- CommaCategory.CommaCategory: [tgtCM] :: CommaMorphism o1 o2 m1 m2 m3 -> CommaObject o1 o2 m3
- CommaCategory.CommaCategory: data CommaCategory c1 m1 o1 c2 m2 o2 c3 m3 o3
- CommaCategory.CommaCategory: data CommaMorphism o1 o2 m1 m2 m3
- CommaCategory.CommaCategory: data CommaObject o1 o2 m3
- CommaCategory.CommaCategory: instance (FiniteCategory.FiniteCategory.FiniteCategory c1 m1 o1, FiniteCategory.FiniteCategory.Morphism m1 o1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, FiniteCategory.FiniteCategory.FiniteCategory c2 m2 o2, FiniteCategory.FiniteCategory.Morphism m2 o2, GHC.Classes.Eq m2, GHC.Classes.Eq o2, FiniteCategory.FiniteCategory.FiniteCategory c3 m3 o3, FiniteCategory.FiniteCategory.Morphism m3 o3, GHC.Classes.Eq m3) => FiniteCategory.FiniteCategory.FiniteCategory (CommaCategory.CommaCategory.CommaCategory c1 m1 o1 c2 m2 o2 c3 m3 o3) (CommaCategory.CommaCategory.CommaMorphism o1 o2 m1 m2 m3) (CommaCategory.CommaCategory.CommaObject o1 o2 m3)
- CommaCategory.CommaCategory: instance (FiniteCategory.FiniteCategory.FiniteCategory c1 m1 o1, FiniteCategory.FiniteCategory.Morphism m1 o1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, FiniteCategory.FiniteCategory.FiniteCategory c2 m2 o2, FiniteCategory.FiniteCategory.Morphism m2 o2, GHC.Classes.Eq m2, GHC.Classes.Eq o2, FiniteCategory.FiniteCategory.FiniteCategory c3 m3 o3, FiniteCategory.FiniteCategory.Morphism m3 o3, GHC.Classes.Eq m3) => FiniteCategory.FiniteCategory.GeneratedFiniteCategory (CommaCategory.CommaCategory.CommaCategory c1 m1 o1 c2 m2 o2 c3 m3 o3) (CommaCategory.CommaCategory.CommaMorphism o1 o2 m1 m2 m3) (CommaCategory.CommaCategory.CommaObject o1 o2 m3)
- CommaCategory.CommaCategory: instance (FiniteCategory.FiniteCategory.Morphism m1 o1, FiniteCategory.FiniteCategory.Morphism m2 o2, GHC.Classes.Eq o1, GHC.Classes.Eq o2, GHC.Classes.Eq m3) => FiniteCategory.FiniteCategory.Morphism (CommaCategory.CommaCategory.CommaMorphism o1 o2 m1 m2 m3) (CommaCategory.CommaCategory.CommaObject o1 o2 m3)
- CommaCategory.CommaCategory: instance (GHC.Classes.Eq c1, GHC.Classes.Eq c3, GHC.Classes.Eq o1, GHC.Classes.Eq o3, GHC.Classes.Eq m1, GHC.Classes.Eq m3, GHC.Classes.Eq c2, GHC.Classes.Eq o2, GHC.Classes.Eq m2) => GHC.Classes.Eq (CommaCategory.CommaCategory.CommaCategory c1 m1 o1 c2 m2 o2 c3 m3 o3)
- CommaCategory.CommaCategory: instance (GHC.Classes.Eq o1, GHC.Classes.Eq o2, GHC.Classes.Eq m3) => GHC.Classes.Eq (CommaCategory.CommaCategory.CommaObject o1 o2 m3)
- CommaCategory.CommaCategory: instance (GHC.Classes.Eq o1, GHC.Classes.Eq o2, GHC.Classes.Eq m3, GHC.Classes.Eq m1, GHC.Classes.Eq m2) => GHC.Classes.Eq (CommaCategory.CommaCategory.CommaMorphism o1 o2 m1 m2 m3)
- CommaCategory.CommaCategory: instance (GHC.Show.Show c1, GHC.Show.Show c3, GHC.Show.Show o1, GHC.Show.Show o3, GHC.Show.Show m1, GHC.Show.Show m3, GHC.Show.Show c2, GHC.Show.Show o2, GHC.Show.Show m2) => GHC.Show.Show (CommaCategory.CommaCategory.CommaCategory c1 m1 o1 c2 m2 o2 c3 m3 o3)
- CommaCategory.CommaCategory: instance (GHC.Show.Show o1, GHC.Show.Show o2, GHC.Show.Show m3) => GHC.Show.Show (CommaCategory.CommaCategory.CommaObject o1 o2 m3)
- CommaCategory.CommaCategory: instance (GHC.Show.Show o1, GHC.Show.Show o2, GHC.Show.Show m3, GHC.Show.Show m1, GHC.Show.Show m2) => GHC.Show.Show (CommaCategory.CommaCategory.CommaMorphism o1 o2 m1 m2 m3)
- CommaCategory.CommaCategory: instance (IO.PrettyPrint.PrettyPrintable c1, IO.PrettyPrint.PrettyPrintable m1, IO.PrettyPrint.PrettyPrintable o1, IO.PrettyPrint.PrettyPrintable c2, IO.PrettyPrint.PrettyPrintable m2, IO.PrettyPrint.PrettyPrintable o2, IO.PrettyPrint.PrettyPrintable c3, IO.PrettyPrint.PrettyPrintable m3, IO.PrettyPrint.PrettyPrintable o3, FiniteCategory.FiniteCategory.FiniteCategory c1 m1 o1, FiniteCategory.FiniteCategory.FiniteCategory c2 m2 o2, FiniteCategory.FiniteCategory.FiniteCategory c3 m3 o3, FiniteCategory.FiniteCategory.Morphism m1 o1, FiniteCategory.FiniteCategory.Morphism m2 o2, FiniteCategory.FiniteCategory.Morphism m3 o3, GHC.Classes.Eq m1, GHC.Classes.Eq o1, GHC.Classes.Eq m2, GHC.Classes.Eq o2) => IO.PrettyPrint.PrettyPrintable (CommaCategory.CommaCategory.CommaCategory c1 m1 o1 c2 m2 o2 c3 m3 o3)
- CommaCategory.CommaCategory: instance (IO.PrettyPrint.PrettyPrintable m1, IO.PrettyPrint.PrettyPrintable m2) => IO.PrettyPrint.PrettyPrintable (CommaCategory.CommaCategory.CommaMorphism o1 o2 m1 m2 m3)
- CommaCategory.CommaCategory: instance (IO.PrettyPrint.PrettyPrintable o1, IO.PrettyPrint.PrettyPrintable o2, IO.PrettyPrint.PrettyPrintable m3) => IO.PrettyPrint.PrettyPrintable (CommaCategory.CommaCategory.CommaObject o1 o2 m3)
- CommaCategory.CommaCategory: mkArrowCategory :: (FiniteCategory c m o, Morphism m o, Eq o) => c -> CommaCategory c m o c m o c m o
- CommaCategory.CommaCategory: mkCosliceCategory :: (FiniteCategory c m o, Morphism m o, Eq o) => c -> o -> Maybe (CommaCategory One One One c m o c m o)
- CommaCategory.CommaCategory: mkSliceCategory :: (FiniteCategory c m o, Morphism m o, Eq o) => c -> o -> Maybe (CommaCategory c m o One One One c m o)
- CompositionGraph.CompositionGraph: CGMorphism :: Path a b -> CompositionLaw a b -> CGMorphism a b
- CompositionGraph.CompositionGraph: CompositionGraph :: Graph a b -> CompositionLaw a b -> CompositionGraph a b
- CompositionGraph.CompositionGraph: DeleteCompositeMorph :: CGMorphism a b -> CompositionGraphError a b
- CompositionGraph.CompositionGraph: DeleteIdentity :: CGMorphism a b -> CompositionGraphError a b
- CompositionGraph.CompositionGraph: DeleteNonExistantObject :: a -> CompositionGraphError a b
- CompositionGraph.CompositionGraph: DeleteNonExistantObjectMorph :: CGMorphism a b -> CompositionGraphError a b
- CompositionGraph.CompositionGraph: IdentifyGenerator :: CGMorphism a b -> CompositionGraphError a b
- CompositionGraph.CompositionGraph: InsertMorphismNonExistantSource :: b -> a -> CompositionGraphError a b
- CompositionGraph.CompositionGraph: InsertMorphismNonExistantTarget :: b -> a -> CompositionGraphError a b
- CompositionGraph.CompositionGraph: ReplaceCompositeMorphism :: CGMorphism a b -> CompositionGraphError a b
- CompositionGraph.CompositionGraph: ReplaceNonExistantObject :: a -> CompositionGraphError a b
- CompositionGraph.CompositionGraph: ResultingCategoryError :: FiniteCategoryError (CGMorphism a b) a -> CompositionGraphError a b
- CompositionGraph.CompositionGraph: UnidentifyNonExistantMorphism :: CGMorphism a b -> CompositionGraphError a b
- CompositionGraph.CompositionGraph: [composite] :: CompositionGraphError a b -> CGMorphism a b
- CompositionGraph.CompositionGraph: [compositionLaw] :: CGMorphism a b -> CompositionLaw a b
- CompositionGraph.CompositionGraph: [faultyIdentity] :: CompositionGraphError a b -> CGMorphism a b
- CompositionGraph.CompositionGraph: [faultyMorph] :: CompositionGraphError a b -> b
- CompositionGraph.CompositionGraph: [faultyObj] :: CompositionGraphError a b -> a
- CompositionGraph.CompositionGraph: [faultySrc] :: CompositionGraphError a b -> a
- CompositionGraph.CompositionGraph: [faultyTgt] :: CompositionGraphError a b -> a
- CompositionGraph.CompositionGraph: [gen] :: CompositionGraphError a b -> CGMorphism a b
- CompositionGraph.CompositionGraph: [graph] :: CompositionGraph a b -> Graph a b
- CompositionGraph.CompositionGraph: [law] :: CompositionGraph a b -> CompositionLaw a b
- CompositionGraph.CompositionGraph: [morph] :: CompositionGraphError a b -> CGMorphism a b
- CompositionGraph.CompositionGraph: [neMorph] :: CompositionGraphError a b -> CGMorphism a b
- CompositionGraph.CompositionGraph: [path] :: CGMorphism a b -> Path a b
- CompositionGraph.CompositionGraph: data CGMorphism a b
- CompositionGraph.CompositionGraph: data CompositionGraph a b
- CompositionGraph.CompositionGraph: data CompositionGraphError a b
- CompositionGraph.CompositionGraph: deleteMorphism :: (Eq a, Eq b) => CompositionGraph a b -> CGMorphism a b -> Either (CompositionGraphError a b) (CompositionGraph a b, PartialFunctor (CompositionGraph a b) (CGMorphism a b) a)
- CompositionGraph.CompositionGraph: deleteObject :: (Eq a, Eq b) => CompositionGraph a b -> a -> Either (CompositionGraphError a b) (CompositionGraph a b, PartialFunctor (CompositionGraph a b) (CGMorphism a b) a)
- CompositionGraph.CompositionGraph: finiteCategoryToCompositionGraph :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> (CompositionGraph o m, Diagram c m o (CompositionGraph o m) (CGMorphism o m) o)
- CompositionGraph.CompositionGraph: generatedFiniteCategoryToCompositionGraph :: (GeneratedFiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> (CompositionGraph o m, Diagram c m o (CompositionGraph o m) (CGMorphism o m) o)
- CompositionGraph.CompositionGraph: getLabel :: Eq a => CGMorphism a b -> Maybe b
- CompositionGraph.CompositionGraph: identifyMorphisms :: (Eq a, Eq b) => CompositionGraph a b -> CGMorphism a b -> CGMorphism a b -> Either (CompositionGraphError a b) (CompositionGraph a b, PartialFunctor (CompositionGraph a b) (CGMorphism a b) a)
- CompositionGraph.CompositionGraph: insertMorphism :: (Eq a, Eq b) => CompositionGraph a b -> a -> a -> b -> Either (CompositionGraphError a b) (CompositionGraph a b, PartialFunctor (CompositionGraph a b) (CGMorphism a b) a)
- CompositionGraph.CompositionGraph: insertObject :: (Eq a, Eq b) => CompositionGraph a b -> a -> (CompositionGraph a b, PartialFunctor (CompositionGraph a b) (CGMorphism a b) a)
- CompositionGraph.CompositionGraph: instance (GHC.Classes.Eq a, GHC.Classes.Eq b) => FiniteCategory.FiniteCategory.FiniteCategory (CompositionGraph.CompositionGraph.CompositionGraph a b) (CompositionGraph.CompositionGraph.CGMorphism a b) a
- CompositionGraph.CompositionGraph: instance (GHC.Classes.Eq a, GHC.Classes.Eq b) => FiniteCategory.FiniteCategory.GeneratedFiniteCategory (CompositionGraph.CompositionGraph.CompositionGraph a b) (CompositionGraph.CompositionGraph.CGMorphism a b) a
- CompositionGraph.CompositionGraph: instance (GHC.Classes.Eq a, GHC.Classes.Eq b) => FiniteCategory.FiniteCategory.Morphism (CompositionGraph.CompositionGraph.CGMorphism a b) a
- CompositionGraph.CompositionGraph: instance (GHC.Classes.Eq a, GHC.Classes.Eq b) => GHC.Classes.Eq (CompositionGraph.CompositionGraph.CGMorphism a b)
- CompositionGraph.CompositionGraph: instance (GHC.Classes.Eq a, GHC.Classes.Eq b) => GHC.Classes.Eq (CompositionGraph.CompositionGraph.CompositionGraph a b)
- CompositionGraph.CompositionGraph: instance (GHC.Show.Show a, GHC.Show.Show b) => GHC.Show.Show (CompositionGraph.CompositionGraph.CGMorphism a b)
- CompositionGraph.CompositionGraph: instance (GHC.Show.Show a, GHC.Show.Show b) => GHC.Show.Show (CompositionGraph.CompositionGraph.CompositionGraph a b)
- CompositionGraph.CompositionGraph: instance (IO.PrettyPrint.PrettyPrintable a, IO.PrettyPrint.PrettyPrintable b, GHC.Classes.Eq a, GHC.Classes.Eq b) => IO.PrettyPrint.PrettyPrintable (CompositionGraph.CompositionGraph.CGMorphism a b)
- CompositionGraph.CompositionGraph: instance (IO.PrettyPrint.PrettyPrintable a, IO.PrettyPrint.PrettyPrintable b, GHC.Classes.Eq a, GHC.Classes.Eq b) => IO.PrettyPrint.PrettyPrintable (CompositionGraph.CompositionGraph.CompositionGraph a b)
- CompositionGraph.CompositionGraph: isComp :: Eq a => CGMorphism a b -> Bool
- CompositionGraph.CompositionGraph: isGen :: Eq a => CGMorphism a b -> Bool
- CompositionGraph.CompositionGraph: mkCompositionGraph :: (Eq a, Eq b, Show a) => Graph a b -> CompositionLaw a b -> Either (FiniteCategoryError (CGMorphism a b) a) (CompositionGraph a b)
- CompositionGraph.CompositionGraph: mkEmptyCompositionGraph :: CompositionGraph a b
- CompositionGraph.CompositionGraph: replaceMorphism :: (Eq a, Eq b) => CompositionGraph a b -> CGMorphism a b -> b -> Either (CompositionGraphError a b) (CompositionGraph a b, PartialFunctor (CompositionGraph a b) (CGMorphism a b) a)
- CompositionGraph.CompositionGraph: replaceObject :: (Eq a, Eq b) => CompositionGraph a b -> a -> a -> Either (CompositionGraphError a b) (CompositionGraph a b, PartialFunctor (CompositionGraph a b) (CGMorphism a b) a)
- CompositionGraph.CompositionGraph: type Arrow a b = (a, a, b)
- CompositionGraph.CompositionGraph: type CompositionLaw a b = AssociationList (RawPath a b) (RawPath a b)
- CompositionGraph.CompositionGraph: type Graph a b = ([a], [Arrow a b])
- CompositionGraph.CompositionGraph: type Path a b = (a, RawPath a b, a)
- CompositionGraph.CompositionGraph: type RawPath a b = [Arrow a b]
- CompositionGraph.CompositionGraph: unidentifyMorphism :: (Eq a, Eq b) => CompositionGraph a b -> CGMorphism a b -> Either (CompositionGraphError a b) (CompositionGraph a b, PartialFunctor (CompositionGraph a b) (CGMorphism a b) a)
- CompositionGraph.SafeCompositionGraph: SCGMorphism :: Path a b -> CompositionLaw a b -> Int -> SCGMorphism a b
- CompositionGraph.SafeCompositionGraph: SafeCompositionGraph :: Graph a b -> CompositionLaw a b -> Int -> SafeCompositionGraph a b
- CompositionGraph.SafeCompositionGraph: [compositionLawS] :: SCGMorphism a b -> CompositionLaw a b
- CompositionGraph.SafeCompositionGraph: [graphS] :: SafeCompositionGraph a b -> Graph a b
- CompositionGraph.SafeCompositionGraph: [lawS] :: SafeCompositionGraph a b -> CompositionLaw a b
- CompositionGraph.SafeCompositionGraph: [maxCycles] :: SafeCompositionGraph a b -> Int
- CompositionGraph.SafeCompositionGraph: [maxNbCycles] :: SCGMorphism a b -> Int
- CompositionGraph.SafeCompositionGraph: [pathS] :: SCGMorphism a b -> Path a b
- CompositionGraph.SafeCompositionGraph: data SCGMorphism a b
- CompositionGraph.SafeCompositionGraph: data SafeCompositionGraph a b
- CompositionGraph.SafeCompositionGraph: deleteMorphismS :: (Eq a, Eq b) => SafeCompositionGraph a b -> SCGMorphism a b -> Either (SafeCompositionGraphError a b) (SafeCompositionGraph a b, PartialFunctor (SafeCompositionGraph a b) (SCGMorphism a b) a)
- CompositionGraph.SafeCompositionGraph: deleteObjectS :: (Eq a, Eq b) => SafeCompositionGraph a b -> a -> Either (SafeCompositionGraphError a b) (SafeCompositionGraph a b, PartialFunctor (SafeCompositionGraph a b) (SCGMorphism a b) a)
- CompositionGraph.SafeCompositionGraph: finiteCategoryToSafeCompositionGraph :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> (SafeCompositionGraph o m, Diagram c m o (SafeCompositionGraph o m) (SCGMorphism o m) o)
- CompositionGraph.SafeCompositionGraph: generatedFiniteCategoryToSafeCompositionGraph :: (GeneratedFiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> (SafeCompositionGraph o m, Diagram c m o (SafeCompositionGraph o m) (SCGMorphism o m) o)
- CompositionGraph.SafeCompositionGraph: getLabelS :: Eq a => SCGMorphism a b -> Maybe b
- CompositionGraph.SafeCompositionGraph: identifyMorphismsS :: (Eq a, Eq b) => SafeCompositionGraph a b -> SCGMorphism a b -> SCGMorphism a b -> Either (SafeCompositionGraphError a b) (SafeCompositionGraph a b, PartialFunctor (SafeCompositionGraph a b) (SCGMorphism a b) a)
- CompositionGraph.SafeCompositionGraph: insertMorphismS :: (Eq a, Eq b) => SafeCompositionGraph a b -> a -> a -> b -> Either (SafeCompositionGraphError a b) (SafeCompositionGraph a b, PartialFunctor (SafeCompositionGraph a b) (SCGMorphism a b) a)
- CompositionGraph.SafeCompositionGraph: insertObjectS :: (Eq a, Eq b) => SafeCompositionGraph a b -> a -> (SafeCompositionGraph a b, PartialFunctor (SafeCompositionGraph a b) (SCGMorphism a b) a)
- CompositionGraph.SafeCompositionGraph: instance (GHC.Classes.Eq a, GHC.Classes.Eq b) => FiniteCategory.FiniteCategory.FiniteCategory (CompositionGraph.SafeCompositionGraph.SafeCompositionGraph a b) (CompositionGraph.SafeCompositionGraph.SCGMorphism a b) a
- CompositionGraph.SafeCompositionGraph: instance (GHC.Classes.Eq a, GHC.Classes.Eq b) => FiniteCategory.FiniteCategory.GeneratedFiniteCategory (CompositionGraph.SafeCompositionGraph.SafeCompositionGraph a b) (CompositionGraph.SafeCompositionGraph.SCGMorphism a b) a
- CompositionGraph.SafeCompositionGraph: instance (GHC.Classes.Eq a, GHC.Classes.Eq b) => FiniteCategory.FiniteCategory.Morphism (CompositionGraph.SafeCompositionGraph.SCGMorphism a b) a
- CompositionGraph.SafeCompositionGraph: instance (GHC.Classes.Eq a, GHC.Classes.Eq b) => GHC.Classes.Eq (CompositionGraph.SafeCompositionGraph.SCGMorphism a b)
- CompositionGraph.SafeCompositionGraph: instance (GHC.Classes.Eq a, GHC.Classes.Eq b) => GHC.Classes.Eq (CompositionGraph.SafeCompositionGraph.SafeCompositionGraph a b)
- CompositionGraph.SafeCompositionGraph: instance (GHC.Show.Show a, GHC.Show.Show b) => GHC.Show.Show (CompositionGraph.SafeCompositionGraph.SCGMorphism a b)
- CompositionGraph.SafeCompositionGraph: instance (GHC.Show.Show a, GHC.Show.Show b) => GHC.Show.Show (CompositionGraph.SafeCompositionGraph.SafeCompositionGraph a b)
- CompositionGraph.SafeCompositionGraph: instance (IO.PrettyPrint.PrettyPrintable a, IO.PrettyPrint.PrettyPrintable b, GHC.Classes.Eq a, GHC.Classes.Eq b) => IO.PrettyPrint.PrettyPrintable (CompositionGraph.SafeCompositionGraph.SCGMorphism a b)
- CompositionGraph.SafeCompositionGraph: instance (IO.PrettyPrint.PrettyPrintable a, IO.PrettyPrint.PrettyPrintable b, GHC.Classes.Eq a, GHC.Classes.Eq b) => IO.PrettyPrint.PrettyPrintable (CompositionGraph.SafeCompositionGraph.SafeCompositionGraph a b)
- CompositionGraph.SafeCompositionGraph: isCompS :: Eq a => SCGMorphism a b -> Bool
- CompositionGraph.SafeCompositionGraph: isGenS :: Eq a => SCGMorphism a b -> Bool
- CompositionGraph.SafeCompositionGraph: mkEmptySafeCompositionGraph :: Int -> SafeCompositionGraph a b
- CompositionGraph.SafeCompositionGraph: mkSafeCompositionGraph :: (Eq a, Eq b, Show a) => Graph a b -> CompositionLaw a b -> Int -> Either (FiniteCategoryError (SCGMorphism a b) a) (SafeCompositionGraph a b)
- CompositionGraph.SafeCompositionGraph: replaceMorphismS :: (Eq a, Eq b) => SafeCompositionGraph a b -> SCGMorphism a b -> b -> Either (SafeCompositionGraphError a b) (SafeCompositionGraph a b, PartialFunctor (SafeCompositionGraph a b) (SCGMorphism a b) a)
- CompositionGraph.SafeCompositionGraph: replaceObjectS :: (Eq a, Eq b) => SafeCompositionGraph a b -> a -> a -> Either (SafeCompositionGraphError a b) (SafeCompositionGraph a b, PartialFunctor (SafeCompositionGraph a b) (SCGMorphism a b) a)
- CompositionGraph.SafeCompositionGraph: unidentifyMorphismS :: (Eq a, Eq b) => SafeCompositionGraph a b -> SCGMorphism a b -> Either (SafeCompositionGraphError a b) (SafeCompositionGraph a b, PartialFunctor (SafeCompositionGraph a b) (SCGMorphism a b) a)
- ConeCategory.ConeCategory: apex :: Cone c1 m1 o1 c2 m2 o2 -> o2
- ConeCategory.ConeCategory: coconeToNaturalTransformation :: Cocone c1 m1 o1 c2 m2 o2 -> NaturalTransformation c1 m1 o1 c2 m2 o2
- ConeCategory.ConeCategory: coconesOfNadir :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => Diagram c1 m1 o1 c2 m2 o2 -> o2 -> [Cocone c1 m1 o1 c2 m2 o2]
- ConeCategory.ConeCategory: colimits :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => Diagram c1 m1 o1 c2 m2 o2 -> [Cocone c1 m1 o1 c2 m2 o2]
- ConeCategory.ConeCategory: coneToNaturalTransformation :: Cone c1 m1 o1 c2 m2 o2 -> NaturalTransformation c1 m1 o1 c2 m2 o2
- ConeCategory.ConeCategory: conesOfApex :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => Diagram c1 m1 o1 c2 m2 o2 -> o2 -> [Cone c1 m1 o1 c2 m2 o2]
- ConeCategory.ConeCategory: initialObjects :: (FiniteCategory c m o, Morphism m o) => c -> [o]
- ConeCategory.ConeCategory: limits :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => Diagram c1 m1 o1 c2 m2 o2 -> [Cone c1 m1 o1 c2 m2 o2]
- ConeCategory.ConeCategory: mkCoconeCategory :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => Diagram c1 m1 o1 c2 m2 o2 -> CoconeCategory c1 m1 o1 c2 m2 o2
- ConeCategory.ConeCategory: mkConeCategory :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => Diagram c1 m1 o1 c2 m2 o2 -> ConeCategory c1 m1 o1 c2 m2 o2
- ConeCategory.ConeCategory: nadir :: Cocone c1 m1 o1 c2 m2 o2 -> o2
- ConeCategory.ConeCategory: naturalTransformationToCocone :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2) => NaturalTransformation c1 m1 o1 c2 m2 o2 -> Cocone c1 m1 o1 c2 m2 o2
- ConeCategory.ConeCategory: naturalTransformationToCone :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2) => NaturalTransformation c1 m1 o1 c2 m2 o2 -> Cone c1 m1 o1 c2 m2 o2
- ConeCategory.ConeCategory: terminalObjects :: (FiniteCategory c m o, Morphism m o) => c -> [o]
- ConeCategory.ConeCategory: type Cocone c1 m1 o1 c2 m2 o2 = CommaObject One o2 (NaturalTransformation c1 m1 o1 c2 m2 o2)
- ConeCategory.ConeCategory: type CoconeCategory c1 m1 o1 c2 m2 o2 = CommaCategory One One One c2 m2 o2 (FunctorCategory c1 m1 o1 c2 m2 o2) (NaturalTransformation c1 m1 o1 c2 m2 o2) (Diagram c1 m1 o1 c2 m2 o2)
- ConeCategory.ConeCategory: type CoconeMorphism c1 m1 o1 c2 m2 o2 = CommaMorphism One o2 One m2 (NaturalTransformation c1 m1 o1 c2 m2 o2)
- ConeCategory.ConeCategory: type Cone c1 m1 o1 c2 m2 o2 = CommaObject o2 One (NaturalTransformation c1 m1 o1 c2 m2 o2)
- ConeCategory.ConeCategory: type ConeCategory c1 m1 o1 c2 m2 o2 = CommaCategory c2 m2 o2 One One One (FunctorCategory c1 m1 o1 c2 m2 o2) (NaturalTransformation c1 m1 o1 c2 m2 o2) (Diagram c1 m1 o1 c2 m2 o2)
- ConeCategory.ConeCategory: type ConeMorphism c1 m1 o1 c2 m2 o2 = CommaMorphism o2 One m2 One (NaturalTransformation c1 m1 o1 c2 m2 o2)
- ConeCategory.LeftCone: ConeCategory :: Diagram c1 m1 o1 c2 m2 o2 -> ConeCategory c1 m1 o1 c2 m2 o2
- ConeCategory.LeftCone: LeftCone :: c -> LeftCone c m o
- ConeCategory.LeftCone: data ConeCategory c1 m1 o1 c2 m2 o2
- ConeCategory.LeftCone: data LeftCone c m o
- ConeCategory.LeftCone: inclusionFunctor :: (FiniteCategory c m o, Morphism m o) => LeftCone c m o -> Diagram c m o (LeftCone c m o) (LeftConeMorphism m o) (LeftConeObject o)
- ConeCategory.LeftCone: instance (FiniteCategory.FiniteCategory.FiniteCategory c m o, FiniteCategory.FiniteCategory.Morphism m o) => FiniteCategory.FiniteCategory.FiniteCategory (ConeCategory.LeftCone.LeftCone c m o) (ConeCategory.LeftCone.LeftConeMorphism m o) (ConeCategory.LeftCone.LeftConeObject o)
- ConeCategory.LeftCone: instance (FiniteCategory.FiniteCategory.FiniteCategory c1 m1 o1, FiniteCategory.FiniteCategory.Morphism m1 o1, GHC.Classes.Eq c1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, FiniteCategory.FiniteCategory.FiniteCategory c2 m2 o2, FiniteCategory.FiniteCategory.Morphism m2 o2, GHC.Classes.Eq c2, GHC.Classes.Eq m2, GHC.Classes.Eq o2) => FiniteCategory.FiniteCategory.FiniteCategory (ConeCategory.LeftCone.ConeCategory c1 m1 o1 c2 m2 o2) (FunctorCategory.FunctorCategory.NaturalTransformation (ConeCategory.LeftCone.LeftCone c1 m1 o1) (ConeCategory.LeftCone.LeftConeMorphism m1 o1) (ConeCategory.LeftCone.LeftConeObject o1) c2 m2 o2) (Diagram.Diagram.Diagram (ConeCategory.LeftCone.LeftCone c1 m1 o1) (ConeCategory.LeftCone.LeftConeMorphism m1 o1) (ConeCategory.LeftCone.LeftConeObject o1) c2 m2 o2)
- ConeCategory.LeftCone: instance (FiniteCategory.FiniteCategory.FiniteCategory c1 m1 o1, FiniteCategory.FiniteCategory.Morphism m1 o1, GHC.Classes.Eq c1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, FiniteCategory.FiniteCategory.FiniteCategory c2 m2 o2, FiniteCategory.FiniteCategory.Morphism m2 o2, GHC.Classes.Eq c2, GHC.Classes.Eq m2, GHC.Classes.Eq o2) => FiniteCategory.FiniteCategory.GeneratedFiniteCategory (ConeCategory.LeftCone.ConeCategory c1 m1 o1 c2 m2 o2) (FunctorCategory.FunctorCategory.NaturalTransformation (ConeCategory.LeftCone.LeftCone c1 m1 o1) (ConeCategory.LeftCone.LeftConeMorphism m1 o1) (ConeCategory.LeftCone.LeftConeObject o1) c2 m2 o2) (Diagram.Diagram.Diagram (ConeCategory.LeftCone.LeftCone c1 m1 o1) (ConeCategory.LeftCone.LeftConeMorphism m1 o1) (ConeCategory.LeftCone.LeftConeObject o1) c2 m2 o2)
- ConeCategory.LeftCone: instance (FiniteCategory.FiniteCategory.GeneratedFiniteCategory c m o, FiniteCategory.FiniteCategory.Morphism m o) => FiniteCategory.FiniteCategory.GeneratedFiniteCategory (ConeCategory.LeftCone.LeftCone c m o) (ConeCategory.LeftCone.LeftConeMorphism m o) (ConeCategory.LeftCone.LeftConeObject o)
- ConeCategory.LeftCone: instance (FiniteCategory.FiniteCategory.Morphism m o, GHC.Classes.Eq o) => FiniteCategory.FiniteCategory.Morphism (ConeCategory.LeftCone.LeftConeMorphism m o) (ConeCategory.LeftCone.LeftConeObject o)
- ConeCategory.LeftCone: instance (GHC.Classes.Eq c1, GHC.Classes.Eq c2, GHC.Classes.Eq o1, GHC.Classes.Eq o2, GHC.Classes.Eq m1, GHC.Classes.Eq m2) => GHC.Classes.Eq (ConeCategory.LeftCone.ConeCategory c1 m1 o1 c2 m2 o2)
- ConeCategory.LeftCone: instance (GHC.Classes.Eq m, GHC.Classes.Eq o) => GHC.Classes.Eq (ConeCategory.LeftCone.LeftConeMorphism m o)
- ConeCategory.LeftCone: instance (GHC.Show.Show c1, GHC.Show.Show c2, GHC.Show.Show o1, GHC.Show.Show o2, GHC.Show.Show m1, GHC.Show.Show m2) => GHC.Show.Show (ConeCategory.LeftCone.ConeCategory c1 m1 o1 c2 m2 o2)
- ConeCategory.LeftCone: instance (GHC.Show.Show m, GHC.Show.Show o) => GHC.Show.Show (ConeCategory.LeftCone.LeftConeMorphism m o)
- ConeCategory.LeftCone: instance (IO.PrettyPrint.PrettyPrintable m, IO.PrettyPrint.PrettyPrintable o) => IO.PrettyPrint.PrettyPrintable (ConeCategory.LeftCone.LeftConeMorphism m o)
- ConeCategory.LeftCone: instance GHC.Classes.Eq c => GHC.Classes.Eq (ConeCategory.LeftCone.LeftCone c m o)
- ConeCategory.LeftCone: instance GHC.Classes.Eq o => GHC.Classes.Eq (ConeCategory.LeftCone.LeftConeObject o)
- ConeCategory.LeftCone: instance GHC.Show.Show c => GHC.Show.Show (ConeCategory.LeftCone.LeftCone c m o)
- ConeCategory.LeftCone: instance GHC.Show.Show o => GHC.Show.Show (ConeCategory.LeftCone.LeftConeObject o)
- ConeCategory.LeftCone: instance IO.PrettyPrint.PrettyPrintable c => IO.PrettyPrint.PrettyPrintable (ConeCategory.LeftCone.LeftCone c m o)
- ConeCategory.LeftCone: instance IO.PrettyPrint.PrettyPrintable o => IO.PrettyPrint.PrettyPrintable (ConeCategory.LeftCone.LeftConeObject o)
- Config.Config: maximumLoopDepth :: Integer
- Currying.Currying: curryDiagram :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2, FiniteCategory c3 m3 o3, Morphism m3 o3) => Diagram (ProductCategory c1 m1 o1 c2 m2 o2) (ProductMorphism m1 o1 m2 o2) (ProductObject o1 o2) c3 m3 o3 -> Diagram c1 m1 o1 (FunctorCategory c2 m2 o2 c3 m3 o3) (NaturalTransformation c2 m2 o2 c3 m3 o3) (Diagram c2 m2 o2 c3 m3 o3)
- Currying.Currying: switchArg :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2, FiniteCategory c3 m3 o3, Morphism m3 o3) => Diagram c1 m1 o1 (FunctorCategory c2 m2 o2 c3 m3 o3) (NaturalTransformation c2 m2 o2 c3 m3 o3) (Diagram c2 m2 o2 c3 m3 o3) -> Diagram c2 m2 o2 (FunctorCategory c1 m1 o1 c3 m3 o3) (NaturalTransformation c1 m1 o1 c3 m3 o3) (Diagram c1 m1 o1 c3 m3 o3)
- Currying.Currying: uncurryDiagram :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2, FiniteCategory c3 m3 o3, Morphism m3 o3) => Diagram c1 m1 o1 (FunctorCategory c2 m2 o2 c3 m3 o3) (NaturalTransformation c2 m2 o2 c3 m3 o3) (Diagram c2 m2 o2 c3 m3 o3) -> Diagram (ProductCategory c1 m1 o1 c2 m2 o2) (ProductMorphism m1 o1 m2 o2) (ProductObject o1 o2) c3 m3 o3
- DiagonalFunctor.DiagonalFunctor: mkDiagonalFunctor :: (FiniteCategory c1 m1 o1, Morphism m1 o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq o2) => c1 -> c2 -> Diagram c2 m2 o2 (FunctorCategory c1 m1 o1 c2 m2 o2) (NaturalTransformation c1 m1 o1 c2 m2 o2) (Diagram c1 m1 o1 c2 m2 o2)
- Diagram.Conversion: diagramToFinFunctor :: (FiniteCategory c m o, Morphism m o) => Diagram c m o c m o -> FinFunctor c m o
- Diagram.Conversion: diagramToPartialFunctor :: (FiniteCategory c m o, Morphism m o) => Diagram c m o c m o -> PartialFunctor c m o
- Diagram.Conversion: finFunctorToDiagram :: FinFunctor c m o -> Diagram c m o c m o
- Diagram.Conversion: finFunctorToPartialFunctor :: (FiniteCategory c m o, Morphism m o) => FinFunctor c m o -> PartialFunctor c m o
- Diagram.Conversion: partialFunctorToDiagram :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o, Show o, Show m) => PartialFunctor c m o -> Maybe (Diagram c m o c m o)
- Diagram.Conversion: partialFunctorToFinFunctor :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o, Show o, Show m) => PartialFunctor c m o -> Maybe (FinFunctor c m o)
- Diagram.Diagram: Diagram :: c1 -> c2 -> AssociationList o1 o2 -> AssociationList m1 m2 -> Diagram c1 m1 o1 c2 m2 o2
- Diagram.Diagram: [mmap] :: Diagram c1 m1 o1 c2 m2 o2 -> AssociationList m1 m2
- Diagram.Diagram: [omap] :: Diagram c1 m1 o1 c2 m2 o2 -> AssociationList o1 o2
- Diagram.Diagram: [src] :: Diagram c1 m1 o1 c2 m2 o2 -> c1
- Diagram.Diagram: [tgt] :: Diagram c1 m1 o1 c2 m2 o2 -> c2
- Diagram.Diagram: checkFunctoriality :: (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 -> Bool
- Diagram.Diagram: completeMmap :: (GeneratedFiniteCategory c1 m1 o1, Morphism m1 o1, Eq o1, Eq m1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq o2, Eq m2) => c1 -> c2 -> AssociationList o1 o2 -> AssociationList m1 m2 -> AssociationList m1 m2
- Diagram.Diagram: composeDiag :: (FiniteCategory c1 m1 o1, Morphism m1 o1, FiniteCategory c2 m2 o2, Morphism m2 o2, FiniteCategory c3 m3 o3, Morphism m3 o3, Eq m1, Eq o1, Eq m2, Eq o2) => Diagram c2 m2 o2 c3 m3 o3 -> Diagram c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 c3 m3 o3
- Diagram.Diagram: data Diagram c1 m1 o1 c2 m2 o2
- Diagram.Diagram: instance (FiniteCategory.FiniteCategory.FiniteCategory c1 m1 o1, FiniteCategory.FiniteCategory.Morphism m1 o1, IO.PrettyPrint.PrettyPrintable m1, IO.PrettyPrint.PrettyPrintable o1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, IO.PrettyPrint.PrettyPrintable c1, FiniteCategory.FiniteCategory.FiniteCategory c2 m2 o2, FiniteCategory.FiniteCategory.Morphism m2 o2, IO.PrettyPrint.PrettyPrintable m2, IO.PrettyPrint.PrettyPrintable o2, IO.PrettyPrint.PrettyPrintable c2) => IO.PrettyPrint.PrettyPrintable (Diagram.Diagram.Diagram c1 m1 o1 c2 m2 o2)
- Diagram.Diagram: instance (GHC.Classes.Eq c1, GHC.Classes.Eq c2, GHC.Classes.Eq o1, GHC.Classes.Eq o2, GHC.Classes.Eq m1, GHC.Classes.Eq m2) => GHC.Classes.Eq (Diagram.Diagram.Diagram c1 m1 o1 c2 m2 o2)
- Diagram.Diagram: instance (GHC.Show.Show c1, GHC.Show.Show c2, GHC.Show.Show o1, GHC.Show.Show o2, GHC.Show.Show m1, GHC.Show.Show m2) => GHC.Show.Show (Diagram.Diagram.Diagram c1 m1 o1 c2 m2 o2)
- Diagram.Diagram: mkConstantDiagram :: (FiniteCategory c1 m1 o1, Morphism m1 o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq o2) => c1 -> c2 -> o2 -> Maybe (Diagram c1 m1 o1 c2 m2 o2)
- Diagram.Diagram: mkDiagram :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2) => c1 -> c2 -> AssociationList o1 o2 -> AssociationList m1 m2 -> Maybe (Diagram c1 m1 o1 c2 m2 o2)
- Diagram.Diagram: mkDiscreteDiagram :: (FiniteCategory c m o, Morphism m o, Eq o) => c -> [o] -> Maybe (Diagram (DiscreteCategory o) (DiscreteIdentity o) (DiscreteObject o) c m o)
- Diagram.Diagram: mkHat :: (FiniteCategory c m o, Morphism m o, Eq o, Eq m) => c -> m -> m -> Maybe (Diagram Hat HatAr HatOb c m o)
- Diagram.Diagram: mkIdentityDiagram :: (FiniteCategory c m o, Morphism m o) => c -> Diagram c m o c m o
- Diagram.Diagram: mkParallel :: (FiniteCategory c m o, Morphism m o, Eq o, Eq m) => c -> m -> m -> Maybe (Diagram Parallel ParallelAr ParallelOb c m o)
- Diagram.Diagram: mkSelect0 :: (FiniteCategory c m o, Morphism m o) => c -> Diagram Zero Zero Zero c m o
- Diagram.Diagram: mkSelect1 :: (FiniteCategory c m o, Morphism m o, Eq o) => c -> o -> Maybe (Diagram One One One c m o)
- Diagram.Diagram: mkSelect2 :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> m -> Maybe (Diagram Two TwoAr TwoOb c m o)
- Diagram.Diagram: mkSelect3 :: (FiniteCategory c m o, Morphism m o, Eq o, Eq m) => c -> m -> m -> Maybe (Diagram Three ThreeAr ThreeOb c m o)
- Diagram.Diagram: mkTriangle :: (FiniteCategory c m o, Morphism m o, Eq o, Eq m) => c -> m -> m -> Maybe (Diagram Three ThreeAr ThreeOb c m o)
- Diagram.Diagram: mkV :: (FiniteCategory c m o, Morphism m o, Eq o, Eq m) => c -> m -> m -> Maybe (Diagram V VAr VOb c m o)
- Diagram.Diagram: objectImage :: (FiniteCategory c1 m1 o1, Morphism m1 o1, FiniteCategory c2 m2 o2, Morphism m2 o2) => Diagram c1 m1 o1 c2 m2 o2 -> [o2]
- ExportGraphViz.ExportGraphViz: catToDot :: (Eq o, PrettyPrintable o, PrettyPrintable m, Morphism m o, GeneratedFiniteCategory c m o) => c -> String -> IO ()
- ExportGraphViz.ExportGraphViz: catToPdf :: (Eq o, PrettyPrintable o, PrettyPrintable m, Morphism m o, GeneratedFiniteCategory c m o) => c -> String -> IO ()
- ExportGraphViz.ExportGraphViz: categoryToGraph :: (Eq o, PrettyPrintable o, PrettyPrintable m, Morphism m o, FiniteCategory c m o) => c -> Gr String String
- ExportGraphViz.ExportGraphViz: coneToDot :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrintable m1, PrettyPrintable o1, Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrintable m2, PrettyPrintable o2) => NaturalTransformation c1 m1 o1 c2 m2 o2 -> String -> IO ()
- ExportGraphViz.ExportGraphViz: coneToPdf :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrintable m1, PrettyPrintable o1, Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrintable m2, PrettyPrintable o2) => NaturalTransformation c1 m1 o1 c2 m2 o2 -> String -> IO ()
- ExportGraphViz.ExportGraphViz: diagToDot :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrintable m1, PrettyPrintable o1, Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrintable m2, PrettyPrintable o2) => Diagram c1 m1 o1 c2 m2 o2 -> String -> IO ()
- ExportGraphViz.ExportGraphViz: diagToDot2 :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrintable m1, PrettyPrintable o1, Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrintable m2, PrettyPrintable o2) => Diagram c1 m1 o1 c2 m2 o2 -> String -> IO ()
- ExportGraphViz.ExportGraphViz: diagToDotCluster :: (Eq c1, Eq o1, PrettyPrintable o1, PrettyPrintable m1, Morphism m1 o1, GeneratedFiniteCategory c1 m1 o1, Eq c2, Eq o2, PrettyPrintable o2, PrettyPrintable m2, Morphism m2 o2, GeneratedFiniteCategory c2 m2 o2) => Diagram c1 m1 o1 c2 m2 o2 -> String -> IO ()
- ExportGraphViz.ExportGraphViz: diagToPdf :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrintable m1, PrettyPrintable o1, Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrintable m2, PrettyPrintable o2) => Diagram c1 m1 o1 c2 m2 o2 -> String -> IO ()
- ExportGraphViz.ExportGraphViz: diagToPdf2 :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrintable m1, PrettyPrintable o1, Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrintable m2, PrettyPrintable o2) => Diagram c1 m1 o1 c2 m2 o2 -> String -> IO ()
- ExportGraphViz.ExportGraphViz: diagToPdfCluster :: (Eq c1, Eq o1, PrettyPrintable o1, PrettyPrintable m1, Morphism m1 o1, GeneratedFiniteCategory c1 m1 o1, Eq c2, Eq o2, PrettyPrintable o2, PrettyPrintable m2, Morphism m2 o2, GeneratedFiniteCategory c2 m2 o2) => Diagram c1 m1 o1 c2 m2 o2 -> String -> IO ()
- ExportGraphViz.ExportGraphViz: genToDot :: (Eq o, PrettyPrintable o, PrettyPrintable m, Morphism m o, GeneratedFiniteCategory c m o) => c -> String -> IO ()
- ExportGraphViz.ExportGraphViz: genToPdf :: (Eq o, PrettyPrintable o, PrettyPrintable m, Morphism m o, GeneratedFiniteCategory c m o) => c -> String -> IO ()
- ExportGraphViz.ExportGraphViz: natToDot :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrintable m1, PrettyPrintable o1, Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrintable m2, PrettyPrintable o2) => NaturalTransformation c1 m1 o1 c2 m2 o2 -> String -> IO ()
- ExportGraphViz.ExportGraphViz: natToPdf :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrintable m1, PrettyPrintable o1, Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrintable m2, PrettyPrintable o2) => NaturalTransformation c1 m1 o1 c2 m2 o2 -> String -> IO ()
- FiniteCategory.FiniteCategory: (@) :: Morphism m o => m -> m -> m
- FiniteCategory.FiniteCategory: ArrowBetweenUnknownObjects :: m -> o -> o -> FiniteCategoryError m o
- FiniteCategory.FiniteCategory: ArrowsNotExhaustive :: m -> FiniteCategoryError m o
- FiniteCategory.FiniteCategory: CompositionNotAssociative :: m -> m -> m -> m -> m -> FiniteCategoryError m o
- FiniteCategory.FiniteCategory: GeneratorIsNotAMorphism :: m -> FiniteCategoryError m o
- FiniteCategory.FiniteCategory: IdentityNotLeftNeutral :: m -> m -> m -> FiniteCategoryError m o
- FiniteCategory.FiniteCategory: IdentityNotRightNeutral :: m -> m -> m -> FiniteCategoryError m o
- FiniteCategory.FiniteCategory: MorphismDoesntDecomposesIntoGenerators :: m -> [m] -> m -> FiniteCategoryError m o
- FiniteCategory.FiniteCategory: MorphismsNotUnique :: m -> FiniteCategoryError m o
- FiniteCategory.FiniteCategory: MorphismsShouldNotBeEqual :: m -> m -> FiniteCategoryError m o
- FiniteCategory.FiniteCategory: NotTransitive :: m -> m -> FiniteCategoryError m o
- FiniteCategory.FiniteCategory: ObjectsNotUnique :: o -> FiniteCategoryError m o
- FiniteCategory.FiniteCategory: WrongDecomposition :: m -> [m] -> m -> FiniteCategoryError m o
- FiniteCategory.FiniteCategory: WrongSource :: m -> o -> FiniteCategoryError m o
- FiniteCategory.FiniteCategory: WrongTarget :: m -> o -> FiniteCategoryError m o
- FiniteCategory.FiniteCategory: [comp] :: FiniteCategoryError m o -> m
- FiniteCategory.FiniteCategory: [decomp] :: FiniteCategoryError m o -> [m]
- FiniteCategory.FiniteCategory: [dupMorph] :: FiniteCategoryError m o -> m
- FiniteCategory.FiniteCategory: [dupObj] :: FiniteCategoryError m o -> o
- FiniteCategory.FiniteCategory: [f] :: FiniteCategoryError m o -> m
- FiniteCategory.FiniteCategory: [f_gh] :: FiniteCategoryError m o -> m
- FiniteCategory.FiniteCategory: [fg_h] :: FiniteCategoryError m o -> m
- FiniteCategory.FiniteCategory: [foidL] :: FiniteCategoryError m o -> m
- FiniteCategory.FiniteCategory: [g] :: FiniteCategoryError m o -> m
- FiniteCategory.FiniteCategory: [h] :: FiniteCategoryError m o -> m
- FiniteCategory.FiniteCategory: [idL] :: FiniteCategoryError m o -> m
- FiniteCategory.FiniteCategory: [idR] :: FiniteCategoryError m o -> m
- FiniteCategory.FiniteCategory: [idRof] :: FiniteCategoryError m o -> m
- FiniteCategory.FiniteCategory: [missingAr] :: FiniteCategoryError m o -> m
- FiniteCategory.FiniteCategory: [notGen] :: FiniteCategoryError m o -> m
- FiniteCategory.FiniteCategory: [realSource] :: FiniteCategoryError m o -> o
- FiniteCategory.FiniteCategory: [realTarget] :: FiniteCategoryError m o -> o
- FiniteCategory.FiniteCategory: [s] :: FiniteCategoryError m o -> o
- FiniteCategory.FiniteCategory: [t] :: FiniteCategoryError m o -> o
- FiniteCategory.FiniteCategory: ar :: (FiniteCategory c m o, Morphism m o) => c -> o -> o -> [m]
- FiniteCategory.FiniteCategory: arFrom :: (FiniteCategory c m o, Morphism m o) => c -> o -> [m]
- FiniteCategory.FiniteCategory: arFrom2 :: (FiniteCategory c m o, Morphism m o) => c -> [o] -> [m]
- FiniteCategory.FiniteCategory: arTo :: (FiniteCategory c m o, Morphism m o) => c -> o -> [m]
- FiniteCategory.FiniteCategory: arTo2 :: (FiniteCategory c m o, Morphism m o) => c -> [o] -> [m]
- FiniteCategory.FiniteCategory: arrows :: (FiniteCategory c m o, FiniteCategory c m o, Morphism m o) => c -> [m]
- FiniteCategory.FiniteCategory: bruteForceDecompose :: (GeneratedFiniteCategory c m o, Morphism m o, Eq m) => c -> m -> [m]
- FiniteCategory.FiniteCategory: checkFiniteCategoryProperties :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> Maybe (FiniteCategoryError m o)
- FiniteCategory.FiniteCategory: checkGeneratedFiniteCategoryProperties :: (GeneratedFiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> Maybe (FiniteCategoryError m o)
- FiniteCategory.FiniteCategory: class FiniteCategory c m o | c -> m, m -> o
- FiniteCategory.FiniteCategory: class (FiniteCategory c m o) => GeneratedFiniteCategory c m o
- FiniteCategory.FiniteCategory: class Morphism m o | m -> o
- FiniteCategory.FiniteCategory: compose :: Morphism m o => [m] -> m
- FiniteCategory.FiniteCategory: data FiniteCategoryError m o
- FiniteCategory.FiniteCategory: decompose :: (GeneratedFiniteCategory c m o, Morphism m o) => c -> m -> [m]
- FiniteCategory.FiniteCategory: defaultDecompose :: (GeneratedFiniteCategory c m o, Morphism m o) => c -> m -> [m]
- FiniteCategory.FiniteCategory: defaultGenAr :: (GeneratedFiniteCategory c m o, Morphism m o) => c -> o -> o -> [m]
- FiniteCategory.FiniteCategory: genAr :: (GeneratedFiniteCategory c m o, Morphism m o) => c -> o -> o -> [m]
- FiniteCategory.FiniteCategory: genArFrom :: (GeneratedFiniteCategory c m o, Morphism m o) => c -> o -> [m]
- FiniteCategory.FiniteCategory: genArFrom2 :: (GeneratedFiniteCategory c m o, Morphism m o) => c -> [o] -> [m]
- FiniteCategory.FiniteCategory: genArTo :: (GeneratedFiniteCategory c m o, Morphism m o) => c -> o -> [m]
- FiniteCategory.FiniteCategory: genArTo2 :: (GeneratedFiniteCategory c m o, Morphism m o) => c -> [o] -> [m]
- FiniteCategory.FiniteCategory: genArrows :: (GeneratedFiniteCategory c m o, GeneratedFiniteCategory c m o, Morphism m o) => c -> [m]
- FiniteCategory.FiniteCategory: identities :: (FiniteCategory c m o, Morphism m o) => c -> [m]
- FiniteCategory.FiniteCategory: identity :: (FiniteCategory c m o, Morphism m o) => c -> o -> m
- FiniteCategory.FiniteCategory: initialObjects :: (FiniteCategory c m o, Morphism m o) => c -> [o]
- FiniteCategory.FiniteCategory: instance (GHC.Classes.Eq m, GHC.Classes.Eq o) => GHC.Classes.Eq (FiniteCategory.FiniteCategory.FiniteCategoryError m o)
- FiniteCategory.FiniteCategory: instance (GHC.Show.Show m, GHC.Show.Show o) => GHC.Show.Show (FiniteCategory.FiniteCategory.FiniteCategoryError m o)
- FiniteCategory.FiniteCategory: instance (GHC.Show.Show m, GHC.Show.Show o) => IO.PrettyPrint.PrettyPrintable (FiniteCategory.FiniteCategory.FiniteCategoryError m o)
- FiniteCategory.FiniteCategory: isComposite :: (GeneratedFiniteCategory c m o, Morphism m o, Eq m) => c -> m -> Bool
- FiniteCategory.FiniteCategory: isGenerator :: (GeneratedFiniteCategory c m o, Morphism m o, Eq m) => c -> m -> Bool
- FiniteCategory.FiniteCategory: isIdentity :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> m -> Bool
- FiniteCategory.FiniteCategory: isInitial :: (FiniteCategory c m o, Morphism m o) => c -> o -> Bool
- FiniteCategory.FiniteCategory: isNotIdentity :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> m -> Bool
- FiniteCategory.FiniteCategory: isTerminal :: (FiniteCategory c m o, Morphism m o) => c -> o -> Bool
- FiniteCategory.FiniteCategory: ob :: FiniteCategory c m o => c -> [o]
- FiniteCategory.FiniteCategory: source :: Morphism m o => m -> o
- FiniteCategory.FiniteCategory: target :: Morphism m o => m -> o
- FiniteCategory.FiniteCategory: terminalObjects :: (FiniteCategory c m o, Morphism m o) => c -> [o]
- FunctorCategory.FunctorCategory: FunctorCategory :: c1 -> c2 -> FunctorCategory c1 m1 o1 c2 m2 o2
- FunctorCategory.FunctorCategory: NaturalTransformation :: Diagram c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 c2 m2 o2 -> (o1 -> m2) -> NaturalTransformation c1 m1 o1 c2 m2 o2
- FunctorCategory.FunctorCategory: [component] :: NaturalTransformation c1 m1 o1 c2 m2 o2 -> o1 -> m2
- FunctorCategory.FunctorCategory: [sourceCat] :: FunctorCategory c1 m1 o1 c2 m2 o2 -> c1
- FunctorCategory.FunctorCategory: [srcNT] :: NaturalTransformation c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 c2 m2 o2
- FunctorCategory.FunctorCategory: [targetCat] :: FunctorCategory c1 m1 o1 c2 m2 o2 -> c2
- FunctorCategory.FunctorCategory: [tgtNT] :: NaturalTransformation c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 c2 m2 o2
- FunctorCategory.FunctorCategory: data FunctorCategory c1 m1 o1 c2 m2 o2
- FunctorCategory.FunctorCategory: data NaturalTransformation c1 m1 o1 c2 m2 o2
- FunctorCategory.FunctorCategory: instance (FiniteCategory.FiniteCategory.FiniteCategory c1 m1 o1, FiniteCategory.FiniteCategory.Morphism m1 o1, GHC.Classes.Eq c1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, FiniteCategory.FiniteCategory.FiniteCategory c2 m2 o2, FiniteCategory.FiniteCategory.Morphism m2 o2, GHC.Classes.Eq c2, GHC.Classes.Eq m2, GHC.Classes.Eq o2) => FiniteCategory.FiniteCategory.Morphism (FunctorCategory.FunctorCategory.NaturalTransformation c1 m1 o1 c2 m2 o2) (Diagram.Diagram.Diagram c1 m1 o1 c2 m2 o2)
- FunctorCategory.FunctorCategory: instance (FiniteCategory.FiniteCategory.FiniteCategory c1 m1 o1, FiniteCategory.FiniteCategory.Morphism m1 o1, GHC.Classes.Eq c1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, FiniteCategory.FiniteCategory.FiniteCategory c2 m2 o2, FiniteCategory.FiniteCategory.Morphism m2 o2, GHC.Classes.Eq c2, GHC.Classes.Eq m2, GHC.Classes.Eq o2) => GHC.Classes.Eq (FunctorCategory.FunctorCategory.NaturalTransformation c1 m1 o1 c2 m2 o2)
- FunctorCategory.FunctorCategory: instance (FiniteCategory.FiniteCategory.FiniteCategory c1 m1 o1, FiniteCategory.FiniteCategory.Morphism m1 o1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, FiniteCategory.FiniteCategory.FiniteCategory c2 m2 o2, FiniteCategory.FiniteCategory.Morphism m2 o2, GHC.Classes.Eq m2, GHC.Classes.Eq o2) => FiniteCategory.FiniteCategory.FiniteCategory (FunctorCategory.FunctorCategory.FunctorCategory c1 m1 o1 c2 m2 o2) (FunctorCategory.FunctorCategory.NaturalTransformation c1 m1 o1 c2 m2 o2) (Diagram.Diagram.Diagram c1 m1 o1 c2 m2 o2)
- FunctorCategory.FunctorCategory: instance (FiniteCategory.FiniteCategory.FiniteCategory c1 m1 o1, FiniteCategory.FiniteCategory.Morphism m1 o1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, FiniteCategory.FiniteCategory.FiniteCategory c2 m2 o2, FiniteCategory.FiniteCategory.Morphism m2 o2, GHC.Classes.Eq m2, GHC.Classes.Eq o2) => FiniteCategory.FiniteCategory.GeneratedFiniteCategory (FunctorCategory.FunctorCategory.FunctorCategory c1 m1 o1 c2 m2 o2) (FunctorCategory.FunctorCategory.NaturalTransformation c1 m1 o1 c2 m2 o2) (Diagram.Diagram.Diagram c1 m1 o1 c2 m2 o2)
- FunctorCategory.FunctorCategory: instance (FiniteCategory.FiniteCategory.FiniteCategory c1 m1 o1, FiniteCategory.FiniteCategory.Morphism m1 o1, GHC.Show.Show c1, GHC.Show.Show m1, GHC.Show.Show o1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, FiniteCategory.FiniteCategory.FiniteCategory c2 m2 o2, FiniteCategory.FiniteCategory.Morphism m2 o2, GHC.Show.Show c2, GHC.Show.Show m2, GHC.Show.Show o2) => GHC.Show.Show (FunctorCategory.FunctorCategory.NaturalTransformation c1 m1 o1 c2 m2 o2)
- FunctorCategory.FunctorCategory: instance (FiniteCategory.FiniteCategory.FiniteCategory c1 m1 o1, FiniteCategory.FiniteCategory.Morphism m1 o1, IO.PrettyPrint.PrettyPrintable c1, IO.PrettyPrint.PrettyPrintable m1, IO.PrettyPrint.PrettyPrintable o1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, FiniteCategory.FiniteCategory.FiniteCategory c2 m2 o2, FiniteCategory.FiniteCategory.Morphism m2 o2, IO.PrettyPrint.PrettyPrintable c2, IO.PrettyPrint.PrettyPrintable m2, IO.PrettyPrint.PrettyPrintable o2) => IO.PrettyPrint.PrettyPrintable (FunctorCategory.FunctorCategory.NaturalTransformation c1 m1 o1 c2 m2 o2)
- FunctorCategory.FunctorCategory: instance (GHC.Classes.Eq c1, GHC.Classes.Eq c2) => GHC.Classes.Eq (FunctorCategory.FunctorCategory.FunctorCategory c1 m1 o1 c2 m2 o2)
- FunctorCategory.FunctorCategory: instance (GHC.Show.Show c1, GHC.Show.Show c2) => GHC.Show.Show (FunctorCategory.FunctorCategory.FunctorCategory c1 m1 o1 c2 m2 o2)
- FunctorCategory.FunctorCategory: instance (IO.PrettyPrint.PrettyPrintable c1, IO.PrettyPrint.PrettyPrintable c2) => IO.PrettyPrint.PrettyPrintable (FunctorCategory.FunctorCategory.FunctorCategory c1 m1 o1 c2 m2 o2)
- FunctorCategory.FunctorCategory: postWhiskering :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2, FiniteCategory c3 m3 o3, Morphism m3 o3) => Diagram c2 m2 o2 c3 m3 o3 -> NaturalTransformation c1 m1 o1 c2 m2 o2 -> NaturalTransformation c1 m1 o1 c3 m3 o3
- FunctorCategory.FunctorCategory: preWhiskering :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2, FiniteCategory c3 m3 o3, Morphism m3 o3) => NaturalTransformation c2 m2 o2 c3 m3 o3 -> Diagram c1 m1 o1 c2 m2 o2 -> NaturalTransformation c1 m1 o1 c3 m3 o3
- IO.CreateAndWriteFile: createAndWriteFile :: FilePath -> Text -> IO ()
- IO.Parsers.CompositionGraph: readCGFile :: String -> IO CG
- IO.Parsers.CompositionGraph: writeCGFile :: (PrettyPrintable a, PrettyPrintable b, Eq a, Eq b) => CompositionGraph a b -> String -> IO ()
- IO.Parsers.Lexer: BeginArrow :: Token
- IO.Parsers.Lexer: BeginSrc :: Token
- IO.Parsers.Lexer: BeginTgt :: Token
- IO.Parsers.Lexer: EndArrow :: Token
- IO.Parsers.Lexer: EndSrc :: Token
- IO.Parsers.Lexer: EndTgt :: Token
- IO.Parsers.Lexer: Equals :: Token
- IO.Parsers.Lexer: Identity :: Token
- IO.Parsers.Lexer: MapsTo :: Token
- IO.Parsers.Lexer: Name :: Text -> Token
- IO.Parsers.Lexer: data Token
- IO.Parsers.Lexer: instance GHC.Classes.Eq IO.Parsers.Lexer.Token
- IO.Parsers.Lexer: instance GHC.Show.Show IO.Parsers.Lexer.Token
- IO.Parsers.Lexer: parserLex :: String -> [Token]
- IO.Parsers.Lexer: strip :: Token -> Token
- IO.Parsers.SafeCompositionGraph: parseSCGString :: String -> SCG
- IO.Parsers.SafeCompositionGraph: readSCGFile :: String -> IO SCG
- IO.Parsers.SafeCompositionGraph: type SCG = SafeCompositionGraph Text Text
- IO.Parsers.SafeCompositionGraph: writeSCGFile :: (PrettyPrintable a, PrettyPrintable b, Eq a, Eq b) => SafeCompositionGraph a b -> String -> IO ()
- IO.Parsers.SafeCompositionGraphFunctor: readFSCGFile :: String -> IO SCGD
- IO.PrettyPrint: class PrettyPrintable a
- IO.PrettyPrint: instance (GHC.Classes.Ord k, IO.PrettyPrint.PrettyPrintable k, IO.PrettyPrint.PrettyPrintable a) => IO.PrettyPrint.PrettyPrintable (Data.Map.Internal.Map k a)
- IO.PrettyPrint: instance (IO.PrettyPrint.PrettyPrintable a, IO.PrettyPrint.PrettyPrintable b) => IO.PrettyPrint.PrettyPrintable (Data.Either.Either a b)
- IO.PrettyPrint: instance (IO.PrettyPrint.PrettyPrintable a, IO.PrettyPrint.PrettyPrintable b) => IO.PrettyPrint.PrettyPrintable (a, b)
- IO.PrettyPrint: instance (IO.PrettyPrint.PrettyPrintable a, IO.PrettyPrint.PrettyPrintable b, IO.PrettyPrint.PrettyPrintable c) => IO.PrettyPrint.PrettyPrintable (a, b, c)
- IO.PrettyPrint: instance IO.PrettyPrint.PrettyPrintable Data.Text.Internal.Text
- IO.PrettyPrint: instance IO.PrettyPrint.PrettyPrintable GHC.Types.Char
- IO.PrettyPrint: instance IO.PrettyPrint.PrettyPrintable GHC.Types.Double
- IO.PrettyPrint: instance IO.PrettyPrint.PrettyPrintable GHC.Types.Int
- IO.PrettyPrint: instance IO.PrettyPrint.PrettyPrintable a => IO.PrettyPrint.PrettyPrintable (Data.Set.Internal.Set a)
- IO.PrettyPrint: instance IO.PrettyPrint.PrettyPrintable a => IO.PrettyPrint.PrettyPrintable (GHC.Maybe.Maybe a)
- IO.PrettyPrint: instance IO.PrettyPrint.PrettyPrintable a => IO.PrettyPrint.PrettyPrintable [a]
- IO.PrettyPrint: pprint :: PrettyPrintable a => a -> String
- IO.PrettyPrint: pprintFunction :: (PrettyPrintable a, PrettyPrintable b) => (a -> b) -> [a] -> String
- IO.Show: showFunction :: (Show a, Show b) => (a -> b) -> [a] -> String
- Limit.Limit: colimitFunctor :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => c1 -> c2 -> Diagram (FunctorCategory c1 m1 o1 c2 m2 o2) (NaturalTransformation c1 m1 o1 c2 m2 o2) (Diagram c1 m1 o1 c2 m2 o2) c2 m2 o2
- Limit.Limit: limitFunctor :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, PrettyPrintable c1, PrettyPrintable c2, PrettyPrintable o1, PrettyPrintable o2, PrettyPrintable m1, PrettyPrintable m2, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => c1 -> c2 -> Diagram (FunctorCategory c1 m1 o1 c2 m2 o2) (NaturalTransformation c1 m1 o1 c2 m2 o2) (Diagram c1 m1 o1 c2 m2 o2) c2 m2 o2
- OppositeCategory.OppositeCategory: Op :: c -> OppositeCategory c m o
- OppositeCategory.OppositeCategory: OpMorph :: m -> OppositeMorphism m o
- OppositeCategory.OppositeCategory: data OppositeCategory c m o
- OppositeCategory.OppositeCategory: data OppositeMorphism m o
- OppositeCategory.OppositeCategory: instance (FiniteCategory.FiniteCategory.FiniteCategory c m o, FiniteCategory.FiniteCategory.Morphism m o) => FiniteCategory.FiniteCategory.FiniteCategory (OppositeCategory.OppositeCategory.OppositeCategory c m o) (OppositeCategory.OppositeCategory.OppositeMorphism m o) o
- OppositeCategory.OppositeCategory: instance (FiniteCategory.FiniteCategory.GeneratedFiniteCategory c m o, FiniteCategory.FiniteCategory.Morphism m o) => FiniteCategory.FiniteCategory.GeneratedFiniteCategory (OppositeCategory.OppositeCategory.OppositeCategory c m o) (OppositeCategory.OppositeCategory.OppositeMorphism m o) o
- OppositeCategory.OppositeCategory: instance FiniteCategory.FiniteCategory.Morphism m o => FiniteCategory.FiniteCategory.Morphism (OppositeCategory.OppositeCategory.OppositeMorphism m o) o
- OppositeCategory.OppositeCategory: instance GHC.Classes.Eq c => GHC.Classes.Eq (OppositeCategory.OppositeCategory.OppositeCategory c m o)
- OppositeCategory.OppositeCategory: instance GHC.Classes.Eq m => GHC.Classes.Eq (OppositeCategory.OppositeCategory.OppositeMorphism m o)
- OppositeCategory.OppositeCategory: instance GHC.Classes.Ord c => GHC.Classes.Ord (OppositeCategory.OppositeCategory.OppositeCategory c m o)
- OppositeCategory.OppositeCategory: instance GHC.Classes.Ord m => GHC.Classes.Ord (OppositeCategory.OppositeCategory.OppositeMorphism m o)
- OppositeCategory.OppositeCategory: instance GHC.Show.Show c => GHC.Show.Show (OppositeCategory.OppositeCategory.OppositeCategory c m o)
- OppositeCategory.OppositeCategory: instance GHC.Show.Show m => GHC.Show.Show (OppositeCategory.OppositeCategory.OppositeMorphism m o)
- OppositeCategory.OppositeCategory: instance IO.PrettyPrint.PrettyPrintable c => IO.PrettyPrint.PrettyPrintable (OppositeCategory.OppositeCategory.OppositeCategory c m o)
- OppositeCategory.OppositeCategory: instance IO.PrettyPrint.PrettyPrintable m => IO.PrettyPrint.PrettyPrintable (OppositeCategory.OppositeCategory.OppositeMorphism m o)
- OppositeCategory.OppositeCategory: opOp :: OppositeCategory c m o -> c
- OppositeCategory.OppositeCategory: opOpMorph :: OppositeMorphism m o -> m
- ProductCategory.ProductCategory: ProductCategory :: c1 -> c2 -> ProductCategory c1 m1 o1 c2 m2 o2
- ProductCategory.ProductCategory: ProductMorphism :: m1 -> m2 -> ProductMorphism m1 o1 m2 o2
- ProductCategory.ProductCategory: ProductObject :: o1 -> o2 -> ProductObject o1 o2
- ProductCategory.ProductCategory: data ProductCategory c1 m1 o1 c2 m2 o2
- ProductCategory.ProductCategory: data ProductMorphism m1 o1 m2 o2
- ProductCategory.ProductCategory: data ProductObject o1 o2
- ProductCategory.ProductCategory: firstCategory :: ProductCategory c1 m1 o1 c2 m2 o2 -> c1
- ProductCategory.ProductCategory: firstMorphism :: ProductMorphism m1 o1 m2 o2 -> m1
- ProductCategory.ProductCategory: firstObject :: ProductObject o1 o2 -> o1
- ProductCategory.ProductCategory: instance (FiniteCategory.FiniteCategory.FiniteCategory c1 m1 o1, FiniteCategory.FiniteCategory.Morphism m1 o1, FiniteCategory.FiniteCategory.FiniteCategory c2 m2 o2, FiniteCategory.FiniteCategory.Morphism m2 o2) => FiniteCategory.FiniteCategory.FiniteCategory (ProductCategory.ProductCategory.ProductCategory c1 m1 o1 c2 m2 o2) (ProductCategory.ProductCategory.ProductMorphism m1 o1 m2 o2) (ProductCategory.ProductCategory.ProductObject o1 o2)
- ProductCategory.ProductCategory: instance (FiniteCategory.FiniteCategory.GeneratedFiniteCategory c1 m1 o1, FiniteCategory.FiniteCategory.Morphism m1 o1, FiniteCategory.FiniteCategory.GeneratedFiniteCategory c2 m2 o2, FiniteCategory.FiniteCategory.Morphism m2 o2) => FiniteCategory.FiniteCategory.GeneratedFiniteCategory (ProductCategory.ProductCategory.ProductCategory c1 m1 o1 c2 m2 o2) (ProductCategory.ProductCategory.ProductMorphism m1 o1 m2 o2) (ProductCategory.ProductCategory.ProductObject o1 o2)
- ProductCategory.ProductCategory: instance (FiniteCategory.FiniteCategory.Morphism m1 o1, FiniteCategory.FiniteCategory.Morphism m2 o2) => FiniteCategory.FiniteCategory.Morphism (ProductCategory.ProductCategory.ProductMorphism m1 o1 m2 o2) (ProductCategory.ProductCategory.ProductObject o1 o2)
- ProductCategory.ProductCategory: instance (GHC.Classes.Eq c1, GHC.Classes.Eq c2) => GHC.Classes.Eq (ProductCategory.ProductCategory.ProductCategory c1 m1 o1 c2 m2 o2)
- ProductCategory.ProductCategory: instance (GHC.Classes.Eq m1, GHC.Classes.Eq m2) => GHC.Classes.Eq (ProductCategory.ProductCategory.ProductMorphism m1 o1 m2 o2)
- ProductCategory.ProductCategory: instance (GHC.Classes.Eq o1, GHC.Classes.Eq o2) => GHC.Classes.Eq (ProductCategory.ProductCategory.ProductObject o1 o2)
- ProductCategory.ProductCategory: instance (GHC.Classes.Ord c1, GHC.Classes.Ord c2) => GHC.Classes.Ord (ProductCategory.ProductCategory.ProductCategory c1 m1 o1 c2 m2 o2)
- ProductCategory.ProductCategory: instance (GHC.Classes.Ord m1, GHC.Classes.Ord m2) => GHC.Classes.Ord (ProductCategory.ProductCategory.ProductMorphism m1 o1 m2 o2)
- ProductCategory.ProductCategory: instance (GHC.Classes.Ord o1, GHC.Classes.Ord o2) => GHC.Classes.Ord (ProductCategory.ProductCategory.ProductObject o1 o2)
- ProductCategory.ProductCategory: instance (GHC.Show.Show c1, GHC.Show.Show c2) => GHC.Show.Show (ProductCategory.ProductCategory.ProductCategory c1 m1 o1 c2 m2 o2)
- ProductCategory.ProductCategory: instance (GHC.Show.Show m1, GHC.Show.Show m2) => GHC.Show.Show (ProductCategory.ProductCategory.ProductMorphism m1 o1 m2 o2)
- ProductCategory.ProductCategory: instance (GHC.Show.Show o1, GHC.Show.Show o2) => GHC.Show.Show (ProductCategory.ProductCategory.ProductObject o1 o2)
- ProductCategory.ProductCategory: instance (IO.PrettyPrint.PrettyPrintable m1, IO.PrettyPrint.PrettyPrintable m2) => IO.PrettyPrint.PrettyPrintable (ProductCategory.ProductCategory.ProductMorphism m1 o1 m2 o2)
- ProductCategory.ProductCategory: instance (IO.PrettyPrint.PrettyPrintable o1, IO.PrettyPrint.PrettyPrintable o2) => IO.PrettyPrint.PrettyPrintable (ProductCategory.ProductCategory.ProductObject o1 o2)
- ProductCategory.ProductCategory: secondCategory :: ProductCategory c1 m1 o1 c2 m2 o2 -> c2
- ProductCategory.ProductCategory: secondMorphism :: ProductMorphism m1 o1 m2 o2 -> m2
- ProductCategory.ProductCategory: secondObject :: ProductObject o1 o2 -> o2
- RandomCompositionGraph.RandomCompositionGraph: defaultMkRandomCompositionGraph :: RandomGen g => g -> (CompositionGraph Int Int, g)
- RandomCompositionGraph.RandomCompositionGraph: mkRandomCompositionGraph :: RandomGen g => Int -> Int -> Int -> g -> (CompositionGraph Int Int, g)
- RandomDiagram.RandomDiagram: defaultMkRandomDiagram :: RandomGen g => g -> (Diagram (CompositionGraph Int Int) (CGMorphism Int Int) Int (CompositionGraph Int Int) (CGMorphism Int Int) Int, g)
- RandomDiagram.RandomDiagram: mkRandomDiagram :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2, RandomGen g) => c1 -> c2 -> g -> (Diagram c1 m1 o1 c2 m2 o2, g)
- Set.FinOrdSet: FinOrdMap :: Set a -> Map a a -> FinOrdMap a
- Set.FinOrdSet: FinOrdSet :: [Set a] -> FinOrdSet a
- Set.FinOrdSet: [codomain] :: FinOrdMap a -> Set a
- Set.FinOrdSet: [function] :: FinOrdMap a -> Map a a
- Set.FinOrdSet: [sets] :: FinOrdSet a -> [Set a]
- Set.FinOrdSet: data FinOrdMap a
- Set.FinOrdSet: data FinOrdSet a
- Set.FinOrdSet: instance (IO.PrettyPrint.PrettyPrintable a, GHC.Classes.Ord a) => IO.PrettyPrint.PrettyPrintable (Set.FinOrdSet.FinOrdMap a)
- Set.FinOrdSet: instance GHC.Classes.Eq a => GHC.Classes.Eq (Set.FinOrdSet.FinOrdMap a)
- Set.FinOrdSet: instance GHC.Classes.Ord a => FiniteCategory.FiniteCategory.FiniteCategory (Set.FinOrdSet.FinOrdSet a) (Set.FinOrdSet.FinOrdMap a) (Data.Set.Internal.Set a)
- Set.FinOrdSet: instance GHC.Classes.Ord a => FiniteCategory.FiniteCategory.GeneratedFiniteCategory (Set.FinOrdSet.FinOrdSet a) (Set.FinOrdSet.FinOrdMap a) (Data.Set.Internal.Set a)
- Set.FinOrdSet: instance GHC.Classes.Ord a => FiniteCategory.FiniteCategory.Morphism (Set.FinOrdSet.FinOrdMap a) (Data.Set.Internal.Set a)
- Set.FinOrdSet: instance GHC.Classes.Ord a => GHC.Classes.Eq (Set.FinOrdSet.FinOrdSet a)
- Set.FinOrdSet: instance GHC.Show.Show a => GHC.Show.Show (Set.FinOrdSet.FinOrdMap a)
- Set.FinOrdSet: instance GHC.Show.Show a => GHC.Show.Show (Set.FinOrdSet.FinOrdSet a)
- Set.FinOrdSet: instance IO.PrettyPrint.PrettyPrintable a => IO.PrettyPrint.PrettyPrintable (Set.FinOrdSet.FinOrdSet a)
- Set.FinOrdSet: powerFinOrdSet :: Ord a => Set a -> FinOrdSet a
- Set.FinSet: (&&&) :: Eq a => FinSet a -> FinSet a -> FinSet a
- Set.FinSet: (|||) :: Eq a => FinSet a -> FinSet a -> FinSet a
- Set.FinSet: Collection :: [FinSet a] -> FinSet a
- Set.FinSet: Elem :: a -> FinSet a
- Set.FinSet: FinMap :: AssociationList (FinSet a) (FinSet a) -> FinSet a -> FinMap a
- Set.FinSet: FinSetCat :: [FinSet a] -> FinSetCat a
- Set.FinSet: [codomain] :: FinMap a -> FinSet a
- Set.FinSet: [finMap] :: FinMap a -> AssociationList (FinSet a) (FinSet a)
- Set.FinSet: card :: FinSet a -> Int
- Set.FinSet: constructLimit :: (FiniteCategory c m o, Morphism m o, Eq a, Eq c, Eq m, Eq o) => Diagram c m o (FinSetCat a) (FinMap a) (FinSet a) -> (Diagram (FinSetCat a) (FinMap a) (FinSet a) (FinSetCat a) (FinMap a) (FinSet a), Diagram c m o (FinSetCat a) (FinMap a) (FinSet a), FinSet a)
- Set.FinSet: data FinMap a
- Set.FinSet: data FinSet a
- Set.FinSet: data FinSetCat a
- Set.FinSet: emptyFinSet :: FinSet a
- Set.FinSet: fromList :: Eq a => [FinSet a] -> FinSet a
- Set.FinSet: generalizeType :: FinSet a -> FinSet (Either a b)
- Set.FinSet: generalizeTypeSetCat :: FinSetCat a -> FinSetCat (Either a b)
- Set.FinSet: includedIn :: Eq a => FinSet a -> FinSet a -> Bool
- Set.FinSet: instance (IO.PrettyPrint.PrettyPrintable a, GHC.Classes.Eq a) => IO.PrettyPrint.PrettyPrintable (Set.FinSet.FinMap a)
- Set.FinSet: instance GHC.Base.Functor Set.FinSet.FinSet
- Set.FinSet: instance GHC.Classes.Eq a => FiniteCategory.FiniteCategory.FiniteCategory (Set.FinSet.FinSetCat a) (Set.FinSet.FinMap a) (Set.FinSet.FinSet a)
- Set.FinSet: instance GHC.Classes.Eq a => FiniteCategory.FiniteCategory.GeneratedFiniteCategory (Set.FinSet.FinSetCat a) (Set.FinSet.FinMap a) (Set.FinSet.FinSet a)
- Set.FinSet: instance GHC.Classes.Eq a => FiniteCategory.FiniteCategory.Morphism (Set.FinSet.FinMap a) (Set.FinSet.FinSet a)
- Set.FinSet: instance GHC.Classes.Eq a => GHC.Classes.Eq (Set.FinSet.FinMap a)
- Set.FinSet: instance GHC.Classes.Eq a => GHC.Classes.Eq (Set.FinSet.FinSet a)
- Set.FinSet: instance GHC.Classes.Eq a => GHC.Classes.Eq (Set.FinSet.FinSetCat a)
- Set.FinSet: instance GHC.Show.Show a => GHC.Show.Show (Set.FinSet.FinMap a)
- Set.FinSet: instance GHC.Show.Show a => GHC.Show.Show (Set.FinSet.FinSet a)
- Set.FinSet: instance GHC.Show.Show a => GHC.Show.Show (Set.FinSet.FinSetCat a)
- Set.FinSet: instance IO.PrettyPrint.PrettyPrintable a => IO.PrettyPrint.PrettyPrintable (Set.FinSet.FinSet a)
- Set.FinSet: instance IO.PrettyPrint.PrettyPrintable a => IO.PrettyPrint.PrettyPrintable (Set.FinSet.FinSetCat a)
- Set.FinSet: intersection :: Eq a => [FinSet a] -> FinSet a
- Set.FinSet: isIn :: Eq a => FinSet a -> FinSet a -> Bool
- Set.FinSet: powerFinSet :: FinSet a -> FinSet a
- Set.FinSet: singleton :: a -> FinSet a
- Set.FinSet: toList :: FinSet a -> [FinSet a]
- Set.FinSet: union :: Eq a => [FinSet a] -> FinSet a
- Subcategories.FreeSubcategory: FreeSubcategory :: c -> [m] -> FreeSubcategory c m o
- Subcategories.FreeSubcategory: data FreeSubcategory c m o
- Subcategories.FreeSubcategory: instance (FiniteCategory.FiniteCategory.FiniteCategory c m o, FiniteCategory.FiniteCategory.Morphism m o, GHC.Classes.Eq m, GHC.Classes.Eq o) => FiniteCategory.FiniteCategory.FiniteCategory (Subcategories.FreeSubcategory.FreeSubcategory c m o) m o
- Subcategories.FreeSubcategory: instance (FiniteCategory.FiniteCategory.FiniteCategory c m o, FiniteCategory.FiniteCategory.Morphism m o, GHC.Classes.Eq m, GHC.Classes.Eq o) => FiniteCategory.FiniteCategory.GeneratedFiniteCategory (Subcategories.FreeSubcategory.FreeSubcategory c m o) m o
- Subcategories.FullSubcategory: FullSubcategory :: c -> [o] -> FullSubcategory c m o
- Subcategories.FullSubcategory: data FullSubcategory c m o
- Subcategories.FullSubcategory: instance (FiniteCategory.FiniteCategory.FiniteCategory c m o, FiniteCategory.FiniteCategory.Morphism m o, GHC.Classes.Eq m, GHC.Classes.Eq o) => FiniteCategory.FiniteCategory.FiniteCategory (Subcategories.FullSubcategory.FullSubcategory c m o) m o
- Subcategories.FullSubcategory: instance (FiniteCategory.FiniteCategory.FiniteCategory c m o, FiniteCategory.FiniteCategory.Morphism m o, GHC.Classes.Eq m, GHC.Classes.Eq o) => FiniteCategory.FiniteCategory.GeneratedFiniteCategory (Subcategories.FullSubcategory.FullSubcategory c m o) m o
- Subcategories.FullSubcategory: instance (GHC.Classes.Eq c, GHC.Classes.Eq o) => GHC.Classes.Eq (Subcategories.FullSubcategory.FullSubcategory c m o)
- Subcategories.FullSubcategory: instance (GHC.Show.Show c, GHC.Show.Show o) => GHC.Show.Show (Subcategories.FullSubcategory.FullSubcategory c m o)
- Subcategories.FullSubcategory: instance (IO.PrettyPrint.PrettyPrintable c, IO.PrettyPrint.PrettyPrintable o) => IO.PrettyPrint.PrettyPrintable (Subcategories.FullSubcategory.FullSubcategory c m o)
- Subcategories.Subcategory: Subcategory :: Diagram c1 m1 o1 c2 m2 o2 -> Subcategory c1 m1 o1 c2 m2 o2
- Subcategories.Subcategory: data Subcategory c1 m1 o1 c2 m2 o2
- Subcategories.Subcategory: fullDiagram :: (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 c1 m1 o1 (Subcategory c1 m1 o1 c2 m2 o2) m2 o2
- Subcategories.Subcategory: instance (FiniteCategory.FiniteCategory.FiniteCategory c1 m1 o1, FiniteCategory.FiniteCategory.Morphism m1 o1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, FiniteCategory.FiniteCategory.FiniteCategory c2 m2 o2, FiniteCategory.FiniteCategory.Morphism m2 o2, GHC.Classes.Eq m2, GHC.Classes.Eq o2) => FiniteCategory.FiniteCategory.FiniteCategory (Subcategories.Subcategory.Subcategory c1 m1 o1 c2 m2 o2) m2 o2
- Subcategories.Subcategory: instance (FiniteCategory.FiniteCategory.GeneratedFiniteCategory c1 m1 o1, FiniteCategory.FiniteCategory.Morphism m1 o1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, FiniteCategory.FiniteCategory.GeneratedFiniteCategory c2 m2 o2, FiniteCategory.FiniteCategory.Morphism m2 o2, GHC.Classes.Eq m2, GHC.Classes.Eq o2) => FiniteCategory.FiniteCategory.GeneratedFiniteCategory (Subcategories.Subcategory.Subcategory c1 m1 o1 c2 m2 o2) m2 o2
- Subcategories.Subcategory: stripDiagram :: (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 -> [o2] -> Diagram c1 m1 o1 (FullSubcategory c2 m2 o2) m2 o2
- UsualCategories.DiscreteCategory: DiscreteCategory :: [a] -> DiscreteCategory a
- UsualCategories.DiscreteCategory: DiscreteIdentity :: a -> DiscreteIdentity a
- UsualCategories.DiscreteCategory: DiscreteObject :: a -> DiscreteObject a
- UsualCategories.DiscreteCategory: data DiscreteCategory a
- UsualCategories.DiscreteCategory: data DiscreteIdentity a
- UsualCategories.DiscreteCategory: data DiscreteObject a
- UsualCategories.DiscreteCategory: instance GHC.Classes.Eq a => FiniteCategory.FiniteCategory.FiniteCategory (UsualCategories.DiscreteCategory.DiscreteCategory a) (UsualCategories.DiscreteCategory.DiscreteIdentity a) (UsualCategories.DiscreteCategory.DiscreteObject a)
- UsualCategories.DiscreteCategory: instance GHC.Classes.Eq a => FiniteCategory.FiniteCategory.GeneratedFiniteCategory (UsualCategories.DiscreteCategory.DiscreteCategory a) (UsualCategories.DiscreteCategory.DiscreteIdentity a) (UsualCategories.DiscreteCategory.DiscreteObject a)
- UsualCategories.DiscreteCategory: instance GHC.Classes.Eq a => FiniteCategory.FiniteCategory.Morphism (UsualCategories.DiscreteCategory.DiscreteIdentity a) (UsualCategories.DiscreteCategory.DiscreteObject a)
- UsualCategories.DiscreteCategory: instance GHC.Classes.Eq a => GHC.Classes.Eq (UsualCategories.DiscreteCategory.DiscreteCategory a)
- UsualCategories.DiscreteCategory: instance GHC.Classes.Eq a => GHC.Classes.Eq (UsualCategories.DiscreteCategory.DiscreteIdentity a)
- UsualCategories.DiscreteCategory: instance GHC.Classes.Eq a => GHC.Classes.Eq (UsualCategories.DiscreteCategory.DiscreteObject a)
- UsualCategories.DiscreteCategory: instance GHC.Show.Show a => GHC.Show.Show (UsualCategories.DiscreteCategory.DiscreteCategory a)
- UsualCategories.DiscreteCategory: instance GHC.Show.Show a => GHC.Show.Show (UsualCategories.DiscreteCategory.DiscreteIdentity a)
- UsualCategories.DiscreteCategory: instance GHC.Show.Show a => GHC.Show.Show (UsualCategories.DiscreteCategory.DiscreteObject a)
- UsualCategories.DiscreteCategory: instance IO.PrettyPrint.PrettyPrintable a => IO.PrettyPrint.PrettyPrintable (UsualCategories.DiscreteCategory.DiscreteCategory a)
- UsualCategories.DiscreteCategory: instance IO.PrettyPrint.PrettyPrintable a => IO.PrettyPrint.PrettyPrintable (UsualCategories.DiscreteCategory.DiscreteIdentity a)
- UsualCategories.DiscreteCategory: instance IO.PrettyPrint.PrettyPrintable a => IO.PrettyPrint.PrettyPrintable (UsualCategories.DiscreteCategory.DiscreteObject a)
- UsualCategories.Hat: A :: HatOb
- UsualCategories.Hat: B :: HatOb
- UsualCategories.Hat: C :: HatOb
- UsualCategories.Hat: F :: HatAr
- UsualCategories.Hat: G :: HatAr
- UsualCategories.Hat: Hat :: Hat
- UsualCategories.Hat: IdA :: HatAr
- UsualCategories.Hat: IdB :: HatAr
- UsualCategories.Hat: IdC :: HatAr
- UsualCategories.Hat: data Hat
- UsualCategories.Hat: data HatAr
- UsualCategories.Hat: data HatOb
- UsualCategories.Hat: instance FiniteCategory.FiniteCategory.FiniteCategory UsualCategories.Hat.Hat UsualCategories.Hat.HatAr UsualCategories.Hat.HatOb
- UsualCategories.Hat: instance FiniteCategory.FiniteCategory.GeneratedFiniteCategory UsualCategories.Hat.Hat UsualCategories.Hat.HatAr UsualCategories.Hat.HatOb
- UsualCategories.Hat: instance FiniteCategory.FiniteCategory.Morphism UsualCategories.Hat.HatAr UsualCategories.Hat.HatOb
- UsualCategories.Hat: instance GHC.Classes.Eq UsualCategories.Hat.Hat
- UsualCategories.Hat: instance GHC.Classes.Eq UsualCategories.Hat.HatAr
- UsualCategories.Hat: instance GHC.Classes.Eq UsualCategories.Hat.HatOb
- UsualCategories.Hat: instance GHC.Show.Show UsualCategories.Hat.Hat
- UsualCategories.Hat: instance GHC.Show.Show UsualCategories.Hat.HatAr
- UsualCategories.Hat: instance GHC.Show.Show UsualCategories.Hat.HatOb
- UsualCategories.Hat: instance IO.PrettyPrint.PrettyPrintable UsualCategories.Hat.Hat
- UsualCategories.Hat: instance IO.PrettyPrint.PrettyPrintable UsualCategories.Hat.HatAr
- UsualCategories.Hat: instance IO.PrettyPrint.PrettyPrintable UsualCategories.Hat.HatOb
- UsualCategories.One: One :: One
- UsualCategories.One: data One
- UsualCategories.One: instance FiniteCategory.FiniteCategory.FiniteCategory UsualCategories.One.One UsualCategories.One.One UsualCategories.One.One
- UsualCategories.One: instance FiniteCategory.FiniteCategory.GeneratedFiniteCategory UsualCategories.One.One UsualCategories.One.One UsualCategories.One.One
- UsualCategories.One: instance FiniteCategory.FiniteCategory.Morphism UsualCategories.One.One UsualCategories.One.One
- UsualCategories.One: instance GHC.Classes.Eq UsualCategories.One.One
- UsualCategories.One: instance GHC.Show.Show UsualCategories.One.One
- UsualCategories.One: instance IO.PrettyPrint.PrettyPrintable UsualCategories.One.One
- UsualCategories.Parallel: A :: ParallelOb
- UsualCategories.Parallel: B :: ParallelOb
- UsualCategories.Parallel: F :: ParallelAr
- UsualCategories.Parallel: G :: ParallelAr
- UsualCategories.Parallel: IdA :: ParallelAr
- UsualCategories.Parallel: IdB :: ParallelAr
- UsualCategories.Parallel: Parallel :: Parallel
- UsualCategories.Parallel: data Parallel
- UsualCategories.Parallel: data ParallelAr
- UsualCategories.Parallel: data ParallelOb
- UsualCategories.Parallel: instance FiniteCategory.FiniteCategory.FiniteCategory UsualCategories.Parallel.Parallel UsualCategories.Parallel.ParallelAr UsualCategories.Parallel.ParallelOb
- UsualCategories.Parallel: instance FiniteCategory.FiniteCategory.GeneratedFiniteCategory UsualCategories.Parallel.Parallel UsualCategories.Parallel.ParallelAr UsualCategories.Parallel.ParallelOb
- UsualCategories.Parallel: instance FiniteCategory.FiniteCategory.Morphism UsualCategories.Parallel.ParallelAr UsualCategories.Parallel.ParallelOb
- UsualCategories.Parallel: instance GHC.Classes.Eq UsualCategories.Parallel.Parallel
- UsualCategories.Parallel: instance GHC.Classes.Eq UsualCategories.Parallel.ParallelAr
- UsualCategories.Parallel: instance GHC.Classes.Eq UsualCategories.Parallel.ParallelOb
- UsualCategories.Parallel: instance GHC.Show.Show UsualCategories.Parallel.Parallel
- UsualCategories.Parallel: instance GHC.Show.Show UsualCategories.Parallel.ParallelAr
- UsualCategories.Parallel: instance GHC.Show.Show UsualCategories.Parallel.ParallelOb
- UsualCategories.Parallel: instance IO.PrettyPrint.PrettyPrintable UsualCategories.Parallel.Parallel
- UsualCategories.Parallel: instance IO.PrettyPrint.PrettyPrintable UsualCategories.Parallel.ParallelAr
- UsualCategories.Parallel: instance IO.PrettyPrint.PrettyPrintable UsualCategories.Parallel.ParallelOb
- UsualCategories.Square: A :: SquareOb
- UsualCategories.Square: B :: SquareOb
- UsualCategories.Square: C :: SquareOb
- UsualCategories.Square: D :: SquareOb
- UsualCategories.Square: F :: SquareAr
- UsualCategories.Square: FH :: SquareAr
- UsualCategories.Square: G :: SquareAr
- UsualCategories.Square: GI :: SquareAr
- UsualCategories.Square: H :: SquareAr
- UsualCategories.Square: I :: SquareAr
- UsualCategories.Square: IdA :: SquareAr
- UsualCategories.Square: IdB :: SquareAr
- UsualCategories.Square: IdC :: SquareAr
- UsualCategories.Square: IdD :: SquareAr
- UsualCategories.Square: Square :: Square
- UsualCategories.Square: data Square
- UsualCategories.Square: data SquareAr
- UsualCategories.Square: data SquareOb
- UsualCategories.Square: instance FiniteCategory.FiniteCategory.FiniteCategory UsualCategories.Square.Square UsualCategories.Square.SquareAr UsualCategories.Square.SquareOb
- UsualCategories.Square: instance FiniteCategory.FiniteCategory.GeneratedFiniteCategory UsualCategories.Square.Square UsualCategories.Square.SquareAr UsualCategories.Square.SquareOb
- UsualCategories.Square: instance FiniteCategory.FiniteCategory.Morphism UsualCategories.Square.SquareAr UsualCategories.Square.SquareOb
- UsualCategories.Square: instance GHC.Classes.Eq UsualCategories.Square.Square
- UsualCategories.Square: instance GHC.Classes.Eq UsualCategories.Square.SquareAr
- UsualCategories.Square: instance GHC.Classes.Eq UsualCategories.Square.SquareOb
- UsualCategories.Square: instance GHC.Show.Show UsualCategories.Square.Square
- UsualCategories.Square: instance GHC.Show.Show UsualCategories.Square.SquareAr
- UsualCategories.Square: instance GHC.Show.Show UsualCategories.Square.SquareOb
- UsualCategories.Square: instance IO.PrettyPrint.PrettyPrintable UsualCategories.Square.Square
- UsualCategories.Square: instance IO.PrettyPrint.PrettyPrintable UsualCategories.Square.SquareAr
- UsualCategories.Square: instance IO.PrettyPrint.PrettyPrintable UsualCategories.Square.SquareOb
- UsualCategories.Three: A :: ThreeOb
- UsualCategories.Three: B :: ThreeOb
- UsualCategories.Three: C :: ThreeOb
- UsualCategories.Three: F :: ThreeAr
- UsualCategories.Three: G :: ThreeAr
- UsualCategories.Three: GF :: ThreeAr
- UsualCategories.Three: IdA :: ThreeAr
- UsualCategories.Three: IdB :: ThreeAr
- UsualCategories.Three: IdC :: ThreeAr
- UsualCategories.Three: Three :: Three
- UsualCategories.Three: data Three
- UsualCategories.Three: data ThreeAr
- UsualCategories.Three: data ThreeOb
- UsualCategories.Three: instance FiniteCategory.FiniteCategory.FiniteCategory UsualCategories.Three.Three UsualCategories.Three.ThreeAr UsualCategories.Three.ThreeOb
- UsualCategories.Three: instance FiniteCategory.FiniteCategory.GeneratedFiniteCategory UsualCategories.Three.Three UsualCategories.Three.ThreeAr UsualCategories.Three.ThreeOb
- UsualCategories.Three: instance FiniteCategory.FiniteCategory.Morphism UsualCategories.Three.ThreeAr UsualCategories.Three.ThreeOb
- UsualCategories.Three: instance GHC.Classes.Eq UsualCategories.Three.Three
- UsualCategories.Three: instance GHC.Classes.Eq UsualCategories.Three.ThreeAr
- UsualCategories.Three: instance GHC.Classes.Eq UsualCategories.Three.ThreeOb
- UsualCategories.Three: instance GHC.Show.Show UsualCategories.Three.Three
- UsualCategories.Three: instance GHC.Show.Show UsualCategories.Three.ThreeAr
- UsualCategories.Three: instance GHC.Show.Show UsualCategories.Three.ThreeOb
- UsualCategories.Three: instance IO.PrettyPrint.PrettyPrintable UsualCategories.Three.Three
- UsualCategories.Three: instance IO.PrettyPrint.PrettyPrintable UsualCategories.Three.ThreeAr
- UsualCategories.Three: instance IO.PrettyPrint.PrettyPrintable UsualCategories.Three.ThreeOb
- UsualCategories.Two: A :: TwoOb
- UsualCategories.Two: B :: TwoOb
- UsualCategories.Two: F :: TwoAr
- UsualCategories.Two: IdA :: TwoAr
- UsualCategories.Two: IdB :: TwoAr
- UsualCategories.Two: Two :: Two
- UsualCategories.Two: data Two
- UsualCategories.Two: data TwoAr
- UsualCategories.Two: data TwoOb
- UsualCategories.Two: instance FiniteCategory.FiniteCategory.FiniteCategory UsualCategories.Two.Two UsualCategories.Two.TwoAr UsualCategories.Two.TwoOb
- UsualCategories.Two: instance FiniteCategory.FiniteCategory.GeneratedFiniteCategory UsualCategories.Two.Two UsualCategories.Two.TwoAr UsualCategories.Two.TwoOb
- UsualCategories.Two: instance FiniteCategory.FiniteCategory.Morphism UsualCategories.Two.TwoAr UsualCategories.Two.TwoOb
- UsualCategories.Two: instance GHC.Classes.Eq UsualCategories.Two.Two
- UsualCategories.Two: instance GHC.Classes.Eq UsualCategories.Two.TwoAr
- UsualCategories.Two: instance GHC.Classes.Eq UsualCategories.Two.TwoOb
- UsualCategories.Two: instance GHC.Show.Show UsualCategories.Two.Two
- UsualCategories.Two: instance GHC.Show.Show UsualCategories.Two.TwoAr
- UsualCategories.Two: instance GHC.Show.Show UsualCategories.Two.TwoOb
- UsualCategories.Two: instance IO.PrettyPrint.PrettyPrintable UsualCategories.Two.Two
- UsualCategories.Two: instance IO.PrettyPrint.PrettyPrintable UsualCategories.Two.TwoAr
- UsualCategories.Two: instance IO.PrettyPrint.PrettyPrintable UsualCategories.Two.TwoOb
- UsualCategories.V: A :: VOb
- UsualCategories.V: B :: VOb
- UsualCategories.V: C :: VOb
- UsualCategories.V: F :: VAr
- UsualCategories.V: G :: VAr
- UsualCategories.V: IdA :: VAr
- UsualCategories.V: IdB :: VAr
- UsualCategories.V: IdC :: VAr
- UsualCategories.V: V :: V
- UsualCategories.V: data V
- UsualCategories.V: data VAr
- UsualCategories.V: data VOb
- UsualCategories.V: instance FiniteCategory.FiniteCategory.FiniteCategory UsualCategories.V.V UsualCategories.V.VAr UsualCategories.V.VOb
- UsualCategories.V: instance FiniteCategory.FiniteCategory.GeneratedFiniteCategory UsualCategories.V.V UsualCategories.V.VAr UsualCategories.V.VOb
- UsualCategories.V: instance FiniteCategory.FiniteCategory.Morphism UsualCategories.V.VAr UsualCategories.V.VOb
- UsualCategories.V: instance GHC.Classes.Eq UsualCategories.V.V
- UsualCategories.V: instance GHC.Classes.Eq UsualCategories.V.VAr
- UsualCategories.V: instance GHC.Classes.Eq UsualCategories.V.VOb
- UsualCategories.V: instance GHC.Show.Show UsualCategories.V.V
- UsualCategories.V: instance GHC.Show.Show UsualCategories.V.VAr
- UsualCategories.V: instance GHC.Show.Show UsualCategories.V.VOb
- UsualCategories.V: instance IO.PrettyPrint.PrettyPrintable UsualCategories.V.V
- UsualCategories.V: instance IO.PrettyPrint.PrettyPrintable UsualCategories.V.VAr
- UsualCategories.V: instance IO.PrettyPrint.PrettyPrintable UsualCategories.V.VOb
- UsualCategories.Zero: Zero :: Zero
- UsualCategories.Zero: data Zero
- UsualCategories.Zero: instance FiniteCategory.FiniteCategory.FiniteCategory UsualCategories.Zero.Zero UsualCategories.Zero.Zero UsualCategories.Zero.Zero
- UsualCategories.Zero: instance FiniteCategory.FiniteCategory.GeneratedFiniteCategory UsualCategories.Zero.Zero UsualCategories.Zero.Zero UsualCategories.Zero.Zero
- UsualCategories.Zero: instance FiniteCategory.FiniteCategory.Morphism UsualCategories.Zero.Zero UsualCategories.Zero.Zero
- UsualCategories.Zero: instance GHC.Classes.Eq UsualCategories.Zero.Zero
- UsualCategories.Zero: instance GHC.Show.Show UsualCategories.Zero.Zero
- UsualCategories.Zero: instance IO.PrettyPrint.PrettyPrintable UsualCategories.Zero.Zero
- Utils.AssociationList: (!-!) :: Eq a => AssociationList a b -> a -> b
- Utils.AssociationList: (!-) :: Eq a => a -> AssociationList a b -> Maybe b
- Utils.AssociationList: (!-.) :: (Eq a, Eq b) => AssociationList b c -> AssociationList a b -> AssociationList a c
- Utils.AssociationList: (!-?) :: Eq a => b -> a -> AssociationList a b -> b
- Utils.AssociationList: assocListToFunct :: Eq a => AssociationList a b -> a -> b
- Utils.AssociationList: enumAssocLists :: [a] -> [b] -> [AssociationList a b]
- Utils.AssociationList: functToAssocList :: (a -> b) -> [a] -> AssociationList a b
- Utils.AssociationList: inverse :: AssociationList a b -> AssociationList b a
- Utils.AssociationList: keys :: AssociationList a b -> [a]
- Utils.AssociationList: mkAssocListIdentity :: [a] -> AssociationList a a
- Utils.AssociationList: removeKey :: Eq a => AssociationList a b -> a -> AssociationList a b
- Utils.AssociationList: removeValue :: Eq b => AssociationList a b -> b -> AssociationList a b
- Utils.AssociationList: type AssociationList a b = [(a, b)]
- Utils.AssociationList: values :: AssociationList a b -> [b]
- Utils.CartesianProduct: (|*|) :: [a] -> [a] -> [[a]]
- Utils.CartesianProduct: (|^|) :: [a] -> Int -> [[a]]
- Utils.CartesianProduct: cartesianPower :: [a] -> Int -> [[a]]
- Utils.CartesianProduct: cartesianProduct :: [[a]] -> [[a]]
- Utils.EnumerateMaps: enumMaps :: [a] -> [b] -> [AssociationList a b]
- Utils.Sample: pickOne :: RandomGen g => [a] -> g -> (a, g)
- Utils.Sample: sample :: RandomGen g => [a] -> Int -> g -> ([a], g)
- Utils.SetList: doubleInclusion :: Eq a => [a] -> [a] -> Bool
- Utils.SetList: isIncludedIn :: Eq a => [a] -> [a] -> Bool
- Utils.SetList: powerList :: Eq a => [a] -> [[a]]
- Utils.Tuple: fst3 :: (a, b, c) -> a
- Utils.Tuple: snd3 :: (a, b, c) -> b
- Utils.Tuple: trd3 :: (a, b, c) -> c
- Utils.Tuple: uncurry3 :: (a -> b -> c -> d) -> (a, b, c) -> d
- YonedaEmbedding.YonedaEmbedding: type PreSheaf c m o = Diagram (OppositeCategory c m o) (OppositeMorphism m o) o (FinSetCat m) (FinMap m) (FinSet m)
- YonedaEmbedding.YonedaEmbedding: type PreSheavesCategory c m o = FunctorCategory (OppositeCategory c m o) (OppositeMorphism m o) o (FinSetCat m) (FinMap m) (FinSet m)
- YonedaEmbedding.YonedaEmbedding: type PreSheavesNatTransfo c m o = NaturalTransformation (OppositeCategory c m o) (OppositeMorphism m o) o (FinSetCat m) (FinMap m) (FinSet m)
- YonedaEmbedding.YonedaEmbedding: yonedaEmbedding :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> (PreSheavesCategory c m o, Diagram c m o (PreSheavesCategory c m o) (PreSheavesNatTransfo c m o) (PreSheaf c m o))
+ Math.Categories.CommaCategory: CommaCategory :: Diagram c1 m1 o1 c3 m3 o3 -> Diagram c2 m2 o2 c3 m3 o3 -> CommaCategory c1 m1 o1 c2 m2 o2 c3 m3 o3
+ Math.Categories.CommaCategory: [leftDiagram] :: CommaCategory c1 m1 o1 c2 m2 o2 c3 m3 o3 -> Diagram c1 m1 o1 c3 m3 o3
+ Math.Categories.CommaCategory: [rightDiagram] :: CommaCategory c1 m1 o1 c2 m2 o2 c3 m3 o3 -> Diagram c2 m2 o2 c3 m3 o3
+ Math.Categories.CommaCategory: arrowCategory :: (FiniteCategory c m o, Morphism m o, Eq c, Eq m, Eq o) => c -> CommaCategory c m o c m o c m o
+ Math.Categories.CommaCategory: commaMorphism :: (Morphism m3 o3, Eq o1, Eq o2, Eq o3, Eq m1, Eq m2, Eq m3) => Diagram c1 m1 o1 c3 m3 o3 -> Diagram c2 m2 o2 c3 m3 o3 -> CommaObject o1 o2 m3 -> CommaObject o1 o2 m3 -> m1 -> m2 -> Maybe (CommaMorphism o1 o2 m1 m2 m3)
+ Math.Categories.CommaCategory: commaObject :: (Morphism m3 o3, Eq o1, Eq o2, Eq o3) => Diagram c1 m1 o1 c3 m3 o3 -> Diagram c2 m2 o2 c3 m3 o3 -> o1 -> o2 -> m3 -> Maybe (CommaObject o1 o2 m3)
+ Math.Categories.CommaCategory: cosliceCategory :: (FiniteCategory c m o, Morphism m o, Eq c, Eq m, Eq o) => c -> o -> Maybe (CommaCategory One One One c m o c m o)
+ Math.Categories.CommaCategory: data CommaCategory c1 m1 o1 c2 m2 o2 c3 m3 o3
+ Math.Categories.CommaCategory: data CommaMorphism o1 o2 m1 m2 m3
+ Math.Categories.CommaCategory: data CommaObject o1 o2 m3
+ Math.Categories.CommaCategory: indexFirstArrow :: CommaMorphism o1 o2 m1 m2 m3 -> m1
+ Math.Categories.CommaCategory: indexSecondArrow :: CommaMorphism o1 o2 m1 m2 m3 -> m2
+ Math.Categories.CommaCategory: indexSource :: CommaObject o1 o2 m3 -> o1
+ Math.Categories.CommaCategory: indexTarget :: CommaObject o1 o2 m3 -> o2
+ Math.Categories.CommaCategory: instance (GHC.Classes.Eq c1, GHC.Classes.Eq c3, GHC.Classes.Eq o1, GHC.Classes.Eq o3, GHC.Classes.Eq m1, GHC.Classes.Eq m3, GHC.Classes.Eq c2, GHC.Classes.Eq o2, GHC.Classes.Eq m2) => GHC.Classes.Eq (Math.Categories.CommaCategory.CommaCategory c1 m1 o1 c2 m2 o2 c3 m3 o3)
+ Math.Categories.CommaCategory: instance (GHC.Classes.Eq o1, GHC.Classes.Eq o2, GHC.Classes.Eq m3) => GHC.Classes.Eq (Math.Categories.CommaCategory.CommaObject o1 o2 m3)
+ Math.Categories.CommaCategory: instance (GHC.Classes.Eq o1, GHC.Classes.Eq o2, GHC.Classes.Eq m3, GHC.Classes.Eq m1, GHC.Classes.Eq m2) => GHC.Classes.Eq (Math.Categories.CommaCategory.CommaMorphism o1 o2 m1 m2 m3)
+ Math.Categories.CommaCategory: instance (GHC.Show.Show c1, GHC.Show.Show c3, GHC.Show.Show o1, GHC.Show.Show o3, GHC.Show.Show m1, GHC.Show.Show m3, GHC.Show.Show c2, GHC.Show.Show o2, GHC.Show.Show m2) => GHC.Show.Show (Math.Categories.CommaCategory.CommaCategory c1 m1 o1 c2 m2 o2 c3 m3 o3)
+ Math.Categories.CommaCategory: instance (GHC.Show.Show o1, GHC.Show.Show o2, GHC.Show.Show m1, GHC.Show.Show m2, GHC.Show.Show m3) => GHC.Show.Show (Math.Categories.CommaCategory.CommaMorphism o1 o2 m1 m2 m3)
+ Math.Categories.CommaCategory: instance (GHC.Show.Show o1, GHC.Show.Show o2, GHC.Show.Show m3) => GHC.Show.Show (Math.Categories.CommaCategory.CommaObject o1 o2 m3)
+ Math.Categories.CommaCategory: instance (Math.Category.Category c1 m1 o1, Math.Category.Morphism m1 o1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, Math.Category.Category c2 m2 o2, Math.Category.Morphism m2 o2, GHC.Classes.Eq m2, GHC.Classes.Eq o2, Math.Category.Category c3 m3 o3, Math.Category.Morphism m3 o3, GHC.Classes.Eq m3, GHC.Classes.Eq o3) => Math.Category.Category (Math.Categories.CommaCategory.CommaCategory c1 m1 o1 c2 m2 o2 c3 m3 o3) (Math.Categories.CommaCategory.CommaMorphism o1 o2 m1 m2 m3) (Math.Categories.CommaCategory.CommaObject o1 o2 m3)
+ Math.Categories.CommaCategory: instance (Math.Category.Morphism m1 o1, Math.Category.Morphism m2 o2, GHC.Classes.Eq o1, GHC.Classes.Eq o2, GHC.Classes.Eq m3) => Math.Category.Morphism (Math.Categories.CommaCategory.CommaMorphism o1 o2 m1 m2 m3) (Math.Categories.CommaCategory.CommaObject o1 o2 m3)
+ Math.Categories.CommaCategory: instance (Math.FiniteCategory.FiniteCategory c1 m1 o1, Math.Category.Morphism m1 o1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, Math.FiniteCategory.FiniteCategory c2 m2 o2, Math.Category.Morphism m2 o2, GHC.Classes.Eq m2, GHC.Classes.Eq o2, Math.FiniteCategory.FiniteCategory c3 m3 o3, Math.Category.Morphism m3 o3, GHC.Classes.Eq m3, GHC.Classes.Eq o3) => Math.FiniteCategory.FiniteCategory (Math.Categories.CommaCategory.CommaCategory c1 m1 o1 c2 m2 o2 c3 m3 o3) (Math.Categories.CommaCategory.CommaMorphism o1 o2 m1 m2 m3) (Math.Categories.CommaCategory.CommaObject o1 o2 m3)
+ Math.Categories.CommaCategory: instance (Math.IO.PrettyPrint.PrettyPrint m1, Math.IO.PrettyPrint.PrettyPrint m2) => Math.IO.PrettyPrint.PrettyPrint (Math.Categories.CommaCategory.CommaMorphism o1 o2 m1 m2 m3)
+ Math.Categories.CommaCategory: instance (Math.IO.PrettyPrint.PrettyPrint o1, Math.IO.PrettyPrint.PrettyPrint o2, Math.IO.PrettyPrint.PrettyPrint m3) => Math.IO.PrettyPrint.PrettyPrint (Math.Categories.CommaCategory.CommaObject o1 o2 m3)
+ Math.Categories.CommaCategory: selectedArrow :: CommaObject o1 o2 m3 -> m3
+ Math.Categories.CommaCategory: sliceCategory :: (FiniteCategory c m o, Morphism m o, Eq c, Eq m, Eq o) => c -> o -> Maybe (CommaCategory c m o One One One c m o)
+ Math.Categories.CommaCategory: unsafeCommaMorphism :: CommaObject o1 o2 m3 -> CommaObject o1 o2 m3 -> m1 -> m2 -> CommaMorphism o1 o2 m1 m2 m3
+ Math.Categories.CommaCategory: unsafeCommaObject :: o1 -> o2 -> m3 -> CommaObject o1 o2 m3
+ Math.Categories.ConeCategory: apex :: Cone c1 m1 o1 c2 m2 o2 -> o2
+ Math.Categories.ConeCategory: baseCocone :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => Cocone c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 c2 m2 o2
+ Math.Categories.ConeCategory: baseCone :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => Cone c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 c2 m2 o2
+ Math.Categories.ConeCategory: bindingMorphismCocone :: CoconeMorphism c1 m1 o1 c2 m2 o2 -> m2
+ Math.Categories.ConeCategory: bindingMorphismCone :: ConeMorphism c1 m1 o1 c2 m2 o2 -> m2
+ Math.Categories.ConeCategory: coconeCategory :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => Diagram c1 m1 o1 c2 m2 o2 -> CoconeCategory c1 m1 o1 c2 m2 o2
+ Math.Categories.ConeCategory: colimits :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => Diagram c1 m1 o1 c2 m2 o2 -> Set (Cocone c1 m1 o1 c2 m2 o2)
+ Math.Categories.ConeCategory: coneCategory :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => Diagram c1 m1 o1 c2 m2 o2 -> ConeCategory c1 m1 o1 c2 m2 o2
+ Math.Categories.ConeCategory: legsCocone :: Cocone c1 m1 o1 c2 m2 o2 -> NaturalTransformation c1 m1 o1 c2 m2 o2
+ Math.Categories.ConeCategory: legsCone :: Cone c1 m1 o1 c2 m2 o2 -> NaturalTransformation c1 m1 o1 c2 m2 o2
+ Math.Categories.ConeCategory: limits :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => Diagram c1 m1 o1 c2 m2 o2 -> Set (Cone c1 m1 o1 c2 m2 o2)
+ Math.Categories.ConeCategory: nadir :: Cocone c1 m1 o1 c2 m2 o2 -> o2
+ Math.Categories.ConeCategory: naturalTransformationToCocone :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => NaturalTransformation c1 m1 o1 c2 m2 o2 -> Maybe (Cocone c1 m1 o1 c2 m2 o2)
+ Math.Categories.ConeCategory: naturalTransformationToCone :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, Category c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => NaturalTransformation c1 m1 o1 c2 m2 o2 -> Maybe (Cone c1 m1 o1 c2 m2 o2)
+ Math.Categories.ConeCategory: type Cocone c1 m1 o1 c2 m2 o2 = CommaObject One o2 (NaturalTransformation c1 m1 o1 c2 m2 o2)
+ Math.Categories.ConeCategory: type CoconeCategory c1 m1 o1 c2 m2 o2 = CommaCategory One One One c2 m2 o2 (FunctorCategory c1 m1 o1 c2 m2 o2) (NaturalTransformation c1 m1 o1 c2 m2 o2) (Diagram c1 m1 o1 c2 m2 o2)
+ Math.Categories.ConeCategory: type CoconeMorphism c1 m1 o1 c2 m2 o2 = CommaMorphism One o2 One m2 (NaturalTransformation c1 m1 o1 c2 m2 o2)
+ Math.Categories.ConeCategory: type Cone c1 m1 o1 c2 m2 o2 = CommaObject o2 One (NaturalTransformation c1 m1 o1 c2 m2 o2)
+ Math.Categories.ConeCategory: type ConeCategory c1 m1 o1 c2 m2 o2 = CommaCategory c2 m2 o2 One One One (FunctorCategory c1 m1 o1 c2 m2 o2) (NaturalTransformation c1 m1 o1 c2 m2 o2) (Diagram c1 m1 o1 c2 m2 o2)
+ Math.Categories.ConeCategory: type ConeMorphism c1 m1 o1 c2 m2 o2 = CommaMorphism o2 One m2 One (NaturalTransformation c1 m1 o1 c2 m2 o2)
+ Math.Categories.FinCat: FinCat :: FinCat c m o
+ Math.Categories.FinCat: data FinCat c m o
+ Math.Categories.FinCat: instance (GHC.Classes.Eq c, GHC.Classes.Eq m, GHC.Classes.Eq o) => Math.Category.Morphism (Math.Categories.FunctorCategory.Diagram c m o c m o) c
+ Math.Categories.FinCat: instance (Math.FiniteCategory.FiniteCategory c m o, Math.Category.Morphism m o, GHC.Classes.Eq c, GHC.Classes.Eq m, GHC.Classes.Eq o) => Math.Category.Category (Math.Categories.FinCat.FinCat c m o) (Math.Categories.FunctorCategory.Diagram c m o c m o) c
+ Math.Categories.FinCat: instance GHC.Classes.Eq (Math.Categories.FinCat.FinCat c m o)
+ Math.Categories.FinCat: instance GHC.Show.Show (Math.Categories.FinCat.FinCat c m o)
+ Math.Categories.FinCat: type FinFunctor c m o = Diagram c m o c m o
+ Math.Categories.FinGrph: Arrow :: n -> n -> e -> Arrow n e
+ Math.Categories.FinGrph: FinGrph :: FinGrph n e
+ Math.Categories.FinGrph: [labelArrow] :: Arrow n e -> e
+ Math.Categories.FinGrph: [sourceArrow] :: Arrow n e -> n
+ Math.Categories.FinGrph: [targetArrow] :: Arrow n e -> n
+ Math.Categories.FinGrph: checkGraphHomomorphism :: (Eq n, Eq e) => GraphHomomorphism n e -> Bool
+ Math.Categories.FinGrph: data Arrow n e
+ Math.Categories.FinGrph: data FinGrph n e
+ Math.Categories.FinGrph: data Graph n e
+ Math.Categories.FinGrph: data GraphHomomorphism n e
+ Math.Categories.FinGrph: edgeMap :: GraphHomomorphism n e -> Map (Arrow n e) (Arrow n e)
+ Math.Categories.FinGrph: edges :: Graph n e -> Set (Arrow n e)
+ Math.Categories.FinGrph: graph :: Eq n => Set n -> Set (Arrow n e) -> Maybe (Graph n e)
+ Math.Categories.FinGrph: graphHomomorphism :: (Eq n, Eq e) => Map n n -> Map (Arrow n e) (Arrow n e) -> Graph n e -> Maybe (GraphHomomorphism n e)
+ Math.Categories.FinGrph: instance (GHC.Classes.Eq n, GHC.Classes.Eq e) => GHC.Classes.Eq (Math.Categories.FinGrph.Arrow n e)
+ Math.Categories.FinGrph: instance (GHC.Classes.Eq n, GHC.Classes.Eq e) => GHC.Classes.Eq (Math.Categories.FinGrph.Graph n e)
+ Math.Categories.FinGrph: instance (GHC.Classes.Eq n, GHC.Classes.Eq e) => GHC.Classes.Eq (Math.Categories.FinGrph.GraphHomomorphism n e)
+ Math.Categories.FinGrph: instance (GHC.Classes.Eq n, GHC.Classes.Eq e) => Math.Category.Morphism (Math.Categories.FinGrph.GraphHomomorphism n e) (Math.Categories.FinGrph.Graph n e)
+ Math.Categories.FinGrph: instance (GHC.Classes.Eq n, GHC.Classes.Eq e, GHC.Show.Show n, GHC.Show.Show e) => Math.Category.Category (Math.Categories.FinGrph.FinGrph n e) (Math.Categories.FinGrph.GraphHomomorphism n e) (Math.Categories.FinGrph.Graph n e)
+ Math.Categories.FinGrph: instance (GHC.Show.Show n, GHC.Show.Show e) => GHC.Show.Show (Math.Categories.FinGrph.Arrow n e)
+ Math.Categories.FinGrph: instance (GHC.Show.Show n, GHC.Show.Show e) => GHC.Show.Show (Math.Categories.FinGrph.Graph n e)
+ Math.Categories.FinGrph: instance (GHC.Show.Show n, GHC.Show.Show e) => GHC.Show.Show (Math.Categories.FinGrph.GraphHomomorphism n e)
+ Math.Categories.FinGrph: instance (Math.IO.PrettyPrint.PrettyPrint n, Math.IO.PrettyPrint.PrettyPrint e) => Math.IO.PrettyPrint.PrettyPrint (Math.Categories.FinGrph.Arrow n e)
+ Math.Categories.FinGrph: instance (Math.IO.PrettyPrint.PrettyPrint n, Math.IO.PrettyPrint.PrettyPrint e, GHC.Classes.Eq n, GHC.Classes.Eq e) => Math.IO.PrettyPrint.PrettyPrint (Math.Categories.FinGrph.FinGrph n e)
+ Math.Categories.FinGrph: instance (Math.IO.PrettyPrint.PrettyPrint n, Math.IO.PrettyPrint.PrettyPrint e, GHC.Classes.Eq n, GHC.Classes.Eq e) => Math.IO.PrettyPrint.PrettyPrint (Math.Categories.FinGrph.Graph n e)
+ Math.Categories.FinGrph: instance (Math.IO.PrettyPrint.PrettyPrint n, Math.IO.PrettyPrint.PrettyPrint e, GHC.Classes.Eq n, GHC.Classes.Eq e) => Math.IO.PrettyPrint.PrettyPrint (Math.Categories.FinGrph.GraphHomomorphism n e)
+ Math.Categories.FinGrph: instance GHC.Classes.Eq (Math.Categories.FinGrph.FinGrph n e)
+ Math.Categories.FinGrph: instance GHC.Show.Show (Math.Categories.FinGrph.FinGrph n e)
+ Math.Categories.FinGrph: nodeMap :: GraphHomomorphism n e -> Map n n
+ Math.Categories.FinGrph: nodes :: Graph n e -> Set n
+ Math.Categories.FinGrph: underlyingGraph :: (FiniteCategory c m o, Morphism m o) => c -> Graph o m
+ Math.Categories.FinGrph: underlyingGraphFormat :: (FiniteCategory c m o, Morphism m o) => (o -> a) -> (m -> b) -> c -> Graph a b
+ Math.Categories.FinGrph: unsafeGraph :: Set n -> Set (Arrow n e) -> Graph n e
+ Math.Categories.FinGrph: unsafeGraphHomomorphism :: Map n n -> Map (Arrow n e) (Arrow n e) -> Graph n e -> GraphHomomorphism n e
+ Math.Categories.FinSet: (||!||) :: Eq a => Function a -> a -> a
+ Math.Categories.FinSet: FinSet :: FinSet a
+ Math.Categories.FinSet: Function :: Map a a -> Set a -> Function a
+ Math.Categories.FinSet: [codomain] :: Function a -> Set a
+ Math.Categories.FinSet: [function] :: Function a -> Map a a
+ Math.Categories.FinSet: data FinSet a
+ Math.Categories.FinSet: data Function a
+ Math.Categories.FinSet: instance (Math.IO.PrettyPrint.PrettyPrint a, GHC.Classes.Eq a) => Math.IO.PrettyPrint.PrettyPrint (Math.Categories.FinSet.FinSet a)
+ Math.Categories.FinSet: instance (Math.IO.PrettyPrint.PrettyPrint a, GHC.Classes.Eq a) => Math.IO.PrettyPrint.PrettyPrint (Math.Categories.FinSet.Function a)
+ Math.Categories.FinSet: instance GHC.Classes.Eq (Math.Categories.FinSet.FinSet a)
+ Math.Categories.FinSet: instance GHC.Classes.Eq a => GHC.Classes.Eq (Math.Categories.FinSet.Function a)
+ Math.Categories.FinSet: instance GHC.Classes.Eq a => Math.Category.Category (Math.Categories.FinSet.FinSet a) (Math.Categories.FinSet.Function a) (Data.WeakSet.Set a)
+ Math.Categories.FinSet: instance GHC.Classes.Eq a => Math.Category.Morphism (Math.Categories.FinSet.Function a) (Data.WeakSet.Set a)
+ Math.Categories.FinSet: instance GHC.Show.Show (Math.Categories.FinSet.FinSet a)
+ Math.Categories.FinSet: instance GHC.Show.Show a => GHC.Show.Show (Math.Categories.FinSet.Function a)
+ Math.Categories.FunctorCategory: (->$) :: Eq o1 => Diagram c1 m1 o1 c2 m2 o2 -> o1 -> o2
+ Math.Categories.FunctorCategory: (->£) :: Eq m1 => Diagram c1 m1 o1 c2 m2 o2 -> m1 -> m2
+ Math.Categories.FunctorCategory: (<-@<-) :: (Eq o2, Eq m2) => Diagram c2 m2 o2 c3 m3 o3 -> Diagram c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 c3 m3 o3
+ Math.Categories.FunctorCategory: (<-@<=) :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => Diagram c2 m2 o2 c3 m3 o3 -> NaturalTransformation c1 m1 o1 c2 m2 o2 -> NaturalTransformation c1 m1 o1 c3 m3 o3
+ Math.Categories.FunctorCategory: (<=@<-) :: (Morphism m1 o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2, Morphism m3 o3, Eq c3, Eq m3, Eq o3) => NaturalTransformation c2 m2 o2 c3 m3 o3 -> Diagram c1 m1 o1 c2 m2 o2 -> NaturalTransformation c1 m1 o1 c3 m3 o3
+ Math.Categories.FunctorCategory: (<=@<=) :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2, Morphism m3 o3, Eq c3, Eq m3, Eq o3) => NaturalTransformation c2 m2 o2 c3 m3 o3 -> NaturalTransformation c1 m1 o1 c2 m2 o2 -> NaturalTransformation c1 m1 o1 c3 m3 o3
+ Math.Categories.FunctorCategory: (=>$) :: Eq o1 => NaturalTransformation c1 m1 o1 c2 m2 o2 -> o1 -> m2
+ Math.Categories.FunctorCategory: Diagram :: c1 -> c2 -> Map o1 o2 -> Map m1 m2 -> Diagram c1 m1 o1 c2 m2 o2
+ Math.Categories.FunctorCategory: FunctorCategory :: c1 -> c2 -> FunctorCategory c1 m1 o1 c2 m2 o2
+ Math.Categories.FunctorCategory: PostcomposedFunctorCategory :: Diagram c2 m2 o2 c3 m3 o3 -> c1 -> PostcomposedFunctorCategory c1 m1 o1 c2 m2 o2 c3 m3 o3
+ Math.Categories.FunctorCategory: PrecomposedFunctorCategory :: Diagram c1 m1 o1 c2 m2 o2 -> c3 -> PrecomposedFunctorCategory c1 m1 o1 c2 m2 o2 c3 m3 o3
+ Math.Categories.FunctorCategory: [mmap] :: Diagram c1 m1 o1 c2 m2 o2 -> Map m1 m2
+ Math.Categories.FunctorCategory: [omap] :: Diagram c1 m1 o1 c2 m2 o2 -> Map o1 o2
+ Math.Categories.FunctorCategory: [src] :: Diagram c1 m1 o1 c2 m2 o2 -> c1
+ Math.Categories.FunctorCategory: [tgt] :: Diagram c1 m1 o1 c2 m2 o2 -> c2
+ Math.Categories.FunctorCategory: checkDiagram :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, Category c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2) => Diagram c1 m1 o1 c2 m2 o2 -> Maybe (DiagramError c1 m1 o1 c2 m2 o2)
+ Math.Categories.FunctorCategory: checkFiniteDiagram :: (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 -> Maybe (DiagramError c1 m1 o1 c2 m2 o2)
+ Math.Categories.FunctorCategory: checkNaturalTransformation :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => NaturalTransformation c1 m1 o1 c2 m2 o2 -> Maybe (NaturalTransformationError c1 m1 o1 c2 m2 o2)
+ Math.Categories.FunctorCategory: completeDiagram :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, Category c2 m2 o2, Morphism m2 o2) => Diagram c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 c2 m2 o2
+ Math.Categories.FunctorCategory: components :: NaturalTransformation c1 m1 o1 c2 m2 o2 -> Map o1 m2
+ Math.Categories.FunctorCategory: constantDiagram :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Category c2 m2 o2, Morphism m2 o2) => c1 -> c2 -> o2 -> Diagram c1 m1 o1 c2 m2 o2
+ Math.Categories.FunctorCategory: data Diagram c1 m1 o1 c2 m2 o2
+ Math.Categories.FunctorCategory: data DiagramError c1 m1 o1 c2 m2 o2
+ Math.Categories.FunctorCategory: data FunctorCategory c1 m1 o1 c2 m2 o2
+ Math.Categories.FunctorCategory: data NaturalTransformation c1 m1 o1 c2 m2 o2
+ Math.Categories.FunctorCategory: data NaturalTransformationError c1 m1 o1 c2 m2 o2
+ Math.Categories.FunctorCategory: data PostcomposedFunctorCategory c1 m1 o1 c2 m2 o2 c3 m3 o3
+ Math.Categories.FunctorCategory: data PrecomposedFunctorCategory c1 m1 o1 c2 m2 o2 c3 m3 o3
+ Math.Categories.FunctorCategory: diagram :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2) => c1 -> c2 -> Map o1 o2 -> Map m1 m2 -> Either (DiagramError c1 m1 o1 c2 m2 o2) (Diagram c1 m1 o1 c2 m2 o2)
+ Math.Categories.FunctorCategory: discreteDiagram :: (Category c m o, Morphism m o, Eq o) => c -> [o] -> Diagram (DiscreteCategory Int) (DiscreteMorphism Int) Int c m o
+ Math.Categories.FunctorCategory: horizontalComposition :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2, Morphism m3 o3, Eq c3, Eq m3, Eq o3) => NaturalTransformation c2 m2 o2 c3 m3 o3 -> NaturalTransformation c1 m1 o1 c2 m2 o2 -> NaturalTransformation c1 m1 o1 c3 m3 o3
+ Math.Categories.FunctorCategory: insertionFunctor1 :: (Category c m o, Morphism m o, Eq o) => FullSubcategory c m o -> Diagram (FullSubcategory c m o) m o c m o
+ Math.Categories.FunctorCategory: insertionFunctor2 :: (Category c m o, Morphism m o, Eq o) => InheritedFullSubcategory c m o -> Diagram (InheritedFullSubcategory c m o) m o c m o
+ Math.Categories.FunctorCategory: instance (GHC.Classes.Eq c1, GHC.Classes.Eq c2) => GHC.Classes.Eq (Math.Categories.FunctorCategory.FunctorCategory c1 m1 o1 c2 m2 o2)
+ Math.Categories.FunctorCategory: instance (GHC.Classes.Eq c1, GHC.Classes.Eq c2, GHC.Classes.Eq o1, GHC.Classes.Eq m1) => GHC.Classes.Eq (Math.Categories.FunctorCategory.NaturalTransformationError c1 m1 o1 c2 m2 o2)
+ Math.Categories.FunctorCategory: instance (GHC.Classes.Eq c1, GHC.Classes.Eq c2, GHC.Classes.Eq o1, GHC.Classes.Eq o2, GHC.Classes.Eq m1, GHC.Classes.Eq m2) => GHC.Classes.Eq (Math.Categories.FunctorCategory.Diagram c1 m1 o1 c2 m2 o2)
+ Math.Categories.FunctorCategory: instance (GHC.Classes.Eq c1, GHC.Classes.Eq c2, GHC.Classes.Eq o1, GHC.Classes.Eq o2, GHC.Classes.Eq m1, GHC.Classes.Eq m2) => GHC.Classes.Eq (Math.Categories.FunctorCategory.NaturalTransformation c1 m1 o1 c2 m2 o2)
+ Math.Categories.FunctorCategory: instance (GHC.Classes.Eq c1, GHC.Classes.Eq c2, GHC.Classes.Eq o1, GHC.Classes.Eq o2, GHC.Classes.Eq m1, GHC.Classes.Eq m2, GHC.Classes.Eq c3) => GHC.Classes.Eq (Math.Categories.FunctorCategory.PrecomposedFunctorCategory c1 m1 o1 c2 m2 o2 c3 m3 o3)
+ Math.Categories.FunctorCategory: instance (GHC.Classes.Eq c2, GHC.Classes.Eq c3, GHC.Classes.Eq o2, GHC.Classes.Eq o3, GHC.Classes.Eq m2, GHC.Classes.Eq m3, GHC.Classes.Eq c1) => GHC.Classes.Eq (Math.Categories.FunctorCategory.PostcomposedFunctorCategory c1 m1 o1 c2 m2 o2 c3 m3 o3)
+ Math.Categories.FunctorCategory: instance (GHC.Classes.Eq o1, GHC.Classes.Eq m1, GHC.Classes.Eq o2, GHC.Classes.Eq m2) => GHC.Classes.Eq (Math.Categories.FunctorCategory.DiagramError c1 m1 o1 c2 m2 o2)
+ Math.Categories.FunctorCategory: instance (GHC.Show.Show c1, GHC.Show.Show c2) => GHC.Show.Show (Math.Categories.FunctorCategory.FunctorCategory c1 m1 o1 c2 m2 o2)
+ Math.Categories.FunctorCategory: instance (GHC.Show.Show c1, GHC.Show.Show c2, GHC.Show.Show o1, GHC.Show.Show m1) => GHC.Show.Show (Math.Categories.FunctorCategory.NaturalTransformationError c1 m1 o1 c2 m2 o2)
+ Math.Categories.FunctorCategory: instance (GHC.Show.Show c1, GHC.Show.Show c2, GHC.Show.Show o1, GHC.Show.Show o2, GHC.Show.Show m1, GHC.Show.Show m2) => GHC.Show.Show (Math.Categories.FunctorCategory.Diagram c1 m1 o1 c2 m2 o2)
+ Math.Categories.FunctorCategory: instance (GHC.Show.Show c1, GHC.Show.Show c2, GHC.Show.Show o1, GHC.Show.Show o2, GHC.Show.Show m1, GHC.Show.Show m2, GHC.Show.Show c3) => GHC.Show.Show (Math.Categories.FunctorCategory.PrecomposedFunctorCategory c1 m1 o1 c2 m2 o2 c3 m3 o3)
+ Math.Categories.FunctorCategory: instance (GHC.Show.Show c1, GHC.Show.Show m1, GHC.Show.Show o1, GHC.Show.Show c2, GHC.Show.Show m2, GHC.Show.Show o2) => GHC.Show.Show (Math.Categories.FunctorCategory.NaturalTransformation c1 m1 o1 c2 m2 o2)
+ Math.Categories.FunctorCategory: instance (GHC.Show.Show c2, GHC.Show.Show c3, GHC.Show.Show o2, GHC.Show.Show o3, GHC.Show.Show m2, GHC.Show.Show m3, GHC.Show.Show c1) => GHC.Show.Show (Math.Categories.FunctorCategory.PostcomposedFunctorCategory c1 m1 o1 c2 m2 o2 c3 m3 o3)
+ Math.Categories.FunctorCategory: instance (GHC.Show.Show o1, GHC.Show.Show m1, GHC.Show.Show o2, GHC.Show.Show m2) => GHC.Show.Show (Math.Categories.FunctorCategory.DiagramError c1 m1 o1 c2 m2 o2)
+ Math.Categories.FunctorCategory: instance (Math.FiniteCategory.FiniteCategory c1 m1 o1, Math.Category.Morphism m1 o1, GHC.Classes.Eq c1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, Math.Category.Category c2 m2 o2, Math.Category.Morphism m2 o2, GHC.Classes.Eq c2, GHC.Classes.Eq m2, GHC.Classes.Eq o2) => Math.Category.Category (Math.Categories.FunctorCategory.FunctorCategory c1 m1 o1 c2 m2 o2) (Math.Categories.FunctorCategory.NaturalTransformation c1 m1 o1 c2 m2 o2) (Math.Categories.FunctorCategory.Diagram c1 m1 o1 c2 m2 o2)
+ Math.Categories.FunctorCategory: instance (Math.FiniteCategory.FiniteCategory c1 m1 o1, Math.Category.Morphism m1 o1, GHC.Classes.Eq c1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, Math.Category.Category c2 m2 o2, Math.Category.Morphism m2 o2, GHC.Classes.Eq c2, GHC.Classes.Eq m2, GHC.Classes.Eq o2, Math.Category.Category c3 m3 o3, Math.Category.Morphism m3 o3, GHC.Classes.Eq c3, GHC.Classes.Eq m3, GHC.Classes.Eq o3) => Math.Category.Category (Math.Categories.FunctorCategory.PostcomposedFunctorCategory c1 m1 o1 c2 m2 o2 c3 m3 o3) (Math.Categories.FunctorCategory.NaturalTransformation c1 m1 o1 c3 m3 o3) (Math.Categories.FunctorCategory.Diagram c1 m1 o1 c3 m3 o3)
+ Math.Categories.FunctorCategory: instance (Math.FiniteCategory.FiniteCategory c1 m1 o1, Math.Category.Morphism m1 o1, GHC.Classes.Eq c1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, Math.Category.Morphism m2 o2, GHC.Classes.Eq c2, GHC.Classes.Eq m2, GHC.Classes.Eq o2) => Math.Category.Morphism (Math.Categories.FunctorCategory.NaturalTransformation c1 m1 o1 c2 m2 o2) (Math.Categories.FunctorCategory.Diagram c1 m1 o1 c2 m2 o2)
+ Math.Categories.FunctorCategory: instance (Math.FiniteCategory.FiniteCategory c1 m1 o1, Math.Category.Morphism m1 o1, GHC.Classes.Eq c1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, Math.FiniteCategory.FiniteCategory c2 m2 o2, Math.Category.Morphism m2 o2, GHC.Classes.Eq c2, GHC.Classes.Eq m2, GHC.Classes.Eq o2) => Math.FiniteCategory.FiniteCategory (Math.Categories.FunctorCategory.FunctorCategory c1 m1 o1 c2 m2 o2) (Math.Categories.FunctorCategory.NaturalTransformation c1 m1 o1 c2 m2 o2) (Math.Categories.FunctorCategory.Diagram c1 m1 o1 c2 m2 o2)
+ Math.Categories.FunctorCategory: instance (Math.FiniteCategory.FiniteCategory c1 m1 o1, Math.Category.Morphism m1 o1, GHC.Classes.Eq c1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, Math.FiniteCategory.FiniteCategory c2 m2 o2, Math.Category.Morphism m2 o2, GHC.Classes.Eq c2, GHC.Classes.Eq m2, GHC.Classes.Eq o2, Math.Category.Category c3 m3 o3, Math.Category.Morphism m3 o3, GHC.Classes.Eq c3, GHC.Classes.Eq m3, GHC.Classes.Eq o3) => Math.Category.Category (Math.Categories.FunctorCategory.PrecomposedFunctorCategory c1 m1 o1 c2 m2 o2 c3 m3 o3) (Math.Categories.FunctorCategory.NaturalTransformation c1 m1 o1 c3 m3 o3) (Math.Categories.FunctorCategory.Diagram c1 m1 o1 c3 m3 o3)
+ Math.Categories.FunctorCategory: instance (Math.FiniteCategory.FiniteCategory c1 m1 o1, Math.Category.Morphism m1 o1, GHC.Classes.Eq c1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, Math.FiniteCategory.FiniteCategory c2 m2 o2, Math.Category.Morphism m2 o2, GHC.Classes.Eq c2, GHC.Classes.Eq m2, GHC.Classes.Eq o2, Math.FiniteCategory.FiniteCategory c3 m3 o3, Math.Category.Morphism m3 o3, GHC.Classes.Eq c3, GHC.Classes.Eq m3, GHC.Classes.Eq o3) => Math.FiniteCategory.FiniteCategory (Math.Categories.FunctorCategory.PostcomposedFunctorCategory c1 m1 o1 c2 m2 o2 c3 m3 o3) (Math.Categories.FunctorCategory.NaturalTransformation c1 m1 o1 c3 m3 o3) (Math.Categories.FunctorCategory.Diagram c1 m1 o1 c3 m3 o3)
+ Math.Categories.FunctorCategory: instance (Math.FiniteCategory.FiniteCategory c1 m1 o1, Math.Category.Morphism m1 o1, GHC.Classes.Eq c1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, Math.FiniteCategory.FiniteCategory c2 m2 o2, Math.Category.Morphism m2 o2, GHC.Classes.Eq c2, GHC.Classes.Eq m2, GHC.Classes.Eq o2, Math.FiniteCategory.FiniteCategory c3 m3 o3, Math.Category.Morphism m3 o3, GHC.Classes.Eq c3, GHC.Classes.Eq m3, GHC.Classes.Eq o3) => Math.FiniteCategory.FiniteCategory (Math.Categories.FunctorCategory.PrecomposedFunctorCategory c1 m1 o1 c2 m2 o2 c3 m3 o3) (Math.Categories.FunctorCategory.NaturalTransformation c1 m1 o1 c3 m3 o3) (Math.Categories.FunctorCategory.Diagram c1 m1 o1 c3 m3 o3)
+ Math.Categories.FunctorCategory: instance (Math.IO.PrettyPrint.PrettyPrint c1, Math.IO.PrettyPrint.PrettyPrint c2) => Math.IO.PrettyPrint.PrettyPrint (Math.Categories.FunctorCategory.FunctorCategory c1 m1 o1 c2 m2 o2)
+ Math.Categories.FunctorCategory: instance (Math.IO.PrettyPrint.PrettyPrint c1, Math.IO.PrettyPrint.PrettyPrint c2, Math.IO.PrettyPrint.PrettyPrint m2, Math.IO.PrettyPrint.PrettyPrint o2, GHC.Classes.Eq m2, GHC.Classes.Eq o2, Math.IO.PrettyPrint.PrettyPrint c3, Math.IO.PrettyPrint.PrettyPrint m3, Math.IO.PrettyPrint.PrettyPrint o3, GHC.Classes.Eq m3, GHC.Classes.Eq o3) => Math.IO.PrettyPrint.PrettyPrint (Math.Categories.FunctorCategory.PostcomposedFunctorCategory c1 m1 o1 c2 m2 o2 c3 m3 o3)
+ Math.Categories.FunctorCategory: instance (Math.IO.PrettyPrint.PrettyPrint c1, Math.IO.PrettyPrint.PrettyPrint m1, Math.IO.PrettyPrint.PrettyPrint o1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, Math.IO.PrettyPrint.PrettyPrint c2, Math.IO.PrettyPrint.PrettyPrint m2, Math.IO.PrettyPrint.PrettyPrint o2, GHC.Classes.Eq m2, GHC.Classes.Eq o2) => Math.IO.PrettyPrint.PrettyPrint (Math.Categories.FunctorCategory.Diagram c1 m1 o1 c2 m2 o2)
+ Math.Categories.FunctorCategory: instance (Math.IO.PrettyPrint.PrettyPrint c1, Math.IO.PrettyPrint.PrettyPrint m1, Math.IO.PrettyPrint.PrettyPrint o1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, Math.IO.PrettyPrint.PrettyPrint c2, Math.IO.PrettyPrint.PrettyPrint m2, Math.IO.PrettyPrint.PrettyPrint o2, GHC.Classes.Eq m2, GHC.Classes.Eq o2) => Math.IO.PrettyPrint.PrettyPrint (Math.Categories.FunctorCategory.NaturalTransformation c1 m1 o1 c2 m2 o2)
+ Math.Categories.FunctorCategory: instance (Math.IO.PrettyPrint.PrettyPrint c1, Math.IO.PrettyPrint.PrettyPrint m1, Math.IO.PrettyPrint.PrettyPrint o1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, Math.IO.PrettyPrint.PrettyPrint c2, Math.IO.PrettyPrint.PrettyPrint m2, Math.IO.PrettyPrint.PrettyPrint o2, GHC.Classes.Eq m2, GHC.Classes.Eq o2, Math.IO.PrettyPrint.PrettyPrint c3) => Math.IO.PrettyPrint.PrettyPrint (Math.Categories.FunctorCategory.PrecomposedFunctorCategory c1 m1 o1 c2 m2 o2 c3 m3 o3)
+ Math.Categories.FunctorCategory: leftWhiskering :: (Morphism m1 o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2, Morphism m3 o3, Eq c3, Eq m3, Eq o3) => NaturalTransformation c2 m2 o2 c3 m3 o3 -> Diagram c1 m1 o1 c2 m2 o2 -> NaturalTransformation c1 m1 o1 c3 m3 o3
+ Math.Categories.FunctorCategory: naturalTransformation :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => Diagram c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 c2 m2 o2 -> Map o1 m2 -> Either (NaturalTransformationError c1 m1 o1 c2 m2 o2) (NaturalTransformation c1 m1 o1 c2 m2 o2)
+ Math.Categories.FunctorCategory: parallelDiagram :: (Category c m o, Morphism m o, Eq o) => c -> m -> m -> Diagram Parallel ParallelAr ParallelOb c m o
+ Math.Categories.FunctorCategory: pickRandomDiagram :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2, RandomGen g) => c1 -> c2 -> g -> (Diagram c1 m1 o1 c2 m2 o2, g)
+ Math.Categories.FunctorCategory: rightWhiskering :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => Diagram c2 m2 o2 c3 m3 o3 -> NaturalTransformation c1 m1 o1 c2 m2 o2 -> NaturalTransformation c1 m1 o1 c3 m3 o3
+ Math.Categories.FunctorCategory: selectObject :: (Category c m o, Morphism m o, Eq o) => c -> o -> Diagram One One One c m o
+ Math.Categories.FunctorCategory: unsafeNaturalTransformation :: Diagram c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 c2 m2 o2 -> Map o1 m2 -> NaturalTransformation c1 m1 o1 c2 m2 o2
+ Math.Categories.Galaxy: Galaxy :: Galaxy a
+ Math.Categories.Galaxy: StarIdentity :: a -> StarIdentity a
+ Math.Categories.Galaxy: data Galaxy a
+ Math.Categories.Galaxy: data StarIdentity a
+ Math.Categories.Galaxy: instance GHC.Classes.Eq (Math.Categories.Galaxy.Galaxy a)
+ Math.Categories.Galaxy: instance GHC.Classes.Eq a => GHC.Classes.Eq (Math.Categories.Galaxy.StarIdentity a)
+ Math.Categories.Galaxy: instance GHC.Classes.Eq a => Math.Category.Category (Math.Categories.Galaxy.Galaxy a) (Math.Categories.Galaxy.StarIdentity a) a
+ Math.Categories.Galaxy: instance GHC.Classes.Eq a => Math.Category.Morphism (Math.Categories.Galaxy.StarIdentity a) a
+ Math.Categories.Galaxy: instance GHC.Show.Show (Math.Categories.Galaxy.Galaxy a)
+ Math.Categories.Galaxy: instance GHC.Show.Show a => GHC.Show.Show (Math.Categories.Galaxy.StarIdentity a)
+ Math.Categories.Galaxy: instance Math.IO.PrettyPrint.PrettyPrint (Math.Categories.Galaxy.Galaxy a)
+ Math.Categories.Galaxy: instance Math.IO.PrettyPrint.PrettyPrint a => Math.IO.PrettyPrint.PrettyPrint (Math.Categories.Galaxy.StarIdentity a)
+ Math.Categories.Omega: omega :: Omega
+ Math.Categories.Omega: type Omega = OrdinalCategory Natural
+ Math.Categories.Opposite: Op :: c -> Op c
+ Math.Categories.Opposite: OpMorphism :: m -> OpMorphism m
+ Math.Categories.Opposite: data Op c
+ Math.Categories.Opposite: data OpMorphism m
+ Math.Categories.Opposite: instance (Math.Category.Category c m o, Math.Category.Morphism m o) => Math.Category.Category (Math.Categories.Opposite.Op c) (Math.Categories.Opposite.OpMorphism m) o
+ Math.Categories.Opposite: instance (Math.FiniteCategory.FiniteCategory c m o, Math.Category.Morphism m o) => Math.FiniteCategory.FiniteCategory (Math.Categories.Opposite.Op c) (Math.Categories.Opposite.OpMorphism m) o
+ Math.Categories.Opposite: instance GHC.Classes.Eq c => GHC.Classes.Eq (Math.Categories.Opposite.Op c)
+ Math.Categories.Opposite: instance GHC.Classes.Eq m => GHC.Classes.Eq (Math.Categories.Opposite.OpMorphism m)
+ Math.Categories.Opposite: instance GHC.Show.Show c => GHC.Show.Show (Math.Categories.Opposite.Op c)
+ Math.Categories.Opposite: instance GHC.Show.Show m => GHC.Show.Show (Math.Categories.Opposite.OpMorphism m)
+ Math.Categories.Opposite: instance Math.Category.Morphism m o => Math.Category.Morphism (Math.Categories.Opposite.OpMorphism m) o
+ Math.Categories.Opposite: instance Math.IO.PrettyPrint.PrettyPrint c => Math.IO.PrettyPrint.PrettyPrint (Math.Categories.Opposite.Op c)
+ Math.Categories.Opposite: instance Math.IO.PrettyPrint.PrettyPrint m => Math.IO.PrettyPrint.PrettyPrint (Math.Categories.Opposite.OpMorphism m)
+ Math.Categories.Opposite: opOp :: Op c -> c
+ Math.Categories.Opposite: opOpMorphism :: OpMorphism m -> m
+ Math.Categories.OrdinalCategory: OrdinalCategory :: TotalOrder a -> OrdinalCategory a
+ Math.Categories.OrdinalCategory: instance (GHC.Enum.Enum a, GHC.Classes.Ord a) => Math.Category.Category (Math.Categories.OrdinalCategory.OrdinalCategory a) (Math.Categories.TotalOrder.IsSmallerThan a) a
+ Math.Categories.OrdinalCategory: instance GHC.Classes.Eq (Math.Categories.OrdinalCategory.OrdinalCategory a)
+ Math.Categories.OrdinalCategory: instance GHC.Show.Show (Math.Categories.OrdinalCategory.OrdinalCategory a)
+ Math.Categories.OrdinalCategory: instance GHC.Show.Show a => Math.IO.PrettyPrint.PrettyPrint (Math.Categories.OrdinalCategory.OrdinalCategory a)
+ Math.Categories.OrdinalCategory: newtype OrdinalCategory a
+ Math.Categories.PresheafCategory: type Presheaf c m o = Diagram (Op c) (OpMorphism m) o (FinSet m) (Function m) (Set m)
+ Math.Categories.PresheafCategory: type PresheafCategory c m o = FunctorCategory (Op c) (OpMorphism m) o (FinSet m) (Function m) (Set m)
+ Math.Categories.PresheafCategory: type PresheafMorphism c m o = NaturalTransformation (Op c) (OpMorphism m) o (FinSet m) (Function m) (Set m)
+ Math.Categories.PresheafCategory: yonedaEmbedding :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> Diagram c m o (PresheafCategory c m o) (PresheafMorphism c m o) (Presheaf c m o)
+ Math.Categories.TotalOrder: IsSmallerThan :: a -> a -> IsSmallerThan a
+ Math.Categories.TotalOrder: TotalOrder :: TotalOrder a
+ Math.Categories.TotalOrder: data IsSmallerThan a
+ Math.Categories.TotalOrder: data TotalOrder a
+ Math.Categories.TotalOrder: instance (GHC.Classes.Eq a, GHC.Classes.Ord a) => Math.Category.Category (Math.Categories.TotalOrder.TotalOrder a) (Math.Categories.TotalOrder.IsSmallerThan a) a
+ Math.Categories.TotalOrder: instance GHC.Classes.Eq (Math.Categories.TotalOrder.TotalOrder a)
+ Math.Categories.TotalOrder: instance GHC.Classes.Eq a => GHC.Classes.Eq (Math.Categories.TotalOrder.IsSmallerThan a)
+ Math.Categories.TotalOrder: instance GHC.Classes.Eq a => Math.Category.Morphism (Math.Categories.TotalOrder.IsSmallerThan a) a
+ Math.Categories.TotalOrder: instance GHC.Show.Show (Math.Categories.TotalOrder.TotalOrder a)
+ Math.Categories.TotalOrder: instance GHC.Show.Show a => GHC.Show.Show (Math.Categories.TotalOrder.IsSmallerThan a)
+ Math.Categories.TotalOrder: instance Math.IO.PrettyPrint.PrettyPrint (Math.Categories.TotalOrder.TotalOrder a)
+ Math.Categories.TotalOrder: instance Math.IO.PrettyPrint.PrettyPrint a => Math.IO.PrettyPrint.PrettyPrint (Math.Categories.TotalOrder.IsSmallerThan a)
+ Math.Category: (@) :: Morphism m o => m -> m -> m
+ Math.Category: (@?) :: Morphism m o => m -> m -> Maybe m
+ Math.Category: ar :: (Category c m o, Morphism m o) => c -> o -> o -> Set m
+ Math.Category: areIsomorphic :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> o -> o -> Bool
+ Math.Category: class Category c m o | c -> m, m -> o
+ Math.Category: class Morphism m o | m -> o
+ Math.Category: compose :: Morphism m o => [m] -> m
+ Math.Category: decompose :: (Category c m o, Morphism m o) => c -> m -> [m]
+ Math.Category: findInverse :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> m -> Maybe m
+ Math.Category: findIsomorphism :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> o -> o -> Maybe m
+ Math.Category: findLeftInverses :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> m -> Set m
+ Math.Category: findRightInverses :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> m -> Set m
+ Math.Category: genAr :: (Category c m o, Morphism m o) => c -> o -> o -> Set m
+ Math.Category: identity :: (Category c m o, Morphism m o) => c -> o -> m
+ Math.Category: isComposite :: (Category c m o, Morphism m o, Eq m) => c -> m -> Bool
+ Math.Category: isGenerator :: (Category c m o, Morphism m o, Eq m) => c -> m -> Bool
+ Math.Category: isIdentity :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> m -> Bool
+ Math.Category: isIso :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> m -> Bool
+ Math.Category: isNotIdentity :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> m -> Bool
+ Math.Category: isRetraction :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> m -> Bool
+ Math.Category: isSection :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> m -> Bool
+ Math.Category: source :: Morphism m o => m -> o
+ Math.Category: target :: Morphism m o => m -> o
+ Math.FiniteCategories.CommaCategory.Example: main :: IO ()
+ Math.FiniteCategories.CompositionGraph: CGMorphism :: Path a b -> CompositionLaw a b -> CGMorphism a b
+ Math.FiniteCategories.CompositionGraph: [compositionLaw] :: CGMorphism a b -> CompositionLaw a b
+ Math.FiniteCategories.CompositionGraph: [path] :: CGMorphism a b -> Path a b
+ Math.FiniteCategories.CompositionGraph: compositionGraph :: (Eq a, Eq b) => Graph a b -> CompositionLaw a b -> Either (FiniteCategoryError (CGMorphism a b) a) (CompositionGraph a b)
+ Math.FiniteCategories.CompositionGraph: constructRandomCompositionGraph :: RandomGen g => Int -> Int -> Int -> g -> (CompositionGraph Int Int, g)
+ Math.FiniteCategories.CompositionGraph: data CGMorphism a b
+ Math.FiniteCategories.CompositionGraph: data CompositionGraph a b
+ Math.FiniteCategories.CompositionGraph: defaultConstructRandomCompositionGraph :: RandomGen g => g -> (CompositionGraph Int Int, g)
+ Math.FiniteCategories.CompositionGraph: defaultConstructRandomDiagram :: RandomGen g => g -> (Diagram (CompositionGraph Int Int) (CGMorphism Int Int) Int (CompositionGraph Int Int) (CGMorphism Int Int) Int, g)
+ Math.FiniteCategories.CompositionGraph: emptyCompositionGraph :: CompositionGraph a b
+ Math.FiniteCategories.CompositionGraph: finiteCategoryToCompositionGraph :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> Diagram c m o (CompositionGraph o m) (CGMorphism o m) o
+ Math.FiniteCategories.CompositionGraph: getLabel :: CGMorphism a b -> Maybe b
+ Math.FiniteCategories.CompositionGraph: instance (GHC.Classes.Eq a, GHC.Classes.Eq b) => GHC.Classes.Eq (Math.FiniteCategories.CompositionGraph.CGMorphism a b)
+ Math.FiniteCategories.CompositionGraph: instance (GHC.Classes.Eq a, GHC.Classes.Eq b) => GHC.Classes.Eq (Math.FiniteCategories.CompositionGraph.CompositionGraph a b)
+ Math.FiniteCategories.CompositionGraph: instance (GHC.Classes.Eq a, GHC.Classes.Eq b) => Math.Category.Category (Math.FiniteCategories.CompositionGraph.CompositionGraph a b) (Math.FiniteCategories.CompositionGraph.CGMorphism a b) a
+ Math.FiniteCategories.CompositionGraph: instance (GHC.Classes.Eq a, GHC.Classes.Eq b) => Math.Category.Morphism (Math.FiniteCategories.CompositionGraph.CGMorphism a b) a
+ Math.FiniteCategories.CompositionGraph: instance (GHC.Classes.Eq a, GHC.Classes.Eq b) => Math.FiniteCategory.FiniteCategory (Math.FiniteCategories.CompositionGraph.CompositionGraph a b) (Math.FiniteCategories.CompositionGraph.CGMorphism a b) a
+ Math.FiniteCategories.CompositionGraph: instance (GHC.Show.Show a, GHC.Show.Show b) => GHC.Show.Show (Math.FiniteCategories.CompositionGraph.CGMorphism a b)
+ Math.FiniteCategories.CompositionGraph: instance (GHC.Show.Show a, GHC.Show.Show b) => GHC.Show.Show (Math.FiniteCategories.CompositionGraph.CompositionGraph a b)
+ Math.FiniteCategories.CompositionGraph: instance (Math.IO.PrettyPrint.PrettyPrint a, Math.IO.PrettyPrint.PrettyPrint b, GHC.Classes.Eq a, GHC.Classes.Eq b) => Math.IO.PrettyPrint.PrettyPrint (Math.FiniteCategories.CompositionGraph.CGMorphism a b)
+ Math.FiniteCategories.CompositionGraph: instance (Math.IO.PrettyPrint.PrettyPrint a, Math.IO.PrettyPrint.PrettyPrint b, GHC.Classes.Eq a, GHC.Classes.Eq b) => Math.IO.PrettyPrint.PrettyPrint (Math.FiniteCategories.CompositionGraph.CompositionGraph a b)
+ Math.FiniteCategories.CompositionGraph: instance GHC.Classes.Eq Math.FiniteCategories.CompositionGraph.Token
+ Math.FiniteCategories.CompositionGraph: instance GHC.Show.Show Math.FiniteCategories.CompositionGraph.Token
+ Math.FiniteCategories.CompositionGraph: law :: CompositionGraph a b -> CompositionLaw a b
+ Math.FiniteCategories.CompositionGraph: readCGDFile :: String -> IO (Either (DiagramError CG (CGMorphism Text Text) Text CG (CGMorphism Text Text) Text) CGD)
+ Math.FiniteCategories.CompositionGraph: readCGDString :: String -> Either (DiagramError CG (CGMorphism Text Text) Text CG (CGMorphism Text Text) Text) CGD
+ Math.FiniteCategories.CompositionGraph: readCGFile :: String -> IO (Either (FiniteCategoryError (CGMorphism Text Text) Text) CG)
+ Math.FiniteCategories.CompositionGraph: readCGString :: String -> Either (FiniteCategoryError (CGMorphism Text Text) Text) CG
+ Math.FiniteCategories.CompositionGraph: support :: CompositionGraph a b -> Graph a b
+ Math.FiniteCategories.CompositionGraph: type CompositionLaw a b = Map (RawPath a b) (RawPath a b)
+ Math.FiniteCategories.CompositionGraph: type Path a b = (a, RawPath a b)
+ Math.FiniteCategories.CompositionGraph: type RawPath a b = [Arrow a b]
+ Math.FiniteCategories.CompositionGraph: unsafeCompositionGraph :: Graph a b -> CompositionLaw a b -> CompositionGraph a b
+ Math.FiniteCategories.CompositionGraph: unsafeReadCGDFile :: String -> IO CGD
+ Math.FiniteCategories.CompositionGraph: unsafeReadCGDString :: String -> CGD
+ Math.FiniteCategories.CompositionGraph: unsafeReadCGFile :: String -> IO CG
+ Math.FiniteCategories.CompositionGraph: unsafeReadCGString :: String -> CG
+ Math.FiniteCategories.CompositionGraph: writeCGDFile :: (PrettyPrint a1, PrettyPrint b1, Eq a1, Eq b1, PrettyPrint a2, PrettyPrint b2, Eq a2, Eq b2) => Diagram (CompositionGraph a1 b1) (CGMorphism a1 b1) a1 (CompositionGraph a2 b2) (CGMorphism a2 b2) a2 -> String -> IO ()
+ Math.FiniteCategories.CompositionGraph: writeCGDString :: (PrettyPrint a1, PrettyPrint b1, Eq a1, Eq b1, PrettyPrint a2, PrettyPrint b2, Eq a2, Eq b2) => Diagram (CompositionGraph a1 b1) (CGMorphism a1 b1) a1 (CompositionGraph a2 b2) (CGMorphism a2 b2) a2 -> String
+ Math.FiniteCategories.CompositionGraph: writeCGFile :: (PrettyPrint a, PrettyPrint b, Eq a, Eq b) => CompositionGraph a b -> String -> IO ()
+ Math.FiniteCategories.CompositionGraph: writeCGString :: (PrettyPrint a, PrettyPrint b, Eq a, Eq b) => CompositionGraph a b -> String
+ Math.FiniteCategories.CompositionGraph.Example: main :: IO ()
+ Math.FiniteCategories.ConeCategory.Example: main :: IO ()
+ Math.FiniteCategories.DiscreteCategory: discreteCategory :: Set a -> DiscreteCategory a
+ Math.FiniteCategories.DiscreteCategory: type DiscreteCategory a = FullSubcategory (Galaxy a) (StarIdentity a) a
+ Math.FiniteCategories.DiscreteCategory: type DiscreteMorphism a = StarIdentity a
+ Math.FiniteCategories.DiscreteCategory.Example: main :: IO ()
+ Math.FiniteCategories.Ens: ens :: Set (Set a) -> Ens a
+ Math.FiniteCategories.Ens: type Ens a = InheritedFullSubcategory (FinSet a) (Function a) (Set a)
+ Math.FiniteCategories.Ens.Example: main :: IO ()
+ Math.FiniteCategories.Examples: main :: IO ()
+ Math.FiniteCategories.FinCat.Example: main :: IO ()
+ Math.FiniteCategories.FinGrph.Example: main :: IO ()
+ Math.FiniteCategories.FullSubcategory: FullSubcategory :: c -> Set o -> FullSubcategory c m o
+ Math.FiniteCategories.FullSubcategory: InheritedFullSubcategory :: c -> Set o -> InheritedFullSubcategory c m o
+ Math.FiniteCategories.FullSubcategory: data FullSubcategory c m o
+ Math.FiniteCategories.FullSubcategory: data InheritedFullSubcategory c m o
+ Math.FiniteCategories.FullSubcategory: instance (GHC.Classes.Eq c, GHC.Classes.Eq o) => GHC.Classes.Eq (Math.FiniteCategories.FullSubcategory.FullSubcategory c m o)
+ Math.FiniteCategories.FullSubcategory: instance (GHC.Classes.Eq c, GHC.Classes.Eq o) => GHC.Classes.Eq (Math.FiniteCategories.FullSubcategory.InheritedFullSubcategory c m o)
+ Math.FiniteCategories.FullSubcategory: instance (GHC.Show.Show c, GHC.Show.Show o) => GHC.Show.Show (Math.FiniteCategories.FullSubcategory.FullSubcategory c m o)
+ Math.FiniteCategories.FullSubcategory: instance (GHC.Show.Show c, GHC.Show.Show o) => GHC.Show.Show (Math.FiniteCategories.FullSubcategory.InheritedFullSubcategory c m o)
+ Math.FiniteCategories.FullSubcategory: instance (Math.Category.Category c m o, GHC.Classes.Eq o) => Math.Category.Category (Math.FiniteCategories.FullSubcategory.FullSubcategory c m o) m o
+ Math.FiniteCategories.FullSubcategory: instance (Math.Category.Category c m o, GHC.Classes.Eq o) => Math.Category.Category (Math.FiniteCategories.FullSubcategory.InheritedFullSubcategory c m o) m o
+ Math.FiniteCategories.FullSubcategory: instance (Math.Category.Category c m o, GHC.Classes.Eq o) => Math.FiniteCategory.FiniteCategory (Math.FiniteCategories.FullSubcategory.FullSubcategory c m o) m o
+ Math.FiniteCategories.FullSubcategory: instance (Math.Category.Category c m o, GHC.Classes.Eq o) => Math.FiniteCategory.FiniteCategory (Math.FiniteCategories.FullSubcategory.InheritedFullSubcategory c m o) m o
+ Math.FiniteCategories.FullSubcategory: instance (Math.IO.PrettyPrint.PrettyPrint c, Math.IO.PrettyPrint.PrettyPrint m, Math.IO.PrettyPrint.PrettyPrint o, GHC.Classes.Eq o) => Math.IO.PrettyPrint.PrettyPrint (Math.FiniteCategories.FullSubcategory.FullSubcategory c m o)
+ Math.FiniteCategories.FullSubcategory: instance (Math.IO.PrettyPrint.PrettyPrint c, Math.IO.PrettyPrint.PrettyPrint m, Math.IO.PrettyPrint.PrettyPrint o, GHC.Classes.Eq o) => Math.IO.PrettyPrint.PrettyPrint (Math.FiniteCategories.FullSubcategory.InheritedFullSubcategory c m o)
+ Math.FiniteCategories.FunctorCategory.Example: main :: IO ()
+ Math.FiniteCategories.Hat: Hat :: Hat
+ Math.FiniteCategories.Hat: HatA :: HatOb
+ Math.FiniteCategories.Hat: HatB :: HatOb
+ Math.FiniteCategories.Hat: HatC :: HatOb
+ Math.FiniteCategories.Hat: HatF :: HatAr
+ Math.FiniteCategories.Hat: HatG :: HatAr
+ Math.FiniteCategories.Hat: HatIdA :: HatAr
+ Math.FiniteCategories.Hat: HatIdB :: HatAr
+ Math.FiniteCategories.Hat: HatIdC :: HatAr
+ Math.FiniteCategories.Hat: data Hat
+ Math.FiniteCategories.Hat: data HatAr
+ Math.FiniteCategories.Hat: data HatOb
+ Math.FiniteCategories.Hat: instance GHC.Classes.Eq Math.FiniteCategories.Hat.Hat
+ Math.FiniteCategories.Hat: instance GHC.Classes.Eq Math.FiniteCategories.Hat.HatAr
+ Math.FiniteCategories.Hat: instance GHC.Classes.Eq Math.FiniteCategories.Hat.HatOb
+ Math.FiniteCategories.Hat: instance GHC.Show.Show Math.FiniteCategories.Hat.Hat
+ Math.FiniteCategories.Hat: instance GHC.Show.Show Math.FiniteCategories.Hat.HatAr
+ Math.FiniteCategories.Hat: instance GHC.Show.Show Math.FiniteCategories.Hat.HatOb
+ Math.FiniteCategories.Hat: instance Math.Category.Category Math.FiniteCategories.Hat.Hat Math.FiniteCategories.Hat.HatAr Math.FiniteCategories.Hat.HatOb
+ Math.FiniteCategories.Hat: instance Math.Category.Morphism Math.FiniteCategories.Hat.HatAr Math.FiniteCategories.Hat.HatOb
+ Math.FiniteCategories.Hat: instance Math.FiniteCategory.FiniteCategory Math.FiniteCategories.Hat.Hat Math.FiniteCategories.Hat.HatAr Math.FiniteCategories.Hat.HatOb
+ Math.FiniteCategories.Hat: instance Math.IO.PrettyPrint.PrettyPrint Math.FiniteCategories.Hat.Hat
+ Math.FiniteCategories.Hat: instance Math.IO.PrettyPrint.PrettyPrint Math.FiniteCategories.Hat.HatAr
+ Math.FiniteCategories.Hat: instance Math.IO.PrettyPrint.PrettyPrint Math.FiniteCategories.Hat.HatOb
+ Math.FiniteCategories.Hat.Example: main :: IO ()
+ Math.FiniteCategories.NumberCategory: IsSmallerThan :: a -> a -> IsSmallerThan a
+ Math.FiniteCategories.NumberCategory: data IsSmallerThan a
+ Math.FiniteCategories.NumberCategory: numberCategory :: Natural -> NumberCategory
+ Math.FiniteCategories.NumberCategory: type NumberCategory = InheritedFullSubcategory Omega (IsSmallerThan Natural) Natural
+ Math.FiniteCategories.NumberCategory: type NumberCategoryMorphism = IsSmallerThan Natural
+ Math.FiniteCategories.NumberCategory: type NumberCategoryObject = Natural
+ Math.FiniteCategories.NumberCategory.Example: main :: IO ()
+ Math.FiniteCategories.One: One :: One
+ Math.FiniteCategories.One: data One
+ Math.FiniteCategories.One: instance GHC.Classes.Eq Math.FiniteCategories.One.One
+ Math.FiniteCategories.One: instance GHC.Show.Show Math.FiniteCategories.One.One
+ Math.FiniteCategories.One: instance Math.Category.Category Math.FiniteCategories.One.One Math.FiniteCategories.One.One Math.FiniteCategories.One.One
+ Math.FiniteCategories.One: instance Math.Category.Morphism Math.FiniteCategories.One.One Math.FiniteCategories.One.One
+ Math.FiniteCategories.One: instance Math.FiniteCategory.FiniteCategory Math.FiniteCategories.One.One Math.FiniteCategories.One.One Math.FiniteCategories.One.One
+ Math.FiniteCategories.One: instance Math.IO.PrettyPrint.PrettyPrint Math.FiniteCategories.One.One
+ Math.FiniteCategories.One.Example: main :: IO ()
+ Math.FiniteCategories.Opposite.Example: main :: IO ()
+ Math.FiniteCategories.Parallel: Parallel :: Parallel
+ Math.FiniteCategories.Parallel: ParallelA :: ParallelOb
+ Math.FiniteCategories.Parallel: ParallelB :: ParallelOb
+ Math.FiniteCategories.Parallel: ParallelF :: ParallelAr
+ Math.FiniteCategories.Parallel: ParallelG :: ParallelAr
+ Math.FiniteCategories.Parallel: ParallelIdA :: ParallelAr
+ Math.FiniteCategories.Parallel: ParallelIdB :: ParallelAr
+ Math.FiniteCategories.Parallel: data Parallel
+ Math.FiniteCategories.Parallel: data ParallelAr
+ Math.FiniteCategories.Parallel: data ParallelOb
+ Math.FiniteCategories.Parallel: instance GHC.Classes.Eq Math.FiniteCategories.Parallel.Parallel
+ Math.FiniteCategories.Parallel: instance GHC.Classes.Eq Math.FiniteCategories.Parallel.ParallelAr
+ Math.FiniteCategories.Parallel: instance GHC.Classes.Eq Math.FiniteCategories.Parallel.ParallelOb
+ Math.FiniteCategories.Parallel: instance GHC.Show.Show Math.FiniteCategories.Parallel.Parallel
+ Math.FiniteCategories.Parallel: instance GHC.Show.Show Math.FiniteCategories.Parallel.ParallelAr
+ Math.FiniteCategories.Parallel: instance GHC.Show.Show Math.FiniteCategories.Parallel.ParallelOb
+ Math.FiniteCategories.Parallel: instance Math.Category.Category Math.FiniteCategories.Parallel.Parallel Math.FiniteCategories.Parallel.ParallelAr Math.FiniteCategories.Parallel.ParallelOb
+ Math.FiniteCategories.Parallel: instance Math.Category.Morphism Math.FiniteCategories.Parallel.ParallelAr Math.FiniteCategories.Parallel.ParallelOb
+ Math.FiniteCategories.Parallel: instance Math.FiniteCategory.FiniteCategory Math.FiniteCategories.Parallel.Parallel Math.FiniteCategories.Parallel.ParallelAr Math.FiniteCategories.Parallel.ParallelOb
+ Math.FiniteCategories.Parallel: instance Math.IO.PrettyPrint.PrettyPrint Math.FiniteCategories.Parallel.Parallel
+ Math.FiniteCategories.Parallel: instance Math.IO.PrettyPrint.PrettyPrint Math.FiniteCategories.Parallel.ParallelAr
+ Math.FiniteCategories.Parallel: instance Math.IO.PrettyPrint.PrettyPrint Math.FiniteCategories.Parallel.ParallelOb
+ Math.FiniteCategories.Parallel.Example: main :: IO ()
+ Math.FiniteCategories.SafeCompositionGraph: SCGMorphism :: Path a b -> CompositionLaw a b -> Int -> SCGMorphism a b
+ Math.FiniteCategories.SafeCompositionGraph: [compositionLawS] :: SCGMorphism a b -> CompositionLaw a b
+ Math.FiniteCategories.SafeCompositionGraph: [maxNbCycles] :: SCGMorphism a b -> Int
+ Math.FiniteCategories.SafeCompositionGraph: [pathS] :: SCGMorphism a b -> Path a b
+ Math.FiniteCategories.SafeCompositionGraph: compositionGraphFromSafeCompositionGraph :: SafeCompositionGraph a b -> CompositionGraph a b
+ Math.FiniteCategories.SafeCompositionGraph: constructRandomSafeCompositionGraph :: RandomGen g => Int -> Int -> Int -> g -> Int -> (SafeCompositionGraph Int Int, g)
+ Math.FiniteCategories.SafeCompositionGraph: data SCGMorphism a b
+ Math.FiniteCategories.SafeCompositionGraph: data SafeCompositionGraph a b
+ Math.FiniteCategories.SafeCompositionGraph: defaultConstructRandomSafeCompositionGraph :: RandomGen g => g -> (SafeCompositionGraph Int Int, g)
+ Math.FiniteCategories.SafeCompositionGraph: defaultConstructRandomSafeDiagram :: RandomGen g => g -> (Diagram (SafeCompositionGraph Int Int) (SCGMorphism Int Int) Int (SafeCompositionGraph Int Int) (SCGMorphism Int Int) Int, g)
+ Math.FiniteCategories.SafeCompositionGraph: getLabelS :: SCGMorphism a b -> Maybe b
+ Math.FiniteCategories.SafeCompositionGraph: instance (GHC.Classes.Eq a, GHC.Classes.Eq b) => GHC.Classes.Eq (Math.FiniteCategories.SafeCompositionGraph.SCGMorphism a b)
+ Math.FiniteCategories.SafeCompositionGraph: instance (GHC.Classes.Eq a, GHC.Classes.Eq b) => GHC.Classes.Eq (Math.FiniteCategories.SafeCompositionGraph.SafeCompositionGraph a b)
+ Math.FiniteCategories.SafeCompositionGraph: instance (GHC.Classes.Eq a, GHC.Classes.Eq b) => Math.Category.Category (Math.FiniteCategories.SafeCompositionGraph.SafeCompositionGraph a b) (Math.FiniteCategories.SafeCompositionGraph.SCGMorphism a b) a
+ Math.FiniteCategories.SafeCompositionGraph: instance (GHC.Classes.Eq a, GHC.Classes.Eq b) => Math.Category.Morphism (Math.FiniteCategories.SafeCompositionGraph.SCGMorphism a b) a
+ Math.FiniteCategories.SafeCompositionGraph: instance (GHC.Classes.Eq a, GHC.Classes.Eq b) => Math.FiniteCategory.FiniteCategory (Math.FiniteCategories.SafeCompositionGraph.SafeCompositionGraph a b) (Math.FiniteCategories.SafeCompositionGraph.SCGMorphism a b) a
+ Math.FiniteCategories.SafeCompositionGraph: instance (GHC.Show.Show a, GHC.Show.Show b) => GHC.Show.Show (Math.FiniteCategories.SafeCompositionGraph.SCGMorphism a b)
+ Math.FiniteCategories.SafeCompositionGraph: instance (GHC.Show.Show a, GHC.Show.Show b) => GHC.Show.Show (Math.FiniteCategories.SafeCompositionGraph.SafeCompositionGraph a b)
+ Math.FiniteCategories.SafeCompositionGraph: instance (Math.IO.PrettyPrint.PrettyPrint a, Math.IO.PrettyPrint.PrettyPrint b, GHC.Classes.Eq a, GHC.Classes.Eq b) => Math.IO.PrettyPrint.PrettyPrint (Math.FiniteCategories.SafeCompositionGraph.SCGMorphism a b)
+ Math.FiniteCategories.SafeCompositionGraph: instance (Math.IO.PrettyPrint.PrettyPrint a, Math.IO.PrettyPrint.PrettyPrint b, GHC.Classes.Eq a, GHC.Classes.Eq b) => Math.IO.PrettyPrint.PrettyPrint (Math.FiniteCategories.SafeCompositionGraph.SafeCompositionGraph a b)
+ Math.FiniteCategories.SafeCompositionGraph: instance GHC.Classes.Eq Math.FiniteCategories.SafeCompositionGraph.Token
+ Math.FiniteCategories.SafeCompositionGraph: instance GHC.Show.Show Math.FiniteCategories.SafeCompositionGraph.Token
+ Math.FiniteCategories.SafeCompositionGraph: lawS :: SafeCompositionGraph a b -> CompositionLaw a b
+ Math.FiniteCategories.SafeCompositionGraph: maxCycles :: SafeCompositionGraph a b -> Int
+ Math.FiniteCategories.SafeCompositionGraph: readSCGDFile :: String -> IO (Either (DiagramError SCG (SCGMorphism Text Text) Text SCG (SCGMorphism Text Text) Text) SCGD)
+ Math.FiniteCategories.SafeCompositionGraph: readSCGDString :: String -> Either (DiagramError SCG (SCGMorphism Text Text) Text SCG (SCGMorphism Text Text) Text) SCGD
+ Math.FiniteCategories.SafeCompositionGraph: readSCGFile :: String -> IO (Either (FiniteCategoryError (SCGMorphism Text Text) Text) SCG)
+ Math.FiniteCategories.SafeCompositionGraph: readSCGString :: String -> Either (FiniteCategoryError (SCGMorphism Text Text) Text) SCG
+ Math.FiniteCategories.SafeCompositionGraph: safeCompositionGraph :: (Eq a, Eq b) => Graph a b -> CompositionLaw a b -> Int -> Either (FiniteCategoryError (SCGMorphism a b) a) (SafeCompositionGraph a b)
+ Math.FiniteCategories.SafeCompositionGraph: safeCompositionGraphFromCompositionGraph :: Int -> CompositionGraph a b -> SafeCompositionGraph a b
+ Math.FiniteCategories.SafeCompositionGraph: supportS :: SafeCompositionGraph a b -> Graph a b
+ Math.FiniteCategories.SafeCompositionGraph: unsafeReadSCGDFile :: String -> IO SCGD
+ Math.FiniteCategories.SafeCompositionGraph: unsafeReadSCGDString :: String -> SCGD
+ Math.FiniteCategories.SafeCompositionGraph: unsafeReadSCGFile :: String -> IO SCG
+ Math.FiniteCategories.SafeCompositionGraph: unsafeReadSCGString :: String -> SCG
+ Math.FiniteCategories.SafeCompositionGraph: unsafeSafeCompositionGraph :: Graph a b -> CompositionLaw a b -> Int -> SafeCompositionGraph a b
+ Math.FiniteCategories.SafeCompositionGraph: writeSCGDFile :: (PrettyPrint a1, PrettyPrint b1, Eq a1, Eq b1, PrettyPrint a2, PrettyPrint b2, Eq a2, Eq b2) => Diagram (SafeCompositionGraph a1 b1) (SCGMorphism a1 b1) a1 (SafeCompositionGraph a2 b2) (SCGMorphism a2 b2) a2 -> String -> IO ()
+ Math.FiniteCategories.SafeCompositionGraph: writeSCGDString :: (PrettyPrint a1, PrettyPrint b1, Eq a1, Eq b1, PrettyPrint a2, PrettyPrint b2, Eq a2, Eq b2) => Diagram (SafeCompositionGraph a1 b1) (SCGMorphism a1 b1) a1 (SafeCompositionGraph a2 b2) (SCGMorphism a2 b2) a2 -> String
+ Math.FiniteCategories.SafeCompositionGraph: writeSCGFile :: (PrettyPrint a, PrettyPrint b, Eq a, Eq b) => SafeCompositionGraph a b -> String -> IO ()
+ Math.FiniteCategories.SafeCompositionGraph: writeSCGString :: (PrettyPrint a, PrettyPrint b, Eq a, Eq b) => SafeCompositionGraph a b -> String
+ Math.FiniteCategories.SafeCompositionGraph.Example: main :: IO ()
+ Math.FiniteCategories.Square: Square :: Square
+ Math.FiniteCategories.Square: SquareA :: SquareOb
+ Math.FiniteCategories.Square: SquareB :: SquareOb
+ Math.FiniteCategories.Square: SquareC :: SquareOb
+ Math.FiniteCategories.Square: SquareD :: SquareOb
+ Math.FiniteCategories.Square: SquareF :: SquareAr
+ Math.FiniteCategories.Square: SquareFH :: SquareAr
+ Math.FiniteCategories.Square: SquareG :: SquareAr
+ Math.FiniteCategories.Square: SquareGI :: SquareAr
+ Math.FiniteCategories.Square: SquareH :: SquareAr
+ Math.FiniteCategories.Square: SquareI :: SquareAr
+ Math.FiniteCategories.Square: SquareIdA :: SquareAr
+ Math.FiniteCategories.Square: SquareIdB :: SquareAr
+ Math.FiniteCategories.Square: SquareIdC :: SquareAr
+ Math.FiniteCategories.Square: SquareIdD :: SquareAr
+ Math.FiniteCategories.Square: data Square
+ Math.FiniteCategories.Square: data SquareAr
+ Math.FiniteCategories.Square: data SquareOb
+ Math.FiniteCategories.Square: instance GHC.Classes.Eq Math.FiniteCategories.Square.Square
+ Math.FiniteCategories.Square: instance GHC.Classes.Eq Math.FiniteCategories.Square.SquareAr
+ Math.FiniteCategories.Square: instance GHC.Classes.Eq Math.FiniteCategories.Square.SquareOb
+ Math.FiniteCategories.Square: instance GHC.Show.Show Math.FiniteCategories.Square.Square
+ Math.FiniteCategories.Square: instance GHC.Show.Show Math.FiniteCategories.Square.SquareAr
+ Math.FiniteCategories.Square: instance GHC.Show.Show Math.FiniteCategories.Square.SquareOb
+ Math.FiniteCategories.Square: instance Math.Category.Category Math.FiniteCategories.Square.Square Math.FiniteCategories.Square.SquareAr Math.FiniteCategories.Square.SquareOb
+ Math.FiniteCategories.Square: instance Math.Category.Morphism Math.FiniteCategories.Square.SquareAr Math.FiniteCategories.Square.SquareOb
+ Math.FiniteCategories.Square: instance Math.FiniteCategory.FiniteCategory Math.FiniteCategories.Square.Square Math.FiniteCategories.Square.SquareAr Math.FiniteCategories.Square.SquareOb
+ Math.FiniteCategories.Square: instance Math.IO.PrettyPrint.PrettyPrint Math.FiniteCategories.Square.Square
+ Math.FiniteCategories.Square: instance Math.IO.PrettyPrint.PrettyPrint Math.FiniteCategories.Square.SquareAr
+ Math.FiniteCategories.Square: instance Math.IO.PrettyPrint.PrettyPrint Math.FiniteCategories.Square.SquareOb
+ Math.FiniteCategories.Square.Example: main :: IO ()
+ Math.FiniteCategories.Subcategory: data InheritedSubcategory c m o
+ Math.FiniteCategories.Subcategory: data Subcategory c m o
+ Math.FiniteCategories.Subcategory: embeddingToInheritedSubcategory :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1) => Diagram c1 m1 o1 c2 m2 o2 -> InheritedSubcategory c2 m2 o2
+ Math.FiniteCategories.Subcategory: embeddingToSubcategory :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1) => Diagram c1 m1 o1 c2 m2 o2 -> Subcategory c2 m2 o2
+ Math.FiniteCategories.Subcategory: fullDiagram :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1) => Diagram c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 (Subcategory c2 m2 o2) m2 o2
+ Math.FiniteCategories.Subcategory: fullDiagram2 :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1) => Diagram c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 (InheritedSubcategory c2 m2 o2) m2 o2
+ Math.FiniteCategories.Subcategory: fullNaturalTransformation :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, Category c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => NaturalTransformation c1 m1 o1 c2 m2 o2 -> NaturalTransformation c1 m1 o1 (Subcategory c2 m2 o2) m2 o2
+ Math.FiniteCategories.Subcategory: fullNaturalTransformation2 :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, Category c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => NaturalTransformation c1 m1 o1 c2 m2 o2 -> NaturalTransformation c1 m1 o1 (InheritedSubcategory c2 m2 o2) m2 o2
+ Math.FiniteCategories.Subcategory: inheritedSubcategory :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> Set o -> Set m -> Either (FiniteCategoryError m o) (InheritedSubcategory c m o)
+ Math.FiniteCategories.Subcategory: instance (GHC.Classes.Eq c, GHC.Classes.Eq o, GHC.Classes.Eq m) => GHC.Classes.Eq (Math.FiniteCategories.Subcategory.InheritedSubcategory c m o)
+ Math.FiniteCategories.Subcategory: instance (GHC.Classes.Eq c, GHC.Classes.Eq o, GHC.Classes.Eq m) => GHC.Classes.Eq (Math.FiniteCategories.Subcategory.Subcategory c m o)
+ Math.FiniteCategories.Subcategory: instance (GHC.Show.Show c, GHC.Show.Show m, GHC.Show.Show o) => GHC.Show.Show (Math.FiniteCategories.Subcategory.InheritedSubcategory c m o)
+ Math.FiniteCategories.Subcategory: instance (GHC.Show.Show c, GHC.Show.Show m, GHC.Show.Show o) => GHC.Show.Show (Math.FiniteCategories.Subcategory.Subcategory c m o)
+ Math.FiniteCategories.Subcategory: instance (Math.Category.Category c m o, GHC.Classes.Eq o, GHC.Classes.Eq m) => Math.Category.Category (Math.FiniteCategories.Subcategory.InheritedSubcategory c m o) m o
+ Math.FiniteCategories.Subcategory: instance (Math.Category.Category c m o, GHC.Classes.Eq o, GHC.Classes.Eq m) => Math.Category.Category (Math.FiniteCategories.Subcategory.Subcategory c m o) m o
+ Math.FiniteCategories.Subcategory: instance (Math.Category.Category c m o, GHC.Classes.Eq o, GHC.Classes.Eq m) => Math.FiniteCategory.FiniteCategory (Math.FiniteCategories.Subcategory.InheritedSubcategory c m o) m o
+ Math.FiniteCategories.Subcategory: instance (Math.Category.Category c m o, GHC.Classes.Eq o, GHC.Classes.Eq m) => Math.FiniteCategory.FiniteCategory (Math.FiniteCategories.Subcategory.Subcategory c m o) m o
+ Math.FiniteCategories.Subcategory: instance (Math.IO.PrettyPrint.PrettyPrint c, Math.IO.PrettyPrint.PrettyPrint m, Math.IO.PrettyPrint.PrettyPrint o, GHC.Classes.Eq o, GHC.Classes.Eq m) => Math.IO.PrettyPrint.PrettyPrint (Math.FiniteCategories.Subcategory.InheritedSubcategory c m o)
+ Math.FiniteCategories.Subcategory: instance (Math.IO.PrettyPrint.PrettyPrint c, Math.IO.PrettyPrint.PrettyPrint m, Math.IO.PrettyPrint.PrettyPrint o, GHC.Classes.Eq o, GHC.Classes.Eq m) => Math.IO.PrettyPrint.PrettyPrint (Math.FiniteCategories.Subcategory.Subcategory c m o)
+ Math.FiniteCategories.Subcategory: originalCategory :: Subcategory c m o -> c
+ Math.FiniteCategories.Subcategory: originalCategory2 :: InheritedSubcategory c m o -> c
+ Math.FiniteCategories.Subcategory: subcategory :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> Set o -> Set m -> Either (FiniteCategoryError m o) (Subcategory c m o)
+ Math.FiniteCategories.Subcategory: unsafeInheritedSubcategory :: c -> Set o -> Set m -> InheritedSubcategory c m o
+ Math.FiniteCategories.Subcategory: unsafeSubcategory :: c -> Set o -> Set m -> Subcategory c m o
+ Math.FiniteCategories.V: V :: V
+ Math.FiniteCategories.V: VA :: VOb
+ Math.FiniteCategories.V: VB :: VOb
+ Math.FiniteCategories.V: VC :: VOb
+ Math.FiniteCategories.V: VF :: VAr
+ Math.FiniteCategories.V: VG :: VAr
+ Math.FiniteCategories.V: VIdA :: VAr
+ Math.FiniteCategories.V: VIdB :: VAr
+ Math.FiniteCategories.V: VIdC :: VAr
+ Math.FiniteCategories.V: data V
+ Math.FiniteCategories.V: data VAr
+ Math.FiniteCategories.V: data VOb
+ Math.FiniteCategories.V: instance GHC.Classes.Eq Math.FiniteCategories.V.V
+ Math.FiniteCategories.V: instance GHC.Classes.Eq Math.FiniteCategories.V.VAr
+ Math.FiniteCategories.V: instance GHC.Classes.Eq Math.FiniteCategories.V.VOb
+ Math.FiniteCategories.V: instance GHC.Show.Show Math.FiniteCategories.V.V
+ Math.FiniteCategories.V: instance GHC.Show.Show Math.FiniteCategories.V.VAr
+ Math.FiniteCategories.V: instance GHC.Show.Show Math.FiniteCategories.V.VOb
+ Math.FiniteCategories.V: instance Math.Category.Category Math.FiniteCategories.V.V Math.FiniteCategories.V.VAr Math.FiniteCategories.V.VOb
+ Math.FiniteCategories.V: instance Math.Category.Morphism Math.FiniteCategories.V.VAr Math.FiniteCategories.V.VOb
+ Math.FiniteCategories.V: instance Math.FiniteCategory.FiniteCategory Math.FiniteCategories.V.V Math.FiniteCategories.V.VAr Math.FiniteCategories.V.VOb
+ Math.FiniteCategories.V: instance Math.IO.PrettyPrint.PrettyPrint Math.FiniteCategories.V.V
+ Math.FiniteCategories.V: instance Math.IO.PrettyPrint.PrettyPrint Math.FiniteCategories.V.VAr
+ Math.FiniteCategories.V: instance Math.IO.PrettyPrint.PrettyPrint Math.FiniteCategories.V.VOb
+ Math.FiniteCategories.V.Example: main :: IO ()
+ Math.FiniteCategory: arFrom :: (FiniteCategory c m o, Morphism m o) => c -> o -> Set m
+ Math.FiniteCategory: arFrom2 :: (FiniteCategory c m o, Morphism m o) => c -> Set o -> Set m
+ Math.FiniteCategory: arTo :: (FiniteCategory c m o, Morphism m o) => c -> o -> Set m
+ Math.FiniteCategory: arTo2 :: (FiniteCategory c m o, Morphism m o) => c -> Set o -> Set m
+ Math.FiniteCategory: arrows :: (FiniteCategory c m o, Morphism m o) => c -> Set m
+ Math.FiniteCategory: bruteForceDecompose :: (FiniteCategory c m o, Morphism m o, Eq m) => c -> m -> [m]
+ Math.FiniteCategory: class (Category c m o) => FiniteCategory c m o | c -> m, m -> o
+ Math.FiniteCategory: genArFrom :: (FiniteCategory c m o, Morphism m o) => c -> o -> Set m
+ Math.FiniteCategory: genArFrom2 :: (FiniteCategory c m o, Morphism m o) => c -> Set o -> Set m
+ Math.FiniteCategory: genArTo :: (FiniteCategory c m o, Morphism m o) => c -> o -> Set m
+ Math.FiniteCategory: genArTo2 :: (FiniteCategory c m o, Morphism m o) => c -> Set o -> Set m
+ Math.FiniteCategory: genArrows :: (FiniteCategory c m o, Morphism m o) => c -> Set m
+ Math.FiniteCategory: identities :: (FiniteCategory c m o, Morphism m o) => c -> Set m
+ Math.FiniteCategory: initialObjects :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> Set o
+ Math.FiniteCategory: isEpic :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> m -> Bool
+ Math.FiniteCategory: isInitial :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> o -> Bool
+ Math.FiniteCategory: isMonic :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> m -> Bool
+ Math.FiniteCategory: isTerminal :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> o -> Bool
+ Math.FiniteCategory: ob :: FiniteCategory c m o => c -> Set o
+ Math.FiniteCategory: terminalObjects :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> Set o
+ Math.FiniteCategoryError: checkFiniteCategory :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> Maybe (FiniteCategoryError m o)
+ Math.FiniteCategoryError: data FiniteCategoryError m o
+ Math.FiniteCategoryError: instance (GHC.Classes.Eq m, GHC.Classes.Eq o) => GHC.Classes.Eq (Math.FiniteCategoryError.FiniteCategoryError m o)
+ Math.FiniteCategoryError: instance (GHC.Show.Show m, GHC.Show.Show o) => GHC.Show.Show (Math.FiniteCategoryError.FiniteCategoryError m o)
+ Math.Functors.Adjunction: 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
+ Math.Functors.Adjunction: 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
+ Math.Functors.Adjunction.Example: main :: IO ()
+ Math.Functors.DataMigration: deltaFunctor :: (FiniteCategory c1 m1 o1, Morphism m1 o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2, FiniteCategory c3 m3 o3, Morphism m3 o3, Eq c3, Eq m3, Eq o3) => c3 -> Diagram c1 m1 o1 c2 m2 o2 -> Diagram (FunctorCategory c2 m2 o2 c3 m3 o3) (NaturalTransformation c2 m2 o2 c3 m3 o3) (Diagram c2 m2 o2 c3 m3 o3) (FunctorCategory c1 m1 o1 c3 m3 o3) (NaturalTransformation c1 m1 o1 c3 m3 o3) (Diagram c1 m1 o1 c3 m3 o3)
+ Math.Functors.DataMigration: piFunctor :: (FiniteCategory c1 m1 o1, FiniteCategory c3 m3 o3, FiniteCategory c2 m2 o2, Morphism m1 o1, Morphism m3 o3, Morphism m2 o2, Eq c1, Eq m1, Eq o1, Eq c3, Eq m3, Eq o3, Eq c2, Eq m2, Eq o2) => c3 -> Diagram c1 m1 o1 c2 m2 o2 -> Diagram (FunctorCategory c1 m1 o1 c3 m3 o3) (NaturalTransformation c1 m1 o1 c3 m3 o3) (Diagram c1 m1 o1 c3 m3 o3) (FunctorCategory c2 m2 o2 c3 m3 o3) (NaturalTransformation c2 m2 o2 c3 m3 o3) (Diagram c2 m2 o2 c3 m3 o3)
+ Math.Functors.DataMigration: sigmaFunctor :: (FiniteCategory c2 m2 o2, FiniteCategory c3 m3 o3, FiniteCategory c1 m1 o1, Morphism m2 o2, Morphism m3 o3, Morphism m1 o1, Eq c2, Eq m2, Eq o2, Eq c3, Eq m3, Eq o3, Eq c1, Eq m1, Eq o1) => c3 -> Diagram c1 m1 o1 c2 m2 o2 -> Diagram (FunctorCategory c1 m1 o1 c3 m3 o3) (NaturalTransformation c1 m1 o1 c3 m3 o3) (Diagram c1 m1 o1 c3 m3 o3) (FunctorCategory c2 m2 o2 c3 m3 o3) (NaturalTransformation c2 m2 o2 c3 m3 o3) (Diagram c2 m2 o2 c3 m3 o3)
+ Math.Functors.DataMigration.Example: main :: IO ()
+ Math.Functors.DiagonalFunctor: diagonalFunctor :: (FiniteCategory c1 m1 o1, Morphism m1 o1, FiniteCategory c2 m2 o2, Morphism m2 o2) => c1 -> c2 -> Diagram c2 m2 o2 (FunctorCategory c1 m1 o1 c2 m2 o2) (NaturalTransformation c1 m1 o1 c2 m2 o2) (Diagram c1 m1 o1 c2 m2 o2)
+ Math.Functors.DiagonalFunctor.Example: main :: IO ()
+ Math.Functors.Examples: main :: IO ()
+ Math.Functors.KanExtension: instance (GHC.Classes.Eq c1, GHC.Classes.Eq c2, GHC.Classes.Eq o1, GHC.Classes.Eq o2, GHC.Classes.Eq m1, GHC.Classes.Eq m2, GHC.Classes.Eq c3, GHC.Classes.Eq o3, GHC.Classes.Eq m3) => GHC.Classes.Eq (Math.Functors.KanExtension.LeftKanCategory c1 m1 o1 c2 m2 o2 c3 m3 o3)
+ Math.Functors.KanExtension: instance (GHC.Classes.Eq c1, GHC.Classes.Eq c2, GHC.Classes.Eq o1, GHC.Classes.Eq o2, GHC.Classes.Eq m1, GHC.Classes.Eq m2, GHC.Classes.Eq c3, GHC.Classes.Eq o3, GHC.Classes.Eq m3) => GHC.Classes.Eq (Math.Functors.KanExtension.RightKanCategory c1 m1 o1 c2 m2 o2 c3 m3 o3)
+ Math.Functors.KanExtension: instance (GHC.Classes.Eq c1, GHC.Classes.Eq c3, GHC.Classes.Eq o1, GHC.Classes.Eq o3, GHC.Classes.Eq m1, GHC.Classes.Eq m3, GHC.Classes.Eq c2, GHC.Classes.Eq o2, GHC.Classes.Eq m2) => GHC.Classes.Eq (Math.Functors.KanExtension.KanObject c1 m1 o1 c2 m2 o2 c3 m3 o3)
+ Math.Functors.KanExtension: instance (GHC.Classes.Eq c2, GHC.Classes.Eq c3, GHC.Classes.Eq o2, GHC.Classes.Eq o3, GHC.Classes.Eq m2, GHC.Classes.Eq m3, GHC.Classes.Eq c1, GHC.Classes.Eq o1, GHC.Classes.Eq m1) => GHC.Classes.Eq (Math.Functors.KanExtension.LeftKanMorphism c1 m1 o1 c2 m2 o2 c3 m3 o3)
+ Math.Functors.KanExtension: instance (GHC.Classes.Eq c2, GHC.Classes.Eq c3, GHC.Classes.Eq o2, GHC.Classes.Eq o3, GHC.Classes.Eq m2, GHC.Classes.Eq m3, GHC.Classes.Eq c1, GHC.Classes.Eq o1, GHC.Classes.Eq m1) => GHC.Classes.Eq (Math.Functors.KanExtension.RightKanMorphism c1 m1 o1 c2 m2 o2 c3 m3 o3)
+ Math.Functors.KanExtension: instance (GHC.Show.Show c1, GHC.Show.Show c2, GHC.Show.Show o1, GHC.Show.Show o2, GHC.Show.Show m1, GHC.Show.Show m2, GHC.Show.Show c3, GHC.Show.Show o3, GHC.Show.Show m3) => GHC.Show.Show (Math.Functors.KanExtension.LeftKanCategory c1 m1 o1 c2 m2 o2 c3 m3 o3)
+ Math.Functors.KanExtension: instance (GHC.Show.Show c1, GHC.Show.Show c2, GHC.Show.Show o1, GHC.Show.Show o2, GHC.Show.Show m1, GHC.Show.Show m2, GHC.Show.Show c3, GHC.Show.Show o3, GHC.Show.Show m3) => GHC.Show.Show (Math.Functors.KanExtension.RightKanCategory c1 m1 o1 c2 m2 o2 c3 m3 o3)
+ Math.Functors.KanExtension: instance (GHC.Show.Show c1, GHC.Show.Show c3, GHC.Show.Show o1, GHC.Show.Show o3, GHC.Show.Show m1, GHC.Show.Show m3, GHC.Show.Show c2, GHC.Show.Show o2, GHC.Show.Show m2) => GHC.Show.Show (Math.Functors.KanExtension.KanObject c1 m1 o1 c2 m2 o2 c3 m3 o3)
+ Math.Functors.KanExtension: instance (GHC.Show.Show c2, GHC.Show.Show m2, GHC.Show.Show o2, GHC.Show.Show c3, GHC.Show.Show m3, GHC.Show.Show o3, GHC.Show.Show c1, GHC.Show.Show o1, GHC.Show.Show m1) => GHC.Show.Show (Math.Functors.KanExtension.LeftKanMorphism c1 m1 o1 c2 m2 o2 c3 m3 o3)
+ Math.Functors.KanExtension: instance (GHC.Show.Show c2, GHC.Show.Show m2, GHC.Show.Show o2, GHC.Show.Show c3, GHC.Show.Show m3, GHC.Show.Show o3, GHC.Show.Show c1, GHC.Show.Show o1, GHC.Show.Show m1) => GHC.Show.Show (Math.Functors.KanExtension.RightKanMorphism c1 m1 o1 c2 m2 o2 c3 m3 o3)
+ Math.Functors.KanExtension: instance (Math.FiniteCategory.FiniteCategory c1 m1 o1, Math.Category.Morphism m1 o1, GHC.Classes.Eq c1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, Math.FiniteCategory.FiniteCategory c2 m2 o2, Math.Category.Morphism m2 o2, GHC.Classes.Eq c2, GHC.Classes.Eq m2, GHC.Classes.Eq o2, Math.Category.Category c3 m3 o3, Math.Category.Morphism m3 o3, GHC.Classes.Eq c3, GHC.Classes.Eq m3, GHC.Classes.Eq o3) => Math.Category.Category (Math.Functors.KanExtension.LeftKanCategory c1 m1 o1 c2 m2 o2 c3 m3 o3) (Math.Functors.KanExtension.LeftKanMorphism c1 m1 o1 c2 m2 o2 c3 m3 o3) (Math.Functors.KanExtension.KanObject c1 m1 o1 c2 m2 o2 c3 m3 o3)
+ Math.Functors.KanExtension: instance (Math.FiniteCategory.FiniteCategory c1 m1 o1, Math.Category.Morphism m1 o1, GHC.Classes.Eq c1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, Math.FiniteCategory.FiniteCategory c2 m2 o2, Math.Category.Morphism m2 o2, GHC.Classes.Eq c2, GHC.Classes.Eq m2, GHC.Classes.Eq o2, Math.Category.Category c3 m3 o3, Math.Category.Morphism m3 o3, GHC.Classes.Eq c3, GHC.Classes.Eq m3, GHC.Classes.Eq o3) => Math.Category.Category (Math.Functors.KanExtension.RightKanCategory c1 m1 o1 c2 m2 o2 c3 m3 o3) (Math.Functors.KanExtension.RightKanMorphism c1 m1 o1 c2 m2 o2 c3 m3 o3) (Math.Functors.KanExtension.KanObject c1 m1 o1 c2 m2 o2 c3 m3 o3)
+ Math.Functors.KanExtension: instance (Math.FiniteCategory.FiniteCategory c1 m1 o1, Math.Category.Morphism m1 o1, GHC.Classes.Eq c1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, Math.FiniteCategory.FiniteCategory c2 m2 o2, Math.Category.Morphism m2 o2, GHC.Classes.Eq c2, GHC.Classes.Eq m2, GHC.Classes.Eq o2, Math.Category.Category c3 m3 o3, Math.Category.Morphism m3 o3, GHC.Classes.Eq c3, GHC.Classes.Eq m3, GHC.Classes.Eq o3) => Math.Category.Morphism (Math.Functors.KanExtension.LeftKanMorphism c1 m1 o1 c2 m2 o2 c3 m3 o3) (Math.Functors.KanExtension.KanObject c1 m1 o1 c2 m2 o2 c3 m3 o3)
+ Math.Functors.KanExtension: instance (Math.FiniteCategory.FiniteCategory c1 m1 o1, Math.Category.Morphism m1 o1, GHC.Classes.Eq c1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, Math.FiniteCategory.FiniteCategory c2 m2 o2, Math.Category.Morphism m2 o2, GHC.Classes.Eq c2, GHC.Classes.Eq m2, GHC.Classes.Eq o2, Math.Category.Category c3 m3 o3, Math.Category.Morphism m3 o3, GHC.Classes.Eq c3, GHC.Classes.Eq m3, GHC.Classes.Eq o3) => Math.Category.Morphism (Math.Functors.KanExtension.RightKanMorphism c1 m1 o1 c2 m2 o2 c3 m3 o3) (Math.Functors.KanExtension.KanObject c1 m1 o1 c2 m2 o2 c3 m3 o3)
+ Math.Functors.KanExtension: instance (Math.FiniteCategory.FiniteCategory c1 m1 o1, Math.Category.Morphism m1 o1, GHC.Classes.Eq c1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, Math.FiniteCategory.FiniteCategory c2 m2 o2, Math.Category.Morphism m2 o2, GHC.Classes.Eq c2, GHC.Classes.Eq m2, GHC.Classes.Eq o2, Math.FiniteCategory.FiniteCategory c3 m3 o3, Math.Category.Morphism m3 o3, GHC.Classes.Eq c3, GHC.Classes.Eq m3, GHC.Classes.Eq o3) => Math.FiniteCategory.FiniteCategory (Math.Functors.KanExtension.LeftKanCategory c1 m1 o1 c2 m2 o2 c3 m3 o3) (Math.Functors.KanExtension.LeftKanMorphism c1 m1 o1 c2 m2 o2 c3 m3 o3) (Math.Functors.KanExtension.KanObject c1 m1 o1 c2 m2 o2 c3 m3 o3)
+ Math.Functors.KanExtension: instance (Math.FiniteCategory.FiniteCategory c1 m1 o1, Math.Category.Morphism m1 o1, GHC.Classes.Eq c1, GHC.Classes.Eq m1, GHC.Classes.Eq o1, Math.FiniteCategory.FiniteCategory c2 m2 o2, Math.Category.Morphism m2 o2, GHC.Classes.Eq c2, GHC.Classes.Eq m2, GHC.Classes.Eq o2, Math.FiniteCategory.FiniteCategory c3 m3 o3, Math.Category.Morphism m3 o3, GHC.Classes.Eq c3, GHC.Classes.Eq m3, GHC.Classes.Eq o3) => Math.FiniteCategory.FiniteCategory (Math.Functors.KanExtension.RightKanCategory c1 m1 o1 c2 m2 o2 c3 m3 o3) (Math.Functors.KanExtension.RightKanMorphism c1 m1 o1 c2 m2 o2 c3 m3 o3) (Math.Functors.KanExtension.KanObject c1 m1 o1 c2 m2 o2 c3 m3 o3)
+ Math.Functors.KanExtension: leftKan :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2, FiniteCategory c3 m3 o3, Morphism m3 o3, Eq c3, Eq m3, Eq o3) => Diagram c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 c3 m3 o3 -> Maybe (Diagram c2 m2 o2 c3 m3 o3, NaturalTransformation c1 m1 o1 c3 m3 o3)
+ Math.Functors.KanExtension: rightKan :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2, FiniteCategory c3 m3 o3, Morphism m3 o3, Eq c3, Eq m3, Eq o3) => Diagram c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 c3 m3 o3 -> Maybe (Diagram c2 m2 o2 c3 m3 o3, NaturalTransformation c1 m1 o1 c3 m3 o3)
+ Math.Functors.KanExtension.Example: main :: IO ()
+ Math.Functors.SetValued: formatColimitObject :: PrettyPrint a => ColimitObject o1 m2 a -> String
+ Math.Functors.SetValued: formatFunctionOfColimitObjects :: (Eq o1, Eq m2, Eq a, PrettyPrint a) => Function (ColimitObject o1 m2 a) -> String
+ Math.Functors.SetValued: formatFunctionOfLimitObjects :: (Eq o1, Eq m2, Eq a, PrettyPrint a) => Function (LimitObject o1 m2 a) -> String
+ Math.Functors.SetValued: formatLimitObject :: (Eq o1, Eq m2, Eq a, PrettyPrint a) => LimitObject o1 m2 a -> String
+ Math.Functors.SetValued: formatSetOfColimitObjects :: (Eq o1, Eq m2, Eq a, PrettyPrint a) => Set (ColimitObject o1 m2 a) -> String
+ Math.Functors.SetValued: formatSetOfLimitObjects :: (Eq o1, Eq m2, Eq a, PrettyPrint a) => Set (LimitObject o1 m2 a) -> String
+ Math.Functors.SetValued: leftKanSetValued :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2, Eq a) => Diagram c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 (FinSet a) (Function a) (Set a) -> (Diagram c2 m2 o2 (FinSet (ColimitObject o1 m2 a)) (Function (ColimitObject o1 m2 a)) (Set (ColimitObject o1 m2 a)), NaturalTransformation c1 m1 o1 (FinSet (ColimitObject o1 m2 a)) (Function (ColimitObject o1 m2 a)) (Set (ColimitObject o1 m2 a)))
+ Math.Functors.SetValued: rightKanSetValued :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2, Eq a) => Diagram c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 (FinSet a) (Function a) (Set a) -> (Diagram c2 m2 o2 (FinSet (LimitObject o1 m2 a)) (Function (LimitObject o1 m2 a)) (Set (LimitObject o1 m2 a)), NaturalTransformation c1 m1 o1 (FinSet (LimitObject o1 m2 a)) (Function (LimitObject o1 m2 a)) (Set (LimitObject o1 m2 a)))
+ Math.Functors.SetValued: type ColimitObject o1 m2 a = Set ((CommaObject o1 One m2), a)
+ Math.Functors.SetValued: type LimitObject o1 m2 a = Map (CommaObject One o1 m2) a
+ Math.Functors.SetValued.Example: main :: IO ()
+ Math.Functors.YonedaEmbedding.Example: main :: IO ()
+ Math.IO.FiniteCategories.ExportGraphViz: catToDot :: (Eq o, PrettyPrint o, PrettyPrint m, Morphism m o, FiniteCategory c m o) => c -> String -> IO ()
+ Math.IO.FiniteCategories.ExportGraphViz: catToDotFormat :: (Eq o, Morphism m o, FiniteCategory c m o) => c -> (o -> String) -> (m -> String) -> String -> IO ()
+ Math.IO.FiniteCategories.ExportGraphViz: catToPdf :: (Eq o, PrettyPrint o, PrettyPrint m, Morphism m o, FiniteCategory c m o) => c -> String -> IO ()
+ Math.IO.FiniteCategories.ExportGraphViz: catToPdfFormat :: (Eq o, Morphism m o, FiniteCategory c m o) => c -> (o -> String) -> (m -> String) -> String -> IO ()
+ Math.IO.FiniteCategories.ExportGraphViz: categoryToGraph :: (Eq o, PrettyPrint o, PrettyPrint m, Morphism m o, FiniteCategory c m o) => c -> Gr String String
+ Math.IO.FiniteCategories.ExportGraphViz: categoryToGraphFormat :: (Eq o, Morphism m o, FiniteCategory c m o) => c -> (o -> String) -> (m -> String) -> Gr String String
+ Math.IO.FiniteCategories.ExportGraphViz: diagToDot :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrint m1, PrettyPrint o1, Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrint m2, PrettyPrint o2) => Diagram c1 m1 o1 c2 m2 o2 -> String -> IO ()
+ Math.IO.FiniteCategories.ExportGraphViz: diagToDot2 :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrint m1, PrettyPrint o1, Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrint m2, PrettyPrint o2) => Diagram c1 m1 o1 c2 m2 o2 -> String -> IO ()
+ Math.IO.FiniteCategories.ExportGraphViz: diagToDot2Format :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrint m1, PrettyPrint o1, Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrint m2, PrettyPrint o2) => Diagram c1 m1 o1 c2 m2 o2 -> (o2 -> String) -> (m2 -> String) -> String -> IO ()
+ Math.IO.FiniteCategories.ExportGraphViz: diagToDotCluster :: (Eq c1, Eq o1, PrettyPrint o1, PrettyPrint m1, Morphism m1 o1, FiniteCategory c1 m1 o1, Eq c2, Eq o2, PrettyPrint o2, PrettyPrint m2, Morphism m2 o2, FiniteCategory c2 m2 o2) => Diagram c1 m1 o1 c2 m2 o2 -> String -> IO ()
+ Math.IO.FiniteCategories.ExportGraphViz: diagToPdf :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrint m1, PrettyPrint o1, Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrint m2, PrettyPrint o2) => Diagram c1 m1 o1 c2 m2 o2 -> String -> IO ()
+ Math.IO.FiniteCategories.ExportGraphViz: diagToPdf2 :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrint m1, PrettyPrint o1, Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrint m2, PrettyPrint o2) => Diagram c1 m1 o1 c2 m2 o2 -> String -> IO ()
+ Math.IO.FiniteCategories.ExportGraphViz: diagToPdf2Format :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrint m1, PrettyPrint o1, Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrint m2, PrettyPrint o2) => Diagram c1 m1 o1 c2 m2 o2 -> (o2 -> String) -> (m2 -> String) -> String -> IO ()
+ Math.IO.FiniteCategories.ExportGraphViz: diagToPdfCluster :: (Eq c1, Eq o1, PrettyPrint o1, PrettyPrint m1, Morphism m1 o1, FiniteCategory c1 m1 o1, Eq c2, Eq o2, PrettyPrint o2, PrettyPrint m2, Morphism m2 o2, FiniteCategory c2 m2 o2) => Diagram c1 m1 o1 c2 m2 o2 -> String -> IO ()
+ Math.IO.FiniteCategories.ExportGraphViz: genToDot :: (Eq o, PrettyPrint o, PrettyPrint m, Morphism m o, FiniteCategory c m o) => c -> String -> IO ()
+ Math.IO.FiniteCategories.ExportGraphViz: genToPdf :: (Eq o, PrettyPrint o, PrettyPrint m, Morphism m o, FiniteCategory c m o) => c -> String -> IO ()
+ Math.IO.FiniteCategories.ExportGraphViz: natToDot :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, Eq c1, PrettyPrint m1, PrettyPrint o1, Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, Eq c2, PrettyPrint m2, PrettyPrint o2) => NaturalTransformation c1 m1 o1 c2 m2 o2 -> String -> IO ()
+ Math.IO.FiniteCategories.ExportGraphViz: natToDotFormat :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, Eq c1, PrettyPrint m1, PrettyPrint o1, Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, Eq c2, PrettyPrint m2, PrettyPrint o2) => NaturalTransformation c1 m1 o1 c2 m2 o2 -> (o2 -> String) -> (m2 -> String) -> String -> IO ()
+ Math.IO.FiniteCategories.ExportGraphViz: natToPdf :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, Eq c1, PrettyPrint m1, PrettyPrint o1, Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, Eq c2, PrettyPrint m2, PrettyPrint o2) => NaturalTransformation c1 m1 o1 c2 m2 o2 -> String -> IO ()
+ Math.IO.FiniteCategories.ExportGraphViz: natToPdfFormat :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, Eq c1, PrettyPrint m1, PrettyPrint o1, Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, Eq c2, PrettyPrint m2, PrettyPrint o2) => NaturalTransformation c1 m1 o1 c2 m2 o2 -> (o2 -> String) -> (m2 -> String) -> String -> IO ()
+ Math.IO.PrettyPrint: class PrettyPrint a
+ Math.IO.PrettyPrint: instance (Math.IO.PrettyPrint.PrettyPrint a, GHC.Classes.Eq a) => Math.IO.PrettyPrint.PrettyPrint (Data.WeakSet.Set a)
+ Math.IO.PrettyPrint: instance (Math.IO.PrettyPrint.PrettyPrint a, GHC.Classes.Eq a, Math.IO.PrettyPrint.PrettyPrint b, GHC.Classes.Eq b) => Math.IO.PrettyPrint.PrettyPrint (Data.WeakMap.Map a b)
+ Math.IO.PrettyPrint: instance (Math.IO.PrettyPrint.PrettyPrint a, Math.IO.PrettyPrint.PrettyPrint b) => Math.IO.PrettyPrint.PrettyPrint (a, b)
+ Math.IO.PrettyPrint: instance (Math.IO.PrettyPrint.PrettyPrint a, Math.IO.PrettyPrint.PrettyPrint b, Math.IO.PrettyPrint.PrettyPrint c) => Math.IO.PrettyPrint.PrettyPrint (a, b, c)
+ Math.IO.PrettyPrint: instance Math.IO.PrettyPrint.PrettyPrint Data.Text.Internal.Text
+ Math.IO.PrettyPrint: instance Math.IO.PrettyPrint.PrettyPrint GHC.Num.Natural.Natural
+ Math.IO.PrettyPrint: instance Math.IO.PrettyPrint.PrettyPrint GHC.Types.Char
+ Math.IO.PrettyPrint: instance Math.IO.PrettyPrint.PrettyPrint GHC.Types.Double
+ Math.IO.PrettyPrint: instance Math.IO.PrettyPrint.PrettyPrint GHC.Types.Int
+ Math.IO.PrettyPrint: instance Math.IO.PrettyPrint.PrettyPrint Math.PureSet.PureSet
+ Math.IO.PrettyPrint: instance Math.IO.PrettyPrint.PrettyPrint a => Math.IO.PrettyPrint.PrettyPrint (Data.Set.Internal.Set a)
+ Math.IO.PrettyPrint: instance Math.IO.PrettyPrint.PrettyPrint a => Math.IO.PrettyPrint.PrettyPrint [a]
+ Math.IO.PrettyPrint: pprint :: PrettyPrint a => a -> String
+ Math.IO.PrettyPrint: pprintFunction :: (PrettyPrint a, PrettyPrint b) => (a -> b) -> [a] -> String
Files
- CHANGELOG.md +4/−0
- FiniteCategories.cabal +75/−104
- Readme.md +5/−5
- src/Adjunction/Adjunction.hs +0/−51
- src/Cat/FinCat.hs +0/−94
- src/Cat/PartialFinCat.hs +0/−147
- src/CommaCategory/CommaCategory.hs +0/−109
- src/CompositionGraph/CompositionGraph.hs +0/−445
- src/CompositionGraph/SafeCompositionGraph.hs +0/−429
- src/ConeCategory/ConeCategory.hs +0/−170
- src/ConeCategory/LeftCone.hs +0/−134
- src/Config/Config.hs +0/−18
- src/Currying/Currying.hs +0/−78
- src/DiagonalFunctor/DiagonalFunctor.hs +0/−36
- src/Diagram/Conversion.hs +0/−61
- src/Diagram/Diagram.hs +0/−229
- src/ExportGraphViz/ExportGraphViz.hs +0/−400
- src/FiniteCategory/FiniteCategory.hs +0/−311
- src/FunctorCategory/FunctorCategory.hs +0/−128
- src/IO/CreateAndWriteFile.hs +0/−28
- src/IO/Parsers/CompositionGraph.hs +0/−116
- src/IO/Parsers/Lexer.hs +0/−45
- src/IO/Parsers/SafeCompositionGraph.hs +0/−114
- src/IO/Parsers/SafeCompositionGraphFunctor.hs +0/−123
- src/IO/PrettyPrint.hs +0/−67
- src/IO/Show.hs +0/−22
- src/Limit/Limit.hs +0/−41
- src/Math/Categories.hs +39/−0
- src/Math/Categories/CommaCategory.hs +200/−0
- src/Math/Categories/ConeCategory.hs +190/−0
- src/Math/Categories/FinCat.hs +70/−0
- src/Math/Categories/FinGrph.hs +155/−0
- src/Math/Categories/FinSet.hs +93/−0
- src/Math/Categories/FunctorCategory.hs +468/−0
- src/Math/Categories/Galaxy.hs +52/−0
- src/Math/Categories/Omega.hs +36/−0
- src/Math/Categories/Opposite.hs +60/−0
- src/Math/Categories/OrdinalCategory.hs +60/−0
- src/Math/Categories/PresheafCategory.hs +75/−0
- src/Math/Categories/TotalOrder.hs +57/−0
- src/Math/Category.hs +192/−0
- src/Math/FiniteCategories.hs +47/−0
- src/Math/FiniteCategories/All.hs +31/−0
- src/Math/FiniteCategories/CommaCategory.hs +19/−0
- src/Math/FiniteCategories/CommaCategory/Example.hs +38/−0
- src/Math/FiniteCategories/CompositionGraph.hs +759/−0
- src/Math/FiniteCategories/CompositionGraph/Example.hs +48/−0
- src/Math/FiniteCategories/ConeCategory.hs +19/−0
- src/Math/FiniteCategories/ConeCategory/Example.hs +45/−0
- src/Math/FiniteCategories/DiscreteCategory.hs +36/−0
- src/Math/FiniteCategories/DiscreteCategory/Example.hs +30/−0
- src/Math/FiniteCategories/Ens.hs +34/−0
- src/Math/FiniteCategories/Ens/Example.hs +29/−0
- src/Math/FiniteCategories/Examples.hs +51/−0
- src/Math/FiniteCategories/FinCat/Example.hs +31/−0
- src/Math/FiniteCategories/FinGrph/Example.hs +39/−0
- src/Math/FiniteCategories/FullSubcategory.hs +73/−0
- src/Math/FiniteCategories/FunctorCategory.hs +20/−0
- src/Math/FiniteCategories/FunctorCategory/Example.hs +43/−0
- src/Math/FiniteCategories/Hat.hs +84/−0
- src/Math/FiniteCategories/Hat/Example.hs +28/−0
- src/Math/FiniteCategories/NumberCategory.hs +46/−0
- src/Math/FiniteCategories/NumberCategory/Example.hs +28/−0
- src/Math/FiniteCategories/One.hs +43/−0
- src/Math/FiniteCategories/One/Example.hs +26/−0
- src/Math/FiniteCategories/Opposite.hs +18/−0
- src/Math/FiniteCategories/Opposite/Example.hs +33/−0
- src/Math/FiniteCategories/Parallel.hs +73/−0
- src/Math/FiniteCategories/Parallel/Example.hs +28/−0
- src/Math/FiniteCategories/SafeCompositionGraph.hs +576/−0
- src/Math/FiniteCategories/SafeCompositionGraph/Example.hs +46/−0
- src/Math/FiniteCategories/Square.hs +131/−0
- src/Math/FiniteCategories/Square/Example.hs +28/−0
- src/Math/FiniteCategories/Subcategory.hs +209/−0
- src/Math/FiniteCategories/V.hs +83/−0
- src/Math/FiniteCategories/V/Example.hs +28/−0
- src/Math/FiniteCategory.hs +154/−0
- src/Math/FiniteCategoryError.hs +72/−0
- src/Math/Functors.hs +25/−0
- src/Math/Functors/Adjunction.hs +62/−0
- src/Math/Functors/Adjunction/Example.hs +46/−0
- src/Math/Functors/DataMigration.hs +48/−0
- src/Math/Functors/DataMigration/Example.hs +79/−0
- src/Math/Functors/DiagonalFunctor.hs +42/−0
- src/Math/Functors/DiagonalFunctor/Example.hs +38/−0
- src/Math/Functors/Examples.hs +31/−0
- src/Math/Functors/KanExtension.hs +161/−0
- src/Math/Functors/KanExtension/Example.hs +64/−0
- src/Math/Functors/SetValued.hs +185/−0
- src/Math/Functors/SetValued/Example.hs +53/−0
- src/Math/Functors/YonedaEmbedding/Example.hs +31/−0
- src/Math/IO/FiniteCategories/ExportGraphViz.hs +487/−0
- src/Math/IO/PrettyPrint.hs +71/−0
- src/OppositeCategory/OppositeCategory.hs +0/−57
- src/ProductCategory/ProductCategory.hs +0/−91
- src/RandomCompositionGraph/RandomCompositionGraph.hs +0/−126
- src/RandomDiagram/RandomDiagram.hs +0/−45
- src/Set/FinOrdSet.hs +0/−96
- src/Set/FinSet.hs +0/−203
- src/Subcategories/FreeSubcategory.hs +0/−50
- src/Subcategories/FullSubcategory.hs +0/−36
- src/Subcategories/Subcategory.hs +0/−54
- src/UsualCategories/DiscreteCategory.hs +0/−54
- src/UsualCategories/Hat.hs +0/−74
- src/UsualCategories/One.hs +0/−40
- src/UsualCategories/Parallel.hs +0/−67
- src/UsualCategories/Square.hs +0/−101
- src/UsualCategories/Three.hs +0/−84
- src/UsualCategories/Two.hs +0/−67
- src/UsualCategories/V.hs +0/−74
- src/UsualCategories/Zero.hs +0/−40
- src/Utils/AssociationList.hs +0/−108
- src/Utils/CartesianProduct.hs +0/−38
- src/Utils/EnumerateMaps.hs +0/−23
- src/Utils/Sample.hs +0/−38
- src/Utils/SetList.hs +0/−34
- src/Utils/Tuple.hs +0/−34
- src/YonedaEmbedding/YonedaEmbedding.hs +0/−69
- test/CheckAllFiniteCategories.hs +69/−0
- test/ExampleAdjunction/ExampleAdjunction.hs +0/−44
- test/ExampleAdjunction/ExampleAdjunction.scg +0/−14
- test/ExampleAdjunction/ExampleAdjunctionDiag1.fscg +0/−21
- test/ExampleAdjunction/ExampleAdjunctionDiag2.fscg +0/−21
- test/ExampleCat/ExampleCat.hs +0/−41
- test/ExampleCat/ExampleFunctor.hs +0/−41
- test/ExampleCat/ExamplePartialFinCat.hs +0/−40
- test/ExampleCommaCategory/ExampleArrowCategory.hs +0/−34
- test/ExampleCommaCategory/ExampleCosliceCategory.hs +0/−37
- test/ExampleCommaCategory/ExampleSliceCategory.hs +0/−37
- test/ExampleCompositionGraph/ExampleCompositionGraph.hs +0/−44
- test/ExampleCompositionGraph/ExampleCompositionGraphConstruction.hs +0/−80
- test/ExampleCompositionGraph/ExampleFinSetToCompositionGraph.hs +0/−34
- test/ExampleCompositionGraph/ExampleSafeCompositionGraph.hs +0/−47
- test/ExampleConeCategory/ExampleCoconeCategory.hs +0/−44
- test/ExampleConeCategory/ExampleColimit.hs +0/−46
- test/ExampleConeCategory/ExampleConeCategory.hs +0/−42
- test/ExampleConeCategory/ExampleLeftCone.hs +0/−40
- test/ExampleConeCategory/ExampleLimit.hs +0/−45
- test/ExampleCurrying/ExampleCurrying.hs +0/−43
- test/ExampleDiagonalFunctor/ExampleDiagonalFunctor.hs +0/−51
- test/ExampleDiagram/ExampleConstantDiagram.hs +0/−40
- test/ExampleDiagram/ExampleConversion.hs +0/−36
- test/ExampleDiagram/ExampleDiagram.hs +0/−53
- test/ExampleDiagram/ExampleDiscreteDiagram.hs +0/−37
- test/ExampleDiagram/ExampleIdentityDiagram.hs +0/−35
- test/ExampleDiagram/ExampleParallelDiagram.hs +0/−40
- test/ExampleDiagram/ExampleSelectOneDiagram.hs +0/−39
- test/ExampleDiagram/ExampleSelectThreeDiagram.hs +0/−41
- test/ExampleDiagram/ExampleSelectTwoDiagram.hs +0/−38
- test/ExampleDiagram/ExampleSelectZeroDiagram.hs +0/−36
- test/ExampleFunctorCategory/ExampleFunctorCategory.hs +0/−47
- test/ExampleOppositeCategory/ExampleOppositeCategory.hs +0/−30
- test/ExampleParsers/Example.fscg +0/−13
- test/ExampleParsers/Example.scg +0/−2
- test/ExampleParsers/Example2.scg +0/−21
- test/ExampleParsers/ExampleSafeCompositionGraph.hs +0/−30
- test/ExampleParsers/ExampleSafeCompositionGraphFunctor.hs +0/−32
- test/ExampleProductCategory/ExampleProductCategory.hs +0/−51
- test/ExampleRandomCompositionGraph/ExampleRandomCompositionGraph.hs +0/−41
- test/ExampleRandomDiagram/ExampleRandomDiagram.hs +0/−44
- test/ExampleRandomDiagram/ExampleRandomTriangle.hs +0/−43
- test/ExampleSet/ExampleCompletion.hs +0/−39
- test/ExampleSet/ExampleOrdSet.hs +0/−30
- test/ExampleSet/ExamplePowerOrdSet.hs +0/−30
- test/ExampleSet/ExamplePowerSet.hs +0/−30
- test/ExampleSet/ExampleSet.hs +0/−33
- test/ExampleSubcategories/ExampleFreeSubcategory.hs +0/−30
- test/ExampleYonedaEmbedding/ExampleYonedaEmbedding.hs +0/−60
- test/RunAllExamples.hs +8/−90
CHANGELOG.md view
@@ -3,3 +3,7 @@ ## 0.1.0.0 -- 2022-03-21 * First version. + +## 0.2.0.0 -- 2023-03-13 + +* Separation between Category and FiniteCategory typeclasses, new architecture for the project, Kan extensions, etc.
FiniteCategories.cabal view
@@ -14,14 +14,14 @@ -- PVP summary: +-+------- breaking API changes -- | | +----- non-breaking API additions -- | | | +--- code changes with no API change -version: 0.1.0.0 +version: 0.2.0.0 -- A short (one-line) description of the package. synopsis: Finite categories and usual categorical constructions on them. -- A longer description of the package. -description: This package provides tools to create categories at the value level. This is different from the __Hask__ category where types are objects in a category with infinite objects and arrows, here we construct categories where objects and arrows are arbitrary values so that we can change categories during runtime. Each category implements three functions following the category structure axioms : @ob@ which returns objects of the category, @ar@ which returns arrows between two objects of the category and @identity@ which returns the identity of an object. Thanks to theses functions, we can construct automatically all the usual constructions on the categories (limits and colimits, adjunctions, Yoneda embedding, etc.) Functors are different from usual @Functor@ typeclass, we store functors as mapping between objects and morphisms of two categories. This package is also different from the package @data-category@ because we can enumerate objects and arrows in a category. This allows us to construct limit, colimits, adjunctions, etc. automatically for arbitrary finite categories. On the other hand, we loose typecheck at compilation time which ensures that composition is sound in __Hask__, composition in our package might lead to an error raised during runtime. See the Readme file for installation help. +description: This package provides tools to create categories at the value level. This is different from the __Hask__ category where types are objects in a category with infinite objects and arrows, here we construct categories where objects and arrows are arbitrary values so that we can change categories during runtime. Each category implements two functions following the category structure axioms : @ar@ which returns arrows between two objects of the category and @identity@ which returns the identity of an object. A FiniteCategory implements an additional function : @ob@ which returns objects of the category. Thanks to these functions, we can construct automatically all the usual constructions on the categories (limits and colimits, adjunctions, Yoneda embedding, etc.) Functors are different from usual @Functor@ typeclass, we store functors as mapping between objects and morphisms of two categories. This package is also different from the package @data-category@ because we can enumerate objects and arrows in a finite category. This allows us to construct limit, colimits, adjunctions, etc. automatically for arbitrary finite categories. On the other hand, we loose typecheck at compilation time which ensures that composition is sound in __Hask__, composition in our package might lead to an error raised during runtime. See the Readme file for installation help. -- URL for the project homepage or repository. homepage: https://gitlab.utc.fr/gsabbagh/FiniteCategories @@ -43,71 +43,83 @@ -- A copyright notice. -- copyright: -category: Data, Maths +category: Maths, Data -- Extra files to be distributed with the package, such as examples or a README. extra-source-files: CHANGELOG.md Readme.md - test/ExampleAdjunction/ExampleAdjunction.scg - test/ExampleAdjunction/ExampleAdjunctionDiag1.fscg - test/ExampleAdjunction/ExampleAdjunctionDiag2.fscg - test/ExampleParsers/Example.fscg - test/ExampleParsers/Example.scg - test/ExampleParsers/Example2.scg library -- Modules exported by the library. - exposed-modules: CompositionGraph.CompositionGraph, - CompositionGraph.SafeCompositionGraph, - ExportGraphViz.ExportGraphViz, - FiniteCategory.FiniteCategory, - RandomCompositionGraph.RandomCompositionGraph, - Set.FinOrdSet, - Utils.CartesianProduct, - IO.CreateAndWriteFile, - Utils.Sample, - Utils.Tuple, - Cat.FinCat, - Utils.EnumerateMaps, - Diagram.Diagram, - UsualCategories.DiscreteCategory, - UsualCategories.One, - UsualCategories.Two, - UsualCategories.Three, - UsualCategories.Zero, - UsualCategories.Parallel, - CommaCategory.CommaCategory, - FunctorCategory.FunctorCategory, - DiagonalFunctor.DiagonalFunctor, - ConeCategory.ConeCategory, - RandomDiagram.RandomDiagram, - IO.PrettyPrint, - IO.Show, - Utils.AssociationList, - Cat.PartialFinCat, - Utils.SetList, - Config.Config, - Diagram.Conversion, - Subcategories.FreeSubcategory, - IO.Parsers.Lexer, - IO.Parsers.CompositionGraph, - IO.Parsers.SafeCompositionGraph, - IO.Parsers.SafeCompositionGraphFunctor, - ConeCategory.LeftCone, - OppositeCategory.OppositeCategory, - Set.FinSet, - YonedaEmbedding.YonedaEmbedding, - Subcategories.Subcategory, - Subcategories.FullSubcategory, - UsualCategories.V, - UsualCategories.Hat, - ProductCategory.ProductCategory, - Currying.Currying, - UsualCategories.Square, - Adjunction.Adjunction, - Limit.Limit + exposed-modules: Math.FiniteCategories.All, + Math.Category, + Math.FiniteCategory, + Math.FiniteCategoryError, + Math.Categories, + Math.Categories.TotalOrder, + Math.Categories.OrdinalCategory, + Math.Categories.Omega, + Math.Categories.Galaxy, + Math.Categories.FinSet, + Math.Categories.FinGrph, + Math.Categories.Opposite, + Math.Categories.FinCat, + Math.Categories.FunctorCategory, + Math.Categories.CommaCategory, + Math.Categories.ConeCategory, + Math.Categories.PresheafCategory, + Math.FiniteCategories, + Math.FiniteCategories.FullSubcategory, + Math.FiniteCategories.NumberCategory, + Math.FiniteCategories.DiscreteCategory, + Math.FiniteCategories.Hat, + Math.FiniteCategories.V, + Math.FiniteCategories.Parallel, + Math.FiniteCategories.Square, + Math.FiniteCategories.Ens, + Math.FiniteCategories.Opposite, + Math.FiniteCategories.FunctorCategory, + Math.FiniteCategories.CompositionGraph, + Math.FiniteCategories.SafeCompositionGraph, + Math.FiniteCategories.CommaCategory, + Math.FiniteCategories.One, + Math.FiniteCategories.ConeCategory, + Math.FiniteCategories.Subcategory, + Math.FiniteCategories.Examples, + Math.FiniteCategories.NumberCategory.Example, + Math.FiniteCategories.DiscreteCategory.Example, + Math.FiniteCategories.Hat.Example, + Math.FiniteCategories.V.Example, + Math.FiniteCategories.Parallel.Example, + Math.FiniteCategories.Square.Example, + Math.FiniteCategories.Ens.Example, + Math.FiniteCategories.FinGrph.Example, + Math.FiniteCategories.Opposite.Example, + Math.FiniteCategories.FinCat.Example, + Math.FiniteCategories.FunctorCategory.Example, + Math.FiniteCategories.CompositionGraph.Example, + Math.FiniteCategories.SafeCompositionGraph.Example, + Math.FiniteCategories.CommaCategory.Example, + Math.FiniteCategories.One.Example, + Math.FiniteCategories.ConeCategory.Example, + Math.Functors, + Math.Functors.Adjunction, + Math.Functors.DiagonalFunctor, + Math.Functors.DataMigration, + Math.Functors.KanExtension, + Math.Functors.SetValued, + Math.Functors.Examples, + Math.Functors.Adjunction.Example, + Math.Functors.DiagonalFunctor.Example, + Math.Functors.DataMigration.Example, + Math.Functors.KanExtension.Example, + Math.Functors.YonedaEmbedding.Example, + Math.Functors.SetValued.Example, + Math.IO.PrettyPrint, + Math.IO.FiniteCategories.ExportGraphViz, + -- Modules included in this library but not exported. -- other-modules: @@ -115,7 +127,7 @@ other-extensions: MultiParamTypeClasses, FunctionalDependencies, UndecidableInstances, FlexibleInstances -- Other library packages from which modules are imported. - build-depends: base >=4.15.0.0 && < 4.16, + build-depends: base >= 4.15.0.0 && < 4.16, containers >= 0.6.4 && < 0.7, directory >= 1.3.6 && < 1.4, filepath >= 1.4.2 && < 1.5, @@ -124,6 +136,7 @@ text >= 1.2.4 && < 1.3, process >= 1.6.11 && < 1.7, random >= 1.2.1 && < 1.3, + WeakSets >= 1.4.0.0 && < 1.4.0.1, -- Directories containing source files. hs-source-dirs: src @@ -143,6 +156,7 @@ -- The entrypoint to the test suite. main-is: RunAllExamples.hs + -- Test dependencies. build-depends: FiniteCategories, @@ -155,48 +169,5 @@ text >= 1.2.4 && < 1.3, process >= 1.6.11 && < 1.7, random >= 1.2.1 && < 1.3, - - other-modules: ExampleAdjunction.ExampleAdjunction - ExampleCat.ExampleCat - ExampleCat.ExampleFunctor - ExampleCat.ExamplePartialFinCat - ExampleCommaCategory.ExampleArrowCategory - ExampleCommaCategory.ExampleCosliceCategory - ExampleCommaCategory.ExampleSliceCategory - ExampleCompositionGraph.ExampleCompositionGraph - ExampleCompositionGraph.ExampleCompositionGraphConstruction - ExampleCompositionGraph.ExampleFinSetToCompositionGraph - ExampleCompositionGraph.ExampleSafeCompositionGraph - ExampleConeCategory.ExampleCoconeCategory - ExampleConeCategory.ExampleColimit - ExampleConeCategory.ExampleConeCategory - ExampleConeCategory.ExampleLeftCone - ExampleConeCategory.ExampleLimit - ExampleCurrying.ExampleCurrying - ExampleDiagonalFunctor.ExampleDiagonalFunctor - ExampleDiagram.ExampleConstantDiagram - ExampleDiagram.ExampleConversion - ExampleDiagram.ExampleDiagram - ExampleDiagram.ExampleDiscreteDiagram - ExampleDiagram.ExampleIdentityDiagram - ExampleDiagram.ExampleParallelDiagram - ExampleDiagram.ExampleSelectOneDiagram - ExampleDiagram.ExampleSelectThreeDiagram - ExampleDiagram.ExampleSelectTwoDiagram - ExampleDiagram.ExampleSelectZeroDiagram - ExampleFunctorCategory.ExampleFunctorCategory - ExampleOppositeCategory.ExampleOppositeCategory - ExampleParsers.ExampleSafeCompositionGraph - ExampleParsers.ExampleSafeCompositionGraphFunctor - ExampleProductCategory.ExampleProductCategory - ExampleRandomCompositionGraph.ExampleRandomCompositionGraph - ExampleRandomDiagram.ExampleRandomDiagram - ExampleRandomDiagram.ExampleRandomTriangle - ExampleSet.ExampleCompletion - ExampleSet.ExampleOrdSet - ExampleSet.ExamplePowerOrdSet - ExampleSet.ExamplePowerSet - ExampleSet.ExampleSet - ExampleSubcategories.ExampleFreeSubcategory - ExampleYonedaEmbedding.ExampleYonedaEmbedding - + WeakSets >= 1.4.0.0 && < 1.4.0.1, + other-modules: CheckAllFiniteCategories
Readme.md view
@@ -11,7 +11,7 @@ ## General Info -This package provides tools to create categories at the value level. This is different from the __Hask__ category where types are objects in a category with infinite objects and arrows, here we construct categories where objects and arrows are arbitrary values so that we can change categories during runtime. Each category implements three functions following the category structure axioms : `ob` which returns objects of the category, `ar` which returns arrows between two objects of the category and `identity` which returns the identity of an object. Thanks to theses functions, we can construct automatically all the usual constructions on the categories (limits and colimits, adjunctions, Yoneda embedding, etc.) Functors are different from usual `Functor` typeclass, we store functors as mapping between objects and morphisms of two categories. +This package provides tools to create categories at the value level. This is different from the __Hask__ category where types are objects in a category with an infinite number of objects and arrows, here we construct categories where objects and arrows are arbitrary values so that we can change categories during runtime. Each category implements two functions following the category structure axioms : `ar` which returns arrows between two objects of the category and `identity` which returns the identity of an object. Each `FiniteCategory` implements an additional function : `ob` which returns the objects of the category. Thanks to theses functions, we can construct automatically all the usual constructions on the categories (limits and colimits, adjunctions, Yoneda embedding, etc.) Functors are different from usual `Functor` typeclass, we store functors as mapping between objects and morphisms of two categories which respect the category structure. This package is also different from the package `data-category` because we can enumerate objects and arrows in a category. This allows us to construct limit, colimits, adjunctions, etc. automatically for arbitrary finite categories. On the other hand, we loose typecheck at compilation time which ensures that composition is sound in __Hask__, composition in our package might lead to an error raised during runtime. @@ -19,26 +19,26 @@ The project uses GraphViz for visualizing the categories created. -There is another version programmed in Python : [repository link](https://gitlab.utc.fr/gsabbagh/modification-de-categories) +There is another version no longer maintained programmed in Python : [repository link](https://gitlab.utc.fr/gsabbagh/modification-de-categories) ## Installation To use the graphviz exports, you must first install graphviz (see [graphviz website](https://graphviz.org/download/)) and make sure that Graphviz folder is in the path (dot should be a callable program from your terminal, if you are on Windows see [this tutorial](https://stackoverflow.com/questions/44272416/how-to-add-a-folder-to-path-environment-variable-in-windows-10-with-screensho#44272417) and if you are on unix see [this tutorial]( https://unix.stackexchange.com/questions/26047/how-to-correctly-add-a-path-to-path)). +Then you can check the numerous examples provided to understand how to use the package. + ## Collaboration All contributions are appreciated! Contact me by email for any information. ## Usage -To run all examples of the project, run in a terminal the following command : +To run all examples of the project, clone the repository and run in a terminal from the repository the following command : ```cabal test``` You can then find the graphviz output in the folder `OutputGraphViz/`. -The first files you should inspect in the documentation are `FiniteCategory.FiniteCategory` and `CompositionGraph.CompositionGraph`. They are the most useful to understand and create new categories from scratch. -You can also take a look at the examples in the test suite. ## Examples
− src/Adjunction/Adjunction.hs
@@ -1,51 +0,0 @@-{-# 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))]
− src/Cat/FinCat.hs
@@ -1,94 +0,0 @@-{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-} - -{-| Module : FiniteCategories -Description : __FinCat__ is the category of finite categories, functors are the morphisms of __FinCat__. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -The __FinCat__ category has as objects finite categories and as morphisms functors between them. -It is itself a large category (therefore not a finite one), -we only construct finite full subcategories of the mathematical infinite __FinCat__ category. -`FinCat` is the type of full finite subcategories of __FinCat__. - -To instantiate it, use the `FinCat` constructor on a list of categories. - -For example, see ExampleCat.ExampleCat - -The `FinCat` type should not be confused with the `FiniteCategory` typeclass. - -The `FiniteCategory` typeclass describes axioms a structure should follow to be considered a finite category. - -The `FinCat` type is itself a `FiniteCategory` and contains finite categories as objects. - -To convert a `FinFunctor` into any other kind of functor, see @Diagram.Conversion@. --} - -module Cat.FinCat -( - FinFunctor(..), - FinCat(..) -) -where - import FiniteCategory.FiniteCategory - import Utils.EnumerateMaps - import Utils.CartesianProduct - import IO.PrettyPrint - import IO.Show - import Utils.AssociationList - - -- | A `FinFunctor` /F/ between two categories is a map between objects and a map between arrows of the two categories such that : - -- - -- prop> F (srcF f) = srcF (F f) - -- prop> F (tgtF f) = tgtF (F f) - -- prop> F (f @ g) = F(f) @ F(g) - -- prop> F (identity a) = identity (F a) - -- - -- It is meant to be a morphism between categories within `FinCat`, it is homogeneous, the type of the source category must be the same as the type of the target category. - -- - -- See /Diagram/ for heterogeneous ones. - -- - -- To convert a `FinFunctor` into any other kind of functor, see @Diagram.Conversion@. - data FinFunctor c m o = FinFunctor {srcF :: c, tgtF :: c, omapF :: AssociationList o o, mmapF :: AssociationList m m} deriving (Eq, Show) - - instance (Eq c, Eq m, Eq o) => Morphism (FinFunctor c m o) c where - (@) FinFunctor{srcF=s2,tgtF=t2,omapF=om2,mmapF=fm2} FinFunctor{srcF=s1,tgtF=t1,omapF=om1,mmapF=fm1} - | t1 /= s2 = error "Illegal composition of FinFunctors." - | otherwise = FinFunctor{srcF=s1,tgtF=t2,omapF=om2!-.om1,mmapF=fm2!-.fm1} - source = srcF - target = tgtF - - instance (FiniteCategory c m o, Morphism m o, PrettyPrintable c, PrettyPrintable m, PrettyPrintable o, Eq m, Eq o) => - PrettyPrintable (FinFunctor c m o) where - pprint FinFunctor{srcF=s,tgtF=t,omapF=om,mmapF=fm} = "FinFunctor ("++pprint s++") -> ("++pprint t++")\n"++pprint om++"\n"++pprint fm - - -- | Checks wether the properties of a FinFunctor are respected. - checkFinFunctoriality :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => FinFunctor c m o -> Bool - checkFinFunctoriality FinFunctor {srcF=s,tgtF=t,omapF=om,mmapF=fm} - | not (and imIdNotId) = False - | not (and errFunct) = False - | otherwise = True - where - imIdNotId = [fm !-! (identity s a) == identity t (om !-! a) | a <- ob s] - errFunct = [fm !-! (g @ f) == (fm !-! g) @ (fm !-! f) | f <- (arrows s), g <- (arFrom s (target f))] - - -- | An instance of `FinCat` is a list of categories of interest. - -- - -- Listing all arrows between two objects (i.e. listing FinFunctors between two categories) is slow (there are a lot of candidates). - newtype FinCat c m o = FinCat [c] - - -- We are forced to use the language extension FlexibleInstances because of this instance declaration : - -- The category 'c' could be itself a `FinCat` category therefore not respecting the uniqueness rule of instanciation. - instance (FiniteCategory c m o, Morphism m o, Eq c, Eq m, Eq o) => FiniteCategory (FinCat c m o) (FinFunctor c m o) c where - ob (FinCat xs) = xs - identity finCat catObj = FinFunctor {srcF=catObj,tgtF=catObj,omapF=functToAssocList id (ob catObj),mmapF=functToAssocList id (arrows catObj)} - ar finCat cat1 cat2 = [FinFunctor{srcF=cat1,tgtF=cat2,mmapF=appF, omapF=appO} | appO <- appObj, appF <- concat <$> cartesianProduct [twoObjToMaps a b appO| a <- ob cat1, b <- ob cat1], checkFinFunctoriality FinFunctor{srcF=cat1,tgtF=cat2,mmapF=appF, omapF=appO}] - where - appObj = enumMaps (ob cat1) (ob cat2) - twoObjToMaps a b appO = enumMaps (ar cat1 a b) (ar cat2 (appO !-! a) (appO !-! b)) - - instance (FiniteCategory c m o, Morphism m o, Eq c, Eq m, Eq o) => GeneratedFiniteCategory (FinCat c m o) (FinFunctor c m o) c where - genAr = defaultGenAr - decompose = defaultDecompose
− src/Cat/PartialFinCat.hs
@@ -1,147 +0,0 @@-{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-} - -{-| Module : FiniteCategories -Description : __PartialFinCat__ is the category of finite categories, partial functors are the morphisms of __FinCat__. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -The __PartialFinCat__ category has as objects finite categories and as morphisms partial functors between them. - -A partial functor is a functor where the object map and the morphism map can be partial functions. - -It is itself a large category (therefore not a finite one), -we only construct finite full subcategories of the mathematical infinite __PartialFinCat__ category. -`PartialFinCat` is the type of full finite subcategories of __PartialFinCat__. - -To instantiate it, use the `PartialFinCat` constructor on a list of categories. - -To convert a `PartialFunctor` into any other kind of functor, see @Diagram.Conversion@. - -For example, see @ExampleCat.ExamplePartialFinCat@. --} - -module Cat.PartialFinCat -( - PartialFunctor(..), - PartialFinCat(..), - domainObjects, - domainArrows, - codomainObjects, - codomainArrows, - objectsNotMapped, - arrowsNotMapped, - objectsNotMappedTo, - arrowsNotMappedTo -) -where - import FiniteCategory.FiniteCategory - import Cat.FinCat - import Utils.EnumerateMaps - import Utils.CartesianProduct - import Utils.AssociationList - import IO.PrettyPrint - import IO.Show - import Utils.SetList - import Data.List ((\\), nub) - - -- | A `PartialFunctor` /F/ between two categories is a partial map between objects and a partial map between arrows of the two categories such that : - -- - -- prop> F (srcPF f) = srcPF (F f) - -- prop> F (tgtPF f) = tgtPF (F f) - -- prop> F (f @ g) = F(f) @ F(g) - -- prop> F (identity a) = identity (F a) - -- - -- It is meant to be a morphism between categories within `PartialFinCat`, it is homogeneous, the type of the source category must be the same as the type of the target category. - -- - -- To convert a `PartialFunctor` into any other kind of functor, see @Diagram.Conversion@. - data PartialFunctor c m o = PartialFunctor {srcPF :: c, tgtPF :: c, omapPF :: AssociationList o o, mmapPF :: AssociationList m m} deriving (Eq, Show) - - instance (Eq c, Eq m, Eq o) => Morphism (PartialFunctor c m o) c where - (@) PartialFunctor{srcPF=s2,tgtPF=t2,omapPF=om2,mmapPF=fm2} PartialFunctor{srcPF=s1,tgtPF=t1,omapPF=om1,mmapPF=fm1} - | t1 /= s2 = error "Illegal composition of PartialFunctors." - | otherwise = PartialFunctor{srcPF=s1,tgtPF=t2,omapPF=om2 !-. om1,mmapPF=fm2 !-. fm1} - source = srcPF - target = tgtPF - - instance (FiniteCategory c m o, Morphism m o, PrettyPrintable c, PrettyPrintable m, PrettyPrintable o, Eq m, Eq o) => - PrettyPrintable (PartialFunctor c m o) where - pprint PartialFunctor{srcPF=s,tgtPF=t,omapPF=om,mmapPF=fm} = "PartialFunctor ("++pprint s++") -> ("++pprint t++")\n\n"++pprint om++"\n\n"++pprint fm - - -- -- | Checks wether the properties of a functor are respected. - checkPartialFunctoriality :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => PartialFunctor c m o -> Bool - checkPartialFunctoriality PartialFunctor {srcPF=s,tgtPF=t,omapPF=om,mmapPF=fm} - | not ((keys om) `isIncludedIn` (ob s)) = False - | not ((keys fm) `isIncludedIn` (arrows s)) = False - | not (and imSrcExists) = False - | not (and imTgtExists) = False - | not (and idMapped) = False - | not (and imIdNotId) = False - | not (and compNotMapped) = False - | not (and errFunct) = False - | otherwise = True - where - imSrcExists = [elem (source f) (keys om) | f <- keys fm] - imTgtExists = [elem (target f) (keys om) | f <- keys fm] - idMapped = [elem (identity s o) (keys fm) | o <- keys om] - imIdNotId = [fm !-! (identity s a) == identity t (om !-! a) | a <- keys om] - compNotMapped = [elem (g @ f) (keys fm) | f <- (arrows s), g <- (arFrom s (target f)), elem f (keys fm), elem g (keys fm)] - errFunct = [fm !-! (g @ f) == (fm !-! g) @ (fm !-! f) | f <- (arrows s), g <- (arFrom s (target f)), elem f (keys fm), elem g (keys fm)] - - -- | An instance of `PartialFinCat` is a list of categories of interest. - -- - -- Listing all arrows between two objects (i.e. listing PartialFunctors between two categories) is slow (there are a lot of candidates). - newtype PartialFinCat c m o = PartialFinCat [c] - - -- We are forced to use the language extension FlexibleInstances because of this instance declaration : - -- The category 'c' could be itself a `FinCat` category therefore not respecting the uniqueness rule of instanciation. - instance (FiniteCategory c m o, Morphism m o, Eq c, Eq m, Eq o) => FiniteCategory (PartialFinCat c m o) (PartialFunctor c m o) c where - ob (PartialFinCat xs) = xs - identity (PartialFinCat xs) catObj - | elem catObj xs = PartialFunctor {srcPF=catObj,tgtPF=catObj,omapPF=mkAssocListIdentity (ob catObj),mmapPF=mkAssocListIdentity (arrows catObj)} - | otherwise = error "Category not in PartialFinCat" - ar (PartialFinCat xs) cat1 cat2 - | elem cat1 xs && elem cat2 xs = [PartialFunctor{srcPF=cat1,tgtPF=cat2,mmapPF=appF, omapPF=appO} | appO <- appObj, appF <- appMorph, checkPartialFunctoriality PartialFunctor{srcPF=cat1,tgtPF=cat2,mmapPF=appF, omapPF=appO}] - | otherwise = error "Category not in PartialFinCat" - where - appObj = concat $ (\x -> enumAssocLists x (ob cat2)) <$> (powerList (ob cat1)) - appMorph = concat $ (\x -> enumAssocLists x (arrows cat2)) <$> (powerList (arrows cat1)) - - instance (FiniteCategory c m o, Morphism m o, Eq c, Eq m, Eq o) => GeneratedFiniteCategory (PartialFinCat c m o) (PartialFunctor c m o) c where - genAr = defaultGenAr - decompose = defaultDecompose - - -- | Returns the objects mapped by a partial functor. - domainObjects :: (FiniteCategory c m o, Morphism m o, Eq c, Eq m, Eq o) => PartialFunctor c m o -> [o] - domainObjects funct = keys (omapPF funct) - - -- | Returns the objects not mapped by a partial functor. - objectsNotMapped :: (FiniteCategory c m o, Morphism m o, Eq c, Eq m, Eq o) => PartialFunctor c m o -> [o] - objectsNotMapped funct = (ob (source funct))\\(domainObjects funct) - - -- | Returns the arrows mapped by a partial functor. - domainArrows :: (FiniteCategory c m o, Morphism m o, Eq c, Eq m, Eq o) => PartialFunctor c m o -> [m] - domainArrows funct = keys (mmapPF funct) - - -- | Returns the arrows not mapped by a partial functor. - arrowsNotMapped :: (FiniteCategory c m o, Morphism m o, Eq c, Eq m, Eq o) => PartialFunctor c m o -> [m] - arrowsNotMapped funct = (arrows (source funct))\\(domainArrows funct) - - -- | Returns the objects mapped onto by a partial functor. - codomainObjects :: (FiniteCategory c m o, Morphism m o, Eq c, Eq m, Eq o) => PartialFunctor c m o -> [o] - codomainObjects funct = nub $ values (omapPF funct) - - -- | Returns the objects not mapped onto by a partial functor. - objectsNotMappedTo :: (FiniteCategory c m o, Morphism m o, Eq c, Eq m, Eq o) => PartialFunctor c m o -> [o] - objectsNotMappedTo funct = (ob (target funct))\\(codomainObjects funct) - - -- | Returns the arrows mapped onto by a partial functor. - codomainArrows :: (FiniteCategory c m o, Morphism m o, Eq c, Eq m, Eq o) => PartialFunctor c m o -> [m] - codomainArrows funct = nub $ values (mmapPF funct) - - -- | Returns the arrows not mapped onto by a partial functor. - arrowsNotMappedTo :: (FiniteCategory c m o, Morphism m o, Eq c, Eq m, Eq o) => PartialFunctor c m o -> [m] - arrowsNotMappedTo funct = (arrows (target funct))\\(codomainArrows funct) -
− src/CommaCategory/CommaCategory.hs
@@ -1,109 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses #-} - -{-| Module : FiniteCategories -Description : A comma category is a category where objects are morphisms of another category /C/ and morphisms are commutative squares in /C/. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -A comma category is a category where objects are morphisms of another category /C/ and morphisms are commutative squares in /C/. - -For example, see Examples.ExampleCommaCategory.* --} - -module CommaCategory.CommaCategory -( - CommaObject(..), - CommaMorphism(..), - CommaCategory(..), - mkSliceCategory, - mkCosliceCategory, - mkArrowCategory, -) -where - import FiniteCategory.FiniteCategory - import Diagram.Diagram - import UsualCategories.One - import IO.PrettyPrint - import Utils.AssociationList - - -- | A `CommaObject` in the `CommaCategory` (/T/|/S/) is a triplet \</e/,/d/,/f/\> where @f : /T/(e) -> /S/(d)@. - -- - -- See /Categories for the working mathematician/, Saunders Mac Lane, P.46. - data CommaObject o1 o2 m3 = CommaObject {indexSrc :: o1 -- ^ /e/ - , indexTgt :: o2 -- ^ /d/ - , arrow :: m3} -- ^ /f/ - deriving (Eq, Show) - - instance (PrettyPrintable o1, PrettyPrintable o2, PrettyPrintable m3) => - PrettyPrintable (CommaObject o1 o2 m3) where - pprint CommaObject{indexSrc=e, indexTgt=d, arrow=f} = "<"++pprint e++", "++pprint d++", "++pprint f++">" - - -- | A `CommaMorphism` in the `CommaCategory` (/T/|/S/) is a couple \</k/,/h/\>. - -- - -- See /Categories for the working mathematician/, Saunders Mac Lane, P.46. - data CommaMorphism o1 o2 m1 m2 m3 = CommaMorphism {srcCM :: (CommaObject o1 o2 m3) -- ^ The source `CommaObject` - , tgtCM :: (CommaObject o1 o2 m3) -- ^ The target `CommaObject` - , indexAr1 :: m1 -- ^ /k/ - , indexAr2 :: m2} -- ^ /h/ - deriving (Eq, Show) - - instance (PrettyPrintable m1, PrettyPrintable m2) => - PrettyPrintable (CommaMorphism o1 o2 m1 m2 m3) where - pprint CommaMorphism{srcCM=_, tgtCM =_, indexAr1=k, indexAr2=h} = "<"++pprint k++", "++pprint h++">" - - instance (Morphism m1 o1, Morphism m2 o2, Eq o1, Eq o2, Eq m3) => Morphism (CommaMorphism o1 o2 m1 m2 m3) (CommaObject o1 o2 m3) where - (@) CommaMorphism{srcCM=s2,tgtCM=t2,indexAr1=k2,indexAr2=h2} CommaMorphism{srcCM=s1,tgtCM=t1,indexAr1=k1,indexAr2=h1} - | t1 /= s2 = error "Illegal composition of CommaMorphism." - | otherwise = CommaMorphism {srcCM=s1,tgtCM=t2,indexAr1=k2 @ k1,indexAr2=h2 @ h1} - source = srcCM - target = tgtCM - - -- | A `CommaCategory` is a couple (/T/|/S/) with /T/ and /S/ two diagrams with the same target. - -- - -- See /Categories for the working mathematician/, Saunders Mac Lane, P.46. - data CommaCategory c1 m1 o1 c2 m2 o2 c3 m3 o3 = CommaCategory {leftDiag :: Diagram c1 m1 o1 c3 m3 o3 -- ^ /T/ - , rightDiag :: Diagram c2 m2 o2 c3 m3 o3} -- ^ /S/ - deriving (Eq, Show) - - instance (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, - FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2, - FiniteCategory c3 m3 o3, Morphism m3 o3, Eq m3) => FiniteCategory (CommaCategory c1 m1 o1 c2 m2 o2 c3 m3 o3) (CommaMorphism o1 o2 m1 m2 m3) (CommaObject o1 o2 m3) where - ob CommaCategory {leftDiag = t, rightDiag = s} = [CommaObject{indexSrc=e,indexTgt=d,arrow=f}| e <- (ob (src t)), d <- (ob (src s)), f <- (ar (tgt t) ((omap t) !-! (e)) ((omap s) !-! (d)))] - identity CommaCategory{leftDiag = t, rightDiag = s} obj@CommaObject{indexSrc=e,indexTgt=d,arrow=f} - = CommaMorphism{srcCM=obj, tgtCM=obj, indexAr1=(identity (src t) e), indexAr2=(identity (src s) d)} - ar CommaCategory{leftDiag = t, rightDiag = s} obj1@CommaObject{indexSrc=e1,indexTgt=d1,arrow=f1} obj2@CommaObject{indexSrc=e2,indexTgt=d2,arrow=f2} - = [CommaMorphism{srcCM=obj1,tgtCM=obj2,indexAr1=k,indexAr2=h}| k <- ar (src t) e1 e2, h <- ar (src s) d1 d2, f2 @ ((mmap t) !-! (k)) == ((mmap s) !-! (h)) @ f1] - - instance (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, - FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2, - FiniteCategory c3 m3 o3, Morphism m3 o3, Eq m3) => GeneratedFiniteCategory (CommaCategory c1 m1 o1 c2 m2 o2 c3 m3 o3) (CommaMorphism o1 o2 m1 m2 m3) (CommaObject o1 o2 m3) where - genAr = defaultGenAr - decompose = defaultDecompose - - instance (PrettyPrintable c1, PrettyPrintable m1, PrettyPrintable o1, - PrettyPrintable c2, PrettyPrintable m2, PrettyPrintable o2, - PrettyPrintable c3, PrettyPrintable m3, PrettyPrintable o3, - FiniteCategory c1 m1 o1, FiniteCategory c2 m2 o2, FiniteCategory c3 m3 o3, - Morphism m1 o1, Morphism m2 o2, Morphism m3 o3, - Eq m1, Eq o1, Eq m2, Eq o2) => - PrettyPrintable (CommaCategory c1 m1 o1 c2 m2 o2 c3 m3 o3) where - pprint CommaCategory{leftDiag=t, rightDiag=s} = "("++pprint t++"|"++pprint s++")" - - -- | Constructs the slice category of a category /C/ over an object /o/. - -- - -- Returns Nothing if the object is not in the category. - mkSliceCategory :: (FiniteCategory c m o, Morphism m o, Eq o) => c -> o -> Maybe (CommaCategory c m o One One One c m o) - mkSliceCategory c o = mkSelect1 c o >>= (\x -> Just CommaCategory{leftDiag=mkIdentityDiagram c, rightDiag=x}) - - -- | Constructs the coslice category of a category /C/ under an object /o/. - -- - -- Returns Nothing if the object is not in the category. - mkCosliceCategory :: (FiniteCategory c m o, Morphism m o, Eq o) => c -> o -> Maybe (CommaCategory One One One c m o c m o) - mkCosliceCategory c o = mkSelect1 c o >>= (\x -> Just CommaCategory{rightDiag=mkIdentityDiagram c, leftDiag=x}) - - -- | Constructs the arrow category of a category /C/. - mkArrowCategory :: (FiniteCategory c m o, Morphism m o, Eq o) => c -> CommaCategory c m o c m o c m o - mkArrowCategory c = CommaCategory{leftDiag=mkIdentityDiagram c, rightDiag=mkIdentityDiagram c}
− src/CompositionGraph/CompositionGraph.hs
@@ -1,445 +0,0 @@-{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-} - -{-| Module : FiniteCategories -Description : Composition graphs are the simpliest way to create simple small categories by hand. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -A `CompositionGraph` is the free category generated by a multidigraph quotiented by an equivalence relation on the paths of the graphs. -A multidigraph is a directed multigraph which means that edges are oriented and there can be multiple arrows between two objects. - -The underlying multidigraph is given by a list of nodes and a list of arrows. - -The equivalence relation is given by a function on paths of the inductive graph. - -The function `mkCompositionGraph` checks the structure of the category and is the preferred way of instantiatiating the `CompositionGraph` type. -If the check takes too long because the category is big, you can use the `CompositionGraph` if you're sure that the category structure is respected. - -Morphisms from different composition graphs should not be composed or compared, if they are, the behavior is undefined. - -When taking subcategories of a composition graph, the composition law might lead to morphisms not existing anymore. -It is not a problem because they are equivalent, it is only counterintuitive for human readability. - -Example.ExampleCompositionGraph provides an example of composition graph construction. --} - - -module CompositionGraph.CompositionGraph -( - -- * Types for a graph - Arrow(..), - Graph(..), - -- * Types for a morphism of composition graph - RawPath(..), - Path(..), - CGMorphism(..), - -- * Types for a composition graph - CompositionLaw(..), - CompositionGraph(..), - -- * Construction - mkCompositionGraph, - mkEmptyCompositionGraph, - finiteCategoryToCompositionGraph, - generatedFiniteCategoryToCompositionGraph, - -- * Error gestion - CompositionGraphError(..), - -- * Insertion - insertObject, - insertMorphism, - -- * Modification - identifyMorphisms, - unidentifyMorphism, - replaceObject, - replaceMorphism, - -- * Deletion - deleteObject, - deleteMorphism, - -- * Utility functions - isGen, - isComp, - getLabel - -) -where - import Data.List ((\\), nub, intercalate, delete) - import FiniteCategory.FiniteCategory - import Utils.CartesianProduct (cartesianProduct, (|^|)) - import Data.Maybe (isNothing, fromJust) - import IO.PrettyPrint - import Utils.AssociationList - import Utils.Tuple - import Diagram.Diagram - import Config.Config - import Cat.PartialFinCat - import Control.Monad (foldM) - - -- | An `Arrow` is a source node, a target node and an identifier (for example a unique label). - type Arrow a b = (a, a, b) - - -- | A `RawPath` is a list of arrows. - type RawPath a b = [Arrow a b] - - -- | A `Path` is a `RawPath` with a source and a target specified. - -- - -- An empty path is an identity in a free category. - -- Therefore, it is useful to keep the source and the target when the path is empty - -- because there is one identity for each node of the graph. (We need to differentiate identites for each node.) - type Path a b = (a, RawPath a b, a) - - -- | A `CompositionLaw` is a `Data.Map` that maps raw paths to smaller raw paths in order to simplify paths - -- so that they don't compose infinitely many times when there is a cycle. - -- - -- prop> length (law ! p) <= length p - type CompositionLaw a b = AssociationList (RawPath a b) (RawPath a b) - - -- | The type `CGMorphism` is the type of composition graph morphisms. - -- - -- It is a path with a composition law, it is necessary to keep the composition law of the composition graph - -- in every morphism of the graph because we need it to compose two morphisms and the morphisms compose - -- independently of the composition graph. - data CGMorphism a b = CGMorphism {path :: Path a b, - compositionLaw :: CompositionLaw a b} deriving (Show, Eq) - - instance (PrettyPrintable a, PrettyPrintable b, Eq a, Eq b) => PrettyPrintable (CGMorphism a b) where - pprint CGMorphism {path=(s,[],t),compositionLaw=cl} = if s == t then "Id"++(pprint s) else error "Identity with source different of target." - pprint CGMorphism {path=(_,rp,_),compositionLaw=cl} = intercalate " o " $ (\(_,_,l) -> pprint l) <$> rp - - -- | A `Graph` is a list of nodes and a list of arrows. - type Graph a b = ([a],[Arrow a b]) - - -- | Helper function for `simplify`. Returns a simplified raw path. - simplifyOnce :: (Eq a, Eq b) => CompositionLaw a b -> RawPath a b -> RawPath a b - simplifyOnce _ [] = [] - simplifyOnce _ [e] = [e] - simplifyOnce cl list - | new_list == [] = [] - | new_list /= list = new_list - | simple_tail /= (tail list) = (head list):simple_tail - | simple_init /= (init list) = simple_init++[(last list)] - | otherwise = list - where - new_list = (!-?) list list cl - simple_tail = simplifyOnce cl (tail list) - simple_init = simplifyOnce cl (init list) - - -- | Returns a completely simplified raw path. - simplify :: (Eq a, Eq b) => CompositionLaw a b -> RawPath a b -> RawPath a b - simplify _ [] = [] - simplify cl rp - | simple_one == rp = rp - | otherwise = simplify cl simple_one - where simple_one = simplifyOnce cl rp - - instance (Eq a, Eq b) => Morphism (CGMorphism a b) a where - (@) CGMorphism{path=(s2,rp2,t2), compositionLaw=cl2} CGMorphism{path=(s1,rp1,t1), compositionLaw=cl1} - | t1 /= s2 = error "Composition of morphisms g@f where target of f is different of source of g" - | cl1 /= cl2 = error "Composition of morphisms with different composition laws" - | otherwise = CGMorphism{path=(s1,(simplify cl1 (rp2++rp1)),t2), compositionLaw=cl1} - - - source CGMorphism{path=(s,_,_), compositionLaw=_} = s - target CGMorphism{path=(_,_,t), compositionLaw=_} = t - - - -- | Constructs a `CGMorphism` from a composition law and an arrow. - mkCGMorphism :: CompositionLaw a b -> Arrow a b -> CGMorphism a b - mkCGMorphism cl e@(s,t,l) = CGMorphism {path=(s,[e],t),compositionLaw=cl} - - -- | Returns the list of arrows of a graph with a given source. - findOutwardEdges :: (Eq a) => Graph a b -> a -> [Arrow a b] - findOutwardEdges (nodes,edges) o = filter (\e@(s,t,_) -> s == o && elem t nodes) edges - - -- | Returns the list of arrows of a graph with a given target. - findInwardEdges :: (Eq a) => Graph a b -> a -> [Arrow a b] - findInwardEdges (nodes,edges) o = filter (\e@(s,t,_) -> t == o && elem s nodes) edges - - -- | Constructs the identity associated to a node of a composition graph. - mkIdentity :: (Eq a) => Graph a b -> CompositionLaw a b -> a -> CGMorphism a b - mkIdentity g@(n,_) cl x - | elem x n = CGMorphism {path=(x,[],x),compositionLaw=cl} - | otherwise = error ("Trying to construct identity of an unknown object.") - - -- | Find all acyclic raw paths between two nodes in a graph. - findAcyclicRawPaths :: (Eq a) => Graph a b -> a -> a -> [RawPath a b] - findAcyclicRawPaths g s t = findAcyclicRawPathsVisitedNodes g s t [] where - findAcyclicRawPathsVisitedNodes g@(n,e) s t v - | elem t v = [] - | s == t = [[]] - | otherwise = (concat (zipWith ($) (fmap fmap (fmap (:) inwardEdges)) (fmap (\x@(s1,t1,l1) -> (findAcyclicRawPathsVisitedNodes g s s1 (t:v))) inwardEdges))) where - inwardEdges = (findInwardEdges g t) - - -- | An elementary cycle is a cycle which is not composed of any other cycle. - findElementaryCycles :: (Eq a, Eq b) => Graph a b -> CompositionLaw a b -> a -> [RawPath a b] - findElementaryCycles g cl o = nub (simplify cl <$> []:(concat (zipWith sequence (fmap (fmap (\x y -> (y:x))) (fmap (\(s,_,_) -> (findAcyclicRawPaths g o s)) inEdges)) inEdges))) where inEdges = (findInwardEdges g o) - - -- | Composes every elementary cycles of a node until they simplify into a fixed set of cycles. - -- - -- Warning : this function can do an infinite loop if the composition law does not simplify a cycle or all of its child cycles. - -- We throw an error to stop this function when we reach a depth of 5. - findCycles :: (Eq a, Eq b) => Graph a b -> CompositionLaw a b -> a -> [RawPath a b] - findCycles g cl o = findCyclesWithPreviousCycles g cl o (findElementaryCycles g cl o) maximumLoopDepth where - findCyclesWithPreviousCycles g cl o p n = if n == 0 then error "Suspected infinite loop because of a malformed composition graph." else if newCycles \\ p == [] then newCycles else (findCyclesWithPreviousCycles g cl o newCycles (n-1)) where - newCycles = nub ((simplify cl) <$> ((++) <$> p <*> findElementaryCycles g cl o)) - - -- | Helper function which intertwine the second list in the first list. - -- - -- Example : intertwine [1,2,3] [4,5] = [1,4,2,5,3] - intertwine :: [a] -> [a] -> [a] - intertwine [] l = l - intertwine l [] = l - intertwine l1@(x1:xs1) l2@(x2:xs2) = (x1:(x2:(intertwine xs1 xs2))) - - -- | Takes a path and intertwine every cycles possible along its path. - intertwineWithCycles :: (Eq a, Eq b) => Graph a b -> CompositionLaw a b -> a -> RawPath a b -> [RawPath a b] - intertwineWithCycles g cl _ p@(x@(_,t,_):xs) = (concat <$> sequence (fmap intertwine prodCycles) (fmap (:[]) p)) where - prodCycles = cartesianProduct cycles - cycles = (findCycles g cl t):((\(s,_,_) -> (findCycles g cl s)) <$> p) - intertwineWithCycles g cl s [] = (findCycles g cl s) - - -- | Enumerates all paths between two nodes and construct composition graph morphisms with them. - mkAr :: (Eq a, Eq b) => Graph a b -> CompositionLaw a b -> a -> a -> [CGMorphism a b] - mkAr g cl s t = (\p -> CGMorphism{path=(s,p,t),compositionLaw=cl}) <$> nub (simplify cl <$> concat((intertwineWithCycles g cl s) <$> acyclicPaths)) where - acyclicPaths = nub $ (simplify cl) <$> (findAcyclicRawPaths g s t) - - -- | A composition graph is a graph with a composition law. Use `mkCompositionGraph` to instantiate it unless it takes too long. - data CompositionGraph a b = CompositionGraph {graph :: Graph a b, law :: CompositionLaw a b} deriving (Eq, Show) - - instance (Eq a, Eq b) => FiniteCategory (CompositionGraph a b) (CGMorphism a b) a where - ob = fst.graph - identity c = mkIdentity (graph c) (law c) - ar c = mkAr (graph c) (law c) - - instance (Eq a, Eq b) => GeneratedFiniteCategory (CompositionGraph a b) (CGMorphism a b) a where - genAr c@CompositionGraph{graph=g,law=l} s t - | s == t = gen ++ [identity c s] - | otherwise = gen - where gen = mkCGMorphism l <$> (filter (\a@(s1,t1,_) -> s == s1 && t == t1) $ snd g) - - decompose c m@CGMorphism{path=(_,rp,_),compositionLaw=l} - | isIdentity c m = [m] - | otherwise = mkCGMorphism l <$> rp - - instance (PrettyPrintable a, PrettyPrintable b, Eq a, Eq b) => PrettyPrintable (CompositionGraph a b) where - pprint cg@CompositionGraph{graph=(nodes,arrs),law=_} = "CompositionGraph("++intercalate "," (pprint <$> nodes)++"\n"++intercalate "," ((\(a,b,c) -> pprint c ++ ":" ++ pprint a ++ "->" ++ pprint b) <$> arrs) - - -- | Optimized version of isGenerator for `CompositionGraph`. - isGen :: (Eq a) => CGMorphism a b -> Bool - isGen m@CGMorphism{path=p@(s,rp,t),compositionLaw=_} = (length rp ) < 2 - - -- | Optimized version of isComposite for `CompositionGraph`. - isComp :: (Eq a) => CGMorphism a b -> Bool - isComp = not.isGen - - -- | Returns the label of a generator arrow which is not an identity. - getLabel :: (Eq a) => CGMorphism a b -> Maybe b - getLabel CGMorphism{path=(_,[(_,_,label)],_),compositionLaw=_} = Just label - getLabel _ = Nothing - - -- | Constructs a `CompositionGraph` from a `Graph` and a `CompositionLaw`. - -- - -- This is the preferred way of instantiating a `CompositionGraph` with `mkEmptyCompositionGraph`. This function checks the category structure, - -- that is why it can return a `FiniteCategoryError` if the graph and the composition law provided don't produce a valid category. - -- If this function takes too much time, use the `CompositionGraph` constructor at your own risk (it is your responsability to check the - -- the category structure is valid). - mkCompositionGraph :: (Eq a, Eq b, Show a) => Graph a b -> CompositionLaw a b -> Either (FiniteCategoryError (CGMorphism a b) a) (CompositionGraph a b) - mkCompositionGraph g l - | isNothing check = Right c_g - | otherwise = Left (fromJust check) - where - c_g = CompositionGraph {graph = g, law = l} - check = checkGeneratedFiniteCategoryProperties c_g - - -- | Constructs an empty `CompositionGraph`. - -- - -- Use `insertObject`, `insertMorphism` and `identifyMorphisms` to build a `CompositionGraph` from it. - mkEmptyCompositionGraph :: CompositionGraph a b - mkEmptyCompositionGraph = CompositionGraph {graph=([],[]), law=[]} - - - - -- | Transforms any `FiniteCategory` into a composition graph. - -- - -- The composition graph will take more space in memory compared to the original category because the composition law is stored as a Data.Map. - -- - -- Returns the `CompositionGraph` and an isofunctor as a `Diagram`. - finiteCategoryToCompositionGraph :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> (CompositionGraph o m, Diagram c m o (CompositionGraph o m) (CGMorphism o m) o) - finiteCategoryToCompositionGraph cat = (cg,isofunct) - where - morphToArrow f = ((source f),(target f),f) - catLaw = [ - if isNotIdentity cat (g @ f) then - ([morphToArrow g,morphToArrow f],[morphToArrow (g @ f)]) - else - ([morphToArrow g,morphToArrow f],[]) | - f <- (arrows cat), g <- (arFrom cat (target f)), isNotIdentity cat f, isNotIdentity cat g] - cg = (CompositionGraph{graph=(ob cat, [morphToArrow f | f <- (arrows cat), isNotIdentity cat f]) - , law= catLaw}) - isofunct = Diagram{src=cat,tgt=cg,omap=functToAssocList id (ob cat),mmap=functToAssocList (\f -> if isNotIdentity cat f - then - mkCGMorphism catLaw (morphToArrow f) - else - identity cg (source f)) (arrows cat)} - - -- | Transforms any `GeneratedFiniteCategory` into a composition graph. - -- - -- The composition graph will take more space in memory compared to the original category because the composition law is stored as a Data.Map. - -- - -- Returns the `CompositionGraph` and an isofunctor as a `Diagram`. - generatedFiniteCategoryToCompositionGraph :: (GeneratedFiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> (CompositionGraph o m, Diagram c m o (CompositionGraph o m) (CGMorphism o m) o) - generatedFiniteCategoryToCompositionGraph cat = (cg,isofunct) - where - morphToArrow f = ((source f),(target f),f) - catLaw = [ - if isNotIdentity cat (g @ f) then - ((morphToArrow <$> (decompose cat g))++(morphToArrow <$> (decompose cat f)), morphToArrow <$> (decompose cat (g @ f))) - else - ((morphToArrow <$> (decompose cat g))++(morphToArrow <$> (decompose cat f)),[]) | - f <- (arrows cat), g <- (arFrom cat (target f)), isNotIdentity cat f, isNotIdentity cat g] - cg = (CompositionGraph{graph=(ob cat, [morphToArrow f | f <- (genArrows cat), isNotIdentity cat f]) - , law= catLaw}) - isofunct = Diagram{src=cat,tgt=cg,omap=functToAssocList id (ob cat),mmap= functToAssocList (\f -> if isNotIdentity cat f - then - CGMorphism {path=(source f,(morphToArrow <$> (decompose cat f)),target f),compositionLaw=catLaw} - else - identity cg (source f)) (arrows cat)} - - -- | The datatype for composition graph construction errors. - data CompositionGraphError a b = InsertMorphismNonExistantSource {faultyMorph :: b, faultySrc :: a} - | InsertMorphismNonExistantTarget {faultyMorph :: b, faultyTgt :: a} - | IdentifyGenerator {gen :: CGMorphism a b} - | UnidentifyNonExistantMorphism {morph :: CGMorphism a b} - | ResultingCategoryError (FiniteCategoryError (CGMorphism a b) a) - | ReplaceNonExistantObject {faultyObj :: a} - | ReplaceCompositeMorphism {composite :: CGMorphism a b} - | DeleteIdentity {faultyIdentity :: CGMorphism a b} - | DeleteCompositeMorph {composite :: CGMorphism a b} - | DeleteNonExistantObjectMorph {neMorph :: CGMorphism a b} - | DeleteNonExistantObject {faultyObj :: a} - - -- | Inserts an object in a `CompositionGraph`, returns the new `CompositionGraph` and a `PartialFunctor` which is the insertion functor. - insertObject :: (Eq a, Eq b) => CompositionGraph a b -> a -> (CompositionGraph a b, (PartialFunctor (CompositionGraph a b) (CGMorphism a b) a)) - insertObject prev@CompositionGraph{graph=(nodes,arrs), law=l} obj = (new, funct) - where - new = CompositionGraph{graph=(obj:nodes,arrs), law=l} - funct = PartialFunctor{srcPF=prev,tgtPF=new,omapPF=functToAssocList id nodes,mmapPF=functToAssocList id (arrows prev)} - - -- | Inserts a morphism in a `CompositionGraph`, returns the new `CompositionGraph` and a `PartialFunctor` which is the insertion functor if it can, returns Nothing otherwise. - -- - -- This function fails if the two nodes provided as source and target for the new morphism are not both in the composition graph. - -- - -- The result may not be a valid `CompositionGraph` (the new morphism might close a loop creating infinitely many morphisms). - -- You can use the function `identifyMorphisms` to transform it back into a valid `CompositionGraph`. - insertMorphism :: (Eq a, Eq b) => CompositionGraph a b -> a -> a -> b -> Either - (CompositionGraphError a b) - (CompositionGraph a b, (PartialFunctor (CompositionGraph a b) (CGMorphism a b) a)) - insertMorphism prev@CompositionGraph{graph=(nodes,arrs), law=l} src tgt morph - | elem src nodes && elem tgt nodes = Right (new, funct) - | not $ elem src nodes = Left InsertMorphismNonExistantSource{faultyMorph=morph, faultySrc=src} - | not $ elem tgt nodes = Left InsertMorphismNonExistantTarget{faultyMorph=morph, faultyTgt=tgt} - where - new = CompositionGraph{graph=(nodes,(src, tgt, morph):arrs), law=l} - funct = PartialFunctor{srcPF=prev,tgtPF=new,omapPF=functToAssocList id nodes,mmapPF=functToAssocList id (arrows prev)} - - -- | Identify two morphisms if it is possible, if not returns an error in a Left member. - -- - -- You can only identify a composite morphism to another morphism. - -- - -- If the resulting composition graph is not associative, it returns Left CompositionNotAssociative. - identifyMorphisms :: (Eq a, Eq b) => CompositionGraph a b -> CGMorphism a b -> CGMorphism a b -> Either - (CompositionGraphError a b) - (CompositionGraph a b, (PartialFunctor (CompositionGraph a b) (CGMorphism a b) a)) - identifyMorphisms prev@CompositionGraph{graph=(nodes,arrs), law=l} srcM tgtM - | isGen srcM = Left IdentifyGenerator{gen=srcM} - | isNothing check = Right (new,funct) - | otherwise = Left $ ResultingCategoryError (fromJust check) - where - newLaw = ((snd3.path) srcM,(snd3.path) tgtM):l - new = CompositionGraph{graph=(nodes,arrs), law=newLaw} - check = checkGeneratedFiniteCategoryProperties new - replaceLaw m = CGMorphism{path=(path m) - ,compositionLaw=newLaw} - funct = PartialFunctor{srcPF=prev,tgtPF=new,omapPF=functToAssocList id nodes,mmapPF=functToAssocList replaceLaw (delete srcM (arrows prev))} - - -- | Unidentify a morphism if it is possible, if not returns an error in a Left member. - -- - -- Unidentifying a morphism means removing all entries in the composition law with results the morphism. - unidentifyMorphism :: (Eq a, Eq b) => CompositionGraph a b -> CGMorphism a b -> Either - (CompositionGraphError a b) - (CompositionGraph a b, (PartialFunctor (CompositionGraph a b) (CGMorphism a b) a)) - unidentifyMorphism prev@CompositionGraph{graph=(nodes,arrs), law=l} m - | elem m (ar prev (source m) (target m)) = Right (new,funct) - | otherwise = Left UnidentifyNonExistantMorphism{morph=m} - where - newLaw = filter (((snd3.path $ m)/=).snd) l - replaceLawInMorph CGMorphism{path=p,compositionLaw=_} = CGMorphism{path=p,compositionLaw=newLaw} - new = CompositionGraph{graph=(nodes,arrs), law=newLaw} - funct = PartialFunctor{srcPF=prev,tgtPF=new,omapPF=functToAssocList id nodes,mmapPF=functToAssocList replaceLawInMorph (arrows prev)} - - -- | Replaces an object with a new one, if the object to replace is not in the composition graph, returns Nothing. - -- - -- It is different from deleting the object and inserting the new one because deleting an object deletes all leaving and coming arrows. - replaceObject :: (Eq a, Eq b) => CompositionGraph a b -> a -> a -> Either - (CompositionGraphError a b) - (CompositionGraph a b, (PartialFunctor (CompositionGraph a b) (CGMorphism a b) a)) - replaceObject prev@CompositionGraph{graph=(nodes,arrs), law=l} prevObj newObj - | elem prevObj (ob prev) = Right (new,funct) - | otherwise = Left ReplaceNonExistantObject {faultyObj=prevObj} - where - replace x = if x == prevObj then newObj else x - replaceArr (s,t,a) = (replace s, replace t, a) - replaceLawEntry (k,v) = (replaceArr <$> k, replaceArr <$> v) - replaceCGMorph CGMorphism{path=(s,rp,t),compositionLaw=l} = CGMorphism{path=(replace s,replaceArr <$> rp,replace t),compositionLaw=replaceLawEntry <$> l} - new = CompositionGraph{graph=(replace <$> nodes,replaceArr <$> arrs), law=replaceLawEntry <$> l} - funct = PartialFunctor{srcPF=prev,tgtPF=new,omapPF=functToAssocList replace nodes,mmapPF=functToAssocList replaceCGMorph (arrows prev)} - - -- | Replaces a generating morphism with a new one, if the morphism to replace is not a generator of the composition graph, returns Nothing. - -- - -- It is different from deleting the morphism and inserting the new one because deleting an object deletes related composition law entries. - replaceMorphism :: (Eq a, Eq b) => CompositionGraph a b -> CGMorphism a b -> b -> Either - (CompositionGraphError a b) - (CompositionGraph a b, (PartialFunctor (CompositionGraph a b) (CGMorphism a b) a)) - replaceMorphism prev@CompositionGraph{graph=(nodes,arrs), law=l} prevMorph newMorph - | elem prevMorph (genAr prev (source prevMorph) (target prevMorph)) = Right (new,funct) - | otherwise = Left ReplaceCompositeMorphism{composite=prevMorph} - where - replaceArr m@(s,t,a) = if [m] == (snd3.path $ prevMorph) then (s, t, newMorph) else m - replaceLawEntry (k,v) = (replaceArr <$> k, replaceArr <$> v) - replaceCGMorph CGMorphism{path=(s,rp,t),compositionLaw=l} = CGMorphism{path=(s,replaceArr <$> rp,t),compositionLaw=replaceLawEntry <$> l} - new = CompositionGraph{graph=(nodes,replaceArr <$> arrs), law=replaceLawEntry <$> l} - funct = PartialFunctor{srcPF=prev,tgtPF=new,omapPF=functToAssocList id nodes,mmapPF=functToAssocList replaceCGMorph (arrows prev)} - - -- | Deletes a generating morphism if it can, the generator should not be an identity. - deleteMorphism :: (Eq a, Eq b) => CompositionGraph a b -> CGMorphism a b -> Either - (CompositionGraphError a b) - (CompositionGraph a b, (PartialFunctor (CompositionGraph a b) (CGMorphism a b) a)) - deleteMorphism prev@CompositionGraph{graph=(nodes,arrs), law=l} morph - | isIdentity prev morph = Left DeleteIdentity {faultyIdentity=morph} - | elem morph (genAr prev (source morph) (target morph)) = Right (new,funct) - | elem morph (ar prev (source morph) (target morph)) = Left DeleteCompositeMorph{composite=morph} - | otherwise = Left DeleteNonExistantObjectMorph{neMorph=morph} - where - arr = head.snd3.path $ morph - newLaw = filter (\(k,v) -> and ((/=arr) <$> k) && and ((/=arr) <$> v)) l - newArrows = filter (\CGMorphism{path=(s,rp,t),compositionLaw=_} -> not (elem arr rp)) (arrows prev) - replaceLaw m = CGMorphism{path=(path m) - ,compositionLaw=newLaw} - new = CompositionGraph{graph=(nodes,delete arr arrs), law=newLaw} - funct = PartialFunctor{srcPF=prev,tgtPF=new,omapPF=functToAssocList id nodes,mmapPF=functToAssocList replaceLaw newArrows} - - -- | Deletes an object and all morphism coming from it or leaving it. - deleteObject :: (Eq a, Eq b) => CompositionGraph a b -> a -> Either - (CompositionGraphError a b) - (CompositionGraph a b, (PartialFunctor (CompositionGraph a b) (CGMorphism a b) a)) - deleteObject prev@CompositionGraph{graph=(nodes,arrs), law=l} obj - | elem obj (ob prev) = (\(cg,f) -> (\(fcg,ffunct) -> (fcg,ffunct @ f)) (delObj cg)) <$> cgWithoutMorphs - | otherwise = Left DeleteNonExistantObject {faultyObj=obj} - where - idFunct = PartialFunctor{srcPF=prev,tgtPF=prev,omapPF=functToAssocList id nodes,mmapPF=functToAssocList id (arrows prev)} - cgWithoutMorphs = foldM (\(cg,f) d -> ((\(ncg,nf) -> (ncg,nf @ f)) <$> (deleteMorphism cg d))) (prev,idFunct) (filter (isNotIdentity prev) (nub ((genArFrom prev obj)++(genArTo prev obj)))) - delObj prev2@CompositionGraph{graph=(nodes2,arrs2), law=l2} = (finalCG, - PartialFunctor{srcPF=prev2,tgtPF=finalCG,omapPF=functToAssocList id (delete obj nodes2),mmapPF=functToAssocList id ((arrows prev2)\\[(identity prev2 obj)])}) - where - finalCG = CompositionGraph{graph=(delete obj nodes2,arrs2), law=l2}
− src/CompositionGraph/SafeCompositionGraph.hs
@@ -1,429 +0,0 @@-{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-} - -{-| Module : FiniteCategories -Description : Composition graphs are the simpliest way to create simple small categories by hand. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -A `SafeCompositionGraph` is the quasi-free category generated by a multidigraph quotiented by an equivalence relation on the paths of the graphs. There is a limit on the number of cycles you can have in a morphism. It prevents any infinite loop from occuring. -A multidigraph is a directed multigraph which means that edges are oriented and there can be multiple arrows between two objects. - -The underlying multidigraph is given by a list of nodes and a list of arrows. - -The equivalence relation is given by a function on paths of the inductive graph. - -The function `mkSafeCompositionGraph` checks the structure of the category and is the preferred way of instantiatiating the `SafeCompositionGraph` type. -If the check takes too long because the category is big, you can use the `SafeCompositionGraph` constructor if you're sure that the category structure is respected. - -Morphisms from different composition graphs should not be composed or compared, if they are, the behavior is undefined. - -When taking subcategories of a composition graph, the composition law might lead to morphisms not existing anymore. -It is not a problem because they are equivalent, it is only counterintuitive for human readability. - -Example.ExampleSafeCompositionGraph provides an example of composition graph construction. --} - - -module CompositionGraph.SafeCompositionGraph -( - -- * Types for a morphism of composition graph - SCGMorphism(..), - -- * Types for a composition graph - SafeCompositionGraph(..), - -- * Construction - mkSafeCompositionGraph, - mkEmptySafeCompositionGraph, - finiteCategoryToSafeCompositionGraph, - generatedFiniteCategoryToSafeCompositionGraph, - -- * Insertion - insertObjectS, - insertMorphismS, - -- * Modification - identifyMorphismsS, - unidentifyMorphismS, - replaceObjectS, - replaceMorphismS, - -- * Deletion - deleteObjectS, - deleteMorphismS, - -- * Utility functions - isGenS, - isCompS, - getLabelS - -) -where - import Data.List ((\\), nub, intercalate, delete) - import FiniteCategory.FiniteCategory - import Utils.CartesianProduct (cartesianProduct, (|^|)) - import Data.Maybe (isNothing, fromJust) - import IO.PrettyPrint - import Utils.AssociationList - import Utils.Tuple - import Diagram.Diagram - import Config.Config - import Cat.PartialFinCat - import Control.Monad (foldM) - import CompositionGraph.CompositionGraph - - -- | The type `SCGMorphism` is the type of safe composition graph morphisms. - -- - -- It is a path with a composition law, it is necessary to keep the composition law of the composition graph - -- in every morphism of the graph because we need it to compose two morphisms and the morphisms compose - -- independently of the composition graph. - -- We also store the maximum number of cycles. - data SCGMorphism a b = SCGMorphism {pathS :: Path a b - ,compositionLawS :: CompositionLaw a b - ,maxNbCycles :: Int} deriving (Show, Eq) - - instance (PrettyPrintable a, PrettyPrintable b, Eq a, Eq b) => PrettyPrintable (SCGMorphism a b) where - pprint SCGMorphism {pathS=(s,[],t),compositionLawS=_,maxNbCycles=_} = if s == t then "Id"++(pprint s) else error "Identity with source different of target." - pprint SCGMorphism {pathS=(_,rp,_),compositionLawS=_,maxNbCycles=_} = intercalate " o " $ (\(_,_,l) -> pprint l) <$> rp - - rawpathToListOfVertices :: RawPath a b -> [a] - rawpathToListOfVertices [] = [] - rawpathToListOfVertices rp = ((snd3 (head rp)):(fst3 <$> rp)) - - -- | Helper function for `simplify`. Returns a simplified raw path. - simplifyOnce :: (Eq a, Eq b) => CompositionLaw a b -> Int -> RawPath a b -> RawPath a b - simplifyOnce _ _ [] = [] - simplifyOnce _ _ [e] = [e] - simplifyOnce cl nb list - | new_list == [] = [] - | isCycle && tooManyCycles = [] - | new_list /= list = new_list - | simple_tail /= (tail list) = (head list):simple_tail - | simple_init /= (init list) = simple_init++[(last list)] - | otherwise = list - where - listOfVertices = rawpathToListOfVertices list - isCycle = (head listOfVertices) == (last listOfVertices) - tooManyCycles = (length $ filter ((head listOfVertices) ==) listOfVertices) == (nb+2) - new_list = (!-?) list list cl - simple_tail = simplifyOnce cl nb (tail list) - simple_init = simplifyOnce cl nb (init list) - - -- | Returns a completely simplified raw path. - simplify :: (Eq a, Eq b) => CompositionLaw a b -> Int -> RawPath a b -> RawPath a b - simplify _ _ [] = [] - simplify cl nb rp - | simple_one == rp = rp - | otherwise = simplify cl nb simple_one - where simple_one = simplifyOnce cl nb rp - - instance (Eq a, Eq b) => Morphism (SCGMorphism a b) a where - (@) SCGMorphism{pathS=(s2,rp2,t2), compositionLawS=cl2, maxNbCycles=nb1} SCGMorphism{pathS=(s1,rp1,t1), compositionLawS=cl1, maxNbCycles=nb2} - | t1 /= s2 = error "Composition of morphisms g@f where target of f is different of source of g" - | cl1 /= cl2 = error "Composition of morphisms with different composition laws" - | nb1 /= nb2 = error "Composition of morphisms with different maximum number of cycles." - | otherwise = SCGMorphism{pathS=(s1,(simplify cl1 nb1 (rp2++rp1)),t2), compositionLawS=cl1, maxNbCycles=nb1} - - - source SCGMorphism{pathS=(s,_,_), compositionLawS=_, maxNbCycles=_} = s - target SCGMorphism{pathS=(_,_,t), compositionLawS=_, maxNbCycles=_} = t - - - -- | Constructs a `SCGMorphism` from a composition law and an arrow. - mkSCGMorphism :: CompositionLaw a b -> Int -> Arrow a b -> SCGMorphism a b - mkSCGMorphism cl nb e@(s,t,l) = SCGMorphism {pathS=(s,[e],t),compositionLawS=cl, maxNbCycles=nb} - - -- | Returns the list of arrows of a graph with a given source. - findOutwardEdges :: (Eq a) => Graph a b -> a -> [Arrow a b] - findOutwardEdges (nodes,edges) o = filter (\e@(s,t,_) -> s == o && elem t nodes) edges - - -- | Returns the list of arrows of a graph with a given target. - findInwardEdges :: (Eq a) => Graph a b -> a -> [Arrow a b] - findInwardEdges (nodes,edges) o = filter (\e@(s,t,_) -> t == o && elem s nodes) edges - - -- | Constructs the identity associated to a node of a composition graph. - mkIdentity :: (Eq a) => Graph a b -> CompositionLaw a b -> Int -> a -> SCGMorphism a b - mkIdentity g@(n,_) cl nb x - | elem x n = SCGMorphism {pathS=(x,[],x),compositionLawS=cl, maxNbCycles=nb} - | otherwise = error ("Trying to construct identity of an unknown object.") - - -- | Find all acyclic raw paths between two nodes in a graph. - findAcyclicRawPaths :: (Eq a) => Graph a b -> a -> a -> [RawPath a b] - findAcyclicRawPaths g s t = findAcyclicRawPathsVisitedNodes g s t [] where - findAcyclicRawPathsVisitedNodes g@(n,e) s t v - | elem t v = [] - | s == t = [[]] - | otherwise = (concat (zipWith ($) (fmap fmap (fmap (:) inwardEdges)) (fmap (\x@(s1,t1,l1) -> (findAcyclicRawPathsVisitedNodes g s s1 (t:v))) inwardEdges))) where - inwardEdges = (findInwardEdges g t) - - -- | An elementary cycle is a cycle which is not composed of any other cycle. - findElementaryCycles :: (Eq a, Eq b) => Graph a b -> CompositionLaw a b -> Int -> a -> [RawPath a b] - findElementaryCycles g cl nb o = nub (simplify cl nb <$> []:(concat (zipWith sequence (fmap (fmap (\x y -> (y:x))) (fmap (\(s,_,_) -> (findAcyclicRawPaths g o s)) inEdges)) inEdges))) where inEdges = (findInwardEdges g o) - - -- | Composes every elementary cycles of a node until they simplify into a fixed set of cycles. - -- - -- Warning : this function can do an infinite loop if the composition law does not simplify a cycle or all of its child cycles. - -- We throw an error to stop this function when we reach a depth of 5. - findCycles :: (Eq a, Eq b) => Graph a b -> CompositionLaw a b -> Int -> a -> [RawPath a b] - findCycles g cl nb o = findCyclesWithPreviousCycles g cl o (findElementaryCycles g cl nb o) where - findCyclesWithPreviousCycles g cl o p = if newCycles \\ p == [] then newCycles else (findCyclesWithPreviousCycles g cl o newCycles) where - newCycles = nub ((simplify cl nb) <$> ((++) <$> p <*> findElementaryCycles g cl nb o)) - - -- | Helper function which intertwine the second list in the first list. - -- - -- Example : intertwine [1,2,3] [4,5] = [1,4,2,5,3] - intertwine :: [a] -> [a] -> [a] - intertwine [] l = l - intertwine l [] = l - intertwine l1@(x1:xs1) l2@(x2:xs2) = (x1:(x2:(intertwine xs1 xs2))) - - -- | Takes a path and intertwine every cycles possible along its path. - intertwineWithCycles :: (Eq a, Eq b) => Graph a b -> CompositionLaw a b -> Int -> a -> RawPath a b -> [RawPath a b] - intertwineWithCycles g cl nb _ p@(x@(_,t,_):xs) = (concat <$> sequence (fmap intertwine prodCycles) (fmap (:[]) p)) where - prodCycles = cartesianProduct cycles - cycles = (findCycles g cl nb t):((\(s,_,_) -> (findCycles g cl nb s)) <$> p) - intertwineWithCycles g cl nb s [] = (findCycles g cl nb s) - - -- | Enumerates all paths between two nodes and construct composition graph morphisms with them. - mkAr :: (Eq a, Eq b) => Graph a b -> CompositionLaw a b -> Int -> a -> a -> [SCGMorphism a b] - mkAr g cl nb s t = (\p -> SCGMorphism{pathS=(s,p,t),compositionLawS=cl,maxNbCycles=nb}) <$> nub (simplify cl nb <$> concat((intertwineWithCycles g cl nb s) <$> acyclicPaths)) where - acyclicPaths = nub $ (simplify cl nb) <$> (findAcyclicRawPaths g s t) - - -- | A composition graph is a graph with a composition law. Use `mkSafeCompositionGraph` to instantiate it unless it takes too long. - data SafeCompositionGraph a b = SafeCompositionGraph {graphS :: Graph a b, lawS :: CompositionLaw a b, maxCycles :: Int} deriving (Eq, Show) - - instance (Eq a, Eq b) => FiniteCategory (SafeCompositionGraph a b) (SCGMorphism a b) a where - ob = fst.graphS - identity c = mkIdentity (graphS c) (lawS c) (maxCycles c) - ar c = mkAr (graphS c) (lawS c) (maxCycles c) - - instance (Eq a, Eq b) => GeneratedFiniteCategory (SafeCompositionGraph a b) (SCGMorphism a b) a where - genAr c@SafeCompositionGraph{graphS=g,lawS=l,maxCycles=nb} s t - | s == t = gen ++ [identity c s] - | otherwise = gen - where gen = mkSCGMorphism l nb <$> (filter (\a@(s1,t1,_) -> s == s1 && t == t1) $ snd g) - - decompose c m@SCGMorphism{pathS=(_,rp,_),compositionLawS=l,maxNbCycles=nb} - | isIdentity c m = [m] - | otherwise = mkSCGMorphism l nb <$> rp - - instance (PrettyPrintable a, PrettyPrintable b, Eq a, Eq b) => PrettyPrintable (SafeCompositionGraph a b) where - pprint cg@SafeCompositionGraph{graphS=(nodes,arrs),lawS=_,maxCycles=_} = "SafeCompositionGraph("++intercalate "," (pprint <$> nodes)++"\n"++intercalate "," ((\(a,b,c) -> pprint c ++ ":" ++ pprint a ++ "->" ++ pprint b) <$> arrs) - - -- | Optimized version of isGenerator for `SafeCompositionGraph`. - isGenS :: (Eq a) => SCGMorphism a b -> Bool - isGenS m@SCGMorphism{pathS=p@(s,rp,t),compositionLawS=_,maxNbCycles=_} = (length rp ) < 2 - - -- | Optimized version of isComposite for `SafeCompositionGraph`. - isCompS :: (Eq a) => SCGMorphism a b -> Bool - isCompS = not.isGenS - - -- | Returns the label of a generator arrow which is not an identity. - getLabelS :: (Eq a) => SCGMorphism a b -> Maybe b - getLabelS SCGMorphism{pathS=(_,[(_,_,label)],_),compositionLawS=_,maxNbCycles=_} = Just label - getLabelS _ = Nothing - - -- | Constructs a `SafeCompositionGraph` from a `Graph` and a `CompositionLaw`. - -- - -- This is the preferred way of instantiating a `SafeCompositionGraph` with `mkEmptySafeCompositionGraph`. This function checks the category structure, - -- that is why it can return a `FiniteCategoryError` if the graph and the composition law provided don't produce a valid category. - -- If this function takes too much time, use the `SafeCompositionGraph` constructor at your own risk (it is your responsability to check the - -- the category structure is valid). - mkSafeCompositionGraph :: (Eq a, Eq b, Show a) => Graph a b -> CompositionLaw a b -> Int -> Either (FiniteCategoryError (SCGMorphism a b) a) (SafeCompositionGraph a b) - mkSafeCompositionGraph g l nb - | isNothing check = Right c_g - | otherwise = Left (fromJust check) - where - c_g = SafeCompositionGraph {graphS=g, lawS=l, maxCycles=nb} - check = checkGeneratedFiniteCategoryProperties c_g - - -- | Constructs an empty `SafeCompositionGraph` with a maximum number of cycles. - -- - -- Use `insertObject`, `insertMorphism` and `identifyMorphisms` to build a `SafeCompositionGraph` from it. - mkEmptySafeCompositionGraph :: Int -> SafeCompositionGraph a b - mkEmptySafeCompositionGraph maxNbOfCycles = SafeCompositionGraph {graphS=([],[]), lawS=[], maxCycles=maxNbOfCycles} - - - - -- | Transforms any `FiniteCategory` into a safe composition graph. - -- - -- The composition graph will take more space in memory compared to the original category because the composition law is stored as a Data.Map. - -- - -- Returns the `SafeCompositionGraph` and an isofunctor as a `Diagram`. - finiteCategoryToSafeCompositionGraph :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> (SafeCompositionGraph o m, Diagram c m o (SafeCompositionGraph o m) (SCGMorphism o m) o) - finiteCategoryToSafeCompositionGraph cat = (cg,isofunct) - where - maxnbcycles = maximum $ length <$> ((\x -> ar cat x x) <$> ob cat) - morphToArrow f = ((source f),(target f),f) - catLaw = [ - if isNotIdentity cat (g @ f) then - ([morphToArrow g,morphToArrow f],[morphToArrow (g @ f)]) - else - ([morphToArrow g,morphToArrow f],[]) | - f <- (arrows cat), g <- (arFrom cat (target f)), isNotIdentity cat f, isNotIdentity cat g] - cg = (SafeCompositionGraph{graphS=(ob cat, [morphToArrow f | f <- (arrows cat), isNotIdentity cat f]) - , lawS= catLaw, maxCycles=maxnbcycles}) - isofunct = Diagram{src=cat,tgt=cg,omap=functToAssocList id (ob cat),mmap=functToAssocList (\f -> if isNotIdentity cat f - then - mkSCGMorphism catLaw maxnbcycles (morphToArrow f) - else - identity cg (source f)) (arrows cat)} - - -- | Transforms any `GeneratedFiniteCategory` into a safe composition graph. - -- - -- The composition graph will take more space in memory compared to the original category because the composition law is stored as a Data.Map. - -- - -- Returns the `SafeCompositionGraph` and an isofunctor as a `Diagram`. - generatedFiniteCategoryToSafeCompositionGraph :: (GeneratedFiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> (SafeCompositionGraph o m, Diagram c m o (SafeCompositionGraph o m) (SCGMorphism o m) o) - generatedFiniteCategoryToSafeCompositionGraph cat = (cg,isofunct) - where - maxnbcycles = maximum $ length <$> ((\x -> ar cat x x) <$> ob cat) - morphToArrow f = ((source f),(target f),f) - catLaw = [ - if isNotIdentity cat (g @ f) then - ((morphToArrow <$> (decompose cat g))++(morphToArrow <$> (decompose cat f)), morphToArrow <$> (decompose cat (g @ f))) - else - ((morphToArrow <$> (decompose cat g))++(morphToArrow <$> (decompose cat f)),[]) | - f <- (arrows cat), g <- (arFrom cat (target f)), isNotIdentity cat f, isNotIdentity cat g] - cg = (SafeCompositionGraph{graphS=(ob cat, [morphToArrow f | f <- (genArrows cat), isNotIdentity cat f]) - , lawS= catLaw, maxCycles=maxnbcycles}) - isofunct = Diagram{src=cat,tgt=cg,omap=functToAssocList id (ob cat),mmap=functToAssocList (\f -> if isNotIdentity cat f - then - SCGMorphism {pathS=(source f,(morphToArrow <$> (decompose cat f)),target f),compositionLawS=catLaw, maxNbCycles=maxnbcycles} - else - identity cg (source f)) (arrows cat)} - - -- | Datatype representing how a safe composition graph might be malformed. - data SafeCompositionGraphError a b = InsertMorphismNonExistantSourceS {faultyMorphS :: b, faultySrcS :: a} - | InsertMorphismNonExistantTargetS {faultyMorphS :: b, faultyTgtS :: a} - | IdentifyGeneratorS {genS :: SCGMorphism a b} - | UnidentifyNonExistantMorphismS {morphS :: SCGMorphism a b} - | ResultingCategoryErrorS (FiniteCategoryError (SCGMorphism a b) a) - | ReplaceNonExistantObjectS {faultyObjS :: a} - | ReplaceCompositeMorphismS {compositeS :: SCGMorphism a b} - | DeleteIdentityS {faultyIdentityS :: SCGMorphism a b} - | DeleteCompositeMorphS {compositeS :: SCGMorphism a b} - | DeleteNonExistantObjectMorphS {neMorphS :: SCGMorphism a b} - | DeleteNonExistantObjectS {faultyObjS :: a} - - -- | Inserts an object in a `SafeCompositionGraph`, returns the new `SafeCompositionGraph` and a `PartialFunctor` which is the insertion functor. - insertObjectS :: (Eq a, Eq b) => SafeCompositionGraph a b -> a -> (SafeCompositionGraph a b, (PartialFunctor (SafeCompositionGraph a b) (SCGMorphism a b) a)) - insertObjectS prev@SafeCompositionGraph{graphS=(nodes,arrs), lawS=l, maxCycles=nb} obj = (new, funct) - where - new = SafeCompositionGraph{graphS=(obj:nodes,arrs), lawS=l, maxCycles=nb} - funct = PartialFunctor{srcPF=prev,tgtPF=new,omapPF=functToAssocList id nodes,mmapPF=functToAssocList id (arrows prev)} - - -- | Inserts a morphism in a `SafeCompositionGraph`, returns the new `SafeCompositionGraph` and a `PartialFunctor` which is the insertion functor if it can, returns Nothing otherwise. - -- - -- This function fails if the two nodes provided as source and target for the new morphism are not both in the composition graph. - -- - -- The result may not be a valid `SafeCompositionGraph` (the new morphism might close a loop creating infinitely many morphisms). - -- You can use the function `identifyMorphisms` to transform it back into a valid `SafeCompositionGraph`. - insertMorphismS :: (Eq a, Eq b) => SafeCompositionGraph a b -> a -> a -> b -> Either - (SafeCompositionGraphError a b) - (SafeCompositionGraph a b, (PartialFunctor (SafeCompositionGraph a b) (SCGMorphism a b) a)) - insertMorphismS prev@SafeCompositionGraph{graphS=(nodes,arrs), lawS=l, maxCycles=nb} src tgt morph - | elem src nodes && elem tgt nodes = Right (new, funct) - | not $ elem src nodes = Left InsertMorphismNonExistantSourceS{faultyMorphS=morph, faultySrcS=src} - | not $ elem tgt nodes = Left InsertMorphismNonExistantTargetS{faultyMorphS=morph, faultyTgtS=tgt} - where - new = SafeCompositionGraph{graphS=(nodes,(src, tgt, morph):arrs), lawS=l, maxCycles=nb} - funct = PartialFunctor{srcPF=prev,tgtPF=new,omapPF=functToAssocList id nodes,mmapPF=functToAssocList id (arrows prev)} - - -- | Identify two morphisms if it is possible, if not returns an error in a Left member. - -- - -- You can only identify a composite morphism to another morphism. - -- - -- If the resulting composition graph is not associative, it returns Left CompositionNotAssociative. - identifyMorphismsS :: (Eq a, Eq b) => SafeCompositionGraph a b -> SCGMorphism a b -> SCGMorphism a b -> Either - (SafeCompositionGraphError a b) - (SafeCompositionGraph a b, (PartialFunctor (SafeCompositionGraph a b) (SCGMorphism a b) a)) - identifyMorphismsS prev@SafeCompositionGraph{graphS=(nodes,arrs), lawS=l, maxCycles=nb} srcM tgtM - | isGenS srcM = Left IdentifyGeneratorS{genS=srcM} - | isNothing check = Right (new,funct) - | otherwise = Left $ ResultingCategoryErrorS (fromJust check) - where - newLaw = ((snd3.pathS) srcM,(snd3.pathS) tgtM):l - new = SafeCompositionGraph{graphS=(nodes,arrs), lawS=newLaw, maxCycles=nb} - check = checkGeneratedFiniteCategoryProperties new - replaceLaw m = SCGMorphism{pathS=(pathS m) - ,compositionLawS=newLaw, maxNbCycles=nb} - funct = PartialFunctor{srcPF=prev,tgtPF=new,omapPF=functToAssocList id nodes,mmapPF=functToAssocList replaceLaw (delete srcM (arrows prev))} - - -- | Unidentify a morphism if it is possible, if not returns an error in a Left member. - -- - -- Unidentifying a morphism means removing all entries in the composition law with results the morphism. - unidentifyMorphismS :: (Eq a, Eq b) => SafeCompositionGraph a b -> SCGMorphism a b -> Either - (SafeCompositionGraphError a b) - (SafeCompositionGraph a b, (PartialFunctor (SafeCompositionGraph a b) (SCGMorphism a b) a)) - unidentifyMorphismS prev@SafeCompositionGraph{graphS=(nodes,arrs), lawS=l, maxCycles=nb} m - | elem m (ar prev (source m) (target m)) = Right (new,funct) - | otherwise = Left UnidentifyNonExistantMorphismS{morphS=m} - where - newLaw = filter (((snd3.pathS $ m)/=).snd) l - replaceLawInMorph SCGMorphism{pathS=p,compositionLawS=_, maxNbCycles=_} = SCGMorphism{pathS=p,compositionLawS=newLaw, maxNbCycles=nb} - new = SafeCompositionGraph{graphS=(nodes,arrs), lawS=newLaw, maxCycles=nb} - funct = PartialFunctor{srcPF=prev,tgtPF=new,omapPF=functToAssocList id nodes,mmapPF=functToAssocList replaceLawInMorph (arrows prev)} - - -- | Replaces an object with a new one, if the object to replace is not in the composition graph, returns Nothing. - -- - -- It is different from deleting the object and inserting the new one because deleting an object deletes all leaving and coming arrows. - replaceObjectS :: (Eq a, Eq b) => SafeCompositionGraph a b -> a -> a -> Either - (SafeCompositionGraphError a b) - (SafeCompositionGraph a b, (PartialFunctor (SafeCompositionGraph a b) (SCGMorphism a b) a)) - replaceObjectS prev@SafeCompositionGraph{graphS=(nodes,arrs), lawS=l, maxCycles=nb} prevObj newObj - | elem prevObj (ob prev) = Right (new,funct) - | otherwise = Left ReplaceNonExistantObjectS {faultyObjS=prevObj} - where - replace x = if x == prevObj then newObj else x - replaceArr (s,t,a) = (replace s, replace t, a) - replaceLawEntry (k,v) = (replaceArr <$> k, replaceArr <$> v) - replaceCGMorph SCGMorphism{pathS=(s,rp,t),compositionLawS=l, maxNbCycles=nb} = SCGMorphism{pathS=(replace s,replaceArr <$> rp,replace t),compositionLawS=replaceLawEntry <$> l, maxNbCycles=nb} - new = SafeCompositionGraph{graphS=(replace <$> nodes,replaceArr <$> arrs), lawS=replaceLawEntry <$> l, maxCycles=nb} - funct = PartialFunctor{srcPF=prev,tgtPF=new,omapPF=functToAssocList replace nodes,mmapPF=functToAssocList replaceCGMorph (arrows prev)} - - -- | Replaces a generating morphism with a new one, if the morphism to replace is not a generator of the composition graph, returns Nothing. - -- - -- It is different from deleting the morphism and inserting the new one because deleting an object deletes related composition law entries. - replaceMorphismS :: (Eq a, Eq b) => SafeCompositionGraph a b -> SCGMorphism a b -> b -> Either - (SafeCompositionGraphError a b) - (SafeCompositionGraph a b, (PartialFunctor (SafeCompositionGraph a b) (SCGMorphism a b) a)) - replaceMorphismS prev@SafeCompositionGraph{graphS=(nodes,arrs), lawS=l, maxCycles=nb} prevMorph newMorph - | elem prevMorph (genAr prev (source prevMorph) (target prevMorph)) = Right (new,funct) - | otherwise = Left ReplaceCompositeMorphismS{compositeS=prevMorph} - where - replaceArr m@(s,t,a) = if [m] == (snd3.pathS $ prevMorph) then (s, t, newMorph) else m - replaceLawEntry (k,v) = (replaceArr <$> k, replaceArr <$> v) - replaceCGMorph SCGMorphism{pathS=(s,rp,t),compositionLawS=l, maxNbCycles=_} = SCGMorphism{pathS=(s,replaceArr <$> rp,t),compositionLawS=replaceLawEntry <$> l, maxNbCycles=nb} - new = SafeCompositionGraph{graphS=(nodes,replaceArr <$> arrs), lawS=replaceLawEntry <$> l, maxCycles=nb} - funct = PartialFunctor{srcPF=prev,tgtPF=new,omapPF=functToAssocList id nodes,mmapPF=functToAssocList replaceCGMorph (arrows prev)} - - -- | Deletes a generating morphism if it can, the generator should not be an identity. - deleteMorphismS :: (Eq a, Eq b) => SafeCompositionGraph a b -> SCGMorphism a b -> Either - (SafeCompositionGraphError a b) - (SafeCompositionGraph a b, (PartialFunctor (SafeCompositionGraph a b) (SCGMorphism a b) a)) - deleteMorphismS prev@SafeCompositionGraph{graphS=(nodes,arrs), lawS=l, maxCycles=nb} morph - | isIdentity prev morph = Left DeleteIdentityS {faultyIdentityS=morph} - | elem morph (genAr prev (source morph) (target morph)) = Right (new,funct) - | elem morph (ar prev (source morph) (target morph)) = Left DeleteCompositeMorphS{compositeS=morph} - | otherwise = Left DeleteNonExistantObjectMorphS{neMorphS=morph} - where - arr = head.snd3.pathS $ morph - newLaw = filter (\(k,v) -> and ((/=arr) <$> k) && and ((/=arr) <$> v)) l - newArrows = filter (\SCGMorphism{pathS=(s,rp,t),compositionLawS=_, maxNbCycles=_} -> not (elem arr rp)) (arrows prev) - replaceLaw m = SCGMorphism{pathS=(pathS m) - ,compositionLawS=newLaw,maxNbCycles=nb} - new = SafeCompositionGraph{graphS=(nodes,delete arr arrs), lawS=newLaw, maxCycles=nb} - funct = PartialFunctor{srcPF=prev,tgtPF=new,omapPF=functToAssocList id nodes,mmapPF=functToAssocList replaceLaw newArrows} - - -- | Deletes an object and all morphism coming from it or leaving it. - deleteObjectS :: (Eq a, Eq b) => SafeCompositionGraph a b -> a -> Either - (SafeCompositionGraphError a b) - (SafeCompositionGraph a b, (PartialFunctor (SafeCompositionGraph a b) (SCGMorphism a b) a)) - deleteObjectS prev@SafeCompositionGraph{graphS=(nodes,arrs), lawS=l, maxCycles=nb} obj - | elem obj (ob prev) = (\(cg,f) -> (\(fcg,ffunct) -> (fcg,ffunct @ f)) (delObj cg)) <$> cgWithoutMorphs - | otherwise = Left DeleteNonExistantObjectS {faultyObjS=obj} - where - idFunct = PartialFunctor{srcPF=prev,tgtPF=prev,omapPF=functToAssocList id nodes,mmapPF=functToAssocList id (arrows prev)} - cgWithoutMorphs = foldM (\(cg,f) d -> ((\(ncg,nf) -> (ncg,nf @ f)) <$> (deleteMorphismS cg d))) (prev,idFunct) (filter (isNotIdentity prev) (nub ((genArFrom prev obj)++(genArTo prev obj)))) - delObj prev2@SafeCompositionGraph{graphS=(nodes2,arrs2), lawS=l2, maxCycles=nb} = (finalCG, - PartialFunctor{srcPF=prev2,tgtPF=finalCG,omapPF=functToAssocList id (delete obj nodes2),mmapPF=functToAssocList id ((arrows prev2)\\[(identity prev2 obj)])}) - where - finalCG = SafeCompositionGraph{graphS=(delete obj nodes2,arrs2), lawS=l2, maxCycles=nb}
− src/ConeCategory/ConeCategory.hs
@@ -1,170 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses #-} - -{-| Module : FiniteCategories -Description : Category of cones and category of cocones of a diagram. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -A cone is an object in the comma category (/D/|1_/F/) where /D/ is the diagonal functor and 1_/F/ is the diagram that selects the diagram of interest in the functor category. - -A cocone is an object in the comma category (1_/F/|/D/). --} - -module ConeCategory.ConeCategory -( - -- * Cone related functions and types. - Cone, - ConeMorphism, - ConeCategory, - apex, - coneToNaturalTransformation, - naturalTransformationToCone, - mkConeCategory, - conesOfApex, - terminalObjects, - limits, - -- * Cocone related functions and types. - Cocone, - CoconeMorphism, - CoconeCategory, - nadir, - coconeToNaturalTransformation, - naturalTransformationToCocone, - mkCoconeCategory, - coconesOfNadir, - initialObjects, - colimits -) -where - import FiniteCategory.FiniteCategory - import Diagram.Diagram - import DiagonalFunctor.DiagonalFunctor - import CommaCategory.CommaCategory - import FunctorCategory.FunctorCategory - import UsualCategories.One - import Data.Maybe (fromJust) - import Utils.AssociationList - - -- -------------------------------- - -- Cone related functions and types. - -- -------------------------------- - - -- | A `Cone` is a `CommaObject` in the `CommaCategory` (/D/|1_/F/). - type Cone c1 m1 o1 c2 m2 o2 = CommaObject o2 One (NaturalTransformation c1 m1 o1 c2 m2 o2) - - -- | A `ConeMorphism` is a morphism between cones. - type ConeMorphism c1 m1 o1 c2 m2 o2 = CommaMorphism o2 One m2 One (NaturalTransformation c1 m1 o1 c2 m2 o2) - - -- | `ConeCategory` is the type of the cone category, it is a `CommaCategory` (/D/|1_/F/). - type ConeCategory c1 m1 o1 c2 m2 o2 = CommaCategory c2 m2 o2 One One One (FunctorCategory c1 m1 o1 c2 m2 o2) (NaturalTransformation c1 m1 o1 c2 m2 o2) (Diagram c1 m1 o1 c2 m2 o2) - - -- | Returns the `apex` of a `Cone`. - apex :: Cone c1 m1 o1 c2 m2 o2 -> o2 - apex = indexSrc - - -- | Returns the `Cone` as a `NaturalTransformation`. - -- - -- prop> naturalTransformationToCone . coneToNaturalTransformation = id - -- prop> coneToNaturalTransformation . naturalTransformationToCone = id - coneToNaturalTransformation :: Cone c1 m1 o1 c2 m2 o2 -> NaturalTransformation c1 m1 o1 c2 m2 o2 - coneToNaturalTransformation = arrow - - -- | Returns a `NaturalTransformation` as a `Cone`. - -- - -- prop> naturalTransformationToCone . coneToNaturalTransformation = id - -- prop> coneToNaturalTransformation . naturalTransformationToCone = id - naturalTransformationToCone :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1 - ,FiniteCategory c2 m2 o2, Morphism m2 o2) => - NaturalTransformation c1 m1 o1 c2 m2 o2 -> Cone c1 m1 o1 c2 m2 o2 - naturalTransformationToCone nt@NaturalTransformation{srcNT=s,tgtNT=t,component=compo} - | null (ob (src s)) = error "Cone of a diagram with empty index category" - | otherwise = CommaObject{indexSrc=(omap s) !-! (head (ob (src s))),indexTgt=One,arrow=nt} - - -- | Constructs the category of cones of a diagram. Objects of the category are `CommaObject` objects with the `apex` of the cone in the `indexSrc` field and the natural transformation in the `arrow` field. - mkConeCategory :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, - FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => - Diagram c1 m1 o1 c2 m2 o2 -> ConeCategory c1 m1 o1 c2 m2 o2 - mkConeCategory diag@Diagram{src=s,tgt=t,omap=om,mmap=fm} = CommaCategory {leftDiag = diagonalFunct - , rightDiag = fromJust $ mkSelect1 (tgt diagonalFunct) diag} - where - diagonalFunct = mkDiagonalFunctor s t - - -- | Returns all cones of a given apex. - conesOfApex :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, - FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => - Diagram c1 m1 o1 c2 m2 o2 -> o2 -> [Cone c1 m1 o1 c2 m2 o2] - conesOfApex diag apx - | not $ elem apx (ob (tgt diag)) = error "Trying to construct cones from an apex not in the target category." - | otherwise = naturalTransformationToCone <$> ar functCat constDiag diag - where - functCat = FunctorCategory (src diag) (tgt diag) - Just constDiag = mkConstantDiagram (src diag) (tgt diag) apx - - -- | Returns limits of a diagram (terminal cones). - limits :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, - FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => - Diagram c1 m1 o1 c2 m2 o2 -> [Cone c1 m1 o1 c2 m2 o2] - limits = terminalObjects.mkConeCategory - - -- -------------------------------- - -- Cocone related functions and types. - -- -------------------------------- - - - -- | A `Cocone` is a `CommaObject` in the `CommaCategory` (1_/F/|/D/). - type Cocone c1 m1 o1 c2 m2 o2 = CommaObject One o2 (NaturalTransformation c1 m1 o1 c2 m2 o2) - - -- | A `CoconeMorphism` is a morphism between cocones. - type CoconeMorphism c1 m1 o1 c2 m2 o2 = CommaMorphism One o2 One m2 (NaturalTransformation c1 m1 o1 c2 m2 o2) - - -- | `CoconeCategory` is the type of the cocone category, it is a `CommaCategory` (1_/F/|/D/). - type CoconeCategory c1 m1 o1 c2 m2 o2 = CommaCategory One One One c2 m2 o2 (FunctorCategory c1 m1 o1 c2 m2 o2) (NaturalTransformation c1 m1 o1 c2 m2 o2) (Diagram c1 m1 o1 c2 m2 o2) - - - -- | Returns the `nadir` of a `Cocone`. - nadir :: Cocone c1 m1 o1 c2 m2 o2 -> o2 - nadir = indexTgt - - -- | Returns the `Cocone` as a `NaturalTransformation`. - coconeToNaturalTransformation :: Cocone c1 m1 o1 c2 m2 o2 -> NaturalTransformation c1 m1 o1 c2 m2 o2 - coconeToNaturalTransformation = arrow - - -- | Returns a `NaturalTransformation` as a `Cocone`. - -- - -- prop> naturalTransformationToCocone . coconeToNaturalTransformation = id - -- prop> coconeToNaturalTransformation . naturalTransformationToCocone = id - naturalTransformationToCocone :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1 - ,FiniteCategory c2 m2 o2, Morphism m2 o2) => - NaturalTransformation c1 m1 o1 c2 m2 o2 -> Cocone c1 m1 o1 c2 m2 o2 - naturalTransformationToCocone nt@NaturalTransformation{srcNT=s,tgtNT=t,component=compo} - | null (ob (src t)) = error "Diagram with empty index category" - | otherwise = CommaObject{indexSrc=One,indexTgt=(omap t) !-! (head (ob (src t))),arrow=nt} - - -- | Constructs the category of cocones of a diagram. Objects of the category are `CommaObject` objects with the nadir of the cone in the `indexTgt` field and the natural transformation in the `arrow` field. - mkCoconeCategory :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, - FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => - Diagram c1 m1 o1 c2 m2 o2 -> CoconeCategory c1 m1 o1 c2 m2 o2 - mkCoconeCategory diag@Diagram{src=s,tgt=t,omap=om,mmap=fm} = CommaCategory {leftDiag = fromJust $ mkSelect1 (tgt diagonalFunct) diag - , rightDiag = diagonalFunct} - where - diagonalFunct = mkDiagonalFunctor s t - - -- | Returns all cocones of a given nadir. - coconesOfNadir :: ( FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, - FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => - Diagram c1 m1 o1 c2 m2 o2 -> o2 -> [Cocone c1 m1 o1 c2 m2 o2] - coconesOfNadir diag nadr - | not $ elem nadr (ob (tgt diag)) = error "Trying to construct cocones to a nadir not in the target category." - | otherwise = naturalTransformationToCocone <$> ar functCat diag constDiag - where - functCat = FunctorCategory (src diag) (tgt diag) - Just constDiag = mkConstantDiagram (src diag) (tgt diag) nadr - - -- | Returns colimits of a diagram (initial cocones). - colimits :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, - FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => - Diagram c1 m1 o1 c2 m2 o2 -> [Cocone c1 m1 o1 c2 m2 o2] - colimits = initialObjects.mkCoconeCategory
− src/ConeCategory/LeftCone.hs
@@ -1,134 +0,0 @@-{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-} - -{-| Module : FiniteCategories -Description : A left cone on I is I with another object called the cone point and a single morphism from the cone point to every other object of I. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -A left cone on I is I with another object called the cone point and a single morphism from the cone point to every other object of I. - -See Category Theory for the Sciences (2014) David I. Spivak for more details. - -An usual cone on C is then a functor from a left cone on I to C. --} - -module ConeCategory.LeftCone -( - -- * Cone related functions and types. - LeftCone(..), - inclusionFunctor, - ConeCategory(..) -) -where - import FiniteCategory.FiniteCategory - import IO.PrettyPrint - import Diagram.Diagram - import FunctorCategory.FunctorCategory - import Utils.AssociationList - - -- | Object in a `LeftCone` category, either an original object or the cone point. - data LeftConeObject o = OriginalObject o - | ConePoint - deriving (Eq, Show) - - instance (PrettyPrintable o) => PrettyPrintable (LeftConeObject o) where - pprint (OriginalObject o) = pprint o - pprint ConePoint = "Left cone point" - - -- | Morphism in a `LeftCone` category, it is either an original morphism, a cone leg or the cone point identity. - data LeftConeMorphism m o = OriginalMorphism m - | ConeLeg o - | ConePointIdentity - deriving (Eq, Show) - - instance (PrettyPrintable m, PrettyPrintable o) => PrettyPrintable (LeftConeMorphism m o) where - pprint (OriginalMorphism m) = pprint m - pprint (ConeLeg o) = "Leg "++(pprint o) - pprint ConePointIdentity = "Id Cone Point" - - instance (Morphism m o, Eq o) => Morphism (LeftConeMorphism m o) (LeftConeObject o) where - (@) (OriginalMorphism g) (OriginalMorphism f) = OriginalMorphism (g @ f) - (@) (ConeLeg _) (OriginalMorphism _) = error "Cannot compose an original morphism with a cone leg." - (@) ConePointIdentity (OriginalMorphism _) = error "Cannot compose an original morphism with a cone point identity." - (@) (OriginalMorphism f) (ConeLeg o) - | (source f) == o = (ConeLeg (target f)) - | otherwise = error "Source of original morphism is not target of cone leg." - (@) (ConeLeg _) (ConeLeg _) = error "Cannot compose two cone legs." - (@) ConePointIdentity (ConeLeg _) = error "Cannot compose a cone leg with a cone point identity" - (@) (ConeLeg o) ConePointIdentity = ConeLeg o - (@) ConePointIdentity ConePointIdentity = ConePointIdentity - - - source (OriginalMorphism m) = OriginalObject (source m) - source (ConeLeg _) = ConePoint - source ConePointIdentity = ConePoint - target (OriginalMorphism m) = OriginalObject (target m) - target (ConeLeg o) = OriginalObject o - target ConePointIdentity = ConePoint - - -- | The left cone category associated to a category. - data LeftCone c m o = LeftCone c deriving (Eq, Show) - - instance (PrettyPrintable c) => PrettyPrintable (LeftCone c m o) where - pprint (LeftCone cat) = "Left cone of "++pprint cat - - instance (FiniteCategory c m o, Morphism m o) => FiniteCategory (LeftCone c m o) (LeftConeMorphism m o) (LeftConeObject o) where - ob (LeftCone cat) = ConePoint: (OriginalObject <$> (ob cat)) - - identity (LeftCone cat) (OriginalObject o) = OriginalMorphism (identity cat o) - identity (LeftCone cat) ConePoint = ConePointIdentity - - ar (LeftCone cat) (OriginalObject s) (OriginalObject t) = OriginalMorphism <$> ar cat s t - ar (LeftCone cat) (OriginalObject s) ConePoint = [] - ar (LeftCone cat) ConePoint (OriginalObject t) = [ConeLeg t] - ar (LeftCone cat) ConePoint ConePoint = [ConePointIdentity] - - instance (GeneratedFiniteCategory c m o, Morphism m o) => GeneratedFiniteCategory (LeftCone c m o) (LeftConeMorphism m o) (LeftConeObject o) where - genAr (LeftCone cat) (OriginalObject s) (OriginalObject t) = OriginalMorphism <$> genAr cat s t - genAr (LeftCone cat) (OriginalObject s) ConePoint = [] - genAr (LeftCone cat) ConePoint (OriginalObject t) = [ConeLeg t] - genAr (LeftCone cat) ConePoint ConePoint = [ConePointIdentity] - - decompose (LeftCone cat) (OriginalMorphism m) = OriginalMorphism <$> (decompose cat m) - decompose (LeftCone cat) (ConeLeg o) = [ConeLeg o] - decompose (LeftCone cat) ConePointIdentity = [ConePointIdentity] - - -- | Inclusion functor from a category to its left cone category. - inclusionFunctor :: (FiniteCategory c m o, Morphism m o) => LeftCone c m o -> Diagram c m o (LeftCone c m o) (LeftConeMorphism m o) (LeftConeObject o) - inclusionFunctor lc@(LeftCone cat) = Diagram{ src=cat - , tgt=lc - , omap=functToAssocList OriginalObject (ob cat) - , mmap=functToAssocList OriginalMorphism (arrows cat) - } - - -- | The category of cones defined according to the left cone definition. - -- - -- It is less efficient than the `ConeCategory.ConeCategory` implementation. This is only defined for pedagogical purposes. - data ConeCategory c1 m1 o1 c2 m2 o2 = ConeCategory (Diagram c1 m1 o1 c2 m2 o2) deriving (Eq, Show) - - instance (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1 - , FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => FiniteCategory - (ConeCategory c1 m1 o1 c2 m2 o2) - (NaturalTransformation (LeftCone c1 m1 o1) (LeftConeMorphism m1 o1) (LeftConeObject o1) c2 m2 o2) - (Diagram (LeftCone c1 m1 o1) (LeftConeMorphism m1 o1) (LeftConeObject o1) c2 m2 o2) where - ob (ConeCategory diag) = [s | s <- ob FunctorCategory{sourceCat = lcone, targetCat = tgt diag}, s `composeDiag` (inclusionFunctor lcone) == diag] - where lcone = LeftCone (src diag) - - identity (ConeCategory diag) cone = identity FunctorCategory{sourceCat = LeftCone (src diag), targetCat = tgt diag} cone - - ar (ConeCategory diag) cone1 cone2 = [nt | nt <- ar functCat cone1 cone2, preWhiskering nt (inclusionFunctor lcone) == (identity functCatDiag diag)] - where - lcone = LeftCone (src diag) - functCat = FunctorCategory{sourceCat = lcone, targetCat = tgt diag} - functCatDiag = FunctorCategory{sourceCat = src diag, targetCat = tgt diag} - - instance (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1 - , FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => GeneratedFiniteCategory - (ConeCategory c1 m1 o1 c2 m2 o2) - (NaturalTransformation (LeftCone c1 m1 o1) (LeftConeMorphism m1 o1) (LeftConeObject o1) c2 m2 o2) - (Diagram (LeftCone c1 m1 o1) (LeftConeMorphism m1 o1) (LeftConeObject o1) c2 m2 o2) where - genAr (ConeCategory diag) cone1 cone2 = genAr FunctorCategory{sourceCat = LeftCone (src diag), targetCat = tgt diag} cone1 cone2 - decompose (ConeCategory diag) cone = decompose FunctorCategory{sourceCat = LeftCone (src diag), targetCat = tgt diag} cone
− src/Config/Config.hs
@@ -1,18 +0,0 @@-{-| Module : FiniteCategories -Description : Arbitrary values you can change. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -Arbitrary values you can change. --} - -module Config.Config -( - maximumLoopDepth -) where - -- | The maximum number of loops in a /CompositionGraph/ before it throws an error. - maximumLoopDepth = 10 -
− src/Currying/Currying.hs
@@ -1,78 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses #-} - -{-| Module : FiniteCategories -Description : Currying a functor @(A x B) -> C@ yields a functor @A -> [B,C]@. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -Currying a functor @(A x B) -> C@ yields a functor @A -> [B,C]@. --} -module Currying.Currying -( -curryDiagram, -uncurryDiagram, -switchArg, -) -where - import FiniteCategory.FiniteCategory - import ProductCategory.ProductCategory - import FunctorCategory.FunctorCategory - import Diagram.Diagram - import Utils.AssociationList - - -- | Curry a functor @D : A x B -> C@ into a functor @D' : A -> [B,C]@. - curryDiagram :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, - FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2, - FiniteCategory c3 m3 o3, Morphism m3 o3) => - Diagram (ProductCategory c1 m1 o1 c2 m2 o2) (ProductMorphism m1 o1 m2 o2) (ProductObject o1 o2) c3 m3 o3 -> Diagram c1 m1 o1 (FunctorCategory c2 m2 o2 c3 m3 o3) (NaturalTransformation c2 m2 o2 c3 m3 o3) (Diagram c2 m2 o2 c3 m3 o3) - curryDiagram diag = Diagram{ - src = (firstCategory (src diag)), - tgt = FunctorCategory{ sourceCat = (secondCategory (src diag)), targetCat = (tgt diag)}, - omap = [(a, diagFromA a) | a <- ob (firstCategory (src diag))], - mmap = [(f, natFromF f) | f <- arrows (firstCategory (src diag))] - } - where - diagFromA a = Diagram{ - src = (secondCategory (src diag)), - tgt = (tgt diag), - omap = [ (b, (omap diag) !-! (ProductObject a b) ) | b <- ob (secondCategory (src diag))], - mmap = [ (g, (mmap diag) !-! (ProductMorphism (identity (firstCategory (src diag)) a) g) ) | g <- arrows (secondCategory (src diag))] - } - natFromF f = NaturalTransformation{ - srcNT = (diagFromA (source f)), - tgtNT = (diagFromA (target f)), - component = (\b -> (mmap diag) !-! (ProductMorphism f (identity (secondCategory (src diag)) b))) - } - - -- | Uncurry a functor @D : A -> [B,C]@ into a functor @D' : A x B -> C@. - uncurryDiagram :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, - FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2, - FiniteCategory c3 m3 o3, Morphism m3 o3) => - Diagram c1 m1 o1 (FunctorCategory c2 m2 o2 c3 m3 o3) (NaturalTransformation c2 m2 o2 c3 m3 o3) (Diagram c2 m2 o2 c3 m3 o3) -> Diagram (ProductCategory c1 m1 o1 c2 m2 o2) (ProductMorphism m1 o1 m2 o2) (ProductObject o1 o2) c3 m3 o3 - uncurryDiagram diag = Diagram{ src = ProductCategory (src diag) (sourceCat.tgt $ diag), - tgt = (targetCat.tgt $ diag), - omap = [(ProductObject a b, (omap ((omap diag) !-! a)) !-! b ) | a <- (ob (src diag)), b <- (ob (sourceCat.tgt $ diag))], - mmap = [(ProductMorphism f g, ((mmap ((omap diag) !-! (target f))) !-! g) @ ((component ((mmap diag) !-! f)) (source g)) ) | f <- (arrows (src diag)), g <- (arrows (sourceCat.tgt $ diag))] - } - - -- | Switches argument of a diagram @D : A x B -> C@ to create a diagram @D' : B x A -> C@. - switch :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, - FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2, - FiniteCategory c3 m3 o3, Morphism m3 o3) => - Diagram (ProductCategory c1 m1 o1 c2 m2 o2) (ProductMorphism m1 o1 m2 o2) (ProductObject o1 o2) c3 m3 o3 -> Diagram (ProductCategory c2 m2 o2 c1 m1 o1) (ProductMorphism m2 o2 m1 o1) (ProductObject o2 o1) c3 m3 o3 - switch diag = Diagram { - src = (ProductCategory (secondCategory.src $ diag) (firstCategory.src $ diag)), - tgt = (tgt diag), - omap = [((ProductObject b a), (omap diag) !-! o) | o@(ProductObject a b) <- (ob.src $ diag)], - mmap = [((ProductMorphism b a), (mmap diag) !-! o) | o@(ProductMorphism a b) <- (arrows.src $ diag)] - } - - -- | Switches argument of a curried diagram. - switchArg :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, - FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2, - FiniteCategory c3 m3 o3, Morphism m3 o3) => - Diagram c1 m1 o1 (FunctorCategory c2 m2 o2 c3 m3 o3) (NaturalTransformation c2 m2 o2 c3 m3 o3) (Diagram c2 m2 o2 c3 m3 o3) -> Diagram c2 m2 o2 (FunctorCategory c1 m1 o1 c3 m3 o3) (NaturalTransformation c1 m1 o1 c3 m3 o3) (Diagram c1 m1 o1 c3 m3 o3) - switchArg = curryDiagram.switch.uncurryDiagram
− src/DiagonalFunctor/DiagonalFunctor.hs
@@ -1,36 +0,0 @@-{-| Module : FiniteCategories -Description : Diagonal functor of an index category. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -Let /J/ and /C/ be two categories, we consider the functor category /C/^/J/. -The diagonal functor /D/ : /C/ -> /C/^/J/ maps each object /x/ of /C/ to the constant diagram /D_x/ from /J/ to /C/. -It maps each morphism to the natural transformation between the two constant diagrams associated to the source and the target of the morphism. --} - -module DiagonalFunctor.DiagonalFunctor -( -mkDiagonalFunctor -) -where - import Diagram.Diagram - import FiniteCategory.FiniteCategory - import FunctorCategory.FunctorCategory - import Data.Maybe (fromJust) - import Utils.AssociationList - - -- | Given two categories /J/ and /C/, returns the diagonal functor /C/ -> /C/^/J/. - mkDiagonalFunctor :: (FiniteCategory c1 m1 o1, Morphism m1 o1, - FiniteCategory c2 m2 o2, Morphism m2 o2, Eq o2) => - c1 -- ^ /J/ - -> c2 -- ^ /C/ - -> Diagram c2 m2 o2 (FunctorCategory c1 m1 o1 c2 m2 o2) (NaturalTransformation c1 m1 o1 c2 m2 o2) (Diagram c1 m1 o1 c2 m2 o2) -- ^ /D/ : /C/ -> /C/^/J/ - mkDiagonalFunctor j c = Diagram{src=c - , tgt=FunctorCategory{sourceCat=j, targetCat=c} - , omap=functToAssocList (\o -> constDiag o) (ob c) - , mmap=functToAssocList (\f -> NaturalTransformation{srcNT=constDiag (source f),tgtNT=constDiag (target f),component=(\x->f)}) (arrows c)} - where - constDiag obj = fromJust $ mkConstantDiagram j c obj
− src/Diagram/Conversion.hs
@@ -1,61 +0,0 @@-{-| Module : FiniteCategories -Description : Functions to convert all functor types. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -Functions to convert all functor types. --} - -module Diagram.Conversion -( - -- * Diagram to something - diagramToFinFunctor, - diagramToPartialFunctor, - -- * FinFunctor to something - finFunctorToDiagram, - finFunctorToPartialFunctor, - -- * PartialFunctor to something - partialFunctorToDiagram, - partialFunctorToFinFunctor -) -where - import FiniteCategory.FiniteCategory - import Diagram.Diagram - import Cat.FinCat - import Cat.PartialFinCat - import Utils.SetList - import Utils.AssociationList - - -- | Converts a homogeneous `Diagram` to a `FinFunctor`. - diagramToFinFunctor :: (FiniteCategory c m o, Morphism m o) => Diagram c m o c m o -> FinFunctor c m o - diagramToFinFunctor Diagram{src=s,tgt=t,omap=om,mmap=fm} = FinFunctor{srcF=s,tgtF=t,omapF=om,mmapF=fm} - - -- | Converts a homogeneous `Diagram` to a `PartialFunctor` - diagramToPartialFunctor :: (FiniteCategory c m o, Morphism m o) => Diagram c m o c m o -> PartialFunctor c m o - diagramToPartialFunctor Diagram{src=s,tgt=t,omap=om,mmap=fm} = PartialFunctor{srcPF=s,tgtPF=t,omapPF=om,mmapPF=fm} - - -- | Converts a `FinFunctor` into a `Diagram`. - -- - -- A `FinFunctor` is a morphism of the `FinCat` category, it is a homogeneous FinFunctor. This functions casts it to a heterogeneous FinFunctor (i.e. a `Diagram`). - finFunctorToDiagram :: FinFunctor c m o -> Diagram c m o c m o - finFunctorToDiagram FinFunctor{srcF=s,tgtF=t,omapF=om,mmapF=fm} = Diagram {src=s,tgt=t,omap=om,mmap=fm} - - -- | Converts a total functor to a partial functor. - finFunctorToPartialFunctor :: (FiniteCategory c m o, Morphism m o) => (FinFunctor c m o) -> (PartialFunctor c m o) - finFunctorToPartialFunctor FinFunctor{srcF=s,tgtF=t,omapF=om,mmapF=fm} = PartialFunctor{srcPF=s,tgtPF=t,omapPF=om,mmapPF=fm} - - -- | Try to convert a `PartialFunctor` into a `Diagram` if it can (if it is total). - partialFunctorToDiagram :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o, Show o, Show m) => PartialFunctor c m o -> Maybe (Diagram c m o c m o) - partialFunctorToDiagram x = finFunctorToDiagram <$> partialFunctorToFinFunctor x - - -- | Try to convert a partial functor to a total functor if it is possible. - partialFunctorToFinFunctor :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o, Show o, Show m) => (PartialFunctor c m o) -> Maybe (FinFunctor c m o) - partialFunctorToFinFunctor PartialFunctor{srcPF=s,tgtPF=t,omapPF=om,mmapPF=fm} - | not ((keys om) `doubleInclusion` (ob s)) = error $ (show $ ob s) ++"," ++ (show $ keys om)--Nothing - | not ((keys fm) `doubleInclusion` (arrows s)) = error $ (show $ arrows s) ++"," ++ (show $ keys fm)--Nothing - | otherwise = Just FinFunctor{srcF=s,tgtF=t,omapF=om,mmapF=fm} - -
− src/Diagram/Diagram.hs
@@ -1,229 +0,0 @@-{-| Module : FiniteCategories -Description : Functions to create usual and arbitrary diagrams. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -A diagram is a heterogeneous FinFunctor, it is a shift of perspective : we view the functor not as a morphism of categories but as a selection in a category. - -By heterogeneous, we mean that the type of the source category may be different from the target category. - -To convert a `Diagram` into any other kind of functor, see @Diagram.Conversion@. - -To enumerate all diagrams between two categories, see the `ob` function of /FunctorCategory/. --} - -module Diagram.Diagram -( - -- * Diagram typeclass and useful functions - Diagram(..), - checkFunctoriality, - completeMmap, - composeDiag, - objectImage, - -- * Constructors of diagrams - mkDiagram, - mkIdentityDiagram, - mkConstantDiagram, - mkDiscreteDiagram, - mkSelect0, - mkSelect1, - mkSelect2, - mkSelect3, - mkTriangle, - mkParallel, - mkV, - mkHat, -) -where - import Prelude hiding ((@)) - import FiniteCategory.FiniteCategory - import Cat.FinCat - import Cat.PartialFinCat - import UsualCategories.DiscreteCategory - import UsualCategories.Zero - import UsualCategories.One - import qualified UsualCategories.Two as Two - import qualified UsualCategories.Three as Three - import qualified UsualCategories.Parallel as Par - import qualified UsualCategories.V as V - import qualified UsualCategories.Hat as Hat - import Data.List (intercalate, nub) - import Utils.SetList - import Utils.AssociationList - import IO.PrettyPrint - import IO.Show - - -- | A diagram is a heterogeneous FinFunctor /F/, it is a shift of perspective : we view the FinFunctor not as a morphism of categories but as a selection in a category. It must obey the following rules : - -- - -- prop> F (src f) = src (F f) - -- prop> F (tgt f) = tgt (F f) - -- prop> F (f @ g) = F(f) @ F(g) - -- prop> F (identity a) = identity (F a) - -- - -- Unlike /FinFunctor/, a `Diagram` can have a source category and a target category with different types. - -- - -- Using constructor functions `mkDiagram`, `mkConstantDiagram`, `mkDiscreteDiagram`, `mkSelect0`, `mkSelect1`, `mkSelect2`, `mkSelect3`, `mkTriangle` and `mkParallel` - -- is the safe way to instantiate a `Diagram` (FinFunctoriality is checked during construction). - -- - -- Therefore, if you want to construct an arbitrary diagram, use the constructor function `mkDiagram` unless it is too long to check FinFunctoriality in which case - -- you should use the `Diagram` constructor. It is then your responsability to ensure the FinFunctoriality property is verified. - data Diagram c1 m1 o1 c2 m2 o2 = Diagram {src :: c1 -- ^ The source category of the `Diagram` - , tgt :: c2 -- ^ The target category of the `Diagram` - , omap :: AssociationList o1 o2 -- ^ The object map - , mmap :: AssociationList m1 m2} -- ^ The morphism map - deriving (Eq, Show) - - -- | Checks wether the properties of a Diagram are respected. Returns True if the diagram is well formed, else False. - checkFunctoriality :: (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 -> Bool - checkFunctoriality Diagram{src=s,tgt=t,omap=om,mmap=fm} - | not (foldr (&&) True imIdNotId) = False - | not (foldr (&&) True errFunct) = False - | otherwise = True - where - imIdNotId = [fm !-! (identity s a) == identity t (om !-! a) | a <- ob s] - errFunct = [fm !-! (g @ f) == (fm !-! g) @ (fm !-! f) | f <- (arrows s), g <- (arFrom s (target f))] - - instance (FiniteCategory c1 m1 o1, Morphism m1 o1, PrettyPrintable m1, PrettyPrintable o1, Eq m1, Eq o1, PrettyPrintable c1, - FiniteCategory c2 m2 o2, Morphism m2 o2, PrettyPrintable m2, PrettyPrintable o2, PrettyPrintable c2) => - PrettyPrintable (Diagram c1 m1 o1 c2 m2 o2) where - pprint Diagram{src=s,tgt=t,omap=om,mmap=fm} = "Diagram "++pprint s++" -> "++pprint t++"\n"++pprint om++"\n"++pprint fm - - -- | Constructor of an arbitrary `Diagram` that checks functoriality. - -- - -- Use the `Diagram` constructor if the functoriality check is too slow. It is then your responsability to ensure the functoriality property is verified. - mkDiagram :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, - FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2) => - c1 -- ^ The source category of the diagram. - -> c2 -- ^ The target category of the diagram. - -> AssociationList o1 o2 -- ^ The object map of the diagram. - -> AssociationList m1 m2 -- ^ The morphism map of the diagram. - -> Maybe (Diagram c1 m1 o1 c2 m2 o2) -- ^ The constructor returns Nothing if the FinFunctoriality check failed. - mkDiagram c1 c2 om fm = if checkFunctoriality diag then Just diag else Nothing - where diag = Diagram {src=c1, tgt=c2, omap=om, mmap=fm} - - -- | Completes the function map `mmap` of a diagram so that you do not have to specify images of identites and composite arrows. - completeMmap :: (GeneratedFiniteCategory c1 m1 o1, Morphism m1 o1, Eq o1, Eq m1, - FiniteCategory c2 m2 o2, Morphism m2 o2, Eq o2, Eq m2) => - c1 -- ^ The source category, it must be a generated category. - -> c2 -- ^ The target category. - -> AssociationList o1 o2 -- ^ The omap. - -> AssociationList m1 m2 -- ^ The mmap to complete. - -> AssociationList m1 m2 -- ^ The completed mmap. - completeMmap c1 c2 om fm = nub fm2 - where - fm1 = [(identity c1 o, identity c2 (om !-! o)) | o <- ob c1]++fm - fm2 = [(a,compose $ (fm1 !-!) <$> decompose c1 a) | a <- arrows c1]++fm1 - - -- | Compose two diagrams. - composeDiag :: (FiniteCategory c1 m1 o1, Morphism m1 o1 - ,FiniteCategory c2 m2 o2, Morphism m2 o2 - ,FiniteCategory c3 m3 o3, Morphism m3 o3 - ,Eq m1, Eq o1, Eq m2, Eq o2) => - Diagram c2 m2 o2 c3 m3 o3 -> Diagram c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 c3 m3 o3 - diag2 `composeDiag` diag1 = Diagram {src=(src diag1), tgt=(tgt diag2), omap=((omap diag2)!-.(omap diag1)), mmap=((mmap diag2)!-.(mmap diag1))} - - -- | Returns the objects image of the diagram. - objectImage :: (FiniteCategory c1 m1 o1, Morphism m1 o1 - ,FiniteCategory c2 m2 o2, Morphism m2 o2) => - Diagram c1 m1 o1 c2 m2 o2 -> [o2] - objectImage diag = snd <$> (omap diag) - - -- | Constructs a diagram which maps a category to itself to that each object is mapped to itself and each morphism is mapped to itself too. - mkIdentityDiagram :: (FiniteCategory c m o, Morphism m o) => c -> (Diagram c m o c m o) - mkIdentityDiagram c = Diagram {src=c, tgt=c, omap=functToAssocList id (ob c),mmap=functToAssocList id (arrows c)} - - -- | Constructs a diagram where every object is mapped to a single object and every morphism is mapped to the identity of this single object. - mkConstantDiagram :: (FiniteCategory c1 m1 o1, Morphism m1 o1, - FiniteCategory c2 m2 o2, Morphism m2 o2, Eq o2) => c1 -> c2 -> o2 -> Maybe (Diagram c1 m1 o1 c2 m2 o2) - mkConstantDiagram c1 c2 o2 - | elem o2 (ob c2) = Just Diagram {src=c1, tgt=c2, omap=functToAssocList (\x -> o2) (ob c1),mmap=functToAssocList (\x -> (identity c2 o2)) (arrows c1)} - | otherwise = Nothing - - -- | Constructs a diagram that selects a list of objects of a category. - mkDiscreteDiagram :: (FiniteCategory c m o, Morphism m o, Eq o) => - c -> [o] -> Maybe (Diagram (DiscreteCategory o) (DiscreteIdentity o) (DiscreteObject o) c m o) - mkDiscreteDiagram c objs - | objs `isIncludedIn` (ob c) = Just Diagram {src=DiscreteCategory objs, tgt=c, omap=functToAssocList (\(DiscreteObject o) -> o) (ob (DiscreteCategory objs)),mmap=functToAssocList (\(DiscreteIdentity o) -> (identity c o)) (arrows (DiscreteCategory objs))} - | otherwise = Nothing - - -- | Constructs a diagram that selects no object and no morphism. - mkSelect0 :: (FiniteCategory c m o, Morphism m o) => c -> Diagram Zero Zero Zero c m o - mkSelect0 c = Diagram {src=Zero, tgt=c, omap=[],mmap=[]} - - -- | Constructs a diagram that selects a single object and its identity. - mkSelect1 :: (FiniteCategory c m o, Morphism m o, Eq o) => c -> o -> Maybe (Diagram One One One c m o) - mkSelect1 c o - | elem o (ob c) = Just Diagram {src=One, tgt=c, omap=[(One,o)],mmap=[(One,(identity c o))]} - | otherwise = Nothing - - -- | Constructs a diagram that selects a single arrow. - mkSelect2 :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> m -> Maybe (Diagram Two.Two Two.TwoAr Two.TwoOb c m o) - mkSelect2 c m - | condition = Just Diagram {src=Two.Two, tgt=c, omap=om,mmap=(completeMmap Two.Two c om [(Two.F,m)])} - | otherwise = Nothing - where - condition = elem (source m) (ob c) && elem (target m) (ob c) && elem m (ar c (source m) (target m)) - om = [(Two.A,source m),(Two.B,target m)] - - -- | Constructs a diagram that selects a triangle. - -- - -- > B <-f- A - -- > | / - -- > g g\@f - -- > | / - -- > v v - -- > C - mkSelect3 :: (FiniteCategory c m o, Morphism m o, Eq o, Eq m) => c -- ^ The target category. - -> m -- ^ /f/ - -> m -- ^ /g/ - -> Maybe (Diagram Three.Three Three.ThreeAr Three.ThreeOb c m o) - mkSelect3 c f g - | condition = Just Diagram {src=Three.Three, tgt=c, omap=om,mmap=(completeMmap Three.Three c om [(Three.F,f),(Three.G,g)])} - | otherwise = Nothing - where - condition = obInCat && arInCat && (source g) == (target f) - obInCat = elem (source f) (ob c) && elem (target f) (ob c) && elem (target g) (ob c) - arInCat = elem f (ar c (source f) (target f)) && elem g (ar c (source g) (target g)) - om = [(Three.A,source f),(Three.B,target f),(Three.C,target g)] - - -- | Constructs a diagram that selects a triangle. (Alias for `mkSelect3`). - mkTriangle :: (FiniteCategory c m o, Morphism m o, Eq o, Eq m) => c -> m -> m -> Maybe (Diagram Three.Three Three.ThreeAr Three.ThreeOb c m o) - mkTriangle = mkSelect3 - - -- | Constructs a diagram that selects two parallel arrows. - mkParallel :: (FiniteCategory c m o, Morphism m o, Eq o, Eq m) => c -> m -> m -> Maybe (Diagram Par.Parallel Par.ParallelAr Par.ParallelOb c m o) - mkParallel c f g - | condition = Just Diagram {src=Par.Parallel, tgt=c, omap=om,mmap=(completeMmap Par.Parallel c om [(Par.F,f),(Par.G,g)])} - | otherwise = Nothing - where - condition = obInCat && arInCat && (source f) == (source g) && (target f) == (target g) - obInCat = elem (source f) (ob c) && elem (target f) (ob c) - arInCat = elem f (ar c (source f) (target f)) && elem g (ar c (source g) (target g)) - om = [(Par.A,source f), (Par.B, target f)] - - -- | Constructs a diagram that selects a V. - mkV :: (FiniteCategory c m o, Morphism m o, Eq o, Eq m) => c -> m -> m -> Maybe (Diagram V.V V.VAr V.VOb c m o) - mkV c f g - | condition = Just Diagram {src=V.V, tgt=c, omap=om,mmap=(completeMmap V.V c om [(V.F,f),(V.G,g)])} - | otherwise = Nothing - where - condition = obInCat && arInCat && (target f) == (target g) - obInCat = elem (source f) (ob c) && elem (target f) (ob c) - arInCat = elem f (ar c (source f) (target f)) && elem g (ar c (source g) (target g)) - om = [(V.A,source f), (V.B, source g), (V.C, target g)] - - -- | Constructs a diagram that selects a Hat. - mkHat :: (FiniteCategory c m o, Morphism m o, Eq o, Eq m) => c -> m -> m -> Maybe (Diagram Hat.Hat Hat.HatAr Hat.HatOb c m o) - mkHat c f g - | condition = Just Diagram {src=Hat.Hat, tgt=c, omap=om,mmap=(completeMmap Hat.Hat c om [(Hat.F,f),(Hat.G,g)])} - | otherwise = Nothing - where - condition = obInCat && arInCat && (source f) == (source g) - obInCat = elem (source f) (ob c) && elem (target f) (ob c) - arInCat = elem f (ar c (source f) (target f)) && elem g (ar c (source g) (target g)) - om = [(Hat.A,source f), (Hat.B, target f), (Hat.C, target g)]
− src/ExportGraphViz/ExportGraphViz.hs
@@ -1,400 +0,0 @@-{-| Module : FiniteCategories -Description : Visualize categories with GraphViz. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -This module is a way of visualizing categories with GraphViz. - -See Example.ExampleCompositionGraph or Example.ExampleSet. --} - -module ExportGraphViz.ExportGraphViz -( - -- * Visualize categories - categoryToGraph, - catToDot, - catToPdf, - genToDot, - genToPdf, - -- * Visualize diagrams - diagToDotCluster, - diagToPdfCluster, - diagToDot, - diagToPdf, - diagToDot2, - diagToPdf2, - -- * Visualize natural transformations - natToDot, - natToPdf, - -- * Visualize cones - coneToDot, - coneToPdf -) -where - import FiniteCategory.FiniteCategory - import Diagram.Diagram - import FunctorCategory.FunctorCategory - import Utils.AssociationList - import ConeCategory.ConeCategory - import Subcategories.FreeSubcategory - - import Data.List (elemIndex,intercalate) - import qualified Data.Text.Lazy as L (pack) - import qualified Data.Text.Lazy.IO as IO (putStrLn) - import IO.CreateAndWriteFile (createAndWriteFile) - import IO.PrettyPrint - import Data.Graph.Inductive.Graph (mkGraph, Node, Edge, LNode, LEdge) - import Data.Graph.Inductive.PatriciaTree (Gr) - import Data.GraphViz (graphToDot, nonClusteredParams, fmtNode, fmtEdge, GraphvizParams(..), NodeCluster(..), blankParams,GraphID( Num ), Number(..)) - import Data.GraphViz.Attributes.Complete (Label(StrLabel), Attribute(Label)) - import Data.Word (Word8) - import Data.GraphViz.Attributes (X11Color(..), color) - import Data.GraphViz.Printing (renderDot, toDot) - import Data.Maybe - - import System.Process (callCommand) - - - objToNode :: (Eq o, FiniteCategory c m o) => c -> o -> Node - objToNode c o - | index == Nothing = error("Call objToNod on an object not in the category.") - | otherwise = i - where - Just i = index - index = elemIndex o (ob c) - - objToLNode :: (Eq o, PrettyPrintable o, FiniteCategory c m o) => c -> o -> LNode String - objToLNode c o = (objToNode c o, pprint o) - - arToEdge :: (Eq o, Morphism m o, FiniteCategory c m o) => c -> m -> Edge - arToEdge c m = ((objToNode c). source $ m, (objToNode c). target $ m) - - arToLEdge :: (Eq o, PrettyPrintable o, PrettyPrintable m, Morphism m o, FiniteCategory c m o) => c -> m -> LEdge String - arToLEdge c m = ((objToNode c). source $ m, (objToNode c). target $ m, pprint m) - - -- | Transforms a category to representation as an inductive graph. - categoryToGraph :: (Eq o, PrettyPrintable o, PrettyPrintable m, Morphism m o, FiniteCategory c m o) => c -> Gr String String - categoryToGraph c = mkGraph (objToLNode c <$> (ob c)) (arToLEdge c <$> (arrows c)) - - dotToPdf :: IO () -> String -> IO () - dotToPdf dot path = dot >> callCommand ("dot "++path++" -o "++path++".pdf -T pdf") - - -- | Export a category with GraphViz. If the category is too large, use `genToDot` instead. - -- - -- The black arrows are generating arrows, grey one are generated arrows. - catToDot :: (Eq o, PrettyPrintable o, PrettyPrintable m, Morphism m o, GeneratedFiniteCategory c m o) => c -> String -> IO () - catToDot c path = createAndWriteFile path $ renderDot $ toDot dot_file where - dot_file = graphToDot nonClusteredParams { fmtNode= \(n,label)-> [Label (StrLabel (L.pack label))], - fmtEdge= \(n1,n2,label)-> [Label (StrLabel (L.pack label)), - if elem label generatorsLabels then color Black else color Gray80]} (categoryToGraph c) - generators = genArrows c - generatorsLabels = pprint <$> generators - - -- | Export a category with GraphViz. If the category is too large, use `genToPdf` instead. - -- - -- The black arrows are generating arrows, grey one are generated arrows. - catToPdf :: (Eq o, PrettyPrintable o, PrettyPrintable m, Morphism m o, GeneratedFiniteCategory c m o) => c -> String -> IO () - catToPdf c path = dotToPdf (catToDot c path) path - - -- | Transforms a category into an inductive graph. - categoryToGeneratorGraph :: (Eq o, PrettyPrintable o, PrettyPrintable m, Morphism m o, GeneratedFiniteCategory c m o) => c -> Gr String String - categoryToGeneratorGraph c = mkGraph (objToLNode c <$> (ob c)) (arToLEdge c <$> (genArrows c)) - - -- | Export the generator of a category with GraphViz. Use this when the category is to large to be fully exported. - genToDot :: (Eq o, PrettyPrintable o, PrettyPrintable m, Morphism m o, GeneratedFiniteCategory c m o) => c -> String -> IO () - genToDot c path = createAndWriteFile path $ renderDot $ toDot dot_file where - dot_file = graphToDot nonClusteredParams { fmtNode= \(n,label)-> [Label (StrLabel (L.pack label))], - fmtEdge= \(n1,n2,label)-> [Label (StrLabel (L.pack label))]} (categoryToGeneratorGraph c) - - -- | Export the generator of a category with GraphViz. Use this when the category is to large to be fully exported. - genToPdf :: (Eq o, PrettyPrintable o, PrettyPrintable m, Morphism m o, GeneratedFiniteCategory c m o) => c -> String -> IO () - genToPdf c path = dotToPdf (genToDot c path) path - - -- __________________________________ - -- __________________________________ - -- - -- Diagram representation with cluster of objects mapped together - -- __________________________________ - -- __________________________________ - - - - -- | If the nodeif pair, then it is part of the source category, else it is part of the target category. - diagObjToNodeCluster :: (Eq o, FiniteCategory c m o) => c -> Bool -> o -> Node - diagObjToNodeCluster c b o - | index == Nothing = error("Call diagObjToNod on an object not in the category.") - | otherwise = if b then 2*i else 2*i+1 - where - Just i = index - index = elemIndex o (ob c) - - diagObjToLNodeCluster :: (Eq o, PrettyPrintable o, FiniteCategory c m o) => c -> Bool -> o -> LNode String - diagObjToLNodeCluster c b o = (diagObjToNodeCluster c b o, pprint o) - - diagArToEdgeCluster :: (Eq o, Morphism m o, FiniteCategory c m o) => c -> Bool -> m -> Edge - diagArToEdgeCluster c b m = ((diagObjToNodeCluster c b). source $ m, (diagObjToNodeCluster c b). target $ m) - - diagArToLEdgeCluster :: (Eq o, PrettyPrintable o, PrettyPrintable m, Morphism m o, FiniteCategory c m o) => c -> Bool -> m -> LEdge String - diagArToLEdgeCluster c b m = ((diagObjToNodeCluster c b). source $ m, (diagObjToNodeCluster c b). target $ m, pprint m) - - diagToGraphCluster :: (Eq c1, Eq o1, PrettyPrintable o1, PrettyPrintable m1, Morphism m1 o1, GeneratedFiniteCategory c1 m1 o1, - Eq c2, Eq o2, PrettyPrintable o2, PrettyPrintable m2, Morphism m2 o2, GeneratedFiniteCategory c2 m2 o2) => - Diagram c1 m1 o1 c2 m2 o2 -> Gr String String - diagToGraphCluster f = mkGraph ((diagObjToLNodeCluster (src f) True <$> (ob (src f)))++(diagObjToLNodeCluster (tgt f) False <$> (ob (tgt f)))) ((diagArToLEdgeCluster (src f) True <$> (genArrows (src f)))++(diagArToLEdgeCluster (tgt f) False <$> (genArrows (tgt f)))) - - -- | Export a functor with GraphViz such that the source category is in green, the target in blue, the objects mapped together are in the same cluster. - diagToDotCluster :: (Eq c1, Eq o1, PrettyPrintable o1, PrettyPrintable m1, Morphism m1 o1, GeneratedFiniteCategory c1 m1 o1, - Eq c2, Eq o2, PrettyPrintable o2, PrettyPrintable m2, Morphism m2 o2, GeneratedFiniteCategory c2 m2 o2) => - Diagram c1 m1 o1 c2 m2 o2 -> String -> IO () - diagToDotCluster f@Diagram{src=s,tgt=t,omap=om,mmap=fm} path = createAndWriteFile path $ renderDot $ toDot dot_file where - dot_file = graphToDot Params { - isDirected = True - ,globalAttributes = [] - ,clusterBy = (\(n,nl) -> if (n `mod` 2) == 0 then (C ((fromJust (elemIndex (om !-! ((ob s) !! (n `div` 2))) (ob t)))) $ N (n,nl)) else (C (fromJust (elemIndex ((ob t) !! (n `div` 2)) (ob t))) $ N (n,nl))) - ,isDotCluster = const True - ,clusterID = Num . Int - ,fmtCluster = const [] - ,fmtNode = \(n,label)-> [Label (StrLabel (L.pack label)), if (n `mod` 2) == 0 then color Green else color Blue] - ,fmtEdge= \(n1,n2,label)-> [Label (StrLabel (L.pack label))] - } (diagToGraphCluster f) - - -- | Export a functor as a pdf with GraphViz such that the source category is in green, the target in blue, the objects mapped together are in the same cluster. - diagToPdfCluster :: (Eq c1, Eq o1, PrettyPrintable o1, PrettyPrintable m1, Morphism m1 o1, GeneratedFiniteCategory c1 m1 o1, - Eq c2, Eq o2, PrettyPrintable o2, PrettyPrintable m2, Morphism m2 o2, GeneratedFiniteCategory c2 m2 o2) => - Diagram c1 m1 o1 c2 m2 o2 -> String -> IO () - diagToPdfCluster f path = dotToPdf (diagToDotCluster f path) path - - -- __________________________________ - -- __________________________________ - -- - -- Diagram representation with arrows between arrows - -- __________________________________ - -- __________________________________ - - indexAr :: (Morphism m o, FiniteCategory c m o, Eq o, Eq m) => c -> m -> Int - indexAr c m - | elem m (arrows c) = fromJust $ elemIndex m (arrows c) - | otherwise = error "indexAr of arrow not in category" - - indexOb :: (FiniteCategory c m o, Eq o) => c -> o -> Int - indexOb c o - | elem o (ob c) = fromJust $ elemIndex o (ob c) - | otherwise = error "indexOb of object not in category" - - -- | If the node%4 == 0, then it is part of the source category, else if node%4 == 1 it is part of the target category. - diagObjToNode :: (Eq o, FiniteCategory c m o) => c -> Bool -> o -> Node - diagObjToNode c b o - | index == Nothing = error("Call diagObjToNode on an object not in the category.") - | otherwise = if b then 4*i else 4*i+1 - where - Just i = index - index = elemIndex o (ob c) - - diagObjToLNode :: (Eq o, PrettyPrintable o, FiniteCategory c m o) => c -> Bool -> o -> LNode String - diagObjToLNode c b o = (diagObjToNode c b o, pprint o) - - -- Creates the invisible node associated to an arrow of the source category if the boolean is True, of the target category if the boolean is False. - invisNodeSrc :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrintable m1, - Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrintable m2) => - (Diagram c1 m1 o1 c2 m2 o2) -> m1 -> LNode String - invisNodeSrc f@Diagram{src=s,tgt=t,mmap=_,omap=_} m = (4*(indexAr s m)+2, pprint m) - - invisNodeTgt :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrintable m1, - Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrintable m2) => - (Diagram c1 m1 o1 c2 m2 o2) -> m2 -> LNode String - invisNodeTgt f@Diagram{src=s,tgt=t,mmap=_,omap=_} m = (4*(indexAr t m)+3, pprint m) - - diagArToLEdges :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrintable m1, - Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrintable m2) => - (Diagram c1 m1 o1 c2 m2 o2) -> Either m1 m2 -> [LEdge String] - diagArToLEdges f@Diagram{src=s,tgt=t,omap=_,mmap=_} (Left m) = [((diagObjToNode s True). source $ m, fst.(invisNodeSrc f) $ m, ""),(fst.(invisNodeSrc f) $ m,(diagObjToNode s True). target $ m, "")] - diagArToLEdges f@Diagram{src=s,tgt=t,omap=_,mmap=_} (Right m) = [((diagObjToNode t False). source $ m, fst.(invisNodeTgt f) $ m, ""),(fst.(invisNodeTgt f) $ m,(diagObjToNode t False). target $ m, "")] - - linkArrows :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrintable m1, - Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrintable m2) => - (Diagram c1 m1 o1 c2 m2 o2) -> [LEdge String] - linkArrows f@Diagram{src=s,tgt=t,omap=_,mmap=fm} = (\m->(fst(invisNodeSrc f m),fst(invisNodeTgt f (fm !-! m)),"")) <$> (arrows s) - - linkObjects :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrintable m1, - Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrintable m2) => - (Diagram c1 m1 o1 c2 m2 o2) -> [LEdge String] - linkObjects f@Diagram{src=s,tgt=t,omap=om,mmap=_} = (\o->(diagObjToNode s True o,diagObjToNode t False (om !-! o),"")) <$> (ob s) - - diagToGraph :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrintable m1, PrettyPrintable o1, - Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrintable m2, PrettyPrintable o2) => - (Diagram c1 m1 o1 c2 m2 o2) -> Gr String String - diagToGraph f = mkGraph ((diagObjToLNode (src f) True <$> (ob (src f)))++(diagObjToLNode (tgt f) False <$> (ob (tgt f)))++((invisNodeSrc f) <$> (arrows (src f)))++((invisNodeTgt f) <$> (arrows (tgt f)))) - ((concat ((diagArToLEdges f <$> (Left <$> (arrows (src f))))++(diagArToLEdges f <$> (Right <$> (arrows (tgt f))))))++(linkArrows f)++(linkObjects f)) - - -- | Export a diagram with GraphViz such that the source category is in green, the target in blue, each morphism is represented by a node. - diagToDot :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrintable m1, PrettyPrintable o1, - Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrintable m2, PrettyPrintable o2) => - (Diagram c1 m1 o1 c2 m2 o2) -> String -> IO () - diagToDot f@Diagram{src=s,tgt=t,omap=om,mmap=fm} path = createAndWriteFile path $ renderDot $ toDot dot_file where - dot_file = graphToDot Params { - isDirected = True - ,globalAttributes = [] - ,clusterBy = (\(n,nl) -> case () of - _ | (n `mod` 2) == 0 -> (C 0 $ N (n,nl)) - | (n `mod` 2) == 1 -> (C 1 $ N (n,nl))) - ,isDotCluster = const True - ,clusterID = Num . Int - ,fmtCluster = const [] - ,fmtNode = \(n,label)-> [Label (StrLabel (L.pack label)), fmtColorN n] - ,fmtEdge= \e@(n1,n2,label)-> [Label (StrLabel (L.pack label)), fmtColorE e] - } (diagToGraph f) - where - fmtColorN n | n `mod` 4 == 0 = color Green - | n `mod` 4 == 1 = color Blue - | n `mod` 4 == 2 = color Red - | n `mod` 4 == 3 = color Pink - fmtColorE (s,t,_) | s `mod ` 4 == 0 = if t `mod` 2 == 1 then color Red else color Green - | t `mod ` 4 == 0 = color Green - | s `mod ` 4 == 1 = color Blue - | t `mod ` 4 == 1 = color Blue - | otherwise = color Black - - -- | Export a diagram as a pdf with GraphViz such that the source category is in green, the target in blue, each morphism is represented by a node. - diagToPdf :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrintable m1, PrettyPrintable o1, - Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrintable m2, PrettyPrintable o2) => - (Diagram c1 m1 o1 c2 m2 o2) -> String -> IO () - diagToPdf f path = dotToPdf (diagToDot f path) path - - - -- __________________________________ - -- __________________________________ - -- - -- Diagram representation as a selection of the target category - -- __________________________________ - -- __________________________________ - - -- | Export a diagram with GraphViz such that a node or an arrow is in orange if it is the target of the functor. - diagToDot2 :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrintable m1, PrettyPrintable o1, - Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrintable m2, PrettyPrintable o2) => - (Diagram c1 m1 o1 c2 m2 o2) -> String -> IO () - diagToDot2 f@Diagram{src=s,tgt=t,omap=om,mmap=fm} path = createAndWriteFile path $ renderDot $ toDot dot_file where - dot_file = graphToDot nonClusteredParams { fmtNode= \(n,label)-> [Label (StrLabel (L.pack label)), colorNode n], - fmtEdge= \(n1,n2,label)-> [Label (StrLabel (L.pack label)), colorEdge label]} (categoryToGraph t) - where - colorNode n = case () of - _ | countPredN == 0 -> color Black - | countPredN == 1 -> color Orange - | countPredN == 2 -> color Orange1 - | countPredN == 3 -> color Orange2 - | countPredN == 4 -> color Orange3 - | countPredN == 5 -> color Orange4 - | otherwise -> color OrangeRed4 - - where - countPredN = length [1 | o <- (ob s), (objToNode t (om !-! o)) == n] - colorEdge e = case () of - _ | countPredE == 0 -> color Black - | countPredE == 1 -> color Orange - | countPredE == 2 -> color Orange1 - | countPredE == 3 -> color Orange2 - | countPredE == 4 -> color Orange3 - | countPredE == 5 -> color Orange4 - | otherwise -> color OrangeRed4 - where - countPredE = length [1 | m <- (arrows s), (pprint (fm !-! m)) == e] - - -- | Export a diagram as a pdf with GraphViz such that a node or an arrow is in orange if it is the target of the functor. - diagToPdf2 :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrintable m1, PrettyPrintable o1, - Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrintable m2, PrettyPrintable o2) => - (Diagram c1 m1 o1 c2 m2 o2) -> String -> IO () - diagToPdf2 f path = dotToPdf (diagToDot2 f path) path - - -- __________________________________ - -- __________________________________ - -- - -- Natural transformation representation as a translation in the target category. - -- __________________________________ - -- __________________________________ - - -- | Export a natural transformation with GraphViz such that the source diagram is in green, the target diagram is in blue and the translation is in yellow. - natToDot :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrintable m1, PrettyPrintable o1, - Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrintable m2, PrettyPrintable o2) => - (NaturalTransformation c1 m1 o1 c2 m2 o2) -> String -> IO () - natToDot NaturalTransformation{srcNT=s,tgtNT=t,component=c} path = createAndWriteFile path $ renderDot $ toDot dot_file where - dot_file = graphToDot nonClusteredParams { fmtNode= \(n,label)-> [Label (StrLabel (L.pack label)), colorNode n], - fmtEdge= \(n1,n2,label)-> [Label (StrLabel (L.pack label)), colorEdge label]} (categoryToGraph (tgt s)) - where - colorNode n = case () of - _ | predNSrc && predNTgt -> color Turquoise - | predNSrc -> color Green - | predNTgt -> color Blue - | otherwise -> color Black - where - predNSrc = foldr (||) False [(objToNode (tgt s) ((omap s) !-! o)) == n | o <- (ob (src s))] - predNTgt = foldr (||) False [(objToNode (tgt t) ((omap t) !-! o)) == n | o <- (ob (src t))] - colorEdge e = case () of - _ | predESrc && predETgt && predENat -> color Beige - | predESrc && predETgt -> color Turquoise - | predESrc && predENat -> color Orange - | predETgt && predENat -> color LightBlue - | predESrc -> color Green - | predETgt -> color Blue - | predENat -> color Yellow - | otherwise -> color Black - where - predESrc = foldr (||) False [(pprint ((mmap s) !-! m)) == e | m <- (arrows (src s))] - predETgt = foldr (||) False [(pprint ((mmap t) !-! m)) == e | m <- (arrows (src t))] - predENat = foldr (||) False [(pprint (c o)) == e | o <- (ob (src s))] - - -- | Export a natural transformation as pdf with GraphViz such that the source diagram is in green, the target diagram is in blue and the translation is in yellow. - natToPdf :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrintable m1, PrettyPrintable o1, - Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrintable m2, PrettyPrintable o2) => - (NaturalTransformation c1 m1 o1 c2 m2 o2) -> String -> IO () - natToPdf nt path = dotToPdf (natToDot nt path) path - - -- __________________________________ - -- __________________________________ - -- - -- Cone representation as a translation in the reduced target category. - -- __________________________________ - -- __________________________________ - - -- | Export a cone with GraphViz such that the legs are in yellow. - extractFromTarget :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, - Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2) => - (NaturalTransformation c1 m1 o1 c2 m2 o2) -> (FreeSubcategory c2 m2 o2) - extractFromTarget NaturalTransformation{srcNT=s,tgtNT=t,component=c} = FreeSubcategory (tgt s) ([(mmap s) !-! m | m <- (arrows (src s))]++[(mmap t) !-! m | m <- (arrows (src s))]++[c o | o <- (ob (src s))]) - - -- | Export a cone with GraphViz such that the source diagram is in green, the target diagram is in blue and the translation is in yellow. - coneToDot :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrintable m1, PrettyPrintable o1, - Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrintable m2, PrettyPrintable o2) => - (NaturalTransformation c1 m1 o1 c2 m2 o2) -> String -> IO () - coneToDot nt@NaturalTransformation{srcNT=s,tgtNT=t,component=c} path = createAndWriteFile path $ renderDot $ toDot dot_file where - dot_file = graphToDot nonClusteredParams { fmtNode= \(n,label)-> [Label (StrLabel (L.pack label)), colorNode n], - fmtEdge= \(n1,n2,label)-> [Label (StrLabel (L.pack label)), colorEdge label]} (categoryToGraph (extractFromTarget nt)) - where - colorNode n = case () of - _ | predNSrc && predNTgt -> color Turquoise - | predNSrc -> color Green - | predNTgt -> color Blue - | otherwise -> color Black - where - predNSrc = foldr (||) False [(objToNode (tgt s) ((omap s) !-! o)) == n | o <- (ob (src s))] - predNTgt = foldr (||) False [(objToNode (tgt t) ((omap t) !-! o)) == n | o <- (ob (src t))] - colorEdge e = case () of - _ | predESrc && predETgt && predENat -> color Beige - | predESrc && predETgt -> color Turquoise - | predESrc && predENat -> color Orange - | predETgt && predENat -> color LightBlue - | predESrc -> color Green - | predETgt -> color Blue - | predENat -> color Yellow - | otherwise -> color Black - where - predESrc = foldr (||) False [(pprint ((mmap s) !-! m)) == e | m <- (arrows (src s))] - predETgt = foldr (||) False [(pprint ((mmap t) !-! m)) == e | m <- (arrows (src t))] - predENat = foldr (||) False [(pprint (c o)) == e | o <- (ob (src s))] - - -- | Export a cone as pdf with GraphViz such that the source diagram is in green, the target diagram is in blue and the translation is in yellow. - coneToPdf :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrintable m1, PrettyPrintable o1, - Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrintable m2, PrettyPrintable o2) => - (NaturalTransformation c1 m1 o1 c2 m2 o2) -> String -> IO () - coneToPdf nt path = dotToPdf (coneToDot nt path) path
− src/FiniteCategory/FiniteCategory.hs
@@ -1,311 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-} - -{-| Module : FiniteCategories -Description : Typeclasses of morphisms and finite categories and general functions on them. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -The goal of this module is to represent small finite categories in order to make usual constructions automatically on them (e.g. (co)limits, (co)completion, etc.) -There is a package that deals with categories as a data type (Data.Category) but it does not provide Ar and Ob operators because -the package uses the fact that the language itself is a category to represent categories -(Hask is (almost) a category, Data.Category benefit from type check at compilation time). -The counterpart is that to use Data.Category, you need to create yourself the usual constructions on your category. -To construct automatically (co)limits and other constructions, we require that the category can enumerate every morphisms between two objects. -We also require that the objects are not types because we want to create objects at runtime (that is why we abandon type check at -compilation time for the structure of our categories). -Lastly, we require that morphisms can be equated for usual constructions purposes. - -For example, see the FinSet category and the Composition Graph. --} - -module FiniteCategory.FiniteCategory -( - -- * Morphism typeclass and related functions - Morphism(..), - compose, - -- * FiniteCategory typeclass - FiniteCategory(..), - -- * FiniteCategory functions - arFrom, - arFrom2, - arTo, - arTo2, - identities, - isIdentity, - isNotIdentity, - isTerminal, - isInitial, - terminalObjects, - initialObjects, - -- * GeneratedFiniteCategory typeclass and related functions - GeneratedFiniteCategory(..), - genArFrom, - genArFrom2, - genArTo, - genArTo2, - defaultGenAr, - defaultDecompose, - bruteForceDecompose, - isGenerator, - isComposite, - -- * Check for category correctness - FiniteCategoryError(..), - checkFiniteCategoryProperties, - checkGeneratedFiniteCategoryProperties -) -where - - import Data.List (elemIndex, elem, concat, nub, intersect, (\\)) - import Data.Maybe (fromJust) - import Utils.Tuple - import IO.PrettyPrint - - -- | A morphism can be composed with the ('@') operator, it has a source and a target. - -- - -- The ('@') operator should not be confused with the as-pattern. When using the operator, surround the '@' symbol with spaces. - -- - -- Morphism is a multiparametrized type class where /m/ is the type of the morphism and /o/ the type of the objects source and target. - -- Source and target are the same type of objects, we distinguish objects not by their type but instead by their values. - class Morphism m o | m -> o where - -- | The composition @g\@f@ should throw an error if @source g != target f@. - -- This is a consequence of loosing type check at compilation time, we defer the exception handling to execution time. - -- - -- Composition is associative : - -- - -- prop> f @ (g @ h) = (f @ g) @ h - (@) :: m -> m -> m - source :: m -> o - target :: m -> o - - -- | Returns the composition of the list of morphisms. - -- - -- For example : - -- @compose [f,g,h] = f \@ g \@ h@ - compose :: (Morphism m o) => [m] -> m - compose l = foldr1 (@) l - - -- | A category is multiparametrized by the type of its morphisms and the type of its objects. - class FiniteCategory c m o | c -> m, m -> o where - -- | `ob` should return a list of unique objects : - -- - -- prop> List.nub (ob c) = ob c - ob :: c -> [o] - -- | `identity` should return the identity associated to the object /o/ in the category /c/. - -- - -- The identity morphism is a morphism such that the two following properties are verified : - -- - -- prop> f @ identity c (source f) = f - -- prop> identity c (target g) @ g = g - identity :: (Morphism m o) => c -> o -> m - -- | `ar` should return the list of all unique arrows between a source and a target : - -- - -- prop> List.nub (ar c s t) = ar c s t - -- - -- Arrows with different source or target should not be equal : - -- - -- prop> (s1 = s2 && t1 = t2) || List.intersect (ar c s1 t1) (ar c s2 t2) = [] - ar :: (Morphism m o) => c -- ^ The category - -> o -- ^ The source of the morphisms - -> o -- ^ The target of the morphisms - -> [m] -- ^ The list of morphisms in the category c between source and target - - {-# MINIMAL ob, identity, ar #-} - - -- | `arrows` returns the list of all unique morphisms of a category. - arrows :: (FiniteCategory c m o, Morphism m o) => c -> [m] - arrows c = concat [ar c s t | s <- ob c, t <- ob c] - - - -- | `arTo` returns the list of unique morphisms going to a specified target. - arTo :: (FiniteCategory c m o, Morphism m o) => c -> o -> [m] - arTo c t = concat [ar c s t | s <- ob c] - - -- | `arTo2` same as `arTo` but for multiple targets. - arTo2 :: (FiniteCategory c m o, Morphism m o) => c -> [o] -> [m] - arTo2 c ts = concat [ar c s t | s <- ob c, t <- ts] - - -- | `arFrom` returns the list of unique morphisms going from a specified source. - arFrom :: (FiniteCategory c m o, Morphism m o) => c -> o -> [m] - arFrom c s = concat [ar c s t | t <- ob c] - - -- | `arFrom2` same as `arFrom` but for multiple sources. - arFrom2 :: (FiniteCategory c m o, Morphism m o) => c -> [o] -> [m] - arFrom2 c ss = concat [ar c s t | t <- ob c, s <- ss] - - -- | `identities` returns all the identities of a category. - identities :: (FiniteCategory c m o, Morphism m o) => c -> [m] - identities c = identity c <$> ob c - - -- | Returns wether a morphism is an identity in a category. - isIdentity :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> m -> Bool - isIdentity c m = identity c (source m) == m - - -- | Returns wether a morphism is not an identity. - isNotIdentity :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> m -> Bool - isNotIdentity c m = not (isIdentity c m) - - -- | Returns wether an object is initial in the category. - isInitial :: (FiniteCategory c m o, Morphism m o) => c -> o -> Bool - isInitial cat obj = and [(not.null $ ar cat obj t) && (null $ tail (ar cat obj t)) | t <- ob cat] - - -- | Returns the list of intial objects in a category. - initialObjects :: (FiniteCategory c m o, Morphism m o) => c -> [o] - initialObjects cat = filter (isInitial cat) (ob cat) - - -- | Returns wether an object is terminal in the category. - isTerminal :: (FiniteCategory c m o, Morphism m o) => c -> o -> Bool - isTerminal cat obj = and [(not.null $ ar cat s obj) && (null $ tail (ar cat s obj)) | s <- ob cat] -- we construct this convoluted condition to avoid length which would compute all the arrows between s and obj even when unnecessary (beyond two arrows it's useless) - - -- | Returns the list of terminal objects in a category. - terminalObjects :: (FiniteCategory c m o, Morphism m o) => c -> [o] - terminalObjects cat = filter (isTerminal cat) (ob cat) - - -- | `GeneratedFiniteCategory` is a `FiniteCategory` where some morphisms are selected as generators. - -- The full category is generated by the generating arrows, which means that every morphism can be written as a composition of several generators. - -- Some algorithms are simplified because they only need to deal with generators, the rest of the properties are deduced by composition. - -- Every `FiniteCategory` has at least one set of generators : the set of all of its morphisms. - class (FiniteCategory c m o) => GeneratedFiniteCategory c m o where - -- | Same as `ar` but only returns the generators. @genAr c s t@ should be included in @ar c s t@. - genAr :: (Morphism m o) => c -> o -> o -> [m] - - -- | `decompose` decomposes a morphism into a list of generators (according to composition) : - -- - -- prop> m = compose (decompose c m) - decompose :: (Morphism m o) => c -> m -> [m] - - {-# MINIMAL genAr, decompose #-} - - -- | Same as `arrows` but only returns the generators. @genArrows c@ should be included in @arrows c@. - genArrows :: (GeneratedFiniteCategory c m o, Morphism m o) => c -> [m] - genArrows c = concat [genAr c s t | s <- ob c, t <- ob c] - - -- | Same as `arTo` but only returns the generators. @genArTo c t@ should be included in @arTo c t@. - genArTo :: (GeneratedFiniteCategory c m o, Morphism m o) => c -> o -> [m] - genArTo c t = concat [genAr c s t | s <- ob c] - - -- | Same as `arTo2` but only returns the generators. @genArTo2 c [t]@ should be included in @arTo2 c [t]@. - genArTo2 :: (GeneratedFiniteCategory c m o, Morphism m o) => c -> [o] -> [m] - genArTo2 c ts = concat [genAr c s t | s <- ob c, t <- ts] - - -- | Same as `arFrom` but only returns the generators. @genArFrom c s@ should be included in @arFrom c s@. - genArFrom :: (GeneratedFiniteCategory c m o, Morphism m o) => c -> o -> [m] - genArFrom c s = concat [genAr c s t | t <- ob c] - - -- | Same as `arFrom2` but only returns the generators. @genArFrom2 c [s]@ should be included in @arFrom2 c [t]@. - genArFrom2 :: (GeneratedFiniteCategory c m o, Morphism m o) => c -> [o] -> [m] - genArFrom2 c ss = concat [genAr c s t | t <- ob c, s <- ss] - - -- | Every `FiniteCategory` has at least one set of generators : the set of all of its morphisms. - -- - -- `defaultGenAr` is a default method for `genAr` in order to transform any `FiniteCategory` into a `GeneratedFiniteCategory`. - -- - -- Use `defaultGenAr` in conjonction with `defaultDecompose`. - defaultGenAr :: (GeneratedFiniteCategory c m o, Morphism m o) => c -> o -> o -> [m] - defaultGenAr = ar - - -- | Every `FiniteCategory` has at least one set of generators : the set of all of its morphisms. - -- - -- `defaultDecompose` is a default method for `decompose` in order to transform any `FiniteCategory` into a `GeneratedFiniteCategory`. - -- - -- Use `defaultDecompose` in conjonction with `defaultGenAr`. - defaultDecompose :: (GeneratedFiniteCategory c m o, Morphism m o) => c -> m -> [m] - defaultDecompose _ m = (m:[]) - - -- | Helper function for `bruteForceDecompose`. - bruteForce :: (GeneratedFiniteCategory c m o, Morphism m o, Eq m) => c -> m -> [[m]] -> [m] - bruteForce c m l = if index == Nothing then bruteForce c m (concat (pathToAugmentedPaths <$> l)) else l !! (fromJust index) where - index = elemIndex m (compose <$> l) - leavingMorph path = (genArFrom c) $ target.head $ path - pathToAugmentedPaths path = (leavingMorph path) >>= (\x -> [(x:path)] ) - - -- | If `genAr` is implemented, we can find the decomposition of a morphism by bruteforce search (we compose every arrow until we get the morphism we want). - -- - -- This method is meant to be used temporarly until a proper decompose method is implemented. (It is very slow.) - bruteForceDecompose :: (GeneratedFiniteCategory c m o, Morphism m o, Eq m) => c -> m -> [m] - bruteForceDecompose c m = bruteForce c m ((:[]) <$> genArFrom c (source m)) - - -- | Returns if a morphism is a generating morphism. - -- It can be overloaded to speed it up (for a morphism /f/, it computes every generators between the source and the target of /f/ and checks if /f/ is in the list.) - isGenerator :: (GeneratedFiniteCategory c m o, Morphism m o, Eq m) => c -> m -> Bool - isGenerator c f = elem f (genAr c (source f) (target f)) - - -- | Opposite of `isGenerator`, i.e. returns if the morphism is composite. - isComposite :: (GeneratedFiniteCategory c m o, Morphism m o, Eq m) => c -> m -> Bool - isComposite c f = not (isGenerator c f) - - -- | A data type to represent an incoherence inside a category. - data FiniteCategoryError m o = - CompositionNotAssociative {f :: m, g :: m, h :: m, fg_h :: m, f_gh :: m} -- ^ @(h\@g)\@f /= h\@(g\@f)@ - | ObjectsNotUnique {dupObj :: o} -- ^ `dupObj` was found multiple times in @ob c@. - | MorphismsNotUnique {dupMorph :: m} -- ^ `dupMorph` was found multiple times in the category. - | ArrowsNotExhaustive {missingAr :: m} -- ^ `missingAr` is an arrow found by calling @ar c@ but is not in @arrows c@. - | ArrowBetweenUnknownObjects {f :: m, s :: o, t :: o} -- ^ `f` was found in the category but its source `s` or target `t` is not in @ob c@. - | WrongSource {f :: m, realSource :: o} -- ^ `f` was found by using @ar c s t@ where @s /= source f@. - | WrongTarget {f :: m, realTarget :: o} -- ^ `f` was found by using @ar c s t@ where @t /= target f@. - | IdentityNotLeftNeutral {idL :: m, f :: m, foidL :: m} -- ^ `idL` is not a valid identity : @f \@ idL /= f@. - | IdentityNotRightNeutral {f :: m, idR :: m, idRof :: m} -- ^ `idR` is not a valid identity : @idR \@ f /= f@. - | MorphismsShouldNotBeEqual {f :: m, g :: m} -- ^ @f == g@ even though they don'y share the same source or target. - | NotTransitive {f :: m, g :: m} -- ^ @f\@g@ is not an element of @ar c (source g) (target g)@. - | GeneratorIsNotAMorphism {f :: m} -- ^ `f` is a generator but not a morphism. - | MorphismDoesntDecomposesIntoGenerators {f :: m, decomp :: [m], notGen :: m} -- ^ The morphism `f` decomposes into `decomp` where `notGen` is a non generating morphism. - | WrongDecomposition {f :: m, decomp :: [m], comp :: m} -- ^ @compose (decompose c f) /= f@. - deriving (Eq, Show) - - -- | Checks every properties listed above for a category. - -- - -- If an error is found in the category, just a `FiniteCategoryError` is returned. - -- Otherwise, nothing is returned. - checkFiniteCategoryProperties :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> Maybe (FiniteCategoryError m o) - checkFiniteCategoryProperties c - | (not.null) dupObjects = Just ObjectsNotUnique {dupObj=head dupObjects} - | (not.null) incoherentEq = Just MorphismsShouldNotBeEqual {f=(fst.head) incoherentEq, g=(snd.head) incoherentEq} - | (not.null) wrongSource = Just WrongSource {f = (fst.head) wrongSource, realSource = (snd.head) wrongSource} - | (not.null) wrongTarget = Just WrongTarget {f = (fst.head) wrongTarget, realTarget = (snd.head) wrongTarget} - | (not.null) dupMorph = Just MorphismsNotUnique {dupMorph=head dupMorph} - | (not.null) missingAr = Just ArrowsNotExhaustive {missingAr=head missingAr} - | (not.null) unknownObjects = Just ArrowBetweenUnknownObjects {f=(fst3.head) unknownObjects, s=(snd3.head) unknownObjects, t=(trd3.head) unknownObjects} - | (not.null) idNotLNeutral = Just IdentityNotLeftNeutral {idL=(fst3.head) idNotLNeutral, f=(snd3.head) idNotLNeutral,foidL=(trd3.head) idNotLNeutral} - | (not.null) idNotRNeutral = Just IdentityNotRightNeutral {f=(fst3.head) idNotRNeutral, idR=(snd3.head) idNotRNeutral,idRof=(trd3.head) idNotRNeutral} - | (not.null) notAssociative = Just CompositionNotAssociative {f=(fst3.head) notAssociative,g=(snd3.head) notAssociative,h=(trd3.head) notAssociative, fg_h=(((fst3.head)notAssociative) @ ((snd3.head)notAssociative)) @ ((trd3.head)notAssociative), - f_gh=((fst3.head)notAssociative) @ (((snd3.head)notAssociative) @ ((trd3.head)notAssociative))} - | (not.null) notTransitive = Just NotTransitive {f=(fst.head) notTransitive, g=(snd.head) notTransitive} - | otherwise = Nothing - where - dupObjects = ob c \\ nub (ob c) - arrowsByAr = concat [ar c s t | s <- (ob c), t <- (ob c)] - incoherentEq = [(f,g) | f <- arrows c, g <- arrows c, f == g && (source f /= source g || target f /= target g)] - wrongSource = [(f,s) | s <- ob c, t <- ob c, f <- ar c s t, source f /= s] - wrongTarget = [(f,t) | s <- ob c, t <- ob c, f <- ar c s t, target f /= t] - dupMorph = arrowsByAr \\ nub arrowsByAr - missingAr = arrowsByAr \\ (arrows c) - unknownObjects = [(f,source f,target f) | f <- arrows c, not ( (source f) `elem` (ob c) && (target f) `elem` (ob c) )] - idNotLNeutral = [(identity c (source f),f,f @ identity c (source f)) | f <- arrows c, f @ identity c (source f) /= f] - idNotRNeutral = [(f,identity c (target f), identity c (target f) @ f) | f <- arrows c, identity c (target f) @ f /= f] - notAssociative = [(x,y,z) | z <- arrows c, y <- arFrom c (target z), x <- arFrom c (target y), (x @ y) @ z /= x @ (y @ z)] - notTransitive = [(f,g) | g <- arrows c, f <- arFrom c (target g), not (elem (f @ g) (ar c (source g) (target f)))] - fst3 (x,_,_) = x - snd3 (_,x,_) = x - trd3 (_,_,x) = x - - -- | Same as `checkFiniteCategoryProperties` but for `GeneratedFiniteCategory`. - checkGeneratedFiniteCategoryProperties :: (GeneratedFiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> Maybe (FiniteCategoryError m o) - checkGeneratedFiniteCategoryProperties c - | errCat /= Nothing = errCat - | (not.null) genNotMorph = Just GeneratorIsNotAMorphism {f=head genNotMorph} - | (not.null) decompIntoComposite = Just MorphismDoesntDecomposesIntoGenerators {f=(fst3.head) decompIntoComposite, decomp=(snd3.head) decompIntoComposite, notGen=(trd3.head) decompIntoComposite} - | (not.null) wrongDecomp = Just WrongDecomposition {f=(fst3.head) wrongDecomp, decomp=(snd3.head) wrongDecomp, comp=(trd3.head) wrongDecomp} - | otherwise = Nothing - where - errCat = checkFiniteCategoryProperties c - genNotMorph = genArrows c \\ arrows c - decompIntoComposite = [(m,decompose c m,f) | m <- arrows c, f <- decompose c m, not (elem f (genAr c (source f) (target f)))] - wrongDecomp = [(f,decompose c f, compose (decompose c f)) | f <- arrows c, compose (decompose c f) /= f] - fst3 (x,_,_) = x - snd3 (_,x,_) = x - trd3 (_,_,x) = x - - instance (Show m, Show o) => PrettyPrintable (FiniteCategoryError m o) where - pprint = show
− src/FunctorCategory/FunctorCategory.hs
@@ -1,128 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses #-} - -{-| Module : FiniteCategories -Description : Given two categories C and D, the `FunctorCategory` D^C has as objects functors from C to D and as morphisms natural transformations between functors. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -Given two categories C and D, the `FunctorCategory` D^C has as objects functors from C to D and as morphisms natural transformations between functors. --} - -module FunctorCategory.FunctorCategory -( - NaturalTransformation(..), - preWhiskering, - postWhiskering, - FunctorCategory(..) -) -where - import FiniteCategory.FiniteCategory - import Diagram.Diagram - import Data.List (intercalate) - import Utils.EnumerateMaps - import Utils.CartesianProduct - import Data.Maybe (isJust, fromJust) - import IO.PrettyPrint - import IO.Show - import Utils.AssociationList - - -- | A `NaturalTransformation` between two heterogeneous functors from /C/ to /D/ is a mapping from objects of /C/ to morphism of /D/ such that naturality is respected. - -- - -- Formally, let /F/ and /G/ be functors, and eta : Ob(/C/) -> Ar(/D/). The following property should be respected : - -- - -- prop> source F = source G - -- prop> target F = target G - -- prop> Forall f in arrows (source F) : eta(target f) @ F(f) = G(f) @ eta(source f) - data NaturalTransformation c1 m1 o1 c2 m2 o2 = NaturalTransformation {srcNT :: Diagram c1 m1 o1 c2 m2 o2 - , tgtNT :: Diagram c1 m1 o1 c2 m2 o2 - , component :: o1 -> m2} - - instance (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, - FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => - Morphism (NaturalTransformation c1 m1 o1 c2 m2 o2) (Diagram c1 m1 o1 c2 m2 o2) where - (@) NaturalTransformation{srcNT=s2,tgtNT=t2,component=c2} NaturalTransformation{srcNT=s1,tgtNT=t1,component=c1} - | t1 /= s2 = error "Illegal composition of natural transformations" - | otherwise = NaturalTransformation{srcNT=s1,tgtNT=t2,component=(\x -> (c2 x) @ (c1 x))} - source = srcNT - target = tgtNT - - instance (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, - FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => - Eq (NaturalTransformation c1 m1 o1 c2 m2 o2) where - NaturalTransformation{srcNT=s1,tgtNT=t1,component=c1} == NaturalTransformation{srcNT=s2,tgtNT=t2,component=c2} - | s1 /= s2 = False - | t1 /= t2 = False - | otherwise = and [c1 o == c2 o | o <- (ob.src) s1] - - instance (FiniteCategory c1 m1 o1, Morphism m1 o1, Show c1, Show m1, Show o1, Eq m1, Eq o1, - FiniteCategory c2 m2 o2, Morphism m2 o2, Show c2, Show m2, Show o2) => - Show (NaturalTransformation c1 m1 o1 c2 m2 o2) where - show NaturalTransformation{srcNT=s,tgtNT=t,component=c} = "NaturalTransformation{srcNT = "++show s++", tgtNT = "++show t++", component = "++showFunction c ((ob.src) s)++"}" - - instance (FiniteCategory c1 m1 o1, Morphism m1 o1, PrettyPrintable c1, PrettyPrintable m1, PrettyPrintable o1, Eq m1, Eq o1, - FiniteCategory c2 m2 o2, Morphism m2 o2, PrettyPrintable c2, PrettyPrintable m2, PrettyPrintable o2) => - PrettyPrintable (NaturalTransformation c1 m1 o1 c2 m2 o2) where - pprint NaturalTransformation{srcNT=s,tgtNT=t,component=c} = "Nat : "++pprint s++" -> "++pprint t++"\\n\\n"++pprintFunction c ((ob.src) s) - - -- | Checks wether the naturality property of a natural transformation is respected. - checkNaturality :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, - Morphism m2 o2, Eq m2, Eq o2) => - NaturalTransformation c1 m1 o1 c2 m2 o2 -> Bool - checkNaturality NaturalTransformation{srcNT=s,tgtNT=t,component=c} = and [((mmap t) !-! f) @ (c (source f)) == (c (target f)) @ ((mmap s) !-! f)| f <- (arrows.src) s] - - -- | Pre-whiskering as defined in Category Theory for the Sciences (2014) by David I. Spivak - preWhiskering :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1 - , FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2 - , FiniteCategory c3 m3 o3, Morphism m3 o3) => - NaturalTransformation c2 m2 o2 c3 m3 o3 -> Diagram c1 m1 o1 c2 m2 o2 -> NaturalTransformation c1 m1 o1 c3 m3 o3 - preWhiskering nt d = NaturalTransformation{ srcNT = (srcNT nt) `composeDiag` d - , tgtNT = (tgtNT nt) `composeDiag` d - , component = (component nt).(assocListToFunct (omap d))} - - -- | Pre-whiskering as defined in Category Theory for the Sciences (2014) by David I. Spivak - postWhiskering :: ( FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1 - , FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2 - , FiniteCategory c3 m3 o3, Morphism m3 o3) => - Diagram c2 m2 o2 c3 m3 o3 -> NaturalTransformation c1 m1 o1 c2 m2 o2 -> NaturalTransformation c1 m1 o1 c3 m3 o3 - postWhiskering d nt = NaturalTransformation{ srcNT = d `composeDiag` (srcNT nt) - , tgtNT = d `composeDiag` (tgtNT nt) - , component = (assocListToFunct (mmap d)).(component nt)} - - - -- | `FunctorCategory` D^C. - data FunctorCategory c1 m1 o1 c2 m2 o2 = FunctorCategory {sourceCat :: c1 -- ^ /C/ - , targetCat :: c2} -- ^ /D/ - deriving (Eq, Show) - - enumerateFunctors :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, - FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2) => - c1 -> c2 -> [Diagram c1 m1 o1 c2 m2 o2] - enumerateFunctors cat1 cat2 = [Diagram{src=cat1,tgt=cat2,mmap=appF, omap=appO} | appO <- appObj, appF <- concat <$> cartesianProduct [twoObjToMaps a b appO| a <- ob cat1, b <- ob cat1], checkFunctoriality Diagram{src=cat1,tgt=cat2,mmap=appF, omap=appO}] - where - appObj = enumMaps (ob cat1) (ob cat2) - twoObjToMaps a b appO = enumMaps (ar cat1 a b) (ar cat2 (appO !-! a) (appO !-! b)) - - instance (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, - FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2) => - FiniteCategory (FunctorCategory c1 m1 o1 c2 m2 o2) (NaturalTransformation c1 m1 o1 c2 m2 o2) (Diagram c1 m1 o1 c2 m2 o2) where - ob FunctorCategory{sourceCat=cat1, targetCat=cat2} = enumerateFunctors cat1 cat2 - - identity c diag = NaturalTransformation{srcNT=diag,tgtNT=diag,component=(identity (tgt diag)).(assocListToFunct (omap diag))} - - ar c diag1 diag2 = [NaturalTransformation{srcNT=diag1,tgtNT=diag2,component=mapCompo} | mapCompo <- mapComponent, checkNaturality NaturalTransformation{srcNT=diag1,tgtNT=diag2,component=mapCompo}] - where - mapComponent = transformToFunction <$> cartesianProduct [(\x -> (o,x)) <$> (ar (tgt diag1) ((omap diag1) !-! o) ((omap diag2) !-! o)) | o <- (ob (src diag1))] - transformToFunction ((o,f):xs) x = if o == x then f else transformToFunction xs x - - instance (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, - FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2) => - GeneratedFiniteCategory (FunctorCategory c1 m1 o1 c2 m2 o2) (NaturalTransformation c1 m1 o1 c2 m2 o2) (Diagram c1 m1 o1 c2 m2 o2) where - genAr = defaultGenAr - decompose = defaultDecompose - - instance (PrettyPrintable c1, PrettyPrintable c2) => - PrettyPrintable (FunctorCategory c1 m1 o1 c2 m2 o2) where - pprint FunctorCategory{sourceCat=s, targetCat=t} = "Fonct("++pprint s++","++pprint t++")"
− src/IO/CreateAndWriteFile.hs
@@ -1,28 +0,0 @@-{-| Module : FiniteCategories -Description : Write into a file, create directories if necessary. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -Write lazy text to a file specified by a path, if the path leads to non existing directories, it creates the directories. -Credits to wisn : https://stackoverflow.com/a/58685979 --} - -module IO.CreateAndWriteFile -( - createAndWriteFile -) -where - import System.Directory (createDirectoryIfMissing) - import System.FilePath.Posix (takeDirectory) - import qualified Data.Text.Lazy as L (Text) - import qualified Data.Text.Lazy.IO as LIO (writeFile) - - -- | Write lazy text to a file specified by a path, if the path leads to non existing directories, it creates the directories. - createAndWriteFile :: FilePath -> L.Text -> IO () - createAndWriteFile path content = do - createDirectoryIfMissing True $ takeDirectory path - - LIO.writeFile path content
− src/IO/Parsers/CompositionGraph.hs
@@ -1,116 +0,0 @@-{-| Module : FiniteCategories -Description : A parser to read .cg files. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -A parser to read .cg files. - -A .cg file follows the following rules : - 1. Each line defines either an object, a morphism or a composition law entry. - 2. The following strings are reserved : ' -','-> ',' = ' - 3. To define an object, write a line containing its name. - 4. To define an arrow, the syntax "source_object -name_of_morphism-> target_object" is used, where "source_object", "target_object" and "name_of_morphism" should be replaced. - 4.1. If an object mentionned does not exist, it is created. - 4.2. The spaces are important. - 5. To define a composition law entry, the syntax "source_object1 -name_of_first_morphism-> middle_object -name_of_second_morphism-> target_object1 = source_object2 -name_of_composite_morphism-> target_object2" is used, where "source_object1", "name_of_first_morphism", "middle_object", "name_of_second_morphism", "target_object1", "source_object2", "name_of_composite_morphism", "target_object2" should be replaced. - 5.1 If an object mentionned does not exist, it is created. - 5.2 If a morphism mentionned does not exist, it is created. - 5.3 You can use the tag <ID/> in order to map a morphism to an identity. --} - -module IO.Parsers.CompositionGraph -( - readCGFile, - writeCGFile -) -where - import FiniteCategory.FiniteCategory - import CompositionGraph.CompositionGraph - import IO.Parsers.Lexer - import Data.IORef - import Data.Text (Text, pack, unpack) - import Data.List (elemIndex, nub, intercalate) - import Utils.Tuple - import IO.PrettyPrint - - import System.Directory (createDirectoryIfMissing) - import System.FilePath.Posix (takeDirectory) - - type CG = CompositionGraph Text Text - - addObject :: [Token] -> CG -> CG - addObject [Name str] cg@CompositionGraph{graph=(n,a),law=l} = if elem str (ob cg) then cg else CompositionGraph{graph=((str:(ob cg)),a),law=l} - addObject otherTokens _ = error $ "addObject on invalid tokens : "++show otherTokens - - addMorphism :: [Token] -> CG -> CG - addMorphism [Name src, BeginArrow, Name arr, EndArrow, Name tgt] cg = if elem (Just arr) (getLabel <$> (ar newCG2 src tgt)) then newCG2 else CompositionGraph{graph=(n,((src,tgt,arr):a)),law=l} - where - newCG1 = addObject [Name src] cg - newCG2@CompositionGraph{graph=(n,a),law=l} = addObject [Name tgt] newCG1 - addMorphism otherTokens _ = error $ "addMorphism on invalid tokens : "++show otherTokens - - extractPath :: [Token] -> RawPath Text Text - extractPath [] = [] - extractPath [Identity] = [] - extractPath [(Name _)] = [] - extractPath ((Name src) : (BeginArrow : ((Name arr) : (EndArrow : ((Name tgt) : ts))))) = (extractPath ((Name tgt) : ts)) ++ [(src,tgt,arr)] - extractPath otherTokens = error $ "extractPath on invalid tokens : "++show otherTokens - - addCompositionLawEntry :: [Token] -> CG -> CG - addCompositionLawEntry tokens cg@CompositionGraph{graph=(n,a),law=l} = CompositionGraph{graph=(n++newObj,a++newMorph),law=(pathLeft,pathRight):l} - where - Just indexEquals = elemIndex Equals tokens - (tokensLeft,(_:tokensRight)) = splitAt indexEquals tokens - pathLeft = extractPath tokensLeft - pathRight = extractPath tokensRight - newObj = nub $ [s | (s,_,_) <- pathLeft++pathRight, not (elem s n)]++[t | (_,t,_) <- pathLeft++pathRight, not (elem t n)] - newMorph = nub [e | e <- pathLeft++pathRight, not (elem e a)] - - readLine :: String -> CG -> CG - readLine line cg - | null lexedLine = cg - | elem Equals lexedLine = addCompositionLawEntry lexedLine cg - | elem BeginArrow lexedLine = addMorphism lexedLine cg - | otherwise = addObject lexedLine cg - where - lexedLine = (parserLex line) - - parseCGString :: String -> CG - parseCGString str = newCG - where - ls = lines str - cg = mkEmptyCompositionGraph - newCG = foldr readLine cg ls - - -- | Reads a cg file and returns a composition graph. - readCGFile :: String -> IO CG - readCGFile path = do - file <- readFile path - return $ parseCGString file - - reversedRawPathToString :: (PrettyPrintable a, PrettyPrintable b) => RawPath a b -> String - reversedRawPathToString [] = "<ID>" - reversedRawPathToString [(s,t,l)] = pprint s ++ " -" ++ pprint l ++ "-> " ++ pprint t - reversedRawPathToString ((s,t,l):xs) = pprint s ++ " -" ++ pprint l ++ "-> " ++ reversedRawPathToString xs - - unparseCG :: (PrettyPrintable a, PrettyPrintable b, Eq a, Eq b) => CompositionGraph a b -> String - unparseCG cg = finalString - where - obString = intercalate "\n" $ pprint <$> ob cg - arNotIdentity = filter (isNotIdentity cg) (genArrows cg) - reversedRawPaths = (reverse.snd3.path) <$> arNotIdentity - arStringBeforeComment = reversedRawPathToString <$> reversedRawPaths - commentOutComposite = [if isComposite cg m then ('#':s) else s | (s,m) <- zip arStringBeforeComment arNotIdentity] - arString = intercalate "\n" $ commentOutComposite - lawString = intercalate "\n" $ (\(rp1,rp2) -> (reversedRawPathToString (reverse rp1)) ++ " = " ++ (reversedRawPathToString (reverse rp2))) <$> (law cg) - finalString = "#Objects :\n"++obString++"\n\n# Arrows :\n"++arString++"\n\n# Composition law :\n"++lawString - - -- | Saves a composition graph into a file located at a given path. - writeCGFile :: (PrettyPrintable a, PrettyPrintable b, Eq a, Eq b) => CompositionGraph a b -> String -> IO () - writeCGFile cg filepath = do - createDirectoryIfMissing True $ takeDirectory filepath - writeFile filepath $ unparseCG cg -
− src/IO/Parsers/Lexer.hs
@@ -1,45 +0,0 @@-{-| Module : FiniteCategories -Description : Lexer for parsers. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -Lexer for parsers. The keywords are ' -', '-> ', ' = ', "#", '<ID/>', '<SRC>', '</SRC>', '<TGT>', '</TGT>', ' => ' --} -module IO.Parsers.Lexer where - import Data.Text (Text, cons, singleton, unpack, pack) - - -- | A token for a scg or fscg file. - data Token = Name Text | BeginArrow | EndArrow | Equals | Identity | BeginSrc | EndSrc | BeginTgt | EndTgt | MapsTo deriving (Eq, Show) - - -- | Strip a token of unnecessary spaces. - strip :: Token -> Token - strip (Name txt) = Name (pack.reverse.stripLeft.reverse.stripLeft $ str) - where - str = unpack txt - stripLeft (' ':s) = s - stripLeft s = s - strip x = x - - -- | Transforms a string into a list of tokens. - parserLex :: String -> [Token] - parserLex str = strip <$> parserLexHelper str - where - parserLexHelper [] = [] - parserLexHelper ('#':str) = [] - parserLexHelper (' ':'-':str) = BeginArrow : (parserLexHelper str) - parserLexHelper ('-':'>':' ':str) = EndArrow : (parserLexHelper str) - parserLexHelper (' ':'=':' ':str) = Equals : (parserLexHelper str) - parserLexHelper ('<':'I':'D':'/':'>':str) = Identity : (parserLexHelper str) - parserLexHelper ('<':'S':'R':'C':'>':str) = BeginSrc : (parserLexHelper str) - parserLexHelper ('<':'T':'G':'T':'>':str) = BeginTgt : (parserLexHelper str) - parserLexHelper ('<':'/':'S':'R':'C':'>':str) = EndSrc : (parserLexHelper str) - parserLexHelper ('<':'/':'T':'G':'T':'>':str) = EndTgt : (parserLexHelper str) - parserLexHelper (' ':'=':'>':' ':str) = MapsTo : (parserLexHelper str) - parserLexHelper (c:str) = (result restLexed) - where - restLexed = (parserLexHelper str) - result (Name txt:xs) = (Name (cons c txt):xs) - result a = ((Name (singleton c)):a)
− src/IO/Parsers/SafeCompositionGraph.hs
@@ -1,114 +0,0 @@-{-| Module : FiniteCategories -Description : A parser to read .scg files. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -A parser to read .scg files. - -A .scg file follows the following rules : - 1. The first line is an integer specifying the max number of loops morphisms can do. - 2. The rest of the file is a cg file. (See IO.Parsers.CompositionGraph) --} - -module IO.Parsers.SafeCompositionGraph -( - SCG(..), - parseSCGString, - readSCGFile, - writeSCGFile -) -where - import FiniteCategory.FiniteCategory - import CompositionGraph.CompositionGraph - import CompositionGraph.SafeCompositionGraph - import IO.Parsers.Lexer - import Data.IORef - import Data.Text (Text, pack, unpack) - import Data.List (elemIndex, nub, intercalate) - import Utils.Tuple - import IO.PrettyPrint - - import System.Directory (createDirectoryIfMissing) - import System.FilePath.Posix (takeDirectory) - - -- | The type of SafeCompositionGraph created by reading a scg file. - type SCG = SafeCompositionGraph Text Text - - addObject :: [Token] -> SCG -> SCG - addObject [Name str] cg@SafeCompositionGraph{graphS=(n,a),lawS=l,maxCycles=mc} = if elem str (ob cg) then cg else SafeCompositionGraph{graphS=((str:(ob cg)),a),lawS=l,maxCycles=mc} - addObject otherTokens _ = error $ "addObject on invalid tokens : "++show otherTokens - - addMorphism :: [Token] -> SCG -> SCG - addMorphism [Name src, BeginArrow, Name arr, EndArrow, Name tgt] cg = if elem (Just arr) (getLabelS <$> (ar newSCG2 src tgt)) then newSCG2 else SafeCompositionGraph{graphS=(n,((src,tgt,arr):a)),lawS=l,maxCycles=mc} - where - newSCG1 = addObject [Name src] cg - newSCG2@SafeCompositionGraph{graphS=(n,a),lawS=l,maxCycles=mc} = addObject [Name tgt] newSCG1 - addMorphism otherTokens _ = error $ "addMorphism on invalid tokens : "++show otherTokens - - extractPath :: [Token] -> RawPath Text Text - extractPath [] = [] - extractPath [Identity] = [] - extractPath [(Name _)] = [] - extractPath ((Name src) : (BeginArrow : ((Name arr) : (EndArrow : ((Name tgt) : ts))))) = (extractPath ((Name tgt) : ts)) ++ [(src,tgt,arr)] - extractPath otherTokens = error $ "extractPath on invalid tokens : "++show otherTokens - - addCompositionLawEntry :: [Token] -> SCG -> SCG - addCompositionLawEntry tokens cg@SafeCompositionGraph{graphS=(n,a),lawS=l,maxCycles=mc} = SafeCompositionGraph{graphS=(n++newObj,a++newMorph),lawS=(pathLeft,pathRight):l,maxCycles=mc} - where - Just indexEquals = elemIndex Equals tokens - (tokensLeft,(_:tokensRight)) = splitAt indexEquals tokens - pathLeft = extractPath tokensLeft - pathRight = extractPath tokensRight - newObj = nub $ [s | (s,_,_) <- pathLeft++pathRight, not (elem s n)]++[t | (_,t,_) <- pathLeft++pathRight, not (elem t n)] - newMorph = nub [e | e <- pathLeft++pathRight, not (elem e a)] - - readLine :: String -> SCG -> SCG - readLine line cg - | null lexedLine = cg - | elem Equals lexedLine = addCompositionLawEntry lexedLine cg - | elem BeginArrow lexedLine = addMorphism lexedLine cg - | otherwise = addObject lexedLine cg - where - lexedLine = (parserLex line) - - -- | Parse a string extracted from a scg file. Returns a safe composition graph. - parseSCGString :: String -> SCG - parseSCGString str = if test then newSCG else error $ "First line of scg file is not a number : "++show ls - where - test = null $ filter (\x -> not $ elem x ['0'..'9']) $ head ls - ls = filter (not.null.parserLex) $ lines str - maxCyc = (read $ head ls) :: Int - cg = mkEmptySafeCompositionGraph maxCyc - newSCG = foldr readLine cg (tail ls) - - -- | Reads a scg file and returns a safe composition graph. - readSCGFile :: String -> IO SCG - readSCGFile path = do - file <- readFile path - return $ parseSCGString file - - reversedRawPathToString :: (PrettyPrintable a, PrettyPrintable b) => RawPath a b -> String - reversedRawPathToString [] = "<ID>" - reversedRawPathToString [(s,t,l)] = pprint s ++ " -" ++ pprint l ++ "-> " ++ pprint t - reversedRawPathToString ((s,t,l):xs) = pprint s ++ " -" ++ pprint l ++ "-> " ++ reversedRawPathToString xs - - unparseSCG :: (PrettyPrintable a, PrettyPrintable b, Eq a, Eq b) => SafeCompositionGraph a b -> String - unparseSCG cg = finalString - where - obString = intercalate "\n" $ pprint <$> ob cg - arNotIdentity = filter (isNotIdentity cg) (arrows cg) - reversedRawPaths = (reverse.snd3.pathS) <$> arNotIdentity - arStringBeforeComment = reversedRawPathToString <$> reversedRawPaths - commentOutComposite = [if isComposite cg m then ('#':s) else s | (s,m) <- zip arStringBeforeComment arNotIdentity] - arString = intercalate "\n" $ commentOutComposite - lawString = intercalate "\n" $ (\(rp1,rp2) -> (reversedRawPathToString (reverse rp1)) ++ " = " ++ (reversedRawPathToString (reverse rp2))) <$> (lawS cg) - finalString = "#Max number of cycles :\n"++show (maxCycles cg)++"\n\n#Objects :\n"++obString++"\n\n# Arrows :\n"++arString++"\n\n# Composition law :\n"++lawString - - -- | Saves a safe composition graph into a file located at a given path. - writeSCGFile :: (PrettyPrintable a, PrettyPrintable b, Eq a, Eq b) => SafeCompositionGraph a b -> String -> IO () - writeSCGFile cg filepath = do - createDirectoryIfMissing True $ takeDirectory filepath - writeFile filepath $ unparseSCG cg
− src/IO/Parsers/SafeCompositionGraphFunctor.hs
@@ -1,123 +0,0 @@-{-| Module : FiniteCategories -Description : A parser to read .fscg files. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -A parser to read .fscg files. - -A .fscg file follows the following rules : - 1. There is a line "<SRC>" and a line "</SRC>". - 1.1 Between these two lines, the source safe composition graph is defined as in a scg file. - 2. There is a line "<TGT>" and a line "</TGT>". - 2.1 Between these two lines, the target safe composition graph is defined as in a scg file. - 3. Outside of the two previously described sections, you can declare the maps between objects and morphisms. - 3.1 You map an object to another with the following syntax : "object1 => object2". - 3.2 You map a morphism to another with the following syntax : "objSrc1 -arrowSrc1-> objSrc2 => objTgt1 -arrowTgt1-> objTgt2". - 4. You don't have to (and you shouldn't) specify maps from identities, nor maps from composite arrows. --} - -module IO.Parsers.SafeCompositionGraphFunctor -( - readFSCGFile -) -where - import FiniteCategory.FiniteCategory - import Cat.PartialFinCat - import CompositionGraph.CompositionGraph - import CompositionGraph.SafeCompositionGraph - import IO.Parsers.Lexer - import IO.Parsers.SafeCompositionGraph - import Data.IORef - import Data.Text (Text, pack, unpack) - import Data.List (elemIndex, nub, intercalate) - import Utils.Tuple - import IO.PrettyPrint - import Utils.AssociationList - import Diagram.Diagram - - import System.Directory (createDirectoryIfMissing) - import System.FilePath.Posix (takeDirectory) - - type SCGF = PartialFunctor SCG (SCGMorphism Text Text) Text - type SCGD = Diagram SCG (SCGMorphism Text Text) Text SCG (SCGMorphism Text Text) Text - - addOMapEntry :: [Token] -> SCGF -> SCGF - addOMapEntry [Name x, MapsTo, Name y] pf - | elem x (keys (omapPF pf)) = if y == ((omapPF pf) !-! x) then pf else error ("Incoherent maps of object : F("++show x++") = "++show y ++ " and "++show ((omapPF pf) !-! x)) - | otherwise = PartialFunctor{srcPF=srcPF pf, tgtPF=tgtPF pf, omapPF=((x,y):(omapPF pf)), mmapPF=mmapPF pf} - addOMapEntry otherTokens _ = error $ "addOMapEntry on invalid tokens : "++show otherTokens - - addMMapEntry :: [Token] -> SCGF -> SCGF - addMMapEntry tks@[Name sx, BeginArrow, Name lx, EndArrow, Name tx, MapsTo, Identity] pf = if elem sx (keys (omapPF pf)) then PartialFunctor{srcPF=srcPF pf, tgtPF=tgtPF pf, omapPF=omapPF pf, mmapPF=((sourceMorph,(identity (target pf) ((omapPF pf) !-! sx))):(mmapPF pf))} else error ("You must specify the image of the source of the morphism before mapping to an identity : "++show tks) - where - sourceMorphCand = filter (\e -> getLabelS e == Just lx) (genAr (source pf) sx tx) - sourceMorph = if null sourceMorphCand then error $ "addMMapEntry : morphism not found in source category for the following map : "++ show tks else head sourceMorphCand - addMMapEntry tks@[Name sx, BeginArrow, Name lx, EndArrow, Name tx, MapsTo, Name sy, BeginArrow, Name ly, EndArrow, Name ty] pf = PartialFunctor{srcPF=srcPF newPF2, tgtPF=tgtPF newPF2, omapPF=omapPF newPF2, mmapPF=((sourceMorph,targetMorph):(mmapPF newPF2))} - where - sourceMorphCand = filter (\e -> getLabelS e == Just lx) (genAr (source pf) sx tx) - targetMorphCand = filter (\e -> getLabelS e == Just ly) (genAr (target pf) sy ty) - sourceMorph = if null sourceMorphCand then error $ "addMMapEntry : morphism not found in source category for the following map : "++ show tks else head sourceMorphCand - targetMorph = if null targetMorphCand then error $ "addMMapEntry : morphism not found in target category for the following map : "++ show tks else head targetMorphCand - newPF1 = addOMapEntry [Name sx, MapsTo, Name sy] pf - newPF2 = addOMapEntry [Name tx, MapsTo, Name ty] newPF1 - - addMMapEntry otherTokens _ = error $ "addMMapEntry on invalid tokens : "++show otherTokens - - readLineF :: String -> SCGF -> SCGF - readLineF line pf@PartialFunctor{srcPF=s, tgtPF=t, omapPF=om, mmapPF=mm} - | null lexedLine = pf - | elem MapsTo lexedLine = if elem BeginArrow lexedLine - then addMMapEntry lexedLine pf - else addOMapEntry lexedLine pf - | otherwise = pf - where - lexedLine = (parserLex line) - - extractSrcSection :: [String] -> [String] - extractSrcSection lines - | not (elem [BeginSrc] (parserLex <$> lines)) = error $ "No <SRC> section or malformed <SRC> section in file : "++ show lines - | not (elem [EndSrc] (parserLex <$> lines)) = error $ "No <SRC> section or malformed <SRC> section in file : "++ show lines - | indexEndSrc < indexBeginSrc = error $ "Malformed <SRC> section in file : "++ show lines - | otherwise = c - where - Just indexBeginSrc = (elemIndex [BeginSrc] (parserLex <$> lines)) - Just indexEndSrc = (elemIndex [EndSrc] (parserLex <$> lines)) - (a,b) = splitAt (indexBeginSrc+1) lines - (c,d) = splitAt (indexEndSrc-indexBeginSrc-1) b - - extractTgtSection :: [String] -> [String] - extractTgtSection lines - | not (elem [BeginTgt] (parserLex <$> lines)) = error $ "No <TGT> section or malformed <TGT> section in file : "++ show lines - | not (elem [EndTgt] (parserLex <$> lines)) = error $ "No <TGT> section or malformed <TGT> section in file : "++ show lines - | indexEndTgt < indexBeginTgt = error $ "Malformed <TGT> section in file : "++ show lines - | otherwise = c - where - Just indexBeginTgt = (elemIndex [BeginTgt] (parserLex <$> lines)) - Just indexEndTgt = (elemIndex [EndTgt] (parserLex <$> lines)) - (a,b) = splitAt (indexBeginTgt+1) lines - (c,d) = splitAt (indexEndTgt-indexBeginTgt-1) b - - rawreadFSCGFile :: String -> IO SCGF - rawreadFSCGFile path = do - file <- readFile path - let ls = filter (not.null.parserLex) $ lines file - let src = parseSCGString $ intercalate "\n" (extractSrcSection ls) - let tgt = parseSCGString $ intercalate "\n" (extractTgtSection ls) - let pf = PartialFunctor{srcPF=src, tgtPF=tgt,omapPF=[], mmapPF=[]} - let finalPF = foldr readLineF pf ls - return finalPF - - -- | Reads a fscg file and completes everything so that it becomes a diagram. - completeFSCG :: SCGF -> SCGD - completeFSCG pf@PartialFunctor{srcPF=s, tgtPF=t, omapPF=om, mmapPF=mm} = - Diagram{src=s, tgt=t, omap=om, mmap=completeMmap s t om mm} - - -- | Reads a fscg file and returns a diagram. - readFSCGFile :: String -> IO SCGD - readFSCGFile path = do - raw <- rawreadFSCGFile path - return (completeFSCG raw) -
− src/IO/PrettyPrint.hs
@@ -1,67 +0,0 @@-{-| Module : FiniteCategories -Description : A simple typeclass for things to be pretty printed. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -A simple typeclass for things to be pretty printed. Things should be pretty printable to be exported with graphviz. --} -module IO.PrettyPrint -( - PrettyPrintable(..), - pprintFunction -) -where - import Data.List (intercalate) - import Data.Set (Set, toList) - import Data.Map (Map, keys, (!)) - import Data.Maybe - import Data.Either - import Data.Text (Text, unpack) - - -- | The typeclass of things that can be pretty printed. - class PrettyPrintable a where - pprint :: a -> String - - instance (PrettyPrintable a) => PrettyPrintable [a] where - pprint xs = "[" ++ intercalate "," (pprint <$> xs) ++ "]" - - - instance (PrettyPrintable a, PrettyPrintable b) => PrettyPrintable (a,b) where - pprint (a,b) = "(" ++ pprint a ++ "," ++ pprint b ++ ")" - - instance (PrettyPrintable a, PrettyPrintable b, PrettyPrintable c) => PrettyPrintable (a,b,c) where - pprint (a,b,c) = "(" ++ pprint a ++ "," ++ pprint b ++ "," ++ pprint c ++ ")" - - instance (PrettyPrintable a) => PrettyPrintable (Set a) where - pprint xs = "{" ++ intercalate "," (pprint <$> (toList xs)) ++ "}" - - instance PrettyPrintable Int where - pprint = show - - instance PrettyPrintable Double where - pprint = show - - instance PrettyPrintable Char where - pprint = show - - instance (Ord k, PrettyPrintable k, PrettyPrintable a) => PrettyPrintable (Map k a) where - pprint m = intercalate "\n" [pprint k ++ "->" ++pprint (m!k)| k <- keys m] - - instance (PrettyPrintable a) => PrettyPrintable (Maybe a) where - pprint Nothing = "Nothing" - pprint (Just a) = pprint a - - instance (PrettyPrintable a, PrettyPrintable b) => PrettyPrintable (Either a b) where - pprint (Left x) = pprint x - pprint (Right x) = pprint x - - instance PrettyPrintable Text where - pprint = unpack - - -- | Pretty print a function on a specific domain. - pprintFunction :: (PrettyPrintable a, PrettyPrintable b) => - (a -> b) -> [a] -> String - pprintFunction f xs = intercalate "\n" [pprint x ++" -> " ++ pprint (f x) | x <- xs]
− src/IO/Show.hs
@@ -1,22 +0,0 @@-{-| Module : FiniteCategories -Description : Helpers for instanciating Show. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -Helpers for instanciating Show. --} -module IO.Show -( - showFunction -) -where - import Data.List (intercalate) - - -- | Show a function on a certain domain. - showFunction :: (Show a, Show b) => - (a -> b) -> [a] -> String - showFunction f xs = "(\\x -> case x of " ++ intercalate ";" [show x ++" -> " ++ show (f x) | x <- xs] ++ ")" -
− src/Limit/Limit.hs
@@ -1,41 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses #-} - -{-| Module : FiniteCategories -Description : The lim functor which takes every diagram to its limit object. See also ConeCategory for the limit of a specific diagram. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -The lim functor which takes every diagram to its limit object according to the global definition of limit. See also ConeCategory for the limit of a specific diagram. --} - -module Limit.Limit -( - limitFunctor, - colimitFunctor, -) -where - import FiniteCategory.FiniteCategory - import Diagram.Diagram - import Adjunction.Adjunction - import FunctorCategory.FunctorCategory - import DiagonalFunctor.DiagonalFunctor - import IO.PrettyPrint - - -- | Returns the limit functor according to the global definition of limit (see https://ncatlab.org/nlab/show/limit#global_definition_in_terms_of_adjoint_of_the_constant_diagram_functor). - -- - -- Given an indexing category @J@ and a category @C@, returns a functor which maps each diagram of form @J@ in @C@ to its limit object in @C@. - limitFunctor :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, PrettyPrintable c1, PrettyPrintable c2, PrettyPrintable o1, PrettyPrintable o2, PrettyPrintable m1, PrettyPrintable m2, - FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => - c1 -> c2 -> Diagram (FunctorCategory c1 m1 o1 c2 m2 o2) (NaturalTransformation c1 m1 o1 c2 m2 o2) (Diagram c1 m1 o1 c2 m2 o2) c2 m2 o2 - limitFunctor j c = rightAdjoint $ mkDiagonalFunctor j c - - -- | Returns the colimit functor according to the global definition of colimit (see https://ncatlab.org/nlab/show/limit#global_definition_in_terms_of_adjoint_of_the_constant_diagram_functor). - -- - -- Given an indexing category @J@ and a category @C@, returns a functor which maps each diagram of form @J@ in @C@ to its colimit object in @C@. - colimitFunctor :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, - FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => - c1 -> c2 -> Diagram (FunctorCategory c1 m1 o1 c2 m2 o2) (NaturalTransformation c1 m1 o1 c2 m2 o2) (Diagram c1 m1 o1 c2 m2 o2) c2 m2 o2 - colimitFunctor j c = leftAdjoint $ mkDiagonalFunctor j c
+ src/Math/Categories.hs view
@@ -0,0 +1,39 @@+{-# LANGUAGE MultiParamTypeClasses #-} + +{-| Module : FiniteCategories +Description : This file exports all categories. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +This file exports all categories. +-} + +module Math.Categories ( + module Math.Categories.Omega, + module Math.Categories.OrdinalCategory, + module Math.Categories.TotalOrder, + module Math.Categories.Galaxy, + module Math.Categories.FinSet, + module Math.Categories.FinGrph, + module Math.Categories.Opposite, + module Math.Categories.FinCat, + module Math.Categories.FunctorCategory, + module Math.Categories.CommaCategory, + module Math.Categories.ConeCategory, + module Math.Categories.PresheafCategory, +) where + import Math.Categories.Omega + import Math.Categories.OrdinalCategory + import Math.Categories.TotalOrder + import Math.Categories.Galaxy + import Math.Categories.FinSet + import Math.Categories.FinGrph + import Math.Categories.Opposite + import Math.Categories.FinCat + import Math.Categories.FunctorCategory + import Math.Categories.CommaCategory + import Math.Categories.ConeCategory + import Math.Categories.PresheafCategory
+ src/Math/Categories/CommaCategory.hs view
@@ -0,0 +1,200 @@+{-# LANGUAGE MultiParamTypeClasses, MonadComprehensions #-} + +{-| Module : FiniteCategories +Description : A 'CommaCategory' is intuitively a category where objects are selected morphisms of another category /C/ and morphisms are selected commutative squares in /C/. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +Each 'Category' has an opposite one where morphisms are reversed. + +A 'CommaCategory' is intuitively a category where objects are selected morphisms of another category /C/ and morphisms are selected commutative squares in /C/. + +More precisely, given two 'Diagram's @/T/ : /E/ -> /C/@ and @/S/ : /D/ -> /C/@, a `CommaObject` in the `CommaCategory` (/T/|/S/) is a triplet \<e,d,f\> where @f : /T/(e) -> /S/(d)@. + +A `CommaMorphism` from \<e1,d1,f1\> to \<e2,d2,f2\> in the `CommaCategory` (/T/|/S/) is a couple \<k,h\> where @/T/(k) : /T/(e1) -> /T/(e2)@, @/S/(h) : /S/(d1) -> /S/(d2)@ such that @f2 \@ /T/(k) = /S/(h) \@ f1@. + +See /Categories for the working mathematician/, Saunders Mac Lane, P.46. + +If the category /C/ is a 'FiniteCategory', then the 'CommaCategory' of /C/ is also a 'FiniteCategory'. Otherwise it is only a 'Category'. +-} + +module Math.Categories.CommaCategory +( + -- * Comma object + CommaObject, + -- ** Getters + indexSource, + indexTarget, + selectedArrow, + -- ** Smart constructors + commaObject, + unsafeCommaObject, + -- * Comma morphism + CommaMorphism, + -- ** Getters + indexFirstArrow, + indexSecondArrow, + -- ** Smart constructors + commaMorphism, + unsafeCommaMorphism, + CommaCategory(..), + sliceCategory, + cosliceCategory, + arrowCategory, +) +where + import qualified Data.WeakSet as Set + import Data.WeakSet (Set) + import Data.WeakSet.Safe + import qualified Data.WeakMap as Map + import Data.WeakMap (Map) + import Data.WeakMap.Safe + + import Math.Category + import Math.FiniteCategory + import Math.Categories.FinCat + import Math.Categories.FunctorCategory + import Math.FiniteCategories.One + import Math.IO.PrettyPrint + + -- | A `CommaObject` in the `CommaCategory` (/T/|/S/) is a triplet \<e,d,f\> where @f : /T/(e) -> /S/(d)@. + -- + -- See "Categories for the working mathematician", Saunders Mac Lane, P.46. + -- + -- The 'CommaObject' constructor is private, use the smart constructor 'commaObject' or the unsafe one 'unsafeCommaObject'. + data CommaObject o1 o2 m3 = CommaObject { indexSource :: o1 -- ^ e, the indexing object of the source of the 'selectedArrow'. + , indexTarget :: o2 -- ^ d, the indexing object of the target of the 'selectedArrow'. + , selectedArrow :: m3 -- ^ f, the selected arrow of the target category. + } deriving (Eq) + + instance (PrettyPrint o1, PrettyPrint o2, PrettyPrint m3) => + PrettyPrint (CommaObject o1 o2 m3) where + pprint CommaObject{indexSource=e, indexTarget=d, selectedArrow=f} = "<"++pprint e++", "++pprint d++", "++pprint f++">" + + instance (Show o1, Show o2, Show m3) => + Show (CommaObject o1 o2 m3) where + show CommaObject{indexSource=e, indexTarget=d, selectedArrow=f} = "(unsafeCommaObject ("++ show e ++ ") (" ++ show d ++ ") (" ++ show f ++ "))" + + -- | Smart constructor of 'CommaObject' which checks the structure of the 'CommaObject'. + commaObject :: (Morphism m3 o3, Eq o1, Eq o2, Eq o3) => Diagram c1 m1 o1 c3 m3 o3 -> Diagram c2 m2 o2 c3 m3 o3 -> o1 -> o2 -> m3 -> Maybe (CommaObject o1 o2 m3) + commaObject d1 d2 iS iT arr + | d1 ->$ iS == (source arr) && d2 ->$ iT == (target arr) = Just CommaObject{indexSource=iS, indexTarget=iT,selectedArrow=arr} + | otherwise = Nothing + + -- | Unsafe way of constructing a 'CommaObject' : the structure of the 'CommaObject' + unsafeCommaObject :: o1 -> o2 -> m3 -> CommaObject o1 o2 m3 + unsafeCommaObject iS iT arr = CommaObject{indexSource=iS, indexTarget=iT,selectedArrow=arr} + + -- | A `CommaMorphism` from \<e1,d1,f1\> to \<e2,d2,f2\> in the `CommaCategory` (/T/|/S/) is a couple \<k,h\> where @/T/(k) : /T/(e1) -> /T/(e2)@, @/S/(h) : /S/(d1) -> /S/(d2)@ such that @f2 \@ /T/(k) = /S/(h) \@ f1@. + -- + -- See "Categories for the working mathematician", Saunders Mac Lane, P.46. + data CommaMorphism o1 o2 m1 m2 m3 = CommaMorphism {srcCM :: (CommaObject o1 o2 m3) -- ^ The source `CommaObject` (private, use 'source' instead). + , tgtCM :: (CommaObject o1 o2 m3) -- ^ The target `CommaObject`, (private, use 'target' instead). + , indexFirstArrow :: m1 -- ^ k, the indexing arrow of the first functor. + , indexSecondArrow :: m2} -- ^ h, the indexing arrow of the second functor. + deriving (Eq) + + -- | Smart constructor of 'CommaMorphism', checks the structure of the 'CommaMorphism' at construction. + commaMorphism :: (Morphism m3 o3, Eq o1, Eq o2, Eq o3, Eq m1, Eq m2, Eq m3) => Diagram c1 m1 o1 c3 m3 o3 -> Diagram c2 m2 o2 c3 m3 o3 -> (CommaObject o1 o2 m3) -> (CommaObject o1 o2 m3) -> m1 -> m2 -> Maybe (CommaMorphism o1 o2 m1 m2 m3) + commaMorphism d1 d2 s t firstArr secondArr + | null m1 || null m2 || m1 /= m2 = Nothing + | otherwise = Just CommaMorphism{srcCM=s, tgtCM=t, indexFirstArrow=firstArr, indexSecondArrow=secondArr} + where + m1 = (selectedArrow t) @? (d1 ->£ firstArr) + m2 = (d2 ->£ secondArr) @? (selectedArrow s) + + -- | Unsafe constructor of 'CommaMorphism', does not check the structure of the 'CommaMorphism'. + unsafeCommaMorphism :: (CommaObject o1 o2 m3) -> (CommaObject o1 o2 m3) -> m1 -> m2 -> CommaMorphism o1 o2 m1 m2 m3 + unsafeCommaMorphism s t firstArr secondArr = CommaMorphism{srcCM=s, tgtCM=t, indexFirstArrow=firstArr, indexSecondArrow=secondArr} + + instance (Show o1, Show o2, Show m1, Show m2, Show m3) => + Show (CommaMorphism o1 o2 m1 m2 m3) where + show CommaMorphism{srcCM=s, tgtCM =t, indexFirstArrow=k, indexSecondArrow=h} = "(unsafeCommaMorphism ("++show s++") ("++show t++") ("++show k++") ("++show h++"))" + + instance (PrettyPrint m1, PrettyPrint m2) => + PrettyPrint (CommaMorphism o1 o2 m1 m2 m3) where + pprint CommaMorphism{srcCM=_, tgtCM =_, indexFirstArrow=k, indexSecondArrow=h} = "<"++pprint k++", "++pprint h++">" + + instance (Morphism m1 o1, Morphism m2 o2, Eq o1, Eq o2, Eq m3) => Morphism (CommaMorphism o1 o2 m1 m2 m3) (CommaObject o1 o2 m3) where + (@?) CommaMorphism{srcCM=s2,tgtCM=t2,indexFirstArrow=k2,indexSecondArrow=h2} CommaMorphism{srcCM=s1,tgtCM=t1,indexFirstArrow=k1,indexSecondArrow=h1} + | t1 /= s2 = Nothing + | null compoK = Nothing + | null compoH = Nothing + | otherwise = Just CommaMorphism{srcCM=s1,tgtCM=t2,indexFirstArrow=k,indexSecondArrow=h} + where + compoK = k2 @? k1 + Just k = compoK + compoH = h2 @? h1 + Just h = compoH + source = srcCM + target = tgtCM + + -- | A `CommaCategory` is a couple (/T/|/S/) with /T/ and /S/ two diagrams with the same target. + -- + -- See "Categories for the working mathematician", Saunders Mac Lane, P.46. + data CommaCategory c1 m1 o1 c2 m2 o2 c3 m3 o3 = CommaCategory {leftDiagram :: Diagram c1 m1 o1 c3 m3 o3 -- ^ /T/ + , rightDiagram :: Diagram c2 m2 o2 c3 m3 o3} -- ^ /S/ + deriving (Eq, Show) + + instance (Category c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, + Category c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2, + Category c3 m3 o3, Morphism m3 o3, Eq m3, Eq o3) => Category (CommaCategory c1 m1 o1 c2 m2 o2 c3 m3 o3) (CommaMorphism o1 o2 m1 m2 m3) (CommaObject o1 o2 m3) where + identity cc co = CommaMorphism{srcCM = co, tgtCM = co, indexFirstArrow = ((identity.src.leftDiagram $ cc) (indexSource co)), indexSecondArrow = ((identity.src.rightDiagram $ cc) (indexTarget co))} + ar CommaCategory{leftDiagram = t, rightDiagram = s} obj1@CommaObject{indexSource=e1,indexTarget=d1,selectedArrow=f1} obj2@CommaObject{indexSource=e2,indexTarget=d2,selectedArrow=f2} + = [CommaMorphism{srcCM=obj1,tgtCM=obj2,indexFirstArrow=k,indexSecondArrow=h}| k <- ar (src t) e1 e2, h <- ar (src s) d1 d2, f2 @ (t ->£ k) == (s ->£ h) @ f1] + + genAr CommaCategory{leftDiagram = t, rightDiagram = s} obj1@CommaObject{indexSource=e1,indexTarget=d1,selectedArrow=f1} obj2@CommaObject{indexSource=e2,indexTarget=d2,selectedArrow=f2} + | d1 == d2 = [CommaMorphism{srcCM=obj1,tgtCM=obj2,indexFirstArrow=k,indexSecondArrow=identity (src s) d1}| k <- genAr (src t) e1 e2, f2 @ (t ->£ k) == f1] + | e1 == e2 = [CommaMorphism{srcCM=obj1,tgtCM=obj2,indexFirstArrow=identity (src t) e1,indexSecondArrow=h}| h <- genAr (src s) d1 d2, f2 == (s ->£ h) @ f1] + | otherwise = set [] + + decompose cc cm + | length hyp == 1 = hyp + | otherwise = filter (isNotIdentity cc) hyp + where + hyp = decomposeHelper cc cm + decomposeHelper cc@CommaCategory{leftDiagram = t, rightDiagram = s} cm@CommaMorphism{srcCM=xfy,tgtCM=x'gy',indexFirstArrow=h,indexSecondArrow=i} + | xfy == x'gy' = [identity cc xfy] + | indexTarget xfy == indexTarget x'gy' = resultT:(decompose cc (unsafeCommaMorphism xfy (source resultT) composeAboveH (identity (src s) (indexTarget xfy)))) + | indexSource xfy == indexSource x'gy' = (decompose cc (unsafeCommaMorphism (target resultI) (target cm) (identity (src t) (indexSource xfy)) composeBelowI))++[resultI] + | otherwise = decompose cc (unsafeCommaMorphism (unsafeCommaObject (indexSource xfy) (indexTarget x'gy') (s ->£ i @ (selectedArrow xfy))) x'gy' h (identity (src s) (indexTarget x'gy'))) ++ decompose cc (unsafeCommaMorphism xfy (unsafeCommaObject (indexSource xfy) (indexTarget x'gy') (s ->£ i @ selectedArrow xfy)) (identity (src t) (indexSource xfy)) i) + where + decompH = decompose (src t) h ++ [identity (src t) (indexSource xfy)] + genH = head decompH + composeAboveH = compose.tail $ decompH + resultT = unsafeCommaMorphism (unsafeCommaObject (source genH) (indexTarget xfy) ((selectedArrow x'gy') @ (t ->£ genH))) x'gy' genH (identity (src s) (indexTarget xfy)) + decompI = [identity (src s) (indexTarget x'gy')] ++ decompose (src s) i + genI = last decompI + composeBelowI = compose.init $ decompI + resultI = unsafeCommaMorphism xfy (unsafeCommaObject (indexSource xfy) (target genI) ((s ->£ genI) @ (selectedArrow xfy))) (identity (src t) (indexSource xfy)) genI + + + instance (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2, + FiniteCategory c3 m3 o3, Morphism m3 o3, Eq m3, Eq o3) => FiniteCategory (CommaCategory c1 m1 o1 c2 m2 o2 c3 m3 o3) (CommaMorphism o1 o2 m1 m2 m3) (CommaObject o1 o2 m3) where + ob CommaCategory{leftDiagram = t, rightDiagram = s} = [CommaObject{indexSource=e,indexTarget=d,selectedArrow=f}| e <- (ob (src t)), d <- (ob (src s)), f <- ar (tgt t) (t ->$ e) (s ->$ d)] + + + + -- | Construct the slice category of a category /C/ over an object /o/. + -- + -- Return Nothing if the object is not in the category. + sliceCategory :: (FiniteCategory c m o, Morphism m o, Eq c, Eq m, Eq o) => c -> o -> Maybe (CommaCategory c m o One One One c m o) + sliceCategory c o + | o `isIn` ob c = Just CommaCategory{leftDiagram=identity FinCat c, rightDiagram=selectObject c o} + | otherwise = Nothing + + -- | Construct the coslice category of a category /C/ under an object /o/. + + -- Return Nothing if the object is not in the category. + cosliceCategory :: (FiniteCategory c m o, Morphism m o, Eq c, Eq m, Eq o) => c -> o -> Maybe (CommaCategory One One One c m o c m o) + cosliceCategory c o + | o `isIn` ob c = Just CommaCategory{leftDiagram=selectObject c o, rightDiagram=identity FinCat c} + | otherwise = Nothing + + -- | Construct the arrow category of a category /C/. + arrowCategory :: (FiniteCategory c m o, Morphism m o, Eq c, Eq m, Eq o) => c -> CommaCategory c m o c m o c m o + arrowCategory c = CommaCategory{leftDiagram=identity FinCat c, rightDiagram=identity FinCat c}
+ src/Math/Categories/ConeCategory.hs view
@@ -0,0 +1,190 @@+{-| Module : FiniteCategories +Description : Category of 'Cone's of a 'Diagram'. +Copyright : Guillaume Sabbagh 2021 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +Category of 'Cone's of a 'Diagram'. + +This module allows to find the (co)'limit' of a 'Diagram'. +-} + +module Math.Categories.ConeCategory +( + -- * Cone + Cone, + -- ** Helper functions + apex, + baseCone, + legsCone, + naturalTransformationToCone, + -- * Cone Morphism + ConeMorphism, + -- ** Helper function + bindingMorphismCone, + -- * Cone Category + ConeCategory, + -- ** Helper functions + coneCategory, + limits, + -- * Cocone + Cocone, + -- ** Helper functions + nadir, + baseCocone, + legsCocone, + naturalTransformationToCocone, + -- * Cocone Morphism + CoconeMorphism, + -- ** Helper function + bindingMorphismCocone, + -- * Cocone Category + CoconeCategory, + -- ** Helper functions + coconeCategory, + colimits, +) +where + 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 Math.Category + import Math.FiniteCategory + import Math.Categories.CommaCategory + import Math.Categories.FunctorCategory + import Math.Functors.DiagonalFunctor + import Math.FiniteCategories.One + + + -- -------------------------------- + -- Cone related functions and types. + -- -------------------------------- + + -- | A `Cone` is a `CommaObject` in the `CommaCategory` (/D/|1_/F/) where /D/ is the 'diagonalFunctor' and /F/ is the 'Diagram' of interest. + -- + -- Intuitively, a 'Cone' is an 'apex', a base and a set of legs indexed by the indexing objects of /F/ such that the legs commute with every arrow in the base of the 'Cone'. + -- + -- See "Categories for the working mathematician", Saunders Mac Lane, P.67. + type Cone c1 m1 o1 c2 m2 o2 = CommaObject o2 One (NaturalTransformation c1 m1 o1 c2 m2 o2) + + -- | Return the apex of a `Cone`. + apex :: Cone c1 m1 o1 c2 m2 o2 -> o2 + apex = indexSource + + -- | Return the base of a 'Cone'. + baseCone :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + Morphism m2 o2, Eq c2, Eq m2, Eq o2) => + Cone c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 c2 m2 o2 + baseCone = target.selectedArrow + + -- | Return the legs of a 'Cone' as a 'NaturalTransformation'. + legsCone :: Cone c1 m1 o1 c2 m2 o2 -> NaturalTransformation c1 m1 o1 c2 m2 o2 + legsCone = selectedArrow + + -- | Transform a `NaturalTransformation` from a 'constantDiagram' to a 'Diagram' /D/ into a `Cone` on /D/. + naturalTransformationToCone :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1 + ,Category c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => + NaturalTransformation c1 m1 o1 c2 m2 o2 -> Maybe (Cone c1 m1 o1 c2 m2 o2) + naturalTransformationToCone nt + | Set.null (ob (src.source $ nt)) = Nothing + | source nt /= constDiag = Nothing + | otherwise = Just $ unsafeCommaObject apexCandidate One nt + where + apexCandidate = (source nt) ->$ (anElement.ob.src.source $ nt) + constDiag = constantDiagram (src.source $ nt) (tgt.source $ nt) apexCandidate + + -- | A `ConeMorphism` is a morphism binding two 'Cone's. Formally, it is a 'CommaMorphism' in the 'CommaCategory' (/D/|1_/F/) where /D/ is the 'diagonalFunctor' and /F/ is the 'Diagram' of interest. + type ConeMorphism c1 m1 o1 c2 m2 o2 = CommaMorphism o2 One m2 One (NaturalTransformation c1 m1 o1 c2 m2 o2) + + -- | Return the binding morphism between the two 'Cone's of a 'ConeMorphism. + bindingMorphismCone :: ConeMorphism c1 m1 o1 c2 m2 o2 -> m2 + bindingMorphismCone = indexFirstArrow + + -- | A `ConeCategory` is the category of 'Cone's of a given 'Diagram', it is a `CommaCategory` (/D/|1_/F/) where /D/ is the 'diagonalFunctor' and /F/ is the 'Diagram' of interest. + type ConeCategory c1 m1 o1 c2 m2 o2 = CommaCategory c2 m2 o2 One One One (FunctorCategory c1 m1 o1 c2 m2 o2) (NaturalTransformation c1 m1 o1 c2 m2 o2) (Diagram c1 m1 o1 c2 m2 o2) + + + -- | Construct the category of cones of a 'Diagram'. + coneCategory :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => + Diagram c1 m1 o1 c2 m2 o2 -> ConeCategory c1 m1 o1 c2 m2 o2 + coneCategory diag@Diagram{src=s,tgt=t,omap=om,mmap=fm} = CommaCategory {leftDiagram = diagonalFunct + , rightDiagram = selectObject (tgt diagonalFunct) diag} + where + diagonalFunct = diagonalFunctor s t + + -- | Returns limits of a diagram (terminal cones). + limits :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => + Diagram c1 m1 o1 c2 m2 o2 -> Set (Cone c1 m1 o1 c2 m2 o2) + limits = terminalObjects.coneCategory + + + -- -- -------------------------------- + -- -- Cocone related functions and types. + -- -- -------------------------------- + + -- | A `Cocone` is a `CommaObject` in the `CommaCategory` (1_/F/|/D/) where /D/ is the 'diagonalFunctor' and /F/ is the 'Diagram' of interest. + -- + -- Intuitively, a 'Cocone' is a 'nadir', a base and a set of legs indexed by the indexing objects of /F/ such that the legs commute with every arrow in the base of the 'Cocone'. + -- + -- A 'Cocone' is simply the dual of a 'Cone'. + type Cocone c1 m1 o1 c2 m2 o2 = CommaObject One o2 (NaturalTransformation c1 m1 o1 c2 m2 o2) + + -- | Return the nadir of a `Cocone`. + nadir :: Cocone c1 m1 o1 c2 m2 o2 -> o2 + nadir = indexTarget + + -- | Return the base of a 'Cocone'. + baseCocone :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + Morphism m2 o2, Eq c2, Eq m2, Eq o2) => + Cocone c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 c2 m2 o2 + baseCocone = source.selectedArrow + + -- | Return the legs of a 'Cocone' as a 'NaturalTransformation'. + legsCocone :: Cocone c1 m1 o1 c2 m2 o2 -> NaturalTransformation c1 m1 o1 c2 m2 o2 + legsCocone = selectedArrow + + -- | Transform a `NaturalTransformation` from a 'Diagram' /D/ to a 'constantDiagram' into a `Cocone` on /D/. + naturalTransformationToCocone :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1 + ,FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => + NaturalTransformation c1 m1 o1 c2 m2 o2 -> Maybe (Cocone c1 m1 o1 c2 m2 o2) + naturalTransformationToCocone nt + | Set.null (ob (src.source $ nt)) = Nothing + | target nt /= constDiag = Nothing + | otherwise = Just $ unsafeCommaObject One nadirCandidate nt + where + nadirCandidate = (target nt) ->$ (anElement.ob.src.source $ nt) + constDiag = constantDiagram (src.source $ nt) (tgt.source $ nt) nadirCandidate + + -- | A `CoconeMorphism` is a morphism binding two 'Cocone's. Formally, it is a 'CommaMorphism' in the 'CommaCategory' (1_/F/|/D/) where /D/ is the 'diagonalFunctor' and /F/ is the 'Diagram' of interest. + type CoconeMorphism c1 m1 o1 c2 m2 o2 = CommaMorphism One o2 One m2 (NaturalTransformation c1 m1 o1 c2 m2 o2) + + -- | Return the binding morphism between the two 'Cocone's of a 'CoconeMorphism. + bindingMorphismCocone :: CoconeMorphism c1 m1 o1 c2 m2 o2 -> m2 + bindingMorphismCocone = indexSecondArrow + + -- | A `CoconeCategory` is the category of 'Cocone's of a given 'Diagram', it is a `CommaCategory` (1_/F/|/D/) where /D/ is the 'diagonalFunctor' and /F/ is the 'Diagram' of interest. + type CoconeCategory c1 m1 o1 c2 m2 o2 = CommaCategory One One One c2 m2 o2 (FunctorCategory c1 m1 o1 c2 m2 o2) (NaturalTransformation c1 m1 o1 c2 m2 o2) (Diagram c1 m1 o1 c2 m2 o2) + + -- | Construct the category of cocones of a 'Diagram'. + coconeCategory :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => + Diagram c1 m1 o1 c2 m2 o2 -> CoconeCategory c1 m1 o1 c2 m2 o2 + coconeCategory diag@Diagram{src=s,tgt=t,omap=om,mmap=fm} = CommaCategory {leftDiagram = selectObject (tgt diagonalFunct) diag + , rightDiagram = diagonalFunct} + where + diagonalFunct = diagonalFunctor s t + + -- | Returns colimits of a diagram (initial cocones). + colimits :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => + Diagram c1 m1 o1 c2 m2 o2 -> Set (Cocone c1 m1 o1 c2 m2 o2) + colimits = initialObjects.coconeCategory +
+ src/Math/Categories/FinCat.hs view
@@ -0,0 +1,70 @@+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, MonadComprehensions #-} + +{-| Module : FiniteCategories +Description : __'FinCat'__ is the category of finite categories, 'FinFunctor's are the morphisms of __'FinCat'__. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +The __FinCat__ category has as objects finite categories and as morphisms homogeneous functors between them. + +Functors must be homogeneous because otherwise we would not be able to compose them with the 'Morphism' typeclass. + +The 'FinCat' datatype should not be confused with the `FiniteCategory` typeclass. The `FiniteCategory` typeclass describes axioms a structure should follow to be considered a finite category. The 'FinCat' type is itself a 'Category'. + +A 'FinFunctor' is a 'Diagram' where the source and target category are the same. The source category of a 'FinFunctor' should be finite. +-} + +module Math.Categories.FinCat +( + -- * Homogeneous functor + FinFunctor(..), + -- * __FinCat__ + FinCat(..) +) +where + 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 Math.Category + import Math.FiniteCategory + import Math.Categories.FunctorCategory + import Math.IO.PrettyPrint + + -- | A `FinFunctor` /funct/ between two categories is a map between objects and a map between arrows of the two categories such that : + -- + -- prop> funct ->$ (source f) == source (funct ->£ f) + -- prop> funct ->$ (target f) == target (funct ->£ f) + -- prop> funct ->£ (f @ g) = (funct ->£ f) @ (funct ->£ g) + -- prop> funct ->£ (identity a) = identity (funct ->$ a) + -- + -- A 'FinFunctor' is a type of 'Diagram'. + -- + -- It is meant to be a morphism between categories within __`FinCat`__, it is homogeneous, the type of the source category must be the same as the type of the target category. + -- + -- See 'Diagram' in Math.Categories.FunctorCategory for heterogeneous ones. + type FinFunctor c m o = Diagram c m o c m o + + instance (Eq c, Eq m, Eq o) => Morphism (Diagram c m o c m o) c where + (@?) Diagram{src=s2,tgt=t2,omap=om2,mmap=fm2} Diagram{src=s1,tgt=t1,omap=om1,mmap=fm1} + | t1 /= s2 = Nothing + | otherwise = Just Diagram{src=s1,tgt=t2,omap=om2|.|om1,mmap=fm2|.|fm1} + source = src + target = tgt + + -- | The __'FinCat'__ category has as objects finite categories and as morphisms homogeneous functors between them. + data FinCat c m o = FinCat deriving (Eq, Show) + + instance (FiniteCategory c m o, Morphism m o, Eq c, Eq m, Eq o) => Category (FinCat c m o) (Diagram c m o c m o) c where + identity _ cat = Diagram{src=cat,tgt=cat,omap=memorizeFunction id (ob cat),mmap=memorizeFunction id (arrows cat)} + ar _ s t = snd.(Set.catEither) $ [diagram s t appO appF | appO <- appObj, appF <- ((fmap $ (Map.unions)).cartesianProductOfSets) [twoObjToMaps a b appO| a <- (setToList $ ob s), b <- (setToList $ ob s)]] + where + appObj = Map.enumerateMaps (ob s) (ob t) + twoObjToMaps a b appO = Map.enumerateMaps (ar s a b) (ar t (appO |!| a) (appO |!| b)) +
+ src/Math/Categories/FinGrph.hs view
@@ -0,0 +1,155 @@+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, MonadComprehensions #-} + +{-| Module : FiniteCategories +Description : The __'FinGrph'__ category has finite multidigraphs as objects and multidigraph homomorphisms as morphisms. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +The __'FinGrph'__ category has finite multidigraphs as objects and multidigraph homomorphisms as morphisms. +-} + +module Math.Categories.FinGrph +( + -- * Graph + Arrow(..), + Graph, + -- ** Getters + nodes, + edges, + -- ** Smart constructors + graph, + unsafeGraph, + -- * Graph homomorphism + GraphHomomorphism, + -- ** Getters + nodeMap, + edgeMap, + -- ** Smart constructor + checkGraphHomomorphism, + graphHomomorphism, + unsafeGraphHomomorphism, + -- * FinGrph + FinGrph(..), + underlyingGraph, + underlyingGraphFormat, +) +where + import Math.Category + import Math.FiniteCategory + 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 + + -- | An 'Arrow' is composed of a source node, a target node and a label. + data Arrow n e = Arrow{ + sourceArrow :: n, + targetArrow :: n, + labelArrow :: e + } + deriving (Eq, Show) + + instance (PrettyPrint n, PrettyPrint e) => PrettyPrint (Arrow n e) where + pprint a = (pprint $ sourceArrow a)++"-"++(pprint $ labelArrow a)++"->"++(pprint $ targetArrow a) + + -- | A 'Graph' is a set of nodes and a set of 'Arrow's. + -- + -- 'Graph' is private, use smart constructor 'graph'. + data Graph n e = Graph { + nodes :: Set n, -- ^ The set of nodes of the graph. + edges :: Set (Arrow n e) -- ^ The set of arrows of the graph. + } deriving (Eq) + + instance (Show n, Show e) => Show (Graph n e) where + show g = "(unsafeGraph "++(show $ nodes g)++" "++(show $ edges g)++")" + + -- | Smart constructor of 'Graph'. + graph :: (Eq n) => Set n -> Set (Arrow n e) -> Maybe (Graph n e) + graph ns es + | (sourceArrow <$> es) `isIncludedIn` ns && (targetArrow <$> es) `isIncludedIn` ns = Just Graph{nodes=ns, edges=es} + | otherwise = Nothing + + -- | Unsafe constructor of 'Graph', does not check the 'Graph' structure. + unsafeGraph :: Set n -> Set (Arrow n e) -> Graph n e + unsafeGraph n e = Graph{nodes=n, edges=e} + + instance (PrettyPrint n, PrettyPrint e, Eq n, Eq e) => PrettyPrint (Graph n e) where + pprint g = "Graph ("++(pprint $ nodes g)++", "++(pprint $ edges g)++")" + + -- | A 'GraphHomomorphism' is composed of a map between the nodes of the graphs, a map between the edges of the graphs, and the target 'Graph' so that we can recover it from the morphism. + -- + -- It must follow axioms such that the image of an arrow is not torn appart, that is why the constructor is private. Use the smart constructor 'graphHomomorphism' instead. + data GraphHomomorphism n e = GraphHomomorphism { + nodeMap :: Map n n, -- ^ The mapping of nodes. + edgeMap :: Map (Arrow n e) (Arrow n e), -- ^ The mapping of edges. + targetGraph :: Graph n e -- ^ The target graph. + } deriving (Eq) + + -- | Check wether the structure of 'GraphHomomorphism' is respected or not. + checkGraphHomomorphism :: (Eq n, Eq e) => GraphHomomorphism n e -> Bool + checkGraphHomomorphism gh = imageInTarget && Set.and noTear + where + noTear = [(nodeMap gh) |!| (sourceArrow arr) == sourceArrow ((edgeMap gh) |!| arr) && (nodeMap gh) |!| (targetArrow arr) == targetArrow ((edgeMap gh) |!| arr)| arr <- (domain.edgeMap) gh] + imageInTarget = (image.nodeMap) gh `isIncludedIn` (nodes.targetGraph) gh && (image.edgeMap) gh `isIncludedIn` (edges.targetGraph) gh + + -- | The smart constructor of 'GraphHomomorphism'. + graphHomomorphism :: (Eq n, Eq e) => Map n n -> Map (Arrow n e) (Arrow n e) -> Graph n e -> Maybe (GraphHomomorphism n e) + graphHomomorphism nm em tg + | checkGraphHomomorphism gh = Just gh + | otherwise = Nothing + where + gh = GraphHomomorphism{nodeMap=nm, edgeMap=em, targetGraph=tg} + + -- | Unsafe constructor of 'GraphHomomorphism' which does not check the structure of the 'GraphHomomorphism'. + unsafeGraphHomomorphism :: Map n n -> Map (Arrow n e) (Arrow n e) -> Graph n e -> GraphHomomorphism n e + unsafeGraphHomomorphism nm em tg = GraphHomomorphism{nodeMap=nm, edgeMap=em, targetGraph=tg} + + instance (Show n, Show e) => Show (GraphHomomorphism n e) where + show gh = "(unsafeGraphHomomorphism "++(show $ nodeMap gh)++" "++(show $ edgeMap gh)++ " " ++ (show $ targetGraph gh) ++")" + + instance (PrettyPrint n, PrettyPrint e, Eq n, Eq e) => PrettyPrint (GraphHomomorphism n e) where + pprint gh = "("++(pprint $ nodeMap gh)++", "++(pprint $ edgeMap gh)++")" + + instance (Eq n, Eq e) => Morphism (GraphHomomorphism n e) (Graph n e) where + source gh = Graph {nodes = (domain.nodeMap) gh, edges = (domain.edgeMap) gh} + target = targetGraph + (@?) gh2 gh1 + | target gh1 == source gh2 = Just $ GraphHomomorphism {nodeMap = (nodeMap gh2) |.| (nodeMap gh1), edgeMap = (edgeMap gh2) |.| (edgeMap gh1), targetGraph = target gh2} + | otherwise = Nothing + + -- | The category of finite graphs. + data FinGrph n e = FinGrph deriving (Eq, Show) + + instance (PrettyPrint n, PrettyPrint e, Eq n, Eq e) => PrettyPrint (FinGrph n e) where + pprint = show + + instance (Eq n, Eq e, Show n ,Show e) => Category (FinGrph n e) (GraphHomomorphism n e) (Graph n e) where + identity _ g = GraphHomomorphism {nodeMap = (idFromSet.nodes) g, edgeMap = (idFromSet.edges) g, targetGraph = g} + ar _ s t = [GraphHomomorphism + { + nodeMap = appO, edgeMap = appF, targetGraph = t + } | appO <- appObj, appF <- ((fmap $ (Map.unions)).cartesianProductOfSets $ [twoObjToEdgeMaps x y appO | x <- (setToList $ nodes s), y <- (setToList $ nodes s)])] + where + appObj = Map.enumerateMaps (nodes s) (nodes t) + twoObjToEdgeMaps n1 n2 nMap = Map.enumerateMaps (Set.filter (\a -> sourceArrow a == n1 && targetArrow a == n2) (edges s)) (Set.filter (\a -> sourceArrow a == nMap |!| n1 && targetArrow a == nMap |!| n2) (edges t)) + + -- | Return the underlying graph of a 'FiniteCategory'. + underlyingGraph :: (FiniteCategory c m o, Morphism m o) => c -> Graph o m + underlyingGraph c = Graph{ + nodes = ob c, + edges = (\m -> Arrow{sourceArrow=source m, targetArrow=target m, labelArrow=m}) <$> arrows c + } + + -- | Return the underlying graph of a 'FiniteCategory' and apply formatting functions on objects and arrows. + underlyingGraphFormat :: (FiniteCategory c m o, Morphism m o) => (o -> a) -> (m -> b) -> c -> Graph a b + underlyingGraphFormat formatObj formatAr c = Graph{ + nodes = formatObj <$> ob c, + edges = (\m -> Arrow{sourceArrow=formatObj.source $ m, targetArrow=formatObj.target $ m, labelArrow=formatAr m}) <$> arrows c + }
+ src/Math/Categories/FinSet.hs view
@@ -0,0 +1,93 @@+{-# 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
+ src/Math/Categories/FunctorCategory.hs view
@@ -0,0 +1,468 @@+{-# LANGUAGE MultiParamTypeClasses, MonadComprehensions #-} + +{-| Module : FiniteCategories +Description : A 'FunctorCategory' has 'Diagram's as objects and 'NaturalTransformation's between them as morphisms. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +A 'FunctorCategory' /D/^/C/ (also written [/C/,/D/]) where /C/ is a 'FiniteCategory' and /D/ is a 'Category' has 'Diagram's @F : C -> D@ as objects and 'NaturalTransformation's between them as morphisms. 'NaturalTransformation's compose vertically in this category. See the operator ('<=@<=') for horizontal composition. + +A 'Diagram' is a heterogeneous functor, meaning that the source category might be different from the target category. We don't see a diagram as a morphism of categories but as a selection in the target category. See 'FinCat' for a context where 'Diagram's are seen as morphisms of categories. + +'Diagram's are objects in a 'FunctorCategory', they therefore can not be composed with the usual operator ('@'). See ('<-@<-') for composing 'Diagram's. + +Beware that 'source' and 'target' are not defined on 'Diagram' because it is not a 'Morphism', use 'src' and 'tgt' instead. + +You can also do left and right whiskering with the operators ('<=@<-') and ('<-@<='). + +A `FunctorCategory` is a 'FiniteCategory' if the source and target category are finite, but it is only a 'Category' if the target category is not finite. + +All operators defined in this module respect the following convention: a "->" arrow represent a functor and a "=>" represent a natural transformation. For example ('<-@<=') allows to compose a natural transformation (the "<=" arrow) with a functor (the "<-" arrow), note that composition is always read from right to left. + +-} + +module Math.Categories.FunctorCategory +( + -- * Diagram + Diagram(..), + -- ** Check diagram structure + DiagramError, + checkFiniteDiagram, + checkDiagram, + diagram, + -- ** Operators + (->$), + (->£), + (<-@<-), + -- ** Usual diagrams + selectObject, + constantDiagram, + discreteDiagram, + parallelDiagram, + -- *** Insertion diagrams for subcategories + insertionFunctor1, + insertionFunctor2, + -- ** Diagram construction helper + completeDiagram, + pickRandomDiagram, + -- * Natural transformation + NaturalTransformation, + -- ** Getter + components, + -- ** Check structure + NaturalTransformationError, + checkNaturalTransformation, + naturalTransformation, + unsafeNaturalTransformation, + -- ** Operators + (=>$), + (<=@<=), + horizontalComposition, + (<=@<-), + leftWhiskering, + (<-@<=), + rightWhiskering, + -- * Functor categories + FunctorCategory(..), + PrecomposedFunctorCategory(..), + PostcomposedFunctorCategory(..), +) +where + 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 Math.Category + import Math.FiniteCategories.One + import Math.Categories.Galaxy + import Math.FiniteCategories.DiscreteCategory + import Math.FiniteCategories.Parallel + import Math.FiniteCategories.FullSubcategory + import Math.FiniteCategory + import Math.IO.PrettyPrint + + import System.Random (RandomGen, uniformR) + + + -- | A 'Diagram' is a functor from a 'FiniteCategory' to a 'Category'. + -- + -- A 'Diagram' can have a source category and a target category with different types. It must obey the following rules : + -- + -- prop> funct ->$ (source f) == source (funct ->£ f) + -- prop> funct ->$ (target f) == target (funct ->£ f) + -- prop> funct ->£ (f @ g) = (funct ->£ f) @ (funct ->£ g) + -- prop> funct ->£ (identity a) = identity (funct ->$ a) + -- + -- 'Diagram' is not private because we can't always check functoriality if the target category is infinite. + -- However it is recommanded to use the smart constructor 'diagram' which checks the structure of the 'Diagram' at construction. + data Diagram c1 m1 o1 c2 m2 o2 = Diagram { + src :: c1, -- ^ The source category + tgt :: c2, -- ^ The target category + omap :: Map o1 o2, -- ^ The object map + mmap :: Map m1 m2 -- ^ The morphism map + } deriving (Eq, Show) + + instance ( PrettyPrint c1, PrettyPrint m1, PrettyPrint o1, Eq m1, Eq o1, + PrettyPrint c2, PrettyPrint m2, PrettyPrint o2, Eq m2, Eq o2) => PrettyPrint (Diagram c1 m1 o1 c2 m2 o2) where + pprint funct = "Diagram(" ++ pprint (src funct) ++ "->" ++ pprint (tgt funct) ++ "," ++ pprint (omap funct) ++ "," ++ pprint (mmap funct) ++ ")" + + -- | Apply a 'Diagram' on an object of the source category. + (->$) :: (Eq o1) => Diagram c1 m1 o1 c2 m2 o2 -> o1 -> o2 + (->$) f x = omap f |!| x + + -- | Apply a 'Diagram' on a morphism of the source category. + (->£) :: (Eq m1) => Diagram c1 m1 o1 c2 m2 o2 -> m1 -> m2 + (->£) f x = mmap f |!| x + + -- | Compose two 'Diagram's. + (<-@<-) :: (Eq o2, Eq m2) => Diagram c2 m2 o2 c3 m3 o3 -> Diagram c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 c3 m3 o3 + (<-@<-) g f = Diagram{src = src f, tgt = tgt g, omap = (omap g) |.| (omap f), mmap = (mmap g) |.| (mmap f)} + + -- | Construct a 'Diagram' selecting an object in a category. + -- + -- There is no check that the object belongs in the category. + selectObject :: (Category c m o, Morphism m o, Eq o) => c -> o -> Diagram One One One c m o + selectObject c o = Diagram{src=One, tgt=c, omap=weakMap [(One,o)], mmap=weakMap [(One, identity c o)]} + + -- | Construct a constant 'Diagram' on an object of the target 'Category' given an indexing 'FiniteCategory'. + -- + -- There is no check that the object belongs in the category. + constantDiagram :: (FiniteCategory c1 m1 o1, Morphism m1 o1, + Category c2 m2 o2, Morphism m2 o2) => + c1 -> c2 -> o2 -> Diagram c1 m1 o1 c2 m2 o2 + constantDiagram index targ o = Diagram{src=index, tgt=targ, omap=memorizeFunction (const o) (ob index), mmap=memorizeFunction (const (identity targ o)) (arrows index)} + + -- | Construct a discrete 'Diagram' on a list of objects of the target 'Category'. + -- + -- We consider list of objects because a single object can be selected several times. + -- + -- There is no check that the objects belongs in the category. + discreteDiagram :: (Category c m o, Morphism m o, Eq o) => + c -> [o] -> Diagram (DiscreteCategory Int) (DiscreteMorphism Int) Int c m o + discreteDiagram targ os = Diagram{src=discreteCategory indices, tgt=targ, omap=memorizeFunction (os !!) indices, mmap=memorizeFunction (\(StarIdentity x) -> identity targ (os !! x)) (arrows (discreteCategory indices))} + where + indices = set [0..((length os)-1)] + + -- | Construct a parallel 'Diagram' on two parallel morphisms of the target 'Category'. + -- + -- There is no check that the morphisms belongs in the category and no check that the two morphisms are parallel. + parallelDiagram :: (Category c m o, Morphism m o, Eq o) => + c -> m -> m -> Diagram Parallel ParallelAr ParallelOb c m o + parallelDiagram targ f g = completeDiagram Diagram{src=Parallel, tgt=targ, omap=weakMap [(ParallelA,source f),(ParallelB,target f)], mmap=weakMap [(ParallelF, f), (ParallelG, g)]} + + + -- Diagram structure check + + -- | A datatype to represent a malformation of a 'Diagram'. + data DiagramError c1 m1 o1 c2 m2 o2 = WrongDomainObjects{srcObjs :: Set o1, domainObjs :: Set o1} -- ^ The objects in the domain of the object mapping are not the same as the objects of the source category. + | WrongDomainMorphisms{srcMorphs :: Set m1, domainMorphs :: Set m1} -- ^ The morphisms in the domain of the morphism mapping are not the same as the morphisms of the source category. + | WrongImageObjects{imageObjs :: Set o2, codomainObjs :: Set o2} -- ^ The objects in the image of the object mapping are not included in the objects of the codomain category. + | WrongImageMorphisms{imageMorphs :: Set m2, codomainMorphs :: Set m2} -- ^ The morphisms in the image of the morphism mapping are not included in the morphisms of the codomain category. + | TornMorphism{f :: m1, fImage :: m2} -- ^ A morphism /f/ is torn apart. + | IdentityNotPreserved{originalId :: m1, imageId :: m2} -- ^ The image of an identity is not an identity. + | CompositionNotPreserved{f :: m1, g :: m1, imageFG :: m2} -- ^ Composition is not preserved by the functor. + deriving (Eq, Show) + + -- | Check wether the properties of a 'Diagram' are respected where the target category is finite. + checkFiniteDiagram :: (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 -> Maybe (DiagramError c1 m1 o1 c2 m2 o2) + checkFiniteDiagram d@Diagram{src=s,tgt=t,omap=om,mmap=fm} + | domain om /= ob s = Just WrongDomainObjects{srcObjs = ob s, domainObjs = domain om} + | domain fm /= arrows s = Just WrongDomainMorphisms{srcMorphs = arrows s, domainMorphs = domain fm} + | not $ image om `isIncludedIn` ob t = Just WrongImageObjects{imageObjs = image om, codomainObjs = ob t} + | not $ image fm `isIncludedIn` arrows t = Just WrongImageMorphisms{imageMorphs = image fm, codomainMorphs = arrows t} + | not.(Set.null) $ tear = Just TornMorphism{f = anElement tear, fImage = d ->£ (anElement tear)} + | not.(Set.null) $ imId = Just IdentityNotPreserved{originalId = identity s (anElement imId), imageId = d ->£ (identity s (anElement imId))} + | not.(Set.null) $ errCompo = Just CompositionNotPreserved{f = fst (anElement errCompo), g = snd (anElement errCompo), imageFG = d ->£ ((snd (anElement errCompo)) @ (fst (anElement errCompo)))} + | otherwise = Nothing + where + tear = [arr | arr <- domain fm, om |!| (source arr) /= source (fm |!| arr) || om |!| (target arr) /= target (fm |!| arr)] + imId = [a | a <- ob s, fm |!| (identity s a) /= identity t (om |!| a)] + errCompo = [(f,g) | f <- (arrows s), g <- (arFrom s (target f)), fm |!| (g @ f) /= (fm |!| g) @ (fm |!| f)] + + -- | Check wether the properties of a 'Diagram' are respected where the target category is infinite. + checkDiagram :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, + Category c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2) => + Diagram c1 m1 o1 c2 m2 o2 -> Maybe (DiagramError c1 m1 o1 c2 m2 o2) + checkDiagram d@Diagram{src=s,tgt=t,omap=om,mmap=fm} + | domain om /= ob s = Just WrongDomainObjects{srcObjs = ob s, domainObjs = domain om} + | domain fm /= arrows s = Just WrongDomainMorphisms{srcMorphs = arrows s, domainMorphs = domain fm} + | not.(Set.null) $ tear = Just TornMorphism{f = anElement tear, fImage = d ->£ (anElement tear)} + | not.(Set.null) $ imId = Just IdentityNotPreserved{originalId = identity s (anElement imId), imageId = d ->£ (identity s (anElement imId))} + | not.(Set.null) $ errCompo = Just CompositionNotPreserved{f = fst (anElement errCompo), g = snd (anElement errCompo), imageFG = d ->£ ((snd (anElement errCompo)) @ (fst (anElement errCompo)))} + | otherwise = Nothing + where + tear = [arr | arr <- domain fm, om |!| (source arr) /= source (fm |!| arr) || om |!| (target arr) /= target (fm |!| arr)] + imId = [a | a <- ob s, fm |!| (identity s a) /= identity t (om |!| a)] + errCompo = [(f,g) | f <- (arrows s), g <- (arFrom s (target f)), fm |!| (g @ f) /= (fm |!| g) @ (fm |!| f)] + + -- | Smart constructor of 'Diagram'. + diagram :: ( FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2) => + c1 -> c2 -> Map o1 o2 -> Map m1 m2 -> Either (DiagramError c1 m1 o1 c2 m2 o2) (Diagram c1 m1 o1 c2 m2 o2) + diagram c1 c2 om mm + | null check = Right diag + | otherwise = Left err + where + diag = Diagram{src = c1, tgt = c2, omap = om, mmap = mm} + check = checkFiniteDiagram diag + Just err = check + + -- | Complete a partial 'Diagram' by adding the mapping between identities and the mapping between composite morphisms using the decomposition of the indexing category. + -- + -- Does not check the structure of the resulting 'Diagram', you can use 'checkFiniteDiagram' to check afterwards. + completeDiagram :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, + Category c2 m2 o2, Morphism m2 o2) => + Diagram c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 c2 m2 o2 + completeDiagram Diagram{src=s,tgt=t,omap=om,mmap=mm} = Diagram{src=s,tgt=t,omap=om, mmap=Map.unions [mm, mapId, mapCompo] } + where + mapId = weakMapFromSet [(identity s o, identity t (om |!| o)) | o <- ob s] + mapCompo = weakMapFromSet [(f, compose $ (mm |!|) <$> decompose s f) | f <- arrows s, isComposite s f] + + + -- | Pick one element of a list randomly. + pickOne :: (RandomGen g) => [a] -> g -> (a,g) + pickOne [] g = error "pickOne in an empty list." + pickOne l g = ((l !! index),newGen) where + (index,newGen) = (uniformR (0,(length l)-1) g) + + -- | Choose a random diagram in the functor category of an index category and an image category. + pickRandomDiagram :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2, + RandomGen g) => c1 -> c2 -> g -> (Diagram c1 m1 o1 c2 m2 o2, g) + pickRandomDiagram index cat gen = pickOne (setToList.ob $ FunctorCategory index cat) gen + + + + + -- NaturalTransformation + + -- | A `NaturalTransformation` between two 'Diagram's from /C/ to /D/ is a mapping from objects of /C/ to morphisms of /D/ such that naturality is respected. /C/ must be a 'FiniteCategory' because we need its objects in the mapping of a 'NaturalTransformation'. + -- + -- Formally, let /F/ and /G/ be functors, and eta : Ob(/C/) -> Ar(/D/). The following properties should be respected : + -- + -- prop> source F = source G + -- prop> target F = target G + -- prop> (eta =>$ target f) @ (F ->£ f) = (G ->£ f) @ (eta =>$ source f) + -- + -- 'NaturalTransformation' is private, use the smart constructor 'naturalTransformation' to instantiate it. + data NaturalTransformation c1 m1 o1 c2 m2 o2 = NaturalTransformation + { + srcNT :: Diagram c1 m1 o1 c2 m2 o2, -- ^ The source functor (private, use 'source' instead). + tgtNT :: Diagram c1 m1 o1 c2 m2 o2, -- ^ The target functor (private, use 'target' instead). + components :: Map o1 m2 -- ^ The components + } deriving (Eq) + + instance (Show c1, Show m1, Show o1, Show c2, Show m2, Show o2) => Show (NaturalTransformation c1 m1 o1 c2 m2 o2) where + show nt = "(unsafeNaturalTransformation "++ (show.srcNT $ nt) ++ " " ++ (show.tgtNT $ nt) ++ " " ++ (show.components $ nt) ++ ")" + + instance ( PrettyPrint c1, PrettyPrint m1, PrettyPrint o1, Eq m1, Eq o1, + PrettyPrint c2, PrettyPrint m2, PrettyPrint o2, Eq m2, Eq o2) => PrettyPrint (NaturalTransformation c1 m1 o1 c2 m2 o2) where + pprint nt = "NaturalTransformation(" ++ pprint (srcNT nt) ++ "->" ++ pprint (tgtNT nt) ++ "," ++ pprint (components nt) ++ ")" + + instance (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + Morphism m2 o2, Eq c2, Eq m2, Eq o2) => + Morphism (NaturalTransformation c1 m1 o1 c2 m2 o2) (Diagram c1 m1 o1 c2 m2 o2) where + source = srcNT + target = tgtNT + (@?) nt2 nt1 + | target nt1 == source nt2 && (src.source $ nt1) == (src.target $ nt2) && (tgt.source $ nt1) == (tgt.target $ nt2) = Just NaturalTransformation{srcNT=source nt1, tgtNT=target nt2, components=weakMapFromSet [(o, (nt2 =>$ o) @ (nt1 =>$ o)) | o <- ob (src.source $ nt1)]} + | otherwise = Nothing + + + -- | Apply a 'NaturalTransformation' on an object of the source 'Diagram'. + (=>$) :: (Eq o1) => NaturalTransformation c1 m1 o1 c2 m2 o2 -> o1 -> m2 + (=>$) nt x = (components nt) |!| x + + -- | Compose horizontally 'NaturalTransformation's. + (<=@<=) :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2, + Morphism m3 o3, Eq c3, Eq m3, Eq o3) => + NaturalTransformation c2 m2 o2 c3 m3 o3 -> NaturalTransformation c1 m1 o1 c2 m2 o2 -> NaturalTransformation c1 m1 o1 c3 m3 o3 + (<=@<=) nt2 nt1 = NaturalTransformation{srcNT=source nt2 <-@<- source nt1, tgtNT=target nt2 <-@<- target nt1, components = weakMapFromSet [(o, ((nt2 <=@<- target nt1) =>$ o) @ ((source nt2 <-@<= nt1) =>$ o)) | o <- ob (src.source $ nt1)]} + + -- | Alias of ('<=@<='). + horizontalComposition :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2, + Morphism m3 o3, Eq c3, Eq m3, Eq o3) => + NaturalTransformation c2 m2 o2 c3 m3 o3 -> NaturalTransformation c1 m1 o1 c2 m2 o2 -> NaturalTransformation c1 m1 o1 c3 m3 o3 + horizontalComposition = (<=@<=) + + -- | Left whiskering allows to compose a 'Diagram' with a 'NaturalTransformation'. + (<=@<-) :: ( Morphism m1 o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2, + Morphism m3 o3, Eq c3, Eq m3, Eq o3) => + NaturalTransformation c2 m2 o2 c3 m3 o3 -> Diagram c1 m1 o1 c2 m2 o2 -> NaturalTransformation c1 m1 o1 c3 m3 o3 + (<=@<-) nt funct = NaturalTransformation{ + srcNT = (source nt) <-@<- funct, + tgtNT = (target nt) <-@<- funct, + components = (components nt) |.| (omap funct) + } + + -- | Alias of ('<=@<-'). + leftWhiskering :: ( Morphism m1 o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2, + Morphism m3 o3, Eq c3, Eq m3, Eq o3) => + NaturalTransformation c2 m2 o2 c3 m3 o3 -> Diagram c1 m1 o1 c2 m2 o2 -> NaturalTransformation c1 m1 o1 c3 m3 o3 + leftWhiskering = (<=@<-) + + -- | Right whiskering allows to compose a 'NaturalTransformation' with a 'Diagram'. + (<-@<=) :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + Morphism m2 o2, Eq c2, Eq m2, Eq o2) => + Diagram c2 m2 o2 c3 m3 o3 -> NaturalTransformation c1 m1 o1 c2 m2 o2 -> NaturalTransformation c1 m1 o1 c3 m3 o3 + (<-@<=) funct nt = NaturalTransformation { + srcNT = funct <-@<- (source nt), + tgtNT = funct <-@<- (target nt), + components = (mmap funct) |.| (components nt) + } + + -- | Alias of ('<-@<='). + rightWhiskering :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + Morphism m2 o2, Eq c2, Eq m2, Eq o2) => + Diagram c2 m2 o2 c3 m3 o3 -> NaturalTransformation c1 m1 o1 c2 m2 o2 -> NaturalTransformation c1 m1 o1 c3 m3 o3 + rightWhiskering = (<-@<=) + + -- | A datatype to represent a malformation of a 'NaturalTransformation'. + data NaturalTransformationError c1 m1 o1 c2 m2 o2 = IncompatibleFunctorsSource{sourceCat :: c1, targetCat :: c1} -- ^ The source and target functors don't have the same source category. + | IncompatibleFunctorsTarget{sourceCat2 :: c2, targetCat2 :: c2} -- ^ The source and target functors don't have the same target category. + | NotTotal{domainNat :: Set o1, objectsCat :: Set o1} -- ^ The mapping from objects to morphisms is not total. + | NaturalityFail{originalMorphism :: m1} -- ^ A morphism does not close a commutative square. + deriving (Eq, Show) + + + -- | Check wether the structure of a 'NaturalTransformation' is respected. + checkNaturalTransformation :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + Morphism m2 o2, Eq c2, Eq m2, Eq o2) => + NaturalTransformation c1 m1 o1 c2 m2 o2 -> Maybe (NaturalTransformationError c1 m1 o1 c2 m2 o2) + checkNaturalTransformation nt + | incompatibleFunctorsSource = Just IncompatibleFunctorsSource{sourceCat=(src.source $ nt), targetCat=(src.target $ nt)} + | incompatibleFunctorsTarget = Just IncompatibleFunctorsTarget{sourceCat2=(tgt.source $ nt), targetCat2=(tgt.target $ nt)} + | notTotal = Just NotTotal{domainNat = (domain.components $ nt), objectsCat = (ob.src.source $ nt)} + | (not.(Set.null)) naturalityFail = Just NaturalityFail{originalMorphism = anElement naturalityFail} + | otherwise = Nothing + where + incompatibleFunctorsSource = (src.source $ nt) /= (src.target $ nt) + incompatibleFunctorsTarget = (tgt.source $ nt) /= (tgt.target $ nt) + notTotal = (domain.components $ nt) /= (ob.src.source $ nt) + naturalityFail = [f | f <- (arrows.src.source $ nt), (target nt ->£ f) @ (nt =>$ (source f)) /= (nt =>$ (target f)) @ (source nt ->£ f)] + + -- | The smart constructor of 'NaturalTransformation'. Checks wether the structure is correct. + naturalTransformation :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + Morphism m2 o2, Eq c2, Eq m2, Eq o2) => + Diagram c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 c2 m2 o2 -> Map o1 m2 -> Either (NaturalTransformationError c1 m1 o1 c2 m2 o2) (NaturalTransformation c1 m1 o1 c2 m2 o2) + naturalTransformation s t c + | null check = Right nt + | otherwise = Left err + where + nt = NaturalTransformation{srcNT=s,tgtNT=t,components=c} + check = checkNaturalTransformation nt + Just err = check + + -- | Unsafe constructor of 'NaturalTransformation' for performance purposes. It does not check the structure of the 'NaturalTransformation'. + -- + -- Use this constructor only if the 'NaturalTransformation' is necessarily well formed. + unsafeNaturalTransformation :: Diagram c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 c2 m2 o2 -> Map o1 m2 -> NaturalTransformation c1 m1 o1 c2 m2 o2 + unsafeNaturalTransformation s t c = NaturalTransformation{srcNT = s, tgtNT = t, components = c} + + -- Functor Category + + + -- | A 'FunctorCategory' /D/^/C/ where /C/ is a 'FiniteCategory' and /D/ is a 'Category' has 'Diagram's @F : C -> D@ as objects and 'NaturalTransformation's between them as morphisms. 'NaturalTransformation's compose vertically in this category. + data FunctorCategory c1 m1 o1 c2 m2 o2 = FunctorCategory c1 c2 deriving (Eq, Show) + + instance (PrettyPrint c1, PrettyPrint c2) => PrettyPrint (FunctorCategory c1 m1 o1 c2 m2 o2) where + pprint (FunctorCategory c d) = "FunctorCategory(" ++ pprint c ++ "," ++ pprint d ++ ")" + + instance (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + Category c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => + Category (FunctorCategory c1 m1 o1 c2 m2 o2) (NaturalTransformation c1 m1 o1 c2 m2 o2) (Diagram c1 m1 o1 c2 m2 o2) where + identity (FunctorCategory c d) funct + | src funct == c && tgt funct == d = NaturalTransformation{srcNT=funct, tgtNT=funct, components=weakMapFromSet [(o, identity d (funct ->$ o))| o <- (ob.src $ funct)]} + | otherwise = error "Math.Categories.FunctorCategory.identity: functor not in the functor category." + ar (FunctorCategory c d) s t + | src s == src t && tgt s == tgt t = snd.(Set.catEither) $ [naturalTransformation s t mapCompo | mapCompo <- mapComponent] + | otherwise = error "Math.Categories.FunctorCategory.ar: incompatible functors" + where + mapComponent = weakMap <$> cartesianProductOfSets [(\x -> (o,x)) <$> (ar (tgt s) (omap s |!| o) (omap t |!| o)) | o <- (setToList (ob.src $ s))] + transformToFunction ((o,f):xs) x = if o == x then f else transformToFunction xs x + + + + -- | A 'FunctorCategory' where the target category is finite allows to enumerate all 'Diagram's thus making it a 'FiniteCategory'. + instance (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => + FiniteCategory (FunctorCategory c1 m1 o1 c2 m2 o2) (NaturalTransformation c1 m1 o1 c2 m2 o2) (Diagram c1 m1 o1 c2 m2 o2) where + ob (FunctorCategory s t) = snd.(Set.catEither) $ [diagram s t appO appF | appO <- appObj, appF <- ((fmap $ (Map.unions)).cartesianProductOfSets) [twoObjToMaps a b appO| a <- (setToList $ ob s), b <- (setToList $ ob s)]] + where + appObj = Map.enumerateMaps (ob s) (ob t) + twoObjToMaps a b appO = Map.enumerateMaps (ar s a b) (ar t (appO |!| a) (appO |!| b)) + + + -- | A 'FunctorCategory' /D/^/C/ precomposed by a functor @F : B -> C@ where /B/ and /C/ are 'FiniteCategory' and /D/ is a 'Category'. + -- + -- It has 'Diagram's @G o F : B -> D@ as objects and 'NaturalTransformation's between them as morphisms. 'NaturalTransformation's compose vertically in this category. + data PrecomposedFunctorCategory c1 m1 o1 c2 m2 o2 c3 m3 o3 = PrecomposedFunctorCategory (Diagram c1 m1 o1 c2 m2 o2) c3 deriving (Eq, Show) + + instance (PrettyPrint c1, PrettyPrint m1, PrettyPrint o1, Eq m1, Eq o1, + PrettyPrint c2, PrettyPrint m2, PrettyPrint o2, Eq m2, Eq o2, + PrettyPrint c3) => PrettyPrint (PrecomposedFunctorCategory c1 m1 o1 c2 m2 o2 c3 m3 o3) where + pprint (PrecomposedFunctorCategory diag d) = "PrecomposedFunctorCategory(" ++ pprint diag ++ "," ++ pprint d ++ ")" + + instance (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2, + Category c3 m3 o3, Morphism m3 o3, Eq c3, Eq m3, Eq o3) => + Category (PrecomposedFunctorCategory c1 m1 o1 c2 m2 o2 c3 m3 o3) (NaturalTransformation c1 m1 o1 c3 m3 o3) (Diagram c1 m1 o1 c3 m3 o3) where + identity (PrecomposedFunctorCategory diag c3) = identity (FunctorCategory (src diag) c3) + ar (PrecomposedFunctorCategory diag c3) = ar (FunctorCategory (src diag) c3) + + + + -- | A 'PrecomposedFunctorCategory' where the target category is finite allows to enumerate all 'Diagram's thus making it a 'FiniteCategory'. + instance (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2, + FiniteCategory c3 m3 o3, Morphism m3 o3, Eq c3, Eq m3, Eq o3) => + FiniteCategory (PrecomposedFunctorCategory c1 m1 o1 c2 m2 o2 c3 m3 o3) (NaturalTransformation c1 m1 o1 c3 m3 o3) (Diagram c1 m1 o1 c3 m3 o3) where + ob (PrecomposedFunctorCategory diag c3) = (<-@<- diag) <$> (ob (FunctorCategory (tgt diag) c3)) + + + -- | A 'FunctorCategory' /D/^/C/ postcomposed by a functor @F : D -> E@ where /C/ is a 'FiniteCategory' and /D/ and /E/ are 'Category'. + -- + -- It has 'Diagram's @ F o G : C -> E@ as objects and 'NaturalTransformation's between them as morphisms. 'NaturalTransformation's compose vertically in this category. + data PostcomposedFunctorCategory c1 m1 o1 c2 m2 o2 c3 m3 o3 = PostcomposedFunctorCategory (Diagram c2 m2 o2 c3 m3 o3) c1 deriving (Eq, Show) + + instance (PrettyPrint c1, + PrettyPrint c2, PrettyPrint m2, PrettyPrint o2, Eq m2, Eq o2, + PrettyPrint c3, PrettyPrint m3, PrettyPrint o3, Eq m3, Eq o3) => PrettyPrint (PostcomposedFunctorCategory c1 m1 o1 c2 m2 o2 c3 m3 o3) where + pprint (PostcomposedFunctorCategory diag d) = "PostcomposedFunctorCategory(" ++ pprint diag ++ "," ++ pprint d ++ ")" + + instance (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + Category c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2, + Category c3 m3 o3, Morphism m3 o3, Eq c3, Eq m3, Eq o3) => + Category (PostcomposedFunctorCategory c1 m1 o1 c2 m2 o2 c3 m3 o3) (NaturalTransformation c1 m1 o1 c3 m3 o3) (Diagram c1 m1 o1 c3 m3 o3) where + identity (PostcomposedFunctorCategory diag c1) = identity (FunctorCategory c1 (tgt diag)) + ar (PostcomposedFunctorCategory diag c1) = ar (FunctorCategory c1 (tgt diag)) + + + + -- | A 'PostcomposedFunctorCategory' where the target category is finite allows to enumerate all 'Diagram's thus making it a 'FiniteCategory'. + instance (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2, + FiniteCategory c3 m3 o3, Morphism m3 o3, Eq c3, Eq m3, Eq o3) => + FiniteCategory (PostcomposedFunctorCategory c1 m1 o1 c2 m2 o2 c3 m3 o3) (NaturalTransformation c1 m1 o1 c3 m3 o3) (Diagram c1 m1 o1 c3 m3 o3) where + ob (PostcomposedFunctorCategory diag c1) = (diag <-@<-) <$> (ob (FunctorCategory c1 (src diag))) + + -- | The insertion functor from the 'FullSubcategory' to the original category. + insertionFunctor1 :: (Category c m o, Morphism m o, Eq o) => FullSubcategory c m o -> Diagram (FullSubcategory c m o) m o c m o + insertionFunctor1 sc@(FullSubcategory c s) = Diagram{src=sc,tgt=c,omap=memorizeFunction id s, mmap=memorizeFunction id (arrows sc)} + + -- | The insertion functor from the 'InheritedFullSubcategory' to the original category. + insertionFunctor2 :: (Category c m o, Morphism m o, Eq o) => InheritedFullSubcategory c m o -> Diagram (InheritedFullSubcategory c m o) m o c m o + insertionFunctor2 sc@(InheritedFullSubcategory c s) = Diagram{src=sc,tgt=c,omap=memorizeFunction id s, mmap=memorizeFunction id (arrows sc)} +
+ src/Math/Categories/Galaxy.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-} + +{-| Module : FiniteCategories +Description : The __'Galaxy'__ category has every objects and no morphism other than identities. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +The __'Galaxy'__ category has every objects and no morphism other than identities. + +It is called __'Galaxy'__ because its underlying graph is composed of a lot of points with no arrow between them. + +It is the biggest 'DiscreteCategory'. +-} + +module Math.Categories.Galaxy +( + StarIdentity(..), + Galaxy(..), +) +where + import Math.Category + import Math.IO.PrettyPrint + + import Data.WeakSet.Safe + + -- | 'StarIdentity' is the identity of a star (an object) in a 'Galaxy'. + data StarIdentity a = StarIdentity a deriving (Eq, Show) + + instance (Eq a) => Morphism (StarIdentity a) a where + (StarIdentity x) @? (StarIdentity y) + | x == y = Just (StarIdentity x) + | otherwise = Nothing + source (StarIdentity x) = x + target = source + + -- | The __'Galaxy'__ category has every objects and no morphism other than identities. + data Galaxy a = Galaxy deriving (Eq,Show) + + instance (Eq a) => Category (Galaxy a) (StarIdentity a) a where + identity _ = StarIdentity + ar _ x y + | x == y = set [StarIdentity x] + | otherwise = set [] + + instance (PrettyPrint a) => PrettyPrint (StarIdentity a) where + pprint (StarIdentity x) = "Id"++ pprint x + + instance PrettyPrint (Galaxy a) where + pprint = show
+ src/Math/Categories/Omega.hs view
@@ -0,0 +1,36 @@+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-} + +{-| Module : FiniteCategories +Description : The category associated to the ordinal number omega is the category generated by the arrows 0 -> 1 -> 2 -> ... (See Categories for the working mathematican. Saunders Mac Lane. p.12) +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +The __'Omega'__ linear order category is the category generated by the arrows 0 -> 1 -> 2 -> ... (See "Categories for the Working Mathematican" Saunders Mac Lane. p.12) +-} + +module Math.Categories.Omega +( + Omega(..), + omega, + module Math.Categories.OrdinalCategory +) +where + import Math.Category + import Math.Categories.OrdinalCategory + import Math.IO.PrettyPrint + + import Data.WeakSet.Safe + + import Numeric.Natural + + -- | __'Omega'__ is an 'OrdinalCategory' on natural numbers. + type Omega = OrdinalCategory Natural + + -- | The __'Omega'__ category. + -- + -- The __'Omega'__ linear order category is the category generated by the arrows 0 -> 1 -> 2 -> ... (See "Categories for the Working Mathematican" Saunders Mac Lane. p.12) + omega :: Omega + omega = OrdinalCategory TotalOrder
+ src/Math/Categories/Opposite.hs view
@@ -0,0 +1,60 @@+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, UndecidableInstances #-} + +{-| Module : FiniteCategories +Description : Each 'Category' has an opposite one where morphisms are reversed. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +Each 'Category' has an opposite one where morphisms are reversed. +-} + +module Math.Categories.Opposite +( + OpMorphism(..), + opOpMorphism, + Op(..), + opOp, +) +where + import Math.Category + import Math.FiniteCategory + import Math.IO.PrettyPrint + + import Data.WeakSet.Safe + + -- | An 'OpMorphism' is a morphism where source and target are reversed. + data OpMorphism m = OpMorphism m deriving (Eq, Show) + + -- | Return the original morphism given an 'OpMorphism'. + opOpMorphism :: OpMorphism m -> m + opOpMorphism (OpMorphism m) = m + + instance (Morphism m o) => Morphism (OpMorphism m) o where + source (OpMorphism m) = target m + target (OpMorphism m) = source m + (@?) (OpMorphism m2) (OpMorphism m1) = OpMorphism <$> m1 @? m2 + + -- | The 'Op' operator gives the opposite of a 'Category'. + data Op c = Op c deriving (Eq, Show) + + -- | Return the original category given an 'Op' category. + opOp :: Op c -> c + opOp (Op c) = c + + instance (Category c m o, Morphism m o) => Category (Op c) (OpMorphism m) o where + identity (Op c) o = OpMorphism $ identity c o + ar (Op c) x y = OpMorphism <$> ar c y x + genAr (Op c) x y = OpMorphism <$> genAr c y x + decompose (Op c) (OpMorphism m) = OpMorphism <$> reverse (decompose c m) + + instance (FiniteCategory c m o, Morphism m o) => FiniteCategory (Op c) (OpMorphism m) o where + ob (Op c) = ob c + + instance (PrettyPrint m) => PrettyPrint (OpMorphism m) where + pprint (OpMorphism m) = "Op("++ pprint m ++ ")" + + instance (PrettyPrint c) => PrettyPrint (Op c) where + pprint (Op x) = "Op("++ pprint x ++ ")"
+ src/Math/Categories/OrdinalCategory.hs view
@@ -0,0 +1,60 @@+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-} + +{-| Module : FiniteCategories +Description : An 'OrdinalCategory' is a 'TotalOrder' category where the total order is an order induced by ordinal numbers. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +An 'OrdinalCategory' is a 'TotalOrder' category where the total order is an order induced by ordinal numbers. + +Concretely the type parameter must implement the Enum typeclass. + +For example, the 'TotalOrder' category induced by (R,<=) is not an 'OrdinalCategory' whereas (N,<=) is. + +It induces a non trivial generating set of arrows thanks to the 'succ' function. +-} + +module Math.Categories.OrdinalCategory +( + OrdinalCategory(..), + module Math.Categories.TotalOrder + +) +where + import Math.Category + import Math.Categories.FunctorCategory + import Math.Categories.ConeCategory + import Math.Categories.TotalOrder + import Math.IO.PrettyPrint + + import Data.WeakSet.Safe + import qualified Data.WeakMap as Map + import Data.WeakMap.Safe + + + -- | An 'OrdinalCategory' is a 'TotalOrder' where the type /a/ follows the Enum typeclass. + newtype OrdinalCategory a = OrdinalCategory (TotalOrder a) deriving (Eq, Show) + + instance (Enum a, Ord a) => Category (OrdinalCategory a) (IsSmallerThan a) a where + ar _ x y + | x <= y = set [IsSmallerThan x y] + | otherwise = set [] + + identity _ x = IsSmallerThan x x + + -- | An 'OrdinalCategory' is generated by morphisms from a number to its successor. + genAr _ x y + | x == y = set [IsSmallerThan x x] + | (succ x) == y = set [IsSmallerThan x y] + | otherwise = set [] + + decompose _ (IsSmallerThan x y) + | x == y = [IsSmallerThan x y] + | otherwise = reverse $ (\n -> IsSmallerThan n (succ n)) <$> [x..(pred y)] + + + instance (Show a) => PrettyPrint (OrdinalCategory a) where + pprint = show
+ src/Math/Categories/PresheafCategory.hs view
@@ -0,0 +1,75 @@+{-# LANGUAGE MultiParamTypeClasses #-} + +{-| Module : FiniteCategories +Description : The category of presheaves on a 'Category' /C/ has functors from /C/^op to __FinSet__ as objects and natural transformations as morphisms. It is a 'FunctorCategory'. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +The category of presheaves on a 'Category' /C/ has functors from /C/^op to __FinSet__ as objects and natural transformations as morphisms. It is a 'FunctorCategory'. + +The 'yonedaEmbedding' goes to a category of presheaves, it allows to cocomplete a 'FiniteCategory'. +-} + +module Math.Categories.PresheafCategory +( + -- * Presheaves + Presheaf(..), + PresheafMorphism(..), + PresheafCategory(..), + -- * Yoneda embedding + yonedaEmbedding +) +where + import Math.Category + import Math.FiniteCategory + import Math.Categories.FunctorCategory + import Math.Categories.Opposite + import Math.Categories.FinSet + + 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 + + -- | A 'Presheaf' on a 'Category' /C/ is a diagram from @/C/^op@ to __FinSet__. + type Presheaf c m o = Diagram (Op c) (OpMorphism m) o (FinSet m) (Function m) (Set m) + + -- | A 'PresheafMorphism' is a 'NaturalTransformation' between presheaves. + type PresheafMorphism c m o = NaturalTransformation (Op c) (OpMorphism m) o (FinSet m) (Function m) (Set m) + + -- | The type of the category of presheaves. + type PresheafCategory c m o = FunctorCategory (Op c) (OpMorphism m) o (FinSet m) (Function m) (Set m) + + -- | Given a 'FiniteCategory' /C/, return its Yoneda embedding in the 'FunctorCategory' [/C/^op, __FinSet__]. + -- + -- It allows to cocomplete a 'FiniteCategory'. The insertion functor from the category to [/C/^op, __FinSet__] is full and faithful. + yonedaEmbedding :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> Diagram c m o (PresheafCategory c m o) (PresheafMorphism c m o) (Presheaf c m o) + yonedaEmbedding cat = functor + where + hom x = (\s -> ar cat s x) <$> (ob cat) + omapPresheaf x s = ar cat s x + mmapPresheaf x m = Function{codomain = omapPresheaf x (target m) + , function = weakMap $ zip (Set.toList (omapPresheaf x (source m))) ((\f -> (f @ (opOpMorphism m))) <$> (Set.toList (omapPresheaf x (source m))))} + presheaf x = Diagram { src = Op cat + , tgt = FinSet + , omap = memorizeFunction (omapPresheaf x) (ob (Op cat)) + , mmap = memorizeFunction (mmapPresheaf x) (arrows (Op cat))} + + ntFromMorph m o = Function {codomain = (presheaf (target m)) ->$ o + , function = weakMap $ zip domain postcom } + where + domain = Set.toList $ (presheaf (source m)) ->$ o + postcom = (m @) <$> domain + mmapFunctor m = unsafeNaturalTransformation (presheaf (source m)) (presheaf (target m)) (memorizeFunction (ntFromMorph m) (ob cat)) + + presheavesCat = FunctorCategory (Op cat) FinSet + functor = Diagram { src = cat + , tgt = presheavesCat + , omap = memorizeFunction presheaf (ob cat) + , mmap = memorizeFunction mmapFunctor (arrows cat) + }
+ src/Math/Categories/TotalOrder.hs view
@@ -0,0 +1,57 @@+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-} + +{-| 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.Category + import Math.Categories.FunctorCategory + import Math.Categories.ConeCategory + import Math.IO.PrettyPrint + + import Data.WeakSet.Safe + import qualified Data.WeakMap as Map + import Data.WeakMap.Safe + + -- | '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) + + instance (Eq a) => Morphism (IsSmallerThan a) a where + (IsSmallerThan m1 t) @? (IsSmallerThan s m2) + | m1 == m2 = Just $ IsSmallerThan s t + | otherwise = Nothing + 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) + + 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 (IsSmallerThan x y) = pprint x ++ " <= " ++ pprint y + + instance PrettyPrint (TotalOrder a) where + pprint = show
+ src/Math/Category.hs view
@@ -0,0 +1,192 @@+{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-} + +{-| Module : FiniteCategories +Description : 'Morphism' and 'Category' typeclasses. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +A `Morphism` is composable, it has a source and a target. + +A `Category` allows to enumerate all arrows between two objects and allows to construct the identity of an object. It is mathematically a locally finite category, we name it 'Category' for simplicity. + +See `FiniteCategory` for the ability to enumerate the objects of a category. + +We don't reify the `Category` concept because we want to be able to equate categories (functions are not equatable). + +A `GeneratedCategory` is a `Category` where some morphisms are selected as generators. Any 'Category' has a trivial set of generators: the set of all of its arrows. You can override the default definition of generators when creating your 'Category' by instantiating 'GeneratedCategory'. +-} + +module Math.Category +( + -- * Morphism + Morphism(..), + -- ** Morphism related functions + (@), + compose, + -- * Category + Category(..), + -- ** Morphism predicates + isIdentity, + isNotIdentity, + isIso, + isSection, + isRetraction, + areIsomorphic, + -- ** Generator predicates + isGenerator, + isComposite, + -- ** Find special morphisms + findInverse, + findIsomorphism, + findRightInverses, + findLeftInverses, +) +where + import Data.WeakSet (Set) + import qualified Data.WeakSet as Set + import Data.WeakSet.Safe + + -- | A `Morphism` can be composed with the ('@?') operator, it has a 'source' and a 'target'. + -- + -- The ('@?') operator should not be confused with the as-pattern. When using the composition operator, surround the '@?' symbol with spaces. + -- + -- 'Morphism' is a multiparametrized typeclass where /m/ is the type of the morphism and /o/ the type of the source and target objects. + -- + -- Source and target are the same type of objects, we distinguish objects not by their type but instead by their values. + class Morphism m o | m -> o where + -- | The composition @g '@?' f@ should return 'Nothing' if @'source' g /= 'target' f@. + -- This is a consequence of loosing type check at compilation time, we defer the exception handling to execution time. + -- + -- Composition is associative : + -- + -- prop> (fmap (f @?)) (g @? h) = fmap (@? h) (f @? g) + (@?) :: m -> m -> Maybe m + + -- | Return the source object of the morphism. + source :: m -> o + + -- | Return the target object of the morphism. + target :: m -> o + + -- | Unsafe version of '(@?)'. + (@) :: (Morphism m o) => m -> m -> m + (@) m2 m1 + | null compo = error "Math.Category.(@): incompatible morphisms" + | otherwise = r + where + compo = m2 @? m1 + Just r = compo + + -- | Return the composition of a list of morphisms. + -- + -- For example : + -- @compose [f,g,h] = f \@ g \@ h@ + -- + -- Return an error if the list is empty : we would have to return an identity but we don't know which one. + compose :: (Morphism m o) => [m] -> m + compose [] = error "Category.compose: empty list to compose" + compose l = foldr1 (@) l + + -- | A `Category` allows to enumerate all arrows between two objects and allows to construct the identity of an object. + -- + -- A 'Category' is multiparametrized by the type of its morphisms and the type of its objects. + -- + -- This typeclass does not assume the category is finite, the number of objects in the category may be infinite. + -- + -- A category is a set of objects and a set of morphisms which follows the category axioms. + -- + -- A category also has sets of generating morphisms. A set of generating morphisms is a set of morphism such that every morphism of the category can be constructed by + -- composing generators. Note that we consider identities should be generators even though they can be constructed as the composition of zero morphism because 'compose' can't compose zero morphism. + -- + -- Some algorithms are simplified because they only need to deal with generators, the rest of the properties are deduced by composition. + -- + -- Every `Category` has at least one set of generators : the set of all of its morphisms. + -- + -- You can override 'genAr' and 'decompose' to define a more interesting set of generating morphisms for a given 'Category'. + class Category c m o | c -> m, m -> o where + -- | `identity` should return the identity associated to the object /o/ in the category /c/. + -- + -- The identity morphism is a morphism such that the two following properties are verified : + -- + -- prop> f '@' 'identity' c ('source' f) = f + -- prop> 'identity' c ('target' g) '@' g = g + identity :: (Morphism m o) => c -> o -> m + + -- | `ar` should return the set of all arrows between a source and a target. + -- + -- Arrows with different source or target should not be equal. + ar :: (Morphism m o) => c -- ^ The category + -> o -- ^ The source of the morphisms + -> o -- ^ The target of the morphisms + -> Set m -- ^ The set of morphisms in the category c between source and target + + {-|# MINIMAL identity, ar #-} + + -- | Same as `ar` but only returns the generators. + -- + -- prop> @('genAr' c s t) `isIncludedIn` ('ar' c s t)@. + -- + -- The default implementation is 'ar' because the set of all arrows generates trivially the category. + genAr :: (Morphism m o) => c -> o -> o -> Set m + genAr = ar + + -- | `decompose` decomposes a morphism into a list of generators (according to composition) : + -- + -- prop> m = compose (decompose c m) + -- + -- An identity should be decomposed into a list containing itself. + -- + -- The default implementation returns the morphism in a list as all arrows are generators. + decompose :: (Morphism m o) => c -> m -> [m] + decompose _ = (:[]) + + -- | Return wether a morphism is an identity in a category. + isIdentity :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> m -> Bool + isIdentity c m = identity c (source m) == m + + -- | Return wether a morphism is not an identity. + isNotIdentity :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> m -> Bool + isNotIdentity c m = not (isIdentity c m) + + -- | Return Just an inverse of a morphism if possible, Nothing otherwise + findInverse :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> m -> Maybe m + findInverse c m = (Set.setToMaybe) $ Set.filter (\f -> isIdentity c (m @ f) && isIdentity c (f @ m)) (ar c (target m) (source m)) + + -- | Return Just an isomorphism from an object to another if possible, Nothing otherwise. + findIsomorphism :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> o -> o -> Maybe m + findIsomorphism c s t = (Set.setToMaybe).(Set.catMaybes) $ findInverse c <$> ar c s t + + -- | Return wether two objects are isomorphic or not. + areIsomorphic :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> o -> o -> Bool + areIsomorphic c s t = not.null $ findIsomorphism c s t + + -- | Return if a morphism is an isomorphism + isIso :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> m -> Bool + isIso c m = not.null $ findInverse c m + + -- | Find all right inverses. + findRightInverses :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> m -> Set m + findRightInverses c f = Set.filter (\g -> isIdentity c (f @ g)) $ ar c (target f) (source f) + + -- | Return wether a morphism is a section. + isSection :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> m -> Bool + isSection c f = not.(Set.null) $ findRightInverses c f + + -- | Find a left inverse if it can, returns Nothing otherwise. + findLeftInverses :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> m -> Set m + findLeftInverses c f = Set.filter (\g -> isIdentity c (g @ f)) $ ar c (target f) (source f) + + -- | Return wether a morphism is a retraction. + isRetraction :: (Category c m o, Morphism m o, Eq m, Eq o) => c -> m -> Bool + isRetraction c f = not.(Set.null) $ findLeftInverses c f + + -- | Return if a morphism is a generating morphism. + isGenerator :: (Category c m o, Morphism m o, Eq m) => c -> m -> Bool + isGenerator c f = f `isIn` (genAr c (source f) (target f)) + + -- | Opposite of `isGenerator`, i.e. returns if the morphism is composite. + isComposite :: (Category c m o, Morphism m o, Eq m) => c -> m -> Bool + isComposite c f = not (isGenerator c f)
+ src/Math/FiniteCategories.hs view
@@ -0,0 +1,47 @@+{-# LANGUAGE MultiParamTypeClasses #-} + +{-| Module : FiniteCategories +Description : This file exports all finite categories. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +This file exports all finite categories. +-} + +module Math.FiniteCategories ( + module Math.FiniteCategories.NumberCategory, + module Math.FiniteCategories.DiscreteCategory, + module Math.FiniteCategories.FullSubcategory, + module Math.FiniteCategories.Hat, + module Math.FiniteCategories.V, + module Math.FiniteCategories.Parallel, + module Math.FiniteCategories.Square, + module Math.FiniteCategories.Ens, + module Math.FiniteCategories.Opposite, + module Math.FiniteCategories.FunctorCategory, + module Math.FiniteCategories.CompositionGraph, + module Math.FiniteCategories.SafeCompositionGraph, + module Math.FiniteCategories.CommaCategory, + module Math.FiniteCategories.One, + module Math.FiniteCategories.ConeCategory, + module Math.FiniteCategories.Subcategory, +) where + import Math.FiniteCategories.NumberCategory + import Math.FiniteCategories.DiscreteCategory + import Math.FiniteCategories.FullSubcategory + import Math.FiniteCategories.Hat + import Math.FiniteCategories.V + import Math.FiniteCategories.Parallel + import Math.FiniteCategories.Square + import Math.FiniteCategories.Ens + import Math.FiniteCategories.Opposite + import Math.FiniteCategories.FunctorCategory + import Math.FiniteCategories.CompositionGraph + import Math.FiniteCategories.SafeCompositionGraph + import Math.FiniteCategories.CommaCategory + import Math.FiniteCategories.One + import Math.FiniteCategories.ConeCategory + import Math.FiniteCategories.Subcategory
+ src/Math/FiniteCategories/All.hs view
@@ -0,0 +1,31 @@+{-| Module : FiniteCategories +Description : Export all modules from the FiniteCategories package. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +Export all modules from the FiniteCategories package. + +Export all categories, all finite categories, category and finite category functions, IO, Debug... +-} + +module Math.FiniteCategories.All ( + module Math.Category, + module Math.FiniteCategory, + module Math.FiniteCategoryError, + module Math.Categories, + module Math.FiniteCategories, + module Math.Functors, + module Math.IO.PrettyPrint, + module Math.IO.FiniteCategories.ExportGraphViz, +) where + import Math.Category + import Math.FiniteCategory + import Math.FiniteCategoryError + import Math.Categories + import Math.Functors + import Math.FiniteCategories + import Math.IO.PrettyPrint + import Math.IO.FiniteCategories.ExportGraphViz
+ src/Math/FiniteCategories/CommaCategory.hs view
@@ -0,0 +1,19 @@+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-} + +{-| Module : FiniteCategories +Description : A 'CommaCategory' can be a 'FiniteCategory' if the target category of the diagrams is finite. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +A 'CommaCategory' can be a 'FiniteCategory' if the target category of the diagrams is finite. +-} + +module Math.FiniteCategories.CommaCategory +( + module Math.Categories.CommaCategory +) +where + import Math.Categories.CommaCategory
+ src/Math/FiniteCategories/CommaCategory/Example.hs view
@@ -0,0 +1,38 @@+{-| Module : FiniteCategories +Description : Examples of 'CommaCategory' exported with GraphViz. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +Examples of 'CommaCategory' exported with GraphViz. + +Export the category in the directory "OutputGraphViz\/Examples\/FiniteCategories\/CommaCategory". +-} +module Math.FiniteCategories.CommaCategory.Example +( + main +) +where + import qualified Data.WeakSet as Set + import Data.WeakSet.Safe + import Data.WeakMap.Safe + + import Math.FiniteCategory + import Math.Categories + import Math.FiniteCategories + import Math.IO.FiniteCategories.ExportGraphViz + import Math.IO.PrettyPrint + + -- | Examples of 'CommaCategory' exported with GraphViz. + main :: IO () + main = do + putStrLn "Start of Math.FiniteCategories.CommaCategory.Example" + catToPdf (numberCategory 4) "OutputGraphViz/Examples/FiniteCategories/CommaCategory/4" + let Just slice = sliceCategory (numberCategory 4) 2 + let Just coslice = cosliceCategory (numberCategory 4) 2 + catToPdf slice "OutputGraphViz/Examples/FiniteCategories/CommaCategory/slice2" + catToPdf coslice "OutputGraphViz/Examples/FiniteCategories/CommaCategory/coslice2" + catToPdf (arrowCategory (numberCategory 4)) "OutputGraphViz/Examples/FiniteCategories/CommaCategory/arrow" + putStrLn "End of Math.FiniteCategories.CommaCategory.Example"
+ src/Math/FiniteCategories/CompositionGraph.hs view
@@ -0,0 +1,759 @@+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, MonadComprehensions #-} + +{-| Module : FiniteCategories +Description : Composition graphs are the simpliest way to create simple small categories by hand. See 'readCGFile'. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +A 'CompositionGraph' is the free category generated by a multidigraph quotiented by an equivalence relation on the paths of the graphs. +A multidigraph is a directed multigraph which means that edges are oriented and there can be multiple arrows between two objects. + +The equivalence relation is given by a map on paths of the graph. + +Morphisms from different composition graphs should not be composed or compared, if they are, the behavior is undefined. + +When taking subcategories of a composition graph, the composition law might lead to morphisms not existing anymore. +It is not a problem because they are equivalent, it is only counterintuitive for human readability. +-} + + +module Math.FiniteCategories.CompositionGraph +( + -- * Types for composition graph morphism + RawPath(..), + Path(..), + CGMorphism(..), + -- ** Functions for composition graph morphism + getLabel, + -- * Composition graph + CompositionLaw(..), + CompositionGraph, + support, + law, + -- * Construction + compositionGraph, + unsafeCompositionGraph, + emptyCompositionGraph, + finiteCategoryToCompositionGraph, + unsafeReadCGString, + readCGString, + unsafeReadCGFile, + readCGFile, + -- * Serialization + writeCGString, + writeCGFile, + -- * Construction of diagrams + unsafeReadCGDString, + readCGDString, + unsafeReadCGDFile, + readCGDFile, + -- * Serialization of diagrams + writeCGDString, + writeCGDFile, + -- * Random composition graph + constructRandomCompositionGraph, + defaultConstructRandomCompositionGraph, + defaultConstructRandomDiagram, +) +where + 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 (intercalate, elemIndex, splitAt) + import Data.Maybe (fromJust, isNothing) + import Data.Text (Text, cons, singleton, unpack, pack) + + import Math.Categories.FinGrph + import Math.Categories.FunctorCategory + import Math.Category + import Math.FiniteCategory + import Math.FiniteCategoryError + import Math.IO.PrettyPrint + + import System.Directory (createDirectoryIfMissing) + import System.FilePath.Posix (takeDirectory) + import System.Random (RandomGen, uniformR) + + -- | A `RawPath` is a list of arrows, arrows should be compatible. + type RawPath a b = [Arrow a b] + + -- | A `Path` is a `RawPath` with a source specified. + -- + -- An empty path is an identity in a free category. + -- Therefore, it is useful to keep the source when the path is empty + -- because there is one identity for each node of the graph. (We need to differentiate identites for each node.) + type Path a b = (a, RawPath a b) + + -- | A `CompositionLaw` is a `Map` that maps raw paths to smaller raw paths in order to simplify paths + -- so that they don't compose infinitely many times when there is a cycle. + -- + -- prop> length (law |!| p) <= length p + type CompositionLaw a b = Map (RawPath a b) (RawPath a b) + + -- | The datatype `CGMorphism` is the type of composition graph morphisms. + -- + -- It is a path with a composition law, it is necessary to keep the composition law of the composition graph + -- in every morphism of the graph because we need it to compose two morphisms and the morphisms compose + -- independently of the composition graph. + data CGMorphism a b = CGMorphism {path :: Path a b, + compositionLaw :: CompositionLaw a b} deriving (Show, Eq) + + instance (PrettyPrint a, PrettyPrint b, Eq a, Eq b) => PrettyPrint (CGMorphism a b) where + pprint CGMorphism {path=(s,[]),compositionLaw=cl} = "Id"++(pprint s) + pprint CGMorphism {path=(_,rp),compositionLaw=cl} = intercalate " o " $ (pprint.labelArrow) <$> rp + + -- | Helper function for `simplify`. Returns a simplified raw path. + simplifyOnce :: (Eq a, Eq b) => CompositionLaw a b -> RawPath a b -> RawPath a b + simplifyOnce _ [] = [] + simplifyOnce _ [e] = [e] + simplifyOnce cl list + | new_list == [] = [] + | new_list /= list = new_list + | simple_tail /= (tail list) = (head list):simple_tail + | simple_init /= (init list) = simple_init++[(last list)] + | otherwise = list + where + new_list = Map.findWithDefault list list cl + simple_tail = simplifyOnce cl (tail list) + simple_init = simplifyOnce cl (init list) + + -- | Return a completely simplified raw path. + simplify :: (Eq a, Eq b) => CompositionLaw a b -> RawPath a b -> RawPath a b + simplify _ [] = [] + simplify cl rp + | simple_one == rp = rp + | otherwise = simplify cl simple_one + where simple_one = simplifyOnce cl rp + + instance (Eq a, Eq b) => Morphism (CGMorphism a b) a where + (@?) m2@CGMorphism{path=(s2,rp2), compositionLaw=cl2} m1@CGMorphism{path=(s1,rp1), compositionLaw=cl1} + | cl1 /= cl2 = Nothing + | source m2 /= target m1 = Nothing + | otherwise = Just CGMorphism{path=(s1,(simplify cl1 (rp2++rp1))), compositionLaw=cl1} + + + source CGMorphism{path=(s,_), compositionLaw=_} = s + target CGMorphism{path=(s,[]), compositionLaw=_} = s + target CGMorphism{path=(_,rp), compositionLaw=_} = targetArrow (head rp) + + + -- | Constructs a `CGMorphism` from a composition law and an arrow. + mkCGMorphism :: CompositionLaw a b -> Arrow a b -> CGMorphism a b + mkCGMorphism cl e = CGMorphism {path=(sourceArrow e,[e]),compositionLaw=cl} + + -- | Returns the list of arrows of a graph with a given target. + findInwardEdges :: (Eq a) => Graph a b -> a -> Set (Arrow a b) + findInwardEdges g o = Set.filter (\e -> (targetArrow e) == o && (sourceArrow e) `isIn` (nodes g)) (edges g) + + -- | Find all acyclic raw paths between two nodes in a graph. + findAcyclicRawPaths :: (Eq a, Eq b) => Graph a b -> a -> a -> Set (RawPath a b) + findAcyclicRawPaths g s t = findAcyclicRawPathsVisitedNodes g s t Set.empty where + findAcyclicRawPathsVisitedNodes g s t v + | t `isIn` v = Set.empty + | s == t = set [[]] + | otherwise = set (concat (zipWith ($) (fmap fmap (fmap (:) inwardEdges)) (fmap (\x -> setToList (findAcyclicRawPathsVisitedNodes g s (sourceArrow x) (Set.insert t v))) inwardEdges))) + where + inwardEdges = (setToList (findInwardEdges g t)) + + -- | An elementary cycle is a cycle which is not composed of any other cycle. + findElementaryCycles :: (Eq a, Eq b) => Graph a b -> CompositionLaw a b -> a -> Set (RawPath a b) + findElementaryCycles g cl o = set $ (simplify cl <$> []:(concat (zipWith sequence (fmap (fmap (\x y -> (y:x))) (fmap (\x -> setToList (findAcyclicRawPaths g o (sourceArrow x))) inEdges)) inEdges))) + where + inEdges = (setToList (findInwardEdges g o)) + + -- | Composes every elementary cycles of a node until they simplify into a fixed set of cycles. + -- + -- Warning : this function can do an infinite loop if the composition law does not simplify a cycle or all of its child cycles. + findCycles :: (Eq a, Eq b) => Graph a b -> CompositionLaw a b -> a -> Set (RawPath a b) + findCycles g cl o = findCyclesWithPreviousCycles g cl o (findElementaryCycles g cl o) + where + findCyclesWithPreviousCycles g cl o p + | newCycles == p = newCycles + | otherwise = findCyclesWithPreviousCycles g cl o newCycles + where + newCycles = (simplify cl) <$> ((++) <$> p <*> findElementaryCycles g cl o) + + -- | Helper function which intertwine the second list in the first list. + -- + -- Example : intertwine [1,2,3] [4,5] = [1,4,2,5,3] + intertwine :: [a] -> [a] -> [a] + intertwine [] l = l + intertwine l [] = l + intertwine l1@(x1:xs1) l2@(x2:xs2) = (x1:(x2:(intertwine xs1 xs2))) + + -- | Takes a path and intertwine every cycles possible along its path. + intertwineWithCycles :: (Eq a, Eq b) => Graph a b -> CompositionLaw a b -> a -> RawPath a b -> Set (RawPath a b) + intertwineWithCycles g cl _ p@(x:xs) = set $ concat <$> ((uncurry intertwine) <$> zip (setToList prodCycles) (repeat ((:[]) <$> p))) where + prodCycles = cartesianProductOfSets cycles + cycles = ((findCycles g cl (targetArrow x))):(((\y -> (findCycles g cl (sourceArrow y)))) <$> p) + intertwineWithCycles g cl s [] = (findCycles g cl s) + + -- | Enumerates all paths between two nodes and construct composition graph morphisms with them. + mkAr :: (Eq a, Eq b) => Graph a b -> CompositionLaw a b -> a -> a -> Set (CGMorphism a b) + mkAr g cl s t = (\p -> CGMorphism{path=(s,p),compositionLaw=cl}) <$> allPaths where + acyclicPaths = (simplify cl) <$> (findAcyclicRawPaths g s t) + allPaths = (simplify cl <$> Set.unions (setToList ((intertwineWithCycles g cl s) <$> acyclicPaths))) + + -- | Return the label of a 'CompositionGraph' generator. + getLabel :: CGMorphism a b -> Maybe b + getLabel CGMorphism{path=(s,rp), compositionLaw=_} + | null rp = Nothing + | null.tail $ rp = Just (labelArrow.head $ rp) + | otherwise = Nothing + + -- | A 'CompositionGraph' is a graph with a composition law such that the free category generated by the graph quotiented out by the composition law gives a 'FiniteCategory'. + -- + -- 'CompositionGraph' is private, use the smart constructors 'compositionGraph' or 'unsafeCompositionGraph' to instantiate one. + data CompositionGraph a b = CompositionGraph { + support :: Graph a b, -- ^ The generating graph (or support) of the composition graph. + law :: CompositionLaw a b -- ^ The composition law of the composition graph. + } deriving (Eq) + + instance (Show a, Show b) => Show (CompositionGraph a b) where + show CompositionGraph{support=g, law=l} = "(unsafeCompositionGraph "++ show g ++ " " ++ show l ++ ")" + + instance (Eq a, Eq b) => Category (CompositionGraph a b) (CGMorphism a b) a where + identity c x + | x `isIn` (nodes (support c)) = CGMorphism {path=(x,[]),compositionLaw=(law c)} + | otherwise = error ("Math.FiniteCategories.CompositionGraph.identity: Trying to construct identity of an unknown object.") + ar c s t = mkAr (support c) (law c) s t + genAr c@CompositionGraph{support=g,law=l} s t + | s == t = Set.insert (identity c s) gen + | otherwise = gen + where gen = mkCGMorphism l <$> (Set.filter (\a -> s == (sourceArrow a) && t == (targetArrow a)) $ (edges g)) + + decompose c m@CGMorphism{path=(_,rp),compositionLaw=l} + | isIdentity c m = [m] + | otherwise = mkCGMorphism l <$> rp + + instance (Eq a, Eq b) => FiniteCategory (CompositionGraph a b) (CGMorphism a b) a where + ob = (nodes.support) + + instance (PrettyPrint a, PrettyPrint b, Eq a, Eq b) => PrettyPrint (CompositionGraph a b) where + pprint CompositionGraph{support=g,law=l} = "CompositionGraph("++pprint g++","++pprint l++")" + + -- | Smart constructor of `CompositionGraph`. + -- + -- If the 'CompositionGraph' constructed is valid, return 'Right' the composition graph, otherwise return Left a 'FiniteCategoryError'. + compositionGraph :: (Eq a, Eq b) => Graph a b -> CompositionLaw a b -> Either (FiniteCategoryError (CGMorphism a b) a) (CompositionGraph a b) + compositionGraph g l + | null check = Right c_g + | otherwise = Left err + where + c_g = CompositionGraph{support = g, law = l} + check = checkFiniteCategory c_g + Just err = check + + -- | Unsafe constructor of 'CompositionGraph' for performance purposes. It does not check the structure of the 'CompositionGraph'. + -- + -- Use this constructor only if the 'CompositionGraph' is necessarily well formed. + unsafeCompositionGraph :: Graph a b -> CompositionLaw a b -> CompositionGraph a b + unsafeCompositionGraph g l = CompositionGraph{support = g, law = l} + + + -- | Transforms any 'FiniteCategory' into a 'CompositionGraph'. + -- + -- The 'CompositionGraph' will take more space in memory compared to the original category because the composition law is stored as a 'Map'. + -- + -- Returns an isofunctor as a `Diagram` from the original category to the created 'CompositionGraph'. + -- + -- If you only want the 'CompositionGraph', take the 'tgt' of the 'Diagram'. + finiteCategoryToCompositionGraph :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> Diagram c m o (CompositionGraph o m) (CGMorphism o m) o + finiteCategoryToCompositionGraph cat = isofunct + where + morphToArrow f = Arrow{sourceArrow = source f, targetArrow = target f, labelArrow = f} + catLaw = weakMapFromSet [ + if isNotIdentity cat (g @ f) then + ((morphToArrow <$> (decompose cat g))++(morphToArrow <$> (decompose cat f)), morphToArrow <$> (decompose cat (g @ f))) + else + ((morphToArrow <$> (decompose cat g))++(morphToArrow <$> (decompose cat f)),[]) | + f <- (arrows cat), g <- (arFrom cat (target f)), isNotIdentity cat f, isNotIdentity cat g] + cg = CompositionGraph{support=(unsafeGraph (ob cat) [morphToArrow f | f <- (genArrows cat), isNotIdentity cat f]) + , law=catLaw} + isofunct = Diagram{src=cat,tgt=cg,omap=memorizeFunction id (ob cat),mmap=memorizeFunction (\f -> if isNotIdentity cat f + then + CGMorphism {path=(source f,(morphToArrow <$> (decompose cat f))),compositionLaw=catLaw} + else + identity cg (source f)) (arrows cat)} + + + + -- | The empty 'CompositionGraph'. + emptyCompositionGraph :: CompositionGraph a b + emptyCompositionGraph = CompositionGraph{support=unsafeGraph Set.empty Set.empty, law=Map.empty} + + ----------------------- + -- CG FILE + ----------------------- + + + -- | A token for a .cg file. + data Token = Name Text | BeginArrow | EndArrow | Equals | Identity | BeginSrc | EndSrc | BeginTgt | EndTgt | MapsTo deriving (Eq, Show) + + -- | Strip a token of unnecessary spaces. + strip :: Token -> Token + strip (Name txt) = Name (pack.reverse.stripLeft.reverse.stripLeft $ str) + where + str = unpack txt + stripLeft (' ':s) = s + stripLeft s = s + strip x = x + + -- | Transforms a string into a list of tokens. + parserLex :: String -> [Token] + parserLex str = strip <$> parserLexHelper str + where + parserLexHelper [] = [] + parserLexHelper ('#':str) = [] + parserLexHelper (' ':'-':str) = BeginArrow : (parserLexHelper str) + parserLexHelper ('-':'>':' ':str) = EndArrow : (parserLexHelper str) + parserLexHelper (' ':'=':' ':str) = Equals : (parserLexHelper str) + parserLexHelper ('<':'I':'D':'/':'>':str) = Identity : (parserLexHelper str) + parserLexHelper ('<':'S':'R':'C':'>':str) = BeginSrc : (parserLexHelper str) + parserLexHelper ('<':'T':'G':'T':'>':str) = BeginTgt : (parserLexHelper str) + parserLexHelper ('<':'/':'S':'R':'C':'>':str) = EndSrc : (parserLexHelper str) + parserLexHelper ('<':'/':'T':'G':'T':'>':str) = EndTgt : (parserLexHelper str) + parserLexHelper (' ':'=':'>':' ':str) = MapsTo : (parserLexHelper str) + parserLexHelper (c:str) = (result restLexed) + where + restLexed = (parserLexHelper str) + result (Name txt:xs) = (Name (cons c txt):xs) + result a = ((Name (singleton c)):a) + + type CG = CompositionGraph Text Text + + addObject :: [Token] -> CG -> CG + addObject [Name str] cg@CompositionGraph{support=g,law=l} = CompositionGraph{support=unsafeGraph (Set.insert str (nodes g)) (edges g),law=l} + addObject otherTokens _ = error $ "addObject on invalid tokens : "++show otherTokens + + addMorphism :: [Token] -> CG -> CG + addMorphism [Name src, BeginArrow, Name arr, EndArrow, Name tgt] cg = CompositionGraph{support=(unsafeGraph (nodes g) (Set.insert Arrow{sourceArrow=src, targetArrow=tgt, labelArrow=arr} (edges g))),law=l} + where + newCG1 = addObject [Name src] cg + newCG2@CompositionGraph{support=g,law=l} = addObject [Name tgt] newCG1 + addMorphism otherTokens _ = error $ "addMorphism on invalid tokens : "++show otherTokens + + extractPath :: [Token] -> RawPath Text Text + extractPath [] = [] + extractPath [Identity] = [] + extractPath [(Name _)] = [] + extractPath ((Name src) : (BeginArrow : ((Name arr) : (EndArrow : ((Name tgt) : ts))))) = (extractPath ((Name tgt) : ts)) ++ [Arrow{sourceArrow=src, targetArrow=tgt, labelArrow=arr}] + extractPath otherTokens = error $ "extractPath on invalid tokens : "++show otherTokens + + addCompositionLawEntry :: [Token] -> CG -> CG + addCompositionLawEntry tokens cg@CompositionGraph{support=g,law=l} = CompositionGraph{support=(unsafeGraph ((nodes g) ||| newObj) ((edges g) ||| newMorph)),law=Map.insert pathLeft pathRight l} + where + Just indexEquals = elemIndex Equals tokens + (tokensLeft,(_:tokensRight)) = splitAt indexEquals tokens + pathLeft = extractPath tokensLeft + pathRight = extractPath tokensRight + newObj = set $ (sourceArrow <$> pathLeft++pathRight)++(targetArrow <$> pathLeft++pathRight) + newMorph = set $ pathLeft++pathRight + + readLine :: String -> CG -> CG + readLine line cg + | null lexedLine = cg + | elem Equals lexedLine = addCompositionLawEntry lexedLine cg + | elem BeginArrow lexedLine = addMorphism lexedLine cg + | otherwise = addObject lexedLine cg + where + lexedLine = (parserLex line) + + -- | Unsafe version of 'readCGString' which does not check the structure of the result 'CompositionGraph'. + unsafeReadCGString :: String -> CG + unsafeReadCGString str = newCG + where + ls = lines str + cg = emptyCompositionGraph + newCG = foldr readLine cg ls + + -- | Read a .cg string to create a 'CompositionGraph'. + -- + -- A .cg string follows the following rules : + -- + -- 0. Every character of a line following a "#" character are ignored. + -- + -- 1. Each line defines either an object, a morphism or a composition law entry. + -- + -- 2. The following strings are reserved : " -","-> "," = ", "\<ID/\>", "\<SRC\>", "\</SRC\>", "\<TGT\>", "\</TGT\>", " => " + -- + -- 3. To define an object, write a line containing its name. + -- + -- 4. To define an arrow, the syntax "source_object -name_of_morphism-> target_object" is used, where "source_object", "target_object" and "name_of_morphism" should be replaced. + -- + -- 4.1. If an object mentionned in an arrow does not exist, it is created. + -- + -- 4.2. The spaces are important. + -- + -- 5. To define a composition law entry, the syntax "source_object1 -name_of_first_morphism-> middle_object -name_of_second_morphism-> target_object1 = source_object2 -name_of_composite_morphism-> target_object2" is used, where "source_object1", "name_of_first_morphism", "middle_object", "name_of_second_morphism", "target_object1", "source_object2", "name_of_composite_morphism", "target_object2" should be replaced. + -- + -- 5.1 If an object mentionned does not exist, it is created. + -- + -- 5.2 If a morphism mentionned does not exist, it is created. + -- + -- 5.3 You can use the tag \<ID/\> in order to map a morphism to an identity. + readCGString :: String -> Either (FiniteCategoryError (CGMorphism Text Text) Text) CG + readCGString str + | null check = Right c_g + | otherwise = Left err + where + c_g = unsafeReadCGString str + check = checkFiniteCategory c_g + Just err = check + + + -- | Unsafe version of 'readCGFile' which does not check the structure of the resulting 'CompositionGraph'. + unsafeReadCGFile :: String -> IO CG + unsafeReadCGFile path = do + file <- readFile path + return $ unsafeReadCGString file + + + -- | Read a .cg file to create a 'CompositionGraph'. + -- + -- A .cg file follows the following rules : + -- + -- 0. Every character of a line following a "#" character are ignored. + -- + -- 1. Each line defines either an object, a morphism or a composition law entry. + -- + -- 2. The following strings are reserved : " -","-> "," = ", "\<ID/\>", "\<SRC\>", "\</SRC\>", "\<TGT\>", "\</TGT\>", " => " + -- + -- 3. To define an object, write a line containing its name. + -- + -- 4. To define an arrow, the syntax "source_object -name_of_morphism-> target_object" is used, where "source_object", "target_object" and "name_of_morphism" should be replaced. + -- + -- 4.1. If an object mentionned in an arrow does not exist, it is created. + -- + -- 4.2. The spaces are important. + -- + -- 5. To define a composition law entry, the syntax "source_object1 -name_of_first_morphism-> middle_object -name_of_second_morphism-> target_object1 = source_object2 -name_of_composite_morphism-> target_object2" is used, where "source_object1", "name_of_first_morphism", "middle_object", "name_of_second_morphism", "target_object1", "source_object2", "name_of_composite_morphism", "target_object2" should be replaced. + -- + -- 5.1 If an object mentionned does not exist, it is created. + -- + -- 5.2 If a morphism mentionned does not exist, it is created. + -- + -- 5.3 You can use the tag \<ID/\> in order to map a morphism to an identity. + readCGFile :: String -> IO (Either (FiniteCategoryError (CGMorphism Text Text) Text) CG) + readCGFile str = do + cg <- unsafeReadCGFile str + let check = checkFiniteCategory cg + return (if null check then Right cg else Left $ fromJust $ check) + where + fromJust (Just x) = x + + reversedRawPathToString :: (PrettyPrint a, PrettyPrint b) => RawPath a b -> String + reversedRawPathToString [] = "<ID>" + reversedRawPathToString [Arrow{sourceArrow = s, targetArrow = t,labelArrow = l}] = pprint s ++ " -" ++ pprint l ++ "-> " ++ pprint t + reversedRawPathToString (Arrow{sourceArrow = s, targetArrow = t,labelArrow = l}:xs) = pprint s ++ " -" ++ pprint l ++ "-> " ++ reversedRawPathToString xs + + -- | Transform a composition graph into a string following the .cg convention. + writeCGString :: (PrettyPrint a, PrettyPrint b, Eq a, Eq b) => CompositionGraph a b -> String + writeCGString cg = finalString + where + obString = intercalate "\n" $ pprint <$> (setToList.ob $ cg) + arNotIdentityAndNotComposite = setToList $ Set.filter (isGenerator cg) $ Set.filter (isNotIdentity cg) (genArrows cg) + reversedRawPaths = (reverse.snd.path) <$> arNotIdentityAndNotComposite + arString = intercalate "\n" $ reversedRawPathToString <$> reversedRawPaths + lawString = intercalate "\n" $ (\(rp1,rp2) -> (reversedRawPathToString (reverse rp1)) ++ " = " ++ (reversedRawPathToString (reverse rp2))) <$> ((Map.toList).law $ cg) + finalString = "#Objects :\n"++obString++"\n\n# Arrows :\n"++arString++"\n\n# Composition law :\n"++lawString + + -- | Saves a composition graph into a file located at a given path. + writeCGFile :: (PrettyPrint a, PrettyPrint b, Eq a, Eq b) => CompositionGraph a b -> String -> IO () + writeCGFile cg filepath = do + createDirectoryIfMissing True $ takeDirectory filepath + writeFile filepath $ writeCGString cg + + + ----------------------- + -- CGD FILE + ----------------------- + + type CGD = Diagram (CompositionGraph Text Text) (CGMorphism Text Text) Text (CompositionGraph Text Text) (CGMorphism Text Text) Text + + addOMapEntry :: [Token] -> CGD -> CGD + addOMapEntry [Name x, MapsTo, Name y] diag + | x `isIn` (domain (omap diag)) = if y == (diag ->$ x) then diag else error ("Incoherent maps of object : F("++show x++") = "++show y ++ " and "++show (diag ->$ x)) + | otherwise = Diagram{src=src diag, tgt=tgt diag, omap=Map.insert x y (omap diag), mmap=mmap diag} + addOMapEntry otherTokens _ = error $ "addOMapEntry on invalid tokens : "++show otherTokens + + addMMapEntry :: [Token] -> CGD -> CGD + addMMapEntry tks@[Name sx, BeginArrow, Name lx, EndArrow, Name tx, MapsTo, Identity] diag = if sx `isIn` (domain (omap diag)) then Diagram{src=src diag, tgt=tgt diag, omap=omap diag, mmap=Map.insert sourceMorph (identity (tgt diag) (diag ->$ sx)) (mmap diag)} else error ("You must specify the image of the source of the morphism before mapping to an identity : "++show tks) + where + sourceMorphCand = Set.filter (\e -> getLabel e == Just lx) (genAr (src diag) sx tx) + sourceMorph = if Set.null sourceMorphCand then error $ "addMMapEntry : morphism not found in source category for the following map : "++ show tks else anElement sourceMorphCand + addMMapEntry tks@[Name sx, BeginArrow, Name lx, EndArrow, Name tx, MapsTo, Name sy, BeginArrow, Name ly, EndArrow, Name ty] diag = Diagram{src=src newDiag2, tgt=tgt newDiag2, omap=omap newDiag2, mmap=Map.insert sourceMorph targetMorph (mmap newDiag2)} + where + sourceMorphCand = Set.filter (\e -> getLabel e == Just lx) (genAr (src diag) sx tx) + targetMorphCand = Set.filter (\e -> getLabel e == Just ly) (genAr (tgt diag) sy ty) + sourceMorph = if Set.null sourceMorphCand then error $ "addMMapEntry : morphism not found in source category for the following map : "++ show tks else anElement sourceMorphCand + targetMorph = if Set.null targetMorphCand then error $ "addMMapEntry : morphism not found in target category for the following map : "++ show tks else anElement targetMorphCand + newDiag1 = addOMapEntry [Name sx, MapsTo, Name sy] diag + newDiag2 = addOMapEntry [Name tx, MapsTo, Name ty] newDiag1 + addMMapEntry otherTokens _ = error $ "addMMapEntry on invalid tokens : "++show otherTokens + + readLineD :: String -> CGD -> CGD + readLineD line diag@Diagram{src=s, tgt=t, omap=om, mmap=mm} + | null lexedLine = diag + | elem MapsTo lexedLine = if elem BeginArrow lexedLine + then addMMapEntry lexedLine diag + else addOMapEntry lexedLine diag + | otherwise = diag + where + lexedLine = (parserLex line) + + extractSrcSection :: [String] -> [String] + extractSrcSection lines + | not (elem [BeginSrc] (parserLex <$> lines)) = error $ "No <SRC> section or malformed <SRC> section in file : "++ show lines + | not (elem [EndSrc] (parserLex <$> lines)) = error $ "No <SRC> section or malformed <SRC> section in file : "++ show lines + | indexEndSrc < indexBeginSrc = error $ "Malformed <SRC> section in file : "++ show lines + | otherwise = c + where + Just indexBeginSrc = (elemIndex [BeginSrc] (parserLex <$> lines)) + Just indexEndSrc = (elemIndex [EndSrc] (parserLex <$> lines)) + (a,b) = splitAt (indexBeginSrc+1) lines + (c,d) = splitAt (indexEndSrc-indexBeginSrc-1) b + + extractTgtSection :: [String] -> [String] + extractTgtSection lines + | not (elem [BeginTgt] (parserLex <$> lines)) = error $ "No <TGT> section or malformed <TGT> section in file : "++ show lines + | not (elem [EndTgt] (parserLex <$> lines)) = error $ "No <TGT> section or malformed <TGT> section in file : "++ show lines + | indexEndTgt < indexBeginTgt = error $ "Malformed <TGT> section in file : "++ show lines + | otherwise = c + where + Just indexBeginTgt = (elemIndex [BeginTgt] (parserLex <$> lines)) + Just indexEndTgt = (elemIndex [EndTgt] (parserLex <$> lines)) + (a,b) = splitAt (indexBeginTgt+1) lines + (c,d) = splitAt (indexEndTgt-indexBeginTgt-1) b + + + -- | Unsafe version of 'readCGDString' which does not check the structure of the resulting 'Diagram'. + unsafeReadCGDString :: String -> CGD + unsafeReadCGDString str = completeDiagram finalDiag + where + ls = filter (not.null.parserLex) $ lines str + s = unsafeReadCGString $ intercalate "\n" (extractSrcSection ls) + t = unsafeReadCGString $ intercalate "\n" (extractTgtSection ls) + diag = Diagram{src=s, tgt=t,omap=weakMap [], mmap=weakMap []} + finalDiag = foldr readLineD diag ls + + -- | Read a .cgd string and returns a diagram. A .cgd string obeys the following rules : + -- + -- 1. There is a line "\<SRC\>" and a line "\</SRC\>". + -- + -- 1.1 Between these two lines, the source composition graph is defined as in a cg file. + -- + -- 2. There is a line "\<TGT\>" and a line "\</TGT\>". + -- + -- 2.1 Between these two lines, the target composition graph is defined as in a cg file. + -- + -- 3. Outside of the two previously described sections, you can declare the maps between objects and morphisms. + -- + -- 3.1 You map an object to another with the following syntax : "object1 => object2". + -- + -- 3.2 You map a morphism to another with the following syntax : "objSrc1 -arrowSrc1-> objSrc2 => objTgt1 -arrowTgt1-> objTgt2". + -- + -- 4. You don't have to (and you shouldn't) specify maps from identities, nor maps from composite arrows. + readCGDString :: String -> Either (DiagramError CG (CGMorphism Text Text) Text CG (CGMorphism Text Text) Text) CGD + readCGDString str + | null check = Right diag + | otherwise = Left err + where + diag = unsafeReadCGDString str + check = checkFiniteDiagram diag + Just err = check + + -- | Unsafe version 'readCGDFile' which does not check the structure of the resulting 'Diagram'. + unsafeReadCGDFile :: String -> IO CGD + unsafeReadCGDFile path = do + raw <- readFile path + return (unsafeReadCGDString raw) + + -- | Read a .cgd file and returns a diagram. A .cgd file obeys the following rules : + -- + -- 1. There is a line "\<SRC\>" and a line "\</SRC\>". + -- + -- 1.1 Between these two lines, the source composition graph is defined as in a cg file. + -- + -- 2. There is a line "\<TGT\>" and a line "\</TGT\>". + -- + -- 2.1 Between these two lines, the target composition graph is defined as in a cg file. + -- + -- 3. Outside of the two previously described sections, you can declare the maps between objects and morphisms. + -- + -- 3.1 You map an object to another with the following syntax : "object1 => object2". + -- + -- 3.2 You map a morphism to another with the following syntax : "objSrc1 -arrowSrc1-> objSrc2 => objTgt1 -arrowTgt1-> objTgt2". + -- + -- 4. You don't have to (and you shouldn't) specify maps from identities, nor maps from composite arrows. + readCGDFile :: String -> IO (Either (DiagramError CG (CGMorphism Text Text) Text CG (CGMorphism Text Text) Text) CGD) + readCGDFile path = do + raw <- readFile path + return (readCGDString raw) + + -- | Transform a composition graph diagram into a string following the .cgd convention. + writeCGDString :: (PrettyPrint a1, PrettyPrint b1, Eq a1, Eq b1, + PrettyPrint a2, PrettyPrint b2, Eq a2, Eq b2) => + Diagram (CompositionGraph a1 b1) (CGMorphism a1 b1) a1 (CompositionGraph a2 b2) (CGMorphism a2 b2) a2 -> String + writeCGDString diag = srcString ++ tgtString ++ "\n" ++ omapString ++ "\n" ++ mmapString + where + srcString = "<SRC>\n"++writeCGString (src diag)++"\n</SRC>\n" + tgtString = "<TGT>\n"++writeCGString (tgt diag)++"</TGT>\n" + omapString = "#Object mapping\n" ++ (intercalate "\n" $ (\o -> (pprint o) ++ " => " ++ (pprint (diag ->$ o)) )<$> (setToList.ob.src $ diag)) ++ "\n" + mmapString = "#Morphism mapping\n" ++ (intercalate "\n" $ (\m -> pprint (source m) ++ " -" ++ pprint m ++ "-> " ++ pprint (target m)++ " => " ++ if isIdentity (tgt diag) (diag ->£ m) then "<ID/>" else pprint (source (diag ->£ m)) ++ " -" ++ pprint (diag ->£ m) ++ "-> " ++ pprint (target (diag ->£ m)))<$> (setToList.(Set.filter (isNotIdentity (src diag))).genArrows.src $ diag)) ++ "\n" + + -- | Saves a composition graph diagram into a file located at a given path. + writeCGDFile :: (PrettyPrint a1, PrettyPrint b1, Eq a1, Eq b1, + PrettyPrint a2, PrettyPrint b2, Eq a2, Eq b2) => + Diagram (CompositionGraph a1 b1) (CGMorphism a1 b1) a1 (CompositionGraph a2 b2) (CGMorphism a2 b2) a2 -> String -> IO () + writeCGDFile diag filepath = do + createDirectoryIfMissing True $ takeDirectory filepath + writeFile filepath $ writeCGDString diag + + + +----------------------- +-- Random CompositionGraph +----------------------- + + + + + + -- | Find first order composites arrows in a composition graph. + compositeMorphisms :: (Eq a, Eq b, Show a) => CompositionGraph a b -> [CGMorphism a b] + compositeMorphisms c = setToList [g @ f | f <- genArrows c, g <- genArFrom c (target f), not (isIn (g @ f) (genAr c (source f) (target g)))] + + -- | Merge two nodes. + mergeNodes :: (Eq a, Eq b) => CompositionGraph a b -> a -> a -> CompositionGraph a b + mergeNodes cg@CompositionGraph{support=g,law=l} s t + | not (isIn s (nodes g)) = error "mapped but not in rcg." + | not (isIn t (nodes g)) = error "mapped to but not in rcg." + | s == t = cg + | otherwise = CompositionGraph {support=unsafeGraph (Set.filter (/=s) (nodes g)) (replaceArrow <$> (edges g)), law=newLaw} + where + replace x = if x == s then t else x + replaceArrow Arrow{sourceArrow=s3,targetArrow=t3,labelArrow=l3} = Arrow{sourceArrow=replace s3,targetArrow=replace t3,labelArrow=l3} + newLaw = weakMap $ (\(k,v) -> (replaceArrow <$> k, replaceArrow <$> v)) <$> (Map.mapToList l) + + -- | Merge two morphisms of a composition graph, the morphism mapped should be composite, the morphism mapped to should be a generator. + mergeMorphisms :: (Eq a, Eq b) => CompositionGraph a b -> CGMorphism a b -> CGMorphism a b -> CompositionGraph a b + mergeMorphisms cg@CompositionGraph{support=g,law=l} s@CGMorphism{path=p1@(s1,rp1),compositionLaw=l1} t@CGMorphism{path=p2@(s2,rp2),compositionLaw=l2} + | (isGenerator cg s) = error "Generator at the start of a merge" + | (isComposite cg t) = error "Composite at the end of a merge" + | s1 == targetPath p1 = mergeNodes CompositionGraph{support=g, law=newLaw} (source s) (source t) + | s1 == targetPath p2 = mergeNodes (mergeNodes CompositionGraph{support=g, law=newLaw} (source s) (source t)) (target s) (source t) + | otherwise = mergeNodes (mergeNodes CompositionGraph{support=g, law=newLaw} (source s) (source t)) (target s) (target t) where + targetPath path = if null (snd path) then fst path else (targetArrow (head (snd path))) + newLaw = Map.insert (replaceArrow <$> rp1) (replaceArrow <$> rp2) (weakMap $ (\(k,v) -> (replaceArrow <$> k, replaceArrow <$> v)) <$> (Map.mapToList l)) + where + replace x = if x == s1 then s2 else (if x == targetPath p1 then targetPath p2 else x) + replaceArrow Arrow{sourceArrow=s3,targetArrow=t3,labelArrow=l3} = Arrow{sourceArrow=replace s3,targetArrow=replace t3,labelArrow=l3} + + -- | Checks associativity of a composition graph. + checkAssociativity :: (Eq a, Eq b, Show a) => CompositionGraph a b -> Bool + checkAssociativity cg = Set.foldr (&&) True [checkTriplet (f,g,h) | f <- genArrows cg, g <- genArFrom cg (target f), h <- genArFrom cg (target g)] + where + checkTriplet (f,g,h) = (h @ g) @ f == h @ (g @ f) + + -- | Find all composite arrows and try to map them to generating arrows. + identifyCompositeToGen :: (RandomGen g, Eq a, Eq b, Show a) => CompositionGraph a b -> Int -> g -> (Maybe (CompositionGraph a b), g) + identifyCompositeToGen _ 0 rGen = (Nothing, rGen) + identifyCompositeToGen cg n rGen + | not (checkAssociativity cg) = (Nothing, rGen) + | null compositeMorphs = (Just cg, rGen) + | otherwise = if isNothing newCG then identifyCompositeToGen cg (n `div` 2) newGen2 else (newCG, newGen2) + where + compositeMorphs = compositeMorphisms cg + morphToMap = (head compositeMorphs) + (selectedGen,newGen1) = if (source morphToMap == target morphToMap) then pickOne [fs | obj <- (setToList (ob cg)), fs <- (setToList (genAr cg obj obj))] rGen else pickOne (setToList (genArrows cg)) rGen + (newCG,newGen2) = identifyCompositeToGen (mergeMorphisms cg morphToMap selectedGen) n newGen1 + + -- | Pick one element of a list randomly. + pickOne :: (RandomGen g) => [a] -> g -> (a,g) + pickOne [] g = error "pickOne in an empty list." + pickOne l g = ((l !! index),newGen) where + (index,newGen) = (uniformR (0,(length l)-1) g) + + listWithoutNthElem :: [a] -> Int -> [a] + listWithoutNthElem [] _ = [] + listWithoutNthElem (x:xs) 0 = xs + listWithoutNthElem (x:xs) k = x:(listWithoutNthElem xs (k-1)) + + -- | Sample /n/ elements of a list randomly. + sample :: (RandomGen g) => [a] -> Int -> g -> ([a],g) + sample _ 0 g = ([],g) + sample [] k g = error "Sample size bigger than the list size." + sample l n g = (((l !! index):rest),finalGen) where + (index,newGen) = (uniformR (0,(length l)-1) g) + new_l = listWithoutNthElem l index + (rest,finalGen) = sample new_l (n-1) newGen + + -- | Algorithm described in `mkRandomCompositionGraph`. + monoidificationAttempt :: (RandomGen g, Eq a, Eq b, Show a) => CompositionGraph a b -> Int -> g -> (CompositionGraph a b, g, [a]) + monoidificationAttempt cg p g = if isNothing result then (cg,finalGen,[]) else (fromJust result, finalGen, [s,t]) + where + ([s,t],newGen) = if ((cardinal (ob cg)) > 1) then sample (setToList.ob $ cg) 2 g else (setToList (ob cg ||| ob cg),g) + newCG = mergeNodes cg s t + (result,finalGen) = identifyCompositeToGen newCG p newGen + + -- | Initialize a composition graph with all arrows seperated. + initRandomCG :: Int -> CompositionGraph Int Int + initRandomCG n = CompositionGraph{support=unsafeGraph (set [0..n+n-1]) (set [Arrow{sourceArrow=(i+i), targetArrow=(i+i+1), labelArrow=i} | i <- [0..n]]),law=weakMap []} + + -- | Generates a random composition graph. + -- + -- We use the fact that a category is a generalized monoid. + -- + -- We try to create a composition law of a monoid greedily. + -- + -- To get a category, we begin with a category with all arrows seperated and not composing with each other. + -- It is equivalent to the monoid with an empty composition law. + -- + -- Then, a monoidification attempt is the following algorihm : + -- + -- 1. Pick two objects, merge them. + -- 2. While there are composite morphisms, try to merge them with generating arrows. + -- 3. If it fails, don't change the composition graph. + -- 4. Else return the new composition graph + -- + -- A monoidification attempt takes a valid category and outputs a valid category, furthermore, the number of arrows is constant + -- and the number of objects is decreasing (not strictly). + constructRandomCompositionGraph :: (RandomGen g) => Int -- ^ Number of arrows of the random composition graph. + -> Int -- ^ Number of monoidification attempts, a bigger number will produce more morphisms that will compose but the function will be slower. + -> Int -- ^ Perseverance : how much we pursure an attempt far away to find a law that works, a bigger number will make the attemps more successful, but slower. (When in doubt put 4.) + -> g -- ^ Random generator. + -> (CompositionGraph Int Int, g) + constructRandomCompositionGraph nbAr nbAttempts perseverance gen = attempt (initRandomCG nbAr) nbAttempts perseverance gen + where + attempt cg 0 _ gen = (cg, gen) + attempt cg n p gen = attempt newCG (n-1) p newGen + where + (newCG, newGen,_) = (monoidificationAttempt cg p gen) + + -- | Creates a random composition graph with default random values. + -- + -- The number of arrows will be in the interval [1, 20]. + defaultConstructRandomCompositionGraph :: (RandomGen g) => g -> (CompositionGraph Int Int, g) + defaultConstructRandomCompositionGraph g1 = constructRandomCompositionGraph nbArrows (min nbAttempts 20) 4 g3 + where + (nbArrows, g2) = uniformR (1,20) g1 + (nbAttempts, g3) = uniformR (0,nbArrows+nbArrows) g2 + + + -- | Constructs two random composition graphs and choose a random diagram between the two. + defaultConstructRandomDiagram :: (RandomGen g) => g -> (Diagram (CompositionGraph Int Int) (CGMorphism Int Int) Int (CompositionGraph Int Int) (CGMorphism Int Int) Int, g) + defaultConstructRandomDiagram g1 = pickRandomDiagram cat1 cat2 g3 + where + (nbArrows1, g2) = uniformR (1,8) g1 + (nbAttempts1, g3) = uniformR (0,nbArrows1+nbArrows1) g2 + (cat1, g4) = constructRandomCompositionGraph nbArrows1 nbAttempts1 5 g3 + (nbArrows2, g5) = uniformR (1,11-nbArrows1) g4 + (nbAttempts2, g6) = uniformR (0,nbArrows2+nbArrows2) g5 + (cat2, g7) = constructRandomCompositionGraph nbArrows2 nbAttempts2 5 g6
+ src/Math/FiniteCategories/CompositionGraph/Example.hs view
@@ -0,0 +1,48 @@+{-| Module : FiniteCategories +Description : An example of 'CompositionGraph' exported with GraphViz. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +An example of 'CompositionGraph' exported with GraphViz. + +Examples of other categories transformed into 'CompositionGraph's are also exported. + +A random example of 'CompositionGraph' is also exported. + +A 'CompositionGraph' created from a string is also exported. + +Export the categories in the directory "OutputGraphViz\/Examples\/FiniteCategories\/CompositionGraph". +-} +module Math.FiniteCategories.CompositionGraph.Example +( + main +) +where + import qualified Data.WeakSet as Set + import Data.WeakSet.Safe + import Data.WeakMap.Safe + + import Math.FiniteCategory + import Math.Categories + import Math.FiniteCategories + import Math.IO.FiniteCategories.ExportGraphViz + import Math.IO.PrettyPrint + + import System.Random + import Numeric.Natural + + -- | An example of 'CompositionGraph' exported with GraphViz. + main :: IO () + main = do + putStrLn "Start of Math.FiniteCategories.CompositionGraph.Example" + catToPdf (unsafeCompositionGraph (unsafeGraph (set [1 :: Int,2,3]) (set [Arrow{sourceArrow=1,targetArrow=1,labelArrow='a'},Arrow{sourceArrow=1,targetArrow=2,labelArrow='b'},Arrow{sourceArrow=2,targetArrow=3,labelArrow='c'}])) (weakMap [([Arrow{sourceArrow=1,targetArrow=1,labelArrow='a'},Arrow{sourceArrow=1,targetArrow=1,labelArrow='a'}],[Arrow{sourceArrow=1,targetArrow=1,labelArrow='a'}])])) "OutputGraphViz/Examples/FiniteCategories/CompositionGraph/CompositionGraph" + diagToPdf2 (finiteCategoryToCompositionGraph (ens.(Set.powerSet).set $ "AB")) "OutputGraphViz/Examples/FiniteCategories/CompositionGraph/EnsToCompositionGraph" + diagToPdf2 (finiteCategoryToCompositionGraph (numberCategory 4)) "OutputGraphViz/Examples/FiniteCategories/CompositionGraph/NumberCategoryToCompositionGraph" + catToPdf (fst.defaultConstructRandomCompositionGraph $ (mkStdGen 123456)) "OutputGraphViz/Examples/FiniteCategories/CompositionGraph/RandomCompositionGraph" + diagToPdf2 (fst.defaultConstructRandomDiagram $ (mkStdGen 12345678)) "OutputGraphViz/Examples/FiniteCategories/CompositionGraph/RandomDiagram" + let (Right cg) = readCGString "A -f-> B -g-> C = A -h-> C" + catToPdf cg "OutputGraphViz/Examples/FiniteCategories/CompositionGraph/CompositionGraphFromString" + putStrLn "End of Math.FiniteCategories.CompositionGraph.Example"
+ src/Math/FiniteCategories/ConeCategory.hs view
@@ -0,0 +1,19 @@+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-} + +{-| Module : FiniteCategories +Description : A 'ConeCategory' can be a 'FiniteCategory' if the target category of the diagrams is finite. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +A 'ConeCategory' can be a 'FiniteCategory' if the target category of the diagrams is finite. +-} + +module Math.FiniteCategories.ConeCategory +( + module Math.Categories.ConeCategory +) +where + import Math.Categories.ConeCategory
+ src/Math/FiniteCategories/ConeCategory/Example.hs view
@@ -0,0 +1,45 @@+{-| Module : FiniteCategories +Description : An exemple of 'ConeCategory' exported with GraphViz. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +An exemple of 'ConeCategory' exported with GraphViz. + +Export the 'ConeCategory' of a 'V' 'Diagram' in a square category in the directory "OutputGraphViz\/Examples\/FiniteCategories\/ConeCategory". +-} +module Math.FiniteCategories.ConeCategory.Example +( + main +) +where + import Math.Category + import Math.Categories.FinGrph + import Math.FiniteCategories.ConeCategory + import Math.FiniteCategories.FunctorCategory + import Math.FiniteCategories.V + import Math.FiniteCategories.Hat + import Math.FiniteCategories.SafeCompositionGraph + import Math.IO.FiniteCategories.ExportGraphViz + + 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 + + -- | An exemple of 'ConeCategory' exported with GraphViz. + main :: IO () + main = do + putStrLn "Start of Math.FiniteCategories.ConeCategory.Example" + let Right scg = safeCompositionGraph (unsafeGraph (set "ABCD") (set [Arrow{sourceArrow = 'A', targetArrow = 'B', labelArrow='f'}, Arrow{sourceArrow = 'A', targetArrow = 'C', labelArrow='g'}, Arrow{sourceArrow = 'B', targetArrow = 'D', labelArrow='h'}, Arrow{sourceArrow = 'C', targetArrow = 'D', labelArrow='I'}])) (weakMap [([Arrow{sourceArrow = 'C', targetArrow = 'D', labelArrow='I'}, Arrow{sourceArrow = 'A', targetArrow = 'C', labelArrow='g'}],[Arrow{sourceArrow = 'B', targetArrow = 'D', labelArrow='h'}, Arrow{sourceArrow = 'A', targetArrow = 'B', labelArrow='f'}])]) 3 + let diag = completeDiagram Diagram{src=V,tgt=scg,omap=weakMap [(VA,'D'),(VB,'B'),(VC,'C')], mmap=weakMap [(VF,anElement (genAr scg 'B' 'D')),(VG,anElement (genAr scg 'C' 'D'))]} + diagToPdf2 diag "OutputGraphViz/Examples/FiniteCategories/ConeCategory/Diag" + catToPdf (coneCategory diag) "OutputGraphViz/Examples/FiniteCategories/ConeCategory/ConeCategory" + let diag2 = completeDiagram Diagram{src=Hat,tgt=scg,omap=weakMap [(HatA,'A'),(HatB,'B'),(HatC,'C')], mmap=weakMap [(HatF,anElement (genAr scg 'A' 'B')),(HatG,anElement (genAr scg 'A' 'C'))]} + diagToPdf2 diag2 "OutputGraphViz/Examples/FiniteCategories/ConeCategory/Diag2" + catToPdf (coconeCategory diag2) "OutputGraphViz/Examples/FiniteCategories/ConeCategory/CoconeCategory" + putStrLn "End of Math.FiniteCategories.ConeCategory.Example"
+ src/Math/FiniteCategories/DiscreteCategory.hs view
@@ -0,0 +1,36 @@+{-# LANGUAGE MultiParamTypeClasses #-} + +{-| Module : FiniteCategories +Description : A discrete category is a full subcategory of __'Galaxy'__. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +A discrete category is a full subcategory of __'Galaxy'__. +-} + +module Math.FiniteCategories.DiscreteCategory +( + DiscreteMorphism(..), + DiscreteCategory(..), + discreteCategory +) +where + import Math.FiniteCategory + import Math.Categories.Galaxy + import Math.FiniteCategories.FullSubcategory + + import Data.WeakSet (Set) + import Data.WeakSet.Safe + + -- | A discrete category is a full subcategory of __'Galaxy'__. + type DiscreteCategory a = FullSubcategory (Galaxy a) (StarIdentity a) a + + -- | A discrete morphism. + type DiscreteMorphism a = StarIdentity a + + -- | Return the 'DiscreteCategory' containing a set of objects. + discreteCategory :: Set a -> DiscreteCategory a + discreteCategory s = FullSubcategory Galaxy s
+ src/Math/FiniteCategories/DiscreteCategory/Example.hs view
@@ -0,0 +1,30 @@+{-| Module : FiniteCategories +Description : Six examples of 'DiscreteCategory' exported with GraphViz. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +Six examples of 'DiscreteCategory' exported with GraphViz. + +Export categories __0__ up to __5__ in the directory "OutputGraphViz\/Examples\/FiniteCategories\/DiscreteCategory". +-} +module Math.FiniteCategories.DiscreteCategory.Example +( + main +) +where + import Data.WeakSet.Safe + + import Math.FiniteCategories.DiscreteCategory + import Math.IO.FiniteCategories.ExportGraphViz + + -- | Six examples of 'DiscreteCategory' exported with GraphViz. + main :: IO () + main = do + putStrLn "Start of Math.FiniteCategories.DiscreteCategory.Example" + let cats = discreteCategory <$> (\n -> set (take n ['A'..])) <$> [0..5] + let exports = uncurry catToPdf <$> zip cats (("OutputGraphViz/Examples/FiniteCategories/DiscreteCategory/"++) <$> show <$> [0..5]) + sequence exports + putStrLn "End of Math.FiniteCategories.DiscreteCategory.Example"
+ src/Math/FiniteCategories/Ens.hs view
@@ -0,0 +1,34 @@+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-} + +{-| Module : FiniteCategories +Description : __'Ens'__ are full subcategories of __Set__ (__'FinSet'__ for us) in a given set universe. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +__'Ens'__ are full subcategories of __Set__ (__'FinSet'__ for us) in a given set universe. + +(See "Categories for the Working Mathematican" Saunders Mac Lane. p.11) +-} + +module Math.FiniteCategories.Ens +( + Ens, + ens +) +where + import Math.FiniteCategory + import Math.FiniteCategories.FullSubcategory + import Math.Categories.FinSet + + import Data.WeakSet (Set) + import Data.WeakSet.Safe + + -- | __'Ens'__ are full subcategories of __Set__ (__'FinSet'__ for us) in a given set universe. + type Ens a = InheritedFullSubcategory (FinSet a) (Function a) (Set a) + + -- | The __'Ens'__ generated by a set universe. (See "Categories for the Working Mathematican" Saunders Mac Lane. p.11) + ens :: Set (Set a) -> Ens a + ens s = InheritedFullSubcategory FinSet s
+ src/Math/FiniteCategories/Ens/Example.hs view
@@ -0,0 +1,29 @@+{-| Module : FiniteCategories +Description : An example of __'Ens'__ exported with GraphViz. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +An example of __'Ens'__ exported with GraphViz. + +Export the category in the directory "OutputGraphViz\/Examples\/FiniteCategories\/Ens". +-} +module Math.FiniteCategories.Ens.Example +( + main +) +where + import Data.WeakSet (powerSet, Set) + import Data.WeakSet.Safe + + import Math.FiniteCategories + import Math.IO.FiniteCategories.ExportGraphViz + + -- | __'Ens'__ exported with GraphViz. + main :: IO () + main = do + putStrLn "Start of Math.FiniteCategories.Ens.Example" + catToPdf (ens.powerSet.set $ "ABC") "OutputGraphViz/Examples/FiniteCategories/Ens/Ens" + putStrLn "End of Math.FiniteCategories.Ens.Example"
+ src/Math/FiniteCategories/Examples.hs view
@@ -0,0 +1,51 @@+{-| Module : FiniteCategories +Description : Run all finite categories examples. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +Run all finite categories examples. See results in the folder "OutputGraphViz\/Examples\/FiniteCategories". +-} + +module Math.FiniteCategories.Examples +( + main +) +where + import qualified Math.FiniteCategories.NumberCategory.Example as NumberCategory + import qualified Math.FiniteCategories.DiscreteCategory.Example as DiscreteCategory + import qualified Math.FiniteCategories.Hat.Example as Hat + import qualified Math.FiniteCategories.V.Example as V + import qualified Math.FiniteCategories.Parallel.Example as Parallel + import qualified Math.FiniteCategories.Square.Example as Square + import qualified Math.FiniteCategories.Ens.Example as Ens + import qualified Math.FiniteCategories.FinGrph.Example as FinGrph + import qualified Math.FiniteCategories.Opposite.Example as Opposite + import qualified Math.FiniteCategories.FinCat.Example as FinCat + import qualified Math.FiniteCategories.FunctorCategory.Example as FunctorCategory + import qualified Math.FiniteCategories.CompositionGraph.Example as CompositionGraph + import qualified Math.FiniteCategories.SafeCompositionGraph.Example as SafeCompositionGraph + import qualified Math.FiniteCategories.CommaCategory.Example as CommaCategory + import qualified Math.FiniteCategories.One.Example as One + import qualified Math.FiniteCategories.ConeCategory.Example as ConeCategory + + -- | Run all examples of the project. See results in the folder OutputGraphViz. + main = do + NumberCategory.main + DiscreteCategory.main + Hat.main + V.main + Parallel.main + Square.main + Ens.main + FinGrph.main + Opposite.main + FinCat.main + FunctorCategory.main + CompositionGraph.main + SafeCompositionGraph.main + CommaCategory.main + One.main + ConeCategory.main
+ src/Math/FiniteCategories/FinCat/Example.hs view
@@ -0,0 +1,31 @@+{-| Module : FiniteCategories +Description : An example of 'FullSubcategory' of __'FinCat'__ exported with GraphViz. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +An example of 'FullSubcategory' of __'FinCat'__ exported with GraphViz. + +Export the category in the directory "OutputGraphViz\/Examples\/FiniteCategories\/FinCat". +-} +module Math.FiniteCategories.FinCat.Example +( + main +) +where + import Data.WeakSet.Safe + + import Math.Categories + import Math.FiniteCategories + import Math.IO.FiniteCategories.ExportGraphViz + + import Numeric.Natural + + -- | An example of 'FullSubcategory' of __'FinCat'__ exported with GraphViz. + main :: IO () + main = do + putStrLn "Start of Math.FiniteCategories.FinCat.Example" + catToPdf (FullSubcategory FinCat (numberCategory <$> (set [0..2])) :: FullSubcategory (FinCat NumberCategory NumberCategoryMorphism Natural) (FinFunctor NumberCategory NumberCategoryMorphism Natural) NumberCategory) "OutputGraphViz/Examples/FiniteCategories/FinCat/FinCat" + putStrLn "End of Math.FiniteCategories.FinCat.Example"
+ src/Math/FiniteCategories/FinGrph/Example.hs view
@@ -0,0 +1,39 @@+{-| Module : FiniteCategories +Description : An example of 'FullSubcategory' of __'FinGrph'__ exported with GraphViz. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +An example of 'FullSubcategory' of __'FinGrph'__ exported with GraphViz. + +Export the category in the directory "OutputGraphViz\/Examples\/FiniteCategories\/FinGrph". +-} +module Math.FiniteCategories.FinGrph.Example +( + main +) +where + 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.Text (Text, pack) + + import Math.Categories + import Math.FiniteCategories + import Math.IO.FiniteCategories.ExportGraphViz + + import Numeric.Natural + + + -- | A 'FullSubcategory' __'FinGrph'__ exported with GraphViz. + main :: IO () + main = do + putStrLn "Start of Math.FiniteCategories.FinGrph.Example" + let c = FullSubcategory FinGrph $ (underlyingGraphFormat id (const.pack $ "")).numberCategory <$> set [0..2] :: FullSubcategory (FinGrph Natural Text) (GraphHomomorphism Natural Text) (Graph Natural Text) + catToPdf c "OutputGraphViz/Examples/FiniteCategories/FinGrph/FinGrph" + putStrLn "End of Math.FiniteCategories.FinGrph.Example"
+ src/Math/FiniteCategories/FullSubcategory.hs view
@@ -0,0 +1,73 @@+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, UndecidableInstances #-} + +{-| Module : FiniteCategories +Description : Selecting a full subcategory yields a finite category. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +Selecting a 'FullSubcategory' in a 'Category' yields a 'FiniteCategory'. + +We have to forget the generating set of morphisms of the original 'Category' as the generators are not always inheritable (see for example the full subcategory of __'Square'__ containing the objects A and D). + +If the generators are inheritable, you can use the constructor 'InheritedFullSubcategory' to inherit the generators of the original 'Category'. +-} + +module Math.FiniteCategories.FullSubcategory +( + FullSubcategory(..), + InheritedFullSubcategory(..), +) +where + import Math.FiniteCategory + import Math.IO.PrettyPrint + + import Data.WeakSet (Set) + import qualified Data.WeakSet as Set + import Data.WeakSet.Safe + + -- | A 'FullSubcategory' needs an original category and a set of objects to select in the category. + -- + -- The generators are forgotten, use 'InheritedFullSubcategory' if the generators are inheritable. + data FullSubcategory c m o = FullSubcategory c (Set o) deriving (Eq, Show) + + instance (Category c m o, Eq o) => Category (FullSubcategory c m o) m o where + identity (FullSubcategory c objs) o + | o `isIn` objs = identity c o + | otherwise = error "Math.FiniteCategories.FullSubcategory.identity: object not in the subcategory" + ar (FullSubcategory c objs) s t + | s `isIn` objs && t `isIn` objs = ar c s t + | otherwise = error "Math.FiniteCategories.FullSubcategory.ar: source or target not in the subcategory" + + instance (Category c m o, Eq o) => FiniteCategory (FullSubcategory c m o) m o where + ob (FullSubcategory _ s) = s + + instance (PrettyPrint c, PrettyPrint m, PrettyPrint o, Eq o) => PrettyPrint (FullSubcategory c m o) where + pprint (FullSubcategory c s) = "FullSubcategory("++ pprint c ++ ","++ pprint s ++")" + + + -- | An 'InheritedFullSubcategory' is a 'FullSubcategory' where the generators are the same as in the original 'Category'. + data InheritedFullSubcategory c m o = InheritedFullSubcategory c (Set o) deriving (Eq, Show) + + instance (Category c m o, Eq o) => Category (InheritedFullSubcategory c m o) m o where + identity (InheritedFullSubcategory c objs) o + | o `isIn` objs = identity c o + | otherwise = error "Math.FiniteCategories.InheritedFullSubcategory.identity: object not in the subcategory" + ar (InheritedFullSubcategory c objs) s t + | s `isIn` objs && t `isIn` objs = ar c s t + | otherwise = error "Math.FiniteCategories.InheritedFullSubcategory.ar: source or target not in the subcategory" + genAr (InheritedFullSubcategory c objs) s t + | s `isIn` objs && t `isIn` objs = genAr c s t + | otherwise = error "Math.FiniteCategories.InheritedFullSubcategory.genAr: source or target not in the subcategory" + decompose (InheritedFullSubcategory c objs) m + | source m `isIn` objs && target m `isIn` objs = decompose c m + | otherwise = error "Math.FiniteCategories.InheritedFullSubcategory.decompose: morphism not in the subcategory" + + instance (Category c m o, Eq o) => FiniteCategory (InheritedFullSubcategory c m o) m o where + ob (InheritedFullSubcategory _ s) = s + + instance (PrettyPrint c, PrettyPrint m, PrettyPrint o, Eq o) => PrettyPrint (InheritedFullSubcategory c m o) where + pprint (InheritedFullSubcategory c s) = "InheritedFullSubcategory("++ pprint c ++ ","++ pprint s ++")" +
+ src/Math/FiniteCategories/FunctorCategory.hs view
@@ -0,0 +1,20 @@+{-| Module : FiniteCategories +Description : A 'FunctorCategory' where the target category is finite is a 'FiniteCategory'. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +The __'Hat'__ category contains two arrows coming from the same object. + +The shape of __'Hat'__ is the following : @`B` <-`F`- `A` -`G`-> `C`@ +-} + +module Math.FiniteCategories.FunctorCategory +( + module Math.Categories.FunctorCategory +) +where + import Math.Categories.FunctorCategory +
+ src/Math/FiniteCategories/FunctorCategory/Example.hs view
@@ -0,0 +1,43 @@+{-| Module : FiniteCategories +Description : An example of 'FunctorCategory' exported with GraphViz. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +An example of 'FunctorCategory' exported with GraphViz. + +Export the category in the directory "OutputGraphViz\/Examples\/FiniteCategories\/FunctorCategory". +-} +module Math.FiniteCategories.FunctorCategory.Example +( + main +) +where + import Data.WeakSet.Safe + import Data.WeakMap.Safe + + import Math.FiniteCategory + import Math.Categories + import Math.FiniteCategories + import Math.IO.FiniteCategories.ExportGraphViz + import Math.IO.PrettyPrint + + import Numeric.Natural + + -- | An example of 'FunctorCategory' exported with GraphViz. + main :: IO () + main = do + putStrLn "Start of Math.FiniteCategories.FunctorCategory.Example" + catToPdf (FunctorCategory (numberCategory 2) (numberCategory 3)) "OutputGraphViz/Examples/FiniteCategories/FunctorCategory/FunctorCategory" + sequence $ (uncurry diagToPdfCluster) <$> zip (setToList (ob (FunctorCategory (numberCategory 2) (numberCategory 3)))) ((("OutputGraphViz/Examples/FiniteCategories/FunctorCategory/functCluster"++).show) <$> (take (cardinal (ob (FunctorCategory (numberCategory 2) (numberCategory 3)))) [1..])) + sequence $ (uncurry diagToPdf) <$> zip (setToList (ob (FunctorCategory (numberCategory 2) (numberCategory 3)))) ((("OutputGraphViz/Examples/FiniteCategories/FunctorCategory/funct"++).show) <$> (take (cardinal (ob (FunctorCategory (numberCategory 2) (numberCategory 3)))) [1..])) + sequence $ (uncurry diagToPdf2) <$> zip (setToList (ob (FunctorCategory (numberCategory 2) (numberCategory 3)))) ((("OutputGraphViz/Examples/FiniteCategories/FunctorCategory/diag"++).show) <$> (take (cardinal (ob (FunctorCategory (numberCategory 2) (numberCategory 3)))) [1..])) + sequence $ (uncurry natToPdf) <$> zip (setToList (arrows (FunctorCategory (numberCategory 2) (numberCategory 3)))) ((("OutputGraphViz/Examples/FiniteCategories/FunctorCategory/nat"++).show) <$> (take (cardinal (arrows (FunctorCategory (numberCategory 2) (numberCategory 3)))) [1..])) + let diag = completeDiagram Diagram{src=discreteCategory (set [1,2]), tgt = (numberCategory 2), omap=memorizeFunction id (set [1,2]), mmap = weakMap []} + diagToPdf2 diag "OutputGraphViz/Examples/FiniteCategories/PrecomposedFunctorCategory/Functor" + catToPdf (PrecomposedFunctorCategory diag (numberCategory 3)) "OutputGraphViz/Examples/FiniteCategories/PrecomposedFunctorCategory/PrecomposedFunctorCategory" + sequence $ (uncurry diagToPdf2) <$> zip (setToList (ob (PrecomposedFunctorCategory diag (numberCategory 3)))) ((("OutputGraphViz/Examples/FiniteCategories/PrecomposedFunctorCategory/precompFunct"++).show) <$> (take (cardinal (ob (PrecomposedFunctorCategory diag (numberCategory 3)))) [1..])) + sequence $ (uncurry natToPdf) <$> zip (setToList (arrows (PrecomposedFunctorCategory diag (numberCategory 3)))) ((("OutputGraphViz/Examples/FiniteCategories/PrecomposedFunctorCategory/nat"++).show) <$> (take (cardinal (arrows (PrecomposedFunctorCategory diag (numberCategory 3)))) [1..])) + putStrLn "End of Math.FiniteCategories.FunctorCategory.Example"
+ src/Math/FiniteCategories/Hat.hs view
@@ -0,0 +1,84 @@+{-# LANGUAGE MultiParamTypeClasses #-} + +{-| Module : FiniteCategories +Description : The __'Hat'__ category contains two arrows coming from the same object. It is the opposite of __'V'__. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +The __'Hat'__ category contains two arrows coming from the same object. + +The shape of __'Hat'__ is the following : @`B` <-`F`- `A` -`G`-> `C`@ +-} + +module Math.FiniteCategories.Hat +( + HatOb(..), + HatAr(..), + Hat(..) +) +where + import Math.FiniteCategory + import Math.IO.PrettyPrint + + import Data.WeakSet.Safe + + -- | Objects of the __'Hat'__ category. + data HatOb = HatA | HatB | HatC deriving (Eq, Show) + + -- | Morphisms of the __'Hat'__ category. + data HatAr = HatIdA | HatIdB | HatIdC | HatF | HatG deriving (Eq, Show) + + -- | The Hat category. + data Hat = Hat deriving (Eq, Show) + + instance Morphism HatAr HatOb where + source HatIdA = HatA + source HatIdB = HatB + source HatIdC = HatC + source _ = HatA + target HatIdA = HatA + target HatIdB = HatB + target HatIdC = HatC + target HatF = HatB + target HatG = HatC + (@?) HatIdA HatIdA = Just HatIdA + (@?) HatF HatIdA = Just HatF + (@?) HatG HatIdA = Just HatG + (@?) HatIdB HatIdB = Just HatIdB + (@?) HatIdC HatIdC = Just HatIdC + (@?) HatIdB HatF = Just HatF + (@?) HatIdC HatG = Just HatG + (@?) _ _ = Nothing + + instance Category Hat HatAr HatOb where + identity _ HatA = HatIdA + identity _ HatB = HatIdB + identity _ HatC = HatIdC + ar _ HatA HatA = set [HatIdA] + ar _ HatB HatB = set [HatIdB] + ar _ HatC HatC = set [HatIdC] + ar _ HatA HatB = set [HatF] + ar _ HatA HatC = set [HatG] + ar _ _ _ = set [] + + instance FiniteCategory Hat HatAr HatOb where + ob _ = set [HatA, HatB, HatC] + + instance PrettyPrint HatOb where + pprint HatA = "A" + pprint HatB = "B" + pprint HatC = "C" + + + instance PrettyPrint HatAr where + pprint HatIdA = "IdA" + pprint HatIdB = "IdB" + pprint HatIdC = "IdC" + pprint HatF = "f" + pprint HatG = "g" + + instance PrettyPrint Hat where + pprint = show
+ src/Math/FiniteCategories/Hat/Example.hs view
@@ -0,0 +1,28 @@+{-| Module : FiniteCategories +Description : __'Hat'__ exported with GraphViz. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +__'Hat'__ exported with GraphViz. + +Export the __'Hat'__ category in the directory "OutputGraphViz\/Examples\/FiniteCategories\/Hat". +-} +module Math.FiniteCategories.Hat.Example +( + main +) +where + import Data.WeakSet.Safe + + import Math.FiniteCategories.Hat + import Math.IO.FiniteCategories.ExportGraphViz + + -- | __'Hat'__ exported with GraphViz. + main :: IO () + main = do + putStrLn "Start of Math.FiniteCategories.Hat.Example" + catToPdf Hat "OutputGraphViz/Examples/FiniteCategories/Hat/Hat" + putStrLn "End of Math.FiniteCategories.Hat.Example"
+ src/Math/FiniteCategories/NumberCategory.hs view
@@ -0,0 +1,46 @@+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-} + +{-| Module : FiniteCategories +Description : By regarding each natural number as the linearly ordered set of all preceding natural number, it yields a category. __0__, __1__, __2__, __3__, ... are all number categories. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +By regarding each natural number as the linearly ordered set of all preceding natural number, it yields a category. __0__, __1__, __2__, __3__, ... are all number categories. + +See (See "Categories for the Working Mathematican" Saunders Mac Lane. p.11) +-} + +module Math.FiniteCategories.NumberCategory +( + -- * Number category + NumberCategoryObject(..), + NumberCategoryMorphism(..), + IsSmallerThan(..), + NumberCategory(..), + numberCategory, +) +where + import Math.FiniteCategory + import Math.FiniteCategories.FullSubcategory + import Math.Categories.TotalOrder + import Math.Categories.Omega + + import Numeric.Natural + + import Data.WeakSet.Safe + + -- | An object in a 'NumberCategory'. + type NumberCategoryObject = Natural + + -- | A morphism in a 'NumberCategory'. + type NumberCategoryMorphism = IsSmallerThan Natural + + -- | A 'NumberCategory' is an 'InheritedFullSubcategory' of __'Omega'__ containing successive numbers beginning from one. + type NumberCategory = InheritedFullSubcategory Omega (IsSmallerThan Natural) Natural + + -- | The 'NumberCategory' associated to a given number. + numberCategory :: Natural -> NumberCategory + numberCategory n = (InheritedFullSubcategory omega (set [1..n]))
+ src/Math/FiniteCategories/NumberCategory/Example.hs view
@@ -0,0 +1,28 @@+{-| Module : FiniteCategories +Description : Six examples of 'NumberCategory' exported with GraphViz. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +Six examples of 'NumberCategory' exported with GraphViz. + +Export categories __0__ up to __5__ in the directory "OutputGraphViz\/Examples\/FiniteCategories\/NumberCategory". +-} +module Math.FiniteCategories.NumberCategory.Example +( + main +) +where + import Math.FiniteCategories.NumberCategory + import Math.IO.FiniteCategories.ExportGraphViz + + -- | Six examples of 'NumberCategory' exported with GraphViz. + main :: IO () + main = do + putStrLn "Start of Math.FiniteCategories.NumberCategory.Example" + let cats = numberCategory <$> [0..5] + let exports = uncurry catToPdf <$> zip cats (("OutputGraphViz/Examples/FiniteCategories/NumberCategory/"++) <$> show <$> [0..5]) + sequence exports + putStrLn "End of Math.FiniteCategories.NumberCategory.Example"
+ src/Math/FiniteCategories/One.hs view
@@ -0,0 +1,43 @@+{-# LANGUAGE MultiParamTypeClasses #-} + +{-| Module : FiniteCategories +Description : The __1__ category contains one object and its identity. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +The __1__ category contains one object and its identity. + +You can construct it using 'NumberCategory', it is defined as a standalone category because it is often used unlike other number categories. +-} + +module Math.FiniteCategories.One +( + One(..) +) +where + import Math.FiniteCategory + import Math.IO.PrettyPrint + + import Data.WeakSet.Safe + + -- | 'One' is a datatype used as the object type, the morphism type and the category type of __1__. + data One = One deriving (Eq, Show) + + instance Morphism One One where + source One = One + target One = One + (@?) One One = Just One + + instance Category One One One where + identity One One = One + ar One One One = set [One] + + instance FiniteCategory One One One where + ob One = set [One] + + instance PrettyPrint One where + pprint = show +
+ src/Math/FiniteCategories/One/Example.hs view
@@ -0,0 +1,26 @@+{-| Module : FiniteCategories +Description : __1__ exported with GraphViz. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +__1__ exported with GraphViz. + +Export the __1__ category in the directory "OutputGraphViz\/Examples\/FiniteCategories\/One". +-} +module Math.FiniteCategories.One.Example +( + main +) +where + import Math.FiniteCategories.One + import Math.IO.FiniteCategories.ExportGraphViz + + -- | __'One'__ exported with GraphViz. + main :: IO () + main = do + putStrLn "Start of Math.FiniteCategories.One.Example" + catToPdf One "OutputGraphViz/Examples/FiniteCategories/One/One" + putStrLn "End of Math.FiniteCategories.One.Example"
+ src/Math/FiniteCategories/Opposite.hs view
@@ -0,0 +1,18 @@+{-| Module : FiniteCategories +Description : The 'Op'posite category of a 'FiniteCategory' is a 'FiniteCategory'. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +The 'Op'posite category of a 'FiniteCategory' is a 'FiniteCategory'. +-} + +module Math.FiniteCategories.Opposite +( + module Math.Categories.Opposite +) +where + import Math.Categories.Opposite +
+ src/Math/FiniteCategories/Opposite/Example.hs view
@@ -0,0 +1,33 @@+{-| Module : FiniteCategories +Description : An example of opposite category exported with GraphViz. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +An example of opposite category exported with GraphViz. + +Export the category in the directory "OutputGraphViz\/Examples\/FiniteCategories\/Opposite". +-} +module Math.FiniteCategories.Opposite.Example +( + main +) +where + import Data.WeakSet (powerSet, Set) + import Data.WeakSet.Safe + + import Math.Categories + import Math.FiniteCategories + import Math.IO.FiniteCategories.ExportGraphViz + + -- | An example of opposite category exported with GraphViz. + main :: IO () + main = do + putStrLn "Start of Math.FiniteCategories.Opposite.Example" + catToPdf (ens.powerSet.set $ "AB") "OutputGraphViz/Examples/FiniteCategories/Opposite/Ens" + catToPdf (Op (ens.powerSet.set $ "AB")) "OutputGraphViz/Examples/FiniteCategories/Opposite/OppositeEns" + catToPdf (numberCategory 4) "OutputGraphViz/Examples/FiniteCategories/Opposite/4" + catToPdf (Op (numberCategory 4)) "OutputGraphViz/Examples/FiniteCategories/Opposite/Opposite4" + putStrLn "End of Math.FiniteCategories.Opposite.Example"
+ src/Math/FiniteCategories/Parallel.hs view
@@ -0,0 +1,73 @@+{-# LANGUAGE MultiParamTypeClasses #-} + +{-| Module : FiniteCategories +Description : The __'Parallel'__ category contains two parallel arrows. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +The __'Parallel'__ category contains two objects `A` and `B` and two morphisms @`F` : `A` -> `B`@ and @`G` : `A` -> `B`@. +-} + +module Math.FiniteCategories.Parallel +( + ParallelOb(..), + ParallelAr(..), + Parallel(..) +) +where + import Math.FiniteCategory + import Math.IO.PrettyPrint + + import Data.WeakSet.Safe + + -- | Objects of the __'Parallel'__ category. + data ParallelOb = ParallelA | ParallelB deriving (Eq, Show) + + -- | Morphisms of the __'Parallel'__ category. + data ParallelAr = ParallelIdA | ParallelIdB | ParallelF | ParallelG deriving (Eq, Show) + + -- | The __'Parallel'__ category. + data Parallel = Parallel deriving (Eq, Show) + + instance Morphism ParallelAr ParallelOb where + source ParallelIdA = ParallelA + source ParallelIdB = ParallelB + source _ = ParallelA + target ParallelIdA = ParallelA + target ParallelIdB = ParallelB + target _ = ParallelB + (@?) ParallelIdA ParallelIdA = Just ParallelIdA + (@?) ParallelF ParallelIdA = Just ParallelF + (@?) ParallelG ParallelIdA = Just ParallelG + (@?) ParallelIdB ParallelIdB = Just ParallelIdB + (@?) ParallelIdB ParallelF = Just ParallelF + (@?) ParallelIdB ParallelG = Just ParallelG + (@?) _ _ = Nothing + + instance Category Parallel ParallelAr ParallelOb where + identity _ ParallelA = ParallelIdA + identity _ ParallelB = ParallelIdB + ar _ ParallelA ParallelA = set [ParallelIdA] + ar _ ParallelA ParallelB = set [ParallelF,ParallelG] + ar _ ParallelB ParallelB = set [ParallelIdB] + ar _ _ _ = set [] + + + instance FiniteCategory Parallel ParallelAr ParallelOb where + ob _ = set [ParallelA,ParallelB] + + instance PrettyPrint ParallelOb where + pprint ParallelA = "A" + pprint ParallelB = "B" + + instance PrettyPrint ParallelAr where + pprint ParallelIdA = "IdA" + pprint ParallelIdB = "IdB" + pprint ParallelF = "f" + pprint ParallelG = "g" + + instance PrettyPrint Parallel where + pprint Parallel = "Parallel"
+ src/Math/FiniteCategories/Parallel/Example.hs view
@@ -0,0 +1,28 @@+{-| Module : FiniteCategories +Description : __'Parallel'__ exported with GraphViz. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +__'Parallel'__ exported with GraphViz. + +Export the __'Parallel'__ category in the directory "OutputGraphViz\/Examples\/FiniteCategories\/Parallel". +-} +module Math.FiniteCategories.Parallel.Example +( + main +) +where + import Data.WeakSet.Safe + + import Math.FiniteCategories.Parallel + import Math.IO.FiniteCategories.ExportGraphViz + + -- | __'Parallel'__ exported with GraphViz. + main :: IO () + main = do + putStrLn "Start of Math.FiniteCategories.Parallel.Example" + catToPdf Parallel "OutputGraphViz/Examples/FiniteCategories/Parallel/Parallel" + putStrLn "End of Math.FiniteCategories.Parallel.Example"
+ src/Math/FiniteCategories/SafeCompositionGraph.hs view
@@ -0,0 +1,576 @@+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, MonadComprehensions #-} +{-| Module : FiniteCategories +Description : A 'SafeCompositionGraph' is a 'CompositionGraph' where infinite loops are prevented. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +A 'SafeCompositionGraph' is a 'CompositionGraph' where infinite loops are prevented. + +The 'readSCGFile' function is the most important for ease of use. +-} + +module Math.FiniteCategories.SafeCompositionGraph +( + -- * Types for a morphism of safe composition graph + SCGMorphism(..), + -- ** Functions for morphism + getLabelS, + -- * Safe composition graph + SafeCompositionGraph, + -- ** Getters + supportS, + lawS, + maxCycles, + -- * Construction + safeCompositionGraph, + unsafeSafeCompositionGraph, + readSCGString, + unsafeReadSCGString, + readSCGFile, + unsafeReadSCGFile, + safeCompositionGraphFromCompositionGraph, + compositionGraphFromSafeCompositionGraph, + -- * Serialization + writeSCGString, + writeSCGFile, + -- * Construction of diagrams + unsafeReadSCGDString, + readSCGDString, + unsafeReadSCGDFile, + readSCGDFile, + -- * Serialization of diagrams + writeSCGDString, + writeSCGDFile, + -- * Random safe composition graph + constructRandomSafeCompositionGraph, + defaultConstructRandomSafeCompositionGraph, + defaultConstructRandomSafeDiagram, +) +where + 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 (intercalate, elemIndex, splitAt) + import Data.Text (Text, singleton, cons, unpack, pack) + + import Math.Category + import Math.FiniteCategory + import Math.FiniteCategories.CompositionGraph + import Math.FiniteCategoryError + import Math.IO.PrettyPrint + import Math.Categories.FinGrph + import Math.Categories.FunctorCategory + + import System.Directory (createDirectoryIfMissing) + import System.FilePath.Posix (takeDirectory) + import System.Random (RandomGen, uniformR) + + -- | The type `SCGMorphism` is the type of 'SafeCompositionGraph's morphisms. + -- + -- It is just like a 'CGMorphism', we also store the maximum number of cycles. + data SCGMorphism a b = SCGMorphism {pathS :: Path a b + ,compositionLawS :: CompositionLaw a b + ,maxNbCycles :: Int} deriving (Show, Eq) + + instance (PrettyPrint a, PrettyPrint b, Eq a, Eq b) => PrettyPrint (SCGMorphism a b) where + pprint SCGMorphism {pathS=(s,[]),compositionLawS=cl} = "Id"++(pprint s) + pprint SCGMorphism {pathS=(_,rp),compositionLawS=cl} = intercalate " o " $ (pprint.labelArrow) <$> rp + + -- | Return the label of a 'SafeCompositionGraph' generator. + getLabelS :: SCGMorphism a b -> Maybe b + getLabelS SCGMorphism{pathS=(s,rp), compositionLawS=_, maxNbCycles=_} + | null rp = Nothing + | null.tail $ rp = Just (labelArrow.head $ rp) + | otherwise = Nothing + + rawpathToListOfVertices :: RawPath a b -> [a] + rawpathToListOfVertices [] = [] + rawpathToListOfVertices rp = ((targetArrow.head $ rp):(sourceArrow <$> rp)) + + -- | Helper function for `simplify`. Returns a simplified raw path. + simplifyOnce :: (Eq a, Eq b) => CompositionLaw a b -> Int -> RawPath a b -> RawPath a b + simplifyOnce _ _ [] = [] + simplifyOnce _ _ [e] = [e] + simplifyOnce cl nb list + | new_list == [] = [] + | isCycle && tooManyCycles = [] + | new_list /= list = new_list + | simple_tail /= (tail list) = (head list):simple_tail + | simple_init /= (init list) = simple_init++[(last list)] + | otherwise = list + where + listOfVertices = rawpathToListOfVertices list + isCycle = (head listOfVertices) == (last listOfVertices) + tooManyCycles = (length $ filter ((head listOfVertices) ==) listOfVertices) == (nb+2) + new_list = Map.findWithDefault list list cl + simple_tail = simplifyOnce cl nb (tail list) + simple_init = simplifyOnce cl nb (init list) + + -- | Returns a completely simplified raw path. + simplify :: (Eq a, Eq b) => CompositionLaw a b -> Int -> RawPath a b -> RawPath a b + simplify _ _ [] = [] + simplify cl nb rp + | simple_one == rp = rp + | otherwise = simplify cl nb simple_one + where simple_one = simplifyOnce cl nb rp + + instance (Eq a, Eq b) => Morphism (SCGMorphism a b) a where + (@?) m2@SCGMorphism{pathS=(s2,rp2), compositionLawS=cl2, maxNbCycles=nb2} m1@SCGMorphism{pathS=(s1,rp1), compositionLawS=cl1, maxNbCycles=nb1} + | nb1 /= nb2 = Nothing + | cl1 /= cl2 = Nothing + | source m2 /= target m1 = Nothing + | otherwise = Just SCGMorphism{pathS=(s1,(simplify cl1 nb1 (rp2++rp1))), compositionLawS=cl1, maxNbCycles=nb1} + + source SCGMorphism{pathS=(s,_), compositionLawS=_, maxNbCycles=_} = s + target SCGMorphism{pathS=(s,[]), compositionLawS=_, maxNbCycles=_} = s + target SCGMorphism{pathS=(_,rp), compositionLawS=_, maxNbCycles=_} = targetArrow (head rp) + + -- | Constructs a `SCGMorphism` from a composition law, an arrow and maxNbCycles. + mkSCGMorphism :: CompositionLaw a b -> Int -> Arrow a b -> SCGMorphism a b + mkSCGMorphism cl nb e = SCGMorphism {pathS=(sourceArrow e,[e]),compositionLawS=cl, maxNbCycles=nb} + + -- | Returns the list of arrows of a graph with a given target. + findInwardEdges :: (Eq a) => Graph a b -> a -> Set (Arrow a b) + findInwardEdges g o = Set.filter (\e -> (targetArrow e) == o && (sourceArrow e) `isIn` (nodes g)) (edges g) + + -- | Find all acyclic raw paths between two nodes in a graph. + findAcyclicRawPaths :: (Eq a, Eq b) => Graph a b -> a -> a -> Set (RawPath a b) + findAcyclicRawPaths g s t = findAcyclicRawPathsVisitedNodes g s t Set.empty where + findAcyclicRawPathsVisitedNodes g s t v + | t `isIn` v = Set.empty + | s == t = set [[]] + | otherwise = set (concat (zipWith ($) (fmap fmap (fmap (:) inwardEdges)) (fmap (\x -> setToList (findAcyclicRawPathsVisitedNodes g s (sourceArrow x) (Set.insert t v))) inwardEdges))) + where + inwardEdges = (setToList (findInwardEdges g t)) + + -- | An elementary cycle is a cycle which is not composed of any other cycle. + findElementaryCycles :: (Eq a, Eq b) => Graph a b -> CompositionLaw a b -> Int -> a -> Set (RawPath a b) + findElementaryCycles g cl nb o = set $ (simplify cl nb <$> []:(concat (zipWith sequence (fmap (fmap (\x y -> (y:x))) (fmap (\x -> setToList (findAcyclicRawPaths g o (sourceArrow x))) inEdges)) inEdges))) + where + inEdges = (setToList (findInwardEdges g o)) + + -- | Composes every elementary cycles of a node until they simplify into a fixed set of cycles or they go beyond the max number of cycles. + findCycles :: (Eq a, Eq b) => Graph a b -> CompositionLaw a b -> Int -> a -> Set (RawPath a b) + findCycles g cl nb o = findCyclesWithPreviousCycles g cl o (findElementaryCycles g cl nb o) + where + findCyclesWithPreviousCycles g cl o p + | newCycles == p = newCycles + | otherwise = findCyclesWithPreviousCycles g cl o newCycles + where + newCycles = (simplify cl nb) <$> ((++) <$> p <*> findElementaryCycles g cl nb o) + + -- | Helper function which intertwine the second list in the first list. + -- + -- Example : intertwine [1,2,3] [4,5] = [1,4,2,5,3] + intertwine :: [a] -> [a] -> [a] + intertwine [] l = l + intertwine l [] = l + intertwine l1@(x1:xs1) l2@(x2:xs2) = (x1:(x2:(intertwine xs1 xs2))) + + -- | Takes a path and intertwine every cycles possible along its path. + intertwineWithCycles :: (Eq a, Eq b) => Graph a b -> CompositionLaw a b -> Int -> a -> RawPath a b -> Set (RawPath a b) + intertwineWithCycles g cl nb _ p@(x:xs) = set $ concat <$> ((uncurry intertwine) <$> zip (setToList prodCycles) (repeat ((:[]) <$> p))) where + prodCycles = cartesianProductOfSets cycles + cycles = ((findCycles g cl nb (targetArrow x))):(((\y -> (findCycles g cl nb (sourceArrow y)))) <$> p) + intertwineWithCycles g cl nb s [] = (findCycles g cl nb s) + + -- | Enumerates all paths between two nodes and construct composition graph morphisms with them. + mkAr :: (Eq a, Eq b) => Graph a b -> CompositionLaw a b -> Int -> a -> a -> Set (SCGMorphism a b) + mkAr g cl nb s t = (\p -> SCGMorphism{pathS=(s,p),compositionLawS=cl,maxNbCycles=nb}) <$> allPaths where + acyclicPaths = (simplify cl nb) <$> (findAcyclicRawPaths g s t) + allPaths = (simplify cl nb <$> Set.unions (setToList ((intertwineWithCycles g cl nb s) <$> acyclicPaths))) + + -- | A 'SafeCompositionGraph' is a graph with a composition law such that the free category generated by the graph quotiented out by the composition law gives a 'FiniteCategory'. It has a maximum number of composition for loops. + -- + -- 'SafeCompositionGraph' is private, use the smart constructors 'safeCompositionGraph' or 'unsafeSafeCompositionGraph' to instantiate one. + data SafeCompositionGraph a b = SafeCompositionGraph { + supportS :: Graph a b, -- ^ The generating graph of the safe composition graph. + lawS :: CompositionLaw a b, -- ^ The composition law of the safe composition graph. + maxCycles :: Int -- ^ The maximum number of times a cycle can be composed with itself. + } deriving (Eq) + + instance (Show a, Show b) => Show (SafeCompositionGraph a b) where + show scg = "(unsafeSafeCompositionGraph "++ show (supportS scg) ++ " " ++ show (lawS scg) ++ " " ++ show (maxCycles scg) ++ ")" + + instance (Eq a, Eq b) => Category (SafeCompositionGraph a b) (SCGMorphism a b) a where + identity c x + | x `isIn` (nodes (supportS c)) = SCGMorphism {pathS=(x,[]),compositionLawS=(lawS c), maxNbCycles = maxCycles c} + | otherwise = error ("Math.FiniteCategories.SafeCompositionGraph.identity: Trying to construct identity of an unknown object.") + ar c s t = mkAr (supportS c) (lawS c) (maxCycles c) s t + genAr cg s t + | s == t = Set.insert (identity cg s) gen + | otherwise = gen + where gen = mkSCGMorphism (lawS cg) (maxCycles cg) <$> (Set.filter (\a -> s == (sourceArrow a) && t == (targetArrow a)) $ (edges (supportS cg))) + + decompose c m@SCGMorphism{pathS=(_,rp),compositionLawS=l,maxNbCycles=nb} + | isIdentity c m = [m] + | otherwise = mkSCGMorphism l nb <$> rp + + instance (Eq a, Eq b) => FiniteCategory (SafeCompositionGraph a b) (SCGMorphism a b) a where + ob = (nodes.supportS) + + instance (PrettyPrint a, PrettyPrint b, Eq a, Eq b) => PrettyPrint (SafeCompositionGraph a b) where + pprint SafeCompositionGraph{supportS=g,lawS=l,maxCycles=nb} = "SafeCompositionGraph("++pprint g++","++pprint l++","++pprint nb++")" + + -- | Smart constructor of `SafeCompositionGraph`. + -- + -- If the 'SafeCompositionGraph' constructed is valid, returns 'Right' the composition graph, otherwise returns Left a 'FiniteCategoryError'. + safeCompositionGraph :: (Eq a, Eq b) => Graph a b -> CompositionLaw a b -> Int -> Either (FiniteCategoryError (SCGMorphism a b) a) (SafeCompositionGraph a b) + safeCompositionGraph g l nb + | null check = Right c_g + | otherwise = Left err + where + c_g = SafeCompositionGraph{supportS = g, lawS = l, maxCycles = nb} + check = checkFiniteCategory c_g + Just err = check + + -- | Unsafe constructor of 'SafeCompositionGraph' for performance purposes. It does not check the structure of the 'SafeCompositionGraph'. + -- + -- Use this constructor only if the 'SafeCompositionGraph' is necessarily well formed. + unsafeSafeCompositionGraph :: Graph a b -> CompositionLaw a b -> Int -> SafeCompositionGraph a b + unsafeSafeCompositionGraph g l nb = SafeCompositionGraph{supportS = g, lawS = l, maxCycles = nb} + + + -- | A token for a .scg file. + data Token = Name Text | BeginArrow | EndArrow | Equals | Identity | BeginSrc | EndSrc | BeginTgt | EndTgt | MapsTo deriving (Eq, Show) + + -- | Strip a token of unnecessary spaces. + strip :: Token -> Token + strip (Name txt) = Name (pack.reverse.stripLeft.reverse.stripLeft $ str) + where + str = unpack txt + stripLeft (' ':s) = s + stripLeft s = s + strip x = x + + -- | Transforms a string into a list of tokens. + parserLex :: String -> [Token] + parserLex str = strip <$> parserLexHelper str + where + parserLexHelper [] = [] + parserLexHelper ('#':str) = [] + parserLexHelper (' ':'-':str) = BeginArrow : (parserLexHelper str) + parserLexHelper ('-':'>':' ':str) = EndArrow : (parserLexHelper str) + parserLexHelper (' ':'=':' ':str) = Equals : (parserLexHelper str) + parserLexHelper ('<':'I':'D':'/':'>':str) = Identity : (parserLexHelper str) + parserLexHelper ('<':'S':'R':'C':'>':str) = BeginSrc : (parserLexHelper str) + parserLexHelper ('<':'T':'G':'T':'>':str) = BeginTgt : (parserLexHelper str) + parserLexHelper ('<':'/':'S':'R':'C':'>':str) = EndSrc : (parserLexHelper str) + parserLexHelper ('<':'/':'T':'G':'T':'>':str) = EndTgt : (parserLexHelper str) + parserLexHelper (' ':'=':'>':' ':str) = MapsTo : (parserLexHelper str) + parserLexHelper (c:str) = (result restLexed) + where + restLexed = (parserLexHelper str) + result (Name txt:xs) = (Name (cons c txt):xs) + result a = ((Name (singleton c)):a) + + type SCG = SafeCompositionGraph Text Text + + -- | Read a .scg string to create a 'SafeCompositionGraph'. + -- + -- A .scg string follows the following rules : + -- + -- 0. Every character of a line following a "#" character are ignored. + -- + -- 1. Each line defines either an object, a morphism or a composition law entry. + -- + -- 2. The following strings are reserved : " -","-> "," = ", "\<ID/\>", "\<SRC\>", "\</SRC\>", "\<TGT\>", "\</TGT\>", " => " + -- + -- 3. To define an object, write a line containing its name. + -- + -- 4. To define an arrow, the syntax "source_object -name_of_morphism-> target_object" is used, where "source_object", "target_object" and "name_of_morphism" should be replaced. + -- + -- 4.1. If an object mentionned in an arrow does not exist, it is created. + -- + -- 4.2. The spaces are important. + -- + -- 5. To define a composition law entry, the syntax "source_object1 -name_of_first_morphism-> middle_object -name_of_second_morphism-> target_object1 = source_object2 -name_of_composite_morphism-> target_object2" is used, where "source_object1", "name_of_first_morphism", "middle_object", "name_of_second_morphism", "target_object1", "source_object2", "name_of_composite_morphism", "target_object2" should be replaced. + -- + -- 5.1 If an object mentionned does not exist, it is created. + -- + -- 5.2 If a morphism mentionned does not exist, it is created. + -- + -- 5.3 You can use the tag \<ID/\> in order to map a morphism to an identity. + -- + -- 6. The first line of the should be a number, this number determines the maximum number of cycles. + readSCGString :: String -> Either (FiniteCategoryError (SCGMorphism Text Text) Text) SCG + readSCGString str + | null check = Right scg + | otherwise = Left err + where + maxCyc = (read.head.lines $ str) :: Int + cg = unsafeReadCGString ((intercalate "\n").tail.lines $ str) + scg = SafeCompositionGraph{supportS = support cg, lawS = law cg, maxCycles = maxCyc} + check = checkFiniteCategory scg + Just err = check + + -- | Unsafe version of 'readSCGString' which does not check the structure of the resulting 'SafeCompositionGraph'. + unsafeReadSCGString :: String -> SCG + unsafeReadSCGString str = scg + where + maxCyc = (read.head.lines $ str) :: Int + cg = unsafeReadCGString ((intercalate "\n").tail.lines $ str) + scg = SafeCompositionGraph{supportS = support cg, lawS = law cg, maxCycles = maxCyc} + + -- | Unsafe version of 'readSCGFile' which does not check the structure of the resulting 'SafeCompositionGraph'. + unsafeReadSCGFile :: String -> IO SCG + unsafeReadSCGFile path = do + file <- readFile path + return $ unsafeReadSCGString file + + + -- | Read a .scg file to create a 'SafeCompositionGraph'. + -- + -- A .scg file follows the following rules : + -- + -- 0. Every character of a line following a "#" character are ignored. + -- + -- 1. Each line defines either an object, a morphism or a composition law entry. + -- + -- 2. The following strings are reserved : " -","-> "," = ", "\<ID/\>", "\<SRC\>", "\</SRC\>", "\<TGT\>", "\</TGT\>", " => " + -- + -- 3. To define an object, write a line containing its name. + -- + -- 4. To define an arrow, the syntax "source_object -name_of_morphism-> target_object" is used, where "source_object", "target_object" and "name_of_morphism" should be replaced. + -- + -- 4.1. If an object mentionned in an arrow does not exist, it is created. + -- + -- 4.2. The spaces are important. + -- + -- 5. To define a composition law entry, the syntax "source_object1 -name_of_first_morphism-> middle_object -name_of_second_morphism-> target_object1 = source_object2 -name_of_composite_morphism-> target_object2" is used, where "source_object1", "name_of_first_morphism", "middle_object", "name_of_second_morphism", "target_object1", "source_object2", "name_of_composite_morphism", "target_object2" should be replaced. + -- + -- 5.1 If an object mentionned does not exist, it is created. + -- + -- 5.2 If a morphism mentionned does not exist, it is created. + -- + -- 5.3 You can use the tag \<ID/\> in order to map a morphism to an identity. + -- + -- 6. The first line of the should be a number, this number determines the maximum number of cycles. + readSCGFile :: String -> IO (Either (FiniteCategoryError (SCGMorphism Text Text) Text) SCG) + readSCGFile str = do + scg <- unsafeReadSCGFile str + let check = checkFiniteCategory scg + return (if null check then Right scg else Left $ fromJust $ check) + where + fromJust (Just x) = x + + + reversedRawPathToString :: (PrettyPrint a, PrettyPrint b) => RawPath a b -> String + reversedRawPathToString [] = "<ID>" + reversedRawPathToString [Arrow{sourceArrow = s, targetArrow = t,labelArrow = l}] = pprint s ++ " -" ++ pprint l ++ "-> " ++ pprint t + reversedRawPathToString (Arrow{sourceArrow = s, targetArrow = t,labelArrow = l}:xs) = pprint s ++ " -" ++ pprint l ++ "-> " ++ reversedRawPathToString xs + + -- | Transform a composition graph into a string following the .scg convention. + writeSCGString :: (PrettyPrint a, PrettyPrint b, Eq a, Eq b) => SafeCompositionGraph a b -> String + writeSCGString cg = finalString + where + obString = intercalate "\n" $ pprint <$> (setToList.ob $ cg) + arNotIdentityAndNotComposite = setToList $ Set.filter (isGenerator cg) $ Set.filter (isNotIdentity cg) (genArrows cg) + reversedRawPaths = (reverse.snd.pathS) <$> arNotIdentityAndNotComposite + arString = intercalate "\n" $ reversedRawPathToString <$> reversedRawPaths + lawString = intercalate "\n" $ (\(rp1,rp2) -> (reversedRawPathToString (reverse rp1)) ++ " = " ++ (reversedRawPathToString (reverse rp2))) <$> ((Map.toList).lawS $ cg) + finalString = (show (maxCycles cg))++"\n#Objects :\n"++obString++"\n\n# Arrows :\n"++arString++"\n\n# Composition law :\n"++lawString + + -- | Saves a safe composition graph into a file located at a given path. + writeSCGFile :: (PrettyPrint a, PrettyPrint b, Eq a, Eq b) => SafeCompositionGraph a b -> String -> IO () + writeSCGFile cg filepath = do + createDirectoryIfMissing True $ takeDirectory filepath + writeFile filepath $ writeSCGString cg + + + + + + ----------------------- + -- SCGD FILE + ----------------------- + + type SCGD = Diagram (SafeCompositionGraph Text Text) (SCGMorphism Text Text) Text (SafeCompositionGraph Text Text) (SCGMorphism Text Text) Text + + addOMapEntry :: [Token] -> SCGD -> SCGD + addOMapEntry [Name x, MapsTo, Name y] diag + | x `isIn` (domain (omap diag)) = if y == (diag ->$ x) then diag else error ("Incoherent maps of object : F("++show x++") = "++show y ++ " and "++show (diag ->$ x)) + | otherwise = Diagram{src=src diag, tgt=tgt diag, omap=Map.insert x y (omap diag), mmap=mmap diag} + addOMapEntry otherTokens _ = error $ "addOMapEntry on invalid tokens : "++show otherTokens + + addMMapEntry :: [Token] -> SCGD -> SCGD + addMMapEntry tks@[Name sx, BeginArrow, Name lx, EndArrow, Name tx, MapsTo, Identity] diag = if sx `isIn` (domain (omap diag)) then Diagram{src=src diag, tgt=tgt diag, omap=omap diag, mmap=Map.insert sourceMorph (identity (tgt diag) (diag ->$ sx)) (mmap diag)} else error ("You must specify the image of the source of the morphism before mapping to an identity : "++show tks) + where + sourceMorphCand = Set.filter (\e -> getLabelS e == Just lx) (genAr (src diag) sx tx) + sourceMorph = if Set.null sourceMorphCand then error $ "addMMapEntry : morphism not found in source category for the following map : "++ show tks else anElement sourceMorphCand + addMMapEntry tks@[Name sx, BeginArrow, Name lx, EndArrow, Name tx, MapsTo, Name sy, BeginArrow, Name ly, EndArrow, Name ty] diag = Diagram{src=src newDiag2, tgt=tgt newDiag2, omap=omap newDiag2, mmap=Map.insert sourceMorph targetMorph (mmap newDiag2)} + where + sourceMorphCand = Set.filter (\e -> getLabelS e == Just lx) (genAr (src diag) sx tx) + targetMorphCand = Set.filter (\e -> getLabelS e == Just ly) (genAr (tgt diag) sy ty) + sourceMorph = if Set.null sourceMorphCand then error $ "addMMapEntry : morphism not found in source category for the following map : "++ show tks else anElement sourceMorphCand + targetMorph = if Set.null targetMorphCand then error $ "addMMapEntry : morphism not found in target category for the following map : "++ show tks else anElement targetMorphCand + newDiag1 = addOMapEntry [Name sx, MapsTo, Name sy] diag + newDiag2 = addOMapEntry [Name tx, MapsTo, Name ty] newDiag1 + addMMapEntry otherTokens _ = error $ "addMMapEntry on invalid tokens : "++show otherTokens + + readLineD :: String -> SCGD -> SCGD + readLineD line diag@Diagram{src=s, tgt=t, omap=om, mmap=mm} + | null lexedLine = diag + | elem MapsTo lexedLine = if elem BeginArrow lexedLine + then addMMapEntry lexedLine diag + else addOMapEntry lexedLine diag + | otherwise = diag + where + lexedLine = (parserLex line) + + extractSrcSection :: [String] -> [String] + extractSrcSection lines + | not (elem [BeginSrc] (parserLex <$> lines)) = error $ "No <SRC> section or malformed <SRC> section in file : "++ show lines + | not (elem [EndSrc] (parserLex <$> lines)) = error $ "No <SRC> section or malformed <SRC> section in file : "++ show lines + | indexEndSrc < indexBeginSrc = error $ "Malformed <SRC> section in file : "++ show lines + | otherwise = c + where + Just indexBeginSrc = (elemIndex [BeginSrc] (parserLex <$> lines)) + Just indexEndSrc = (elemIndex [EndSrc] (parserLex <$> lines)) + (a,b) = splitAt (indexBeginSrc+1) lines + (c,d) = splitAt (indexEndSrc-indexBeginSrc-1) b + + extractTgtSection :: [String] -> [String] + extractTgtSection lines + | not (elem [BeginTgt] (parserLex <$> lines)) = error $ "No <TGT> section or malformed <TGT> section in file : "++ show lines + | not (elem [EndTgt] (parserLex <$> lines)) = error $ "No <TGT> section or malformed <TGT> section in file : "++ show lines + | indexEndTgt < indexBeginTgt = error $ "Malformed <TGT> section in file : "++ show lines + | otherwise = c + where + Just indexBeginTgt = (elemIndex [BeginTgt] (parserLex <$> lines)) + Just indexEndTgt = (elemIndex [EndTgt] (parserLex <$> lines)) + (a,b) = splitAt (indexBeginTgt+1) lines + (c,d) = splitAt (indexEndTgt-indexBeginTgt-1) b + + + -- | Unsafe version of 'readCGDString' which does not check the structure of the resulting 'Diagram'. + unsafeReadSCGDString :: String -> SCGD + unsafeReadSCGDString str = completeDiagram finalDiag + where + ls = filter (not.null.parserLex) $ lines str + s = unsafeReadSCGString $ intercalate "\n" (extractSrcSection ls) + t = unsafeReadSCGString $ intercalate "\n" (extractTgtSection ls) + diag = Diagram{src=s, tgt=t,omap=weakMap [], mmap=weakMap []} + finalDiag = foldr readLineD diag ls + + -- | Read a .scgd string and returns a diagram. A .scgd string obeys the following rules : + -- + -- 1. There is a line "\<SRC\>" and a line "\</SRC\>". + -- + -- 1.1 Between these two lines, the source composition graph is defined as in a scg file. + -- + -- 2. There is a line "\<TGT\>" and a line "\</TGT\>". + -- + -- 2.1 Between these two lines, the target composition graph is defined as in a scg file. + -- + -- 3. Outside of the two previously described sections, you can declare the maps between objects and morphisms. + -- + -- 3.1 You map an object to another with the following syntax : "object1 => object2". + -- + -- 3.2 You map a morphism to another with the following syntax : "objSrc1 -arrowSrc1-> objSrc2 => objTgt1 -arrowTgt1-> objTgt2". + -- + -- 4. You don't have to (and you shouldn't) specify maps from identities, nor maps from composite arrows. + readSCGDString :: String -> Either (DiagramError SCG (SCGMorphism Text Text) Text SCG (SCGMorphism Text Text) Text) SCGD + readSCGDString str + | null check = Right diag + | otherwise = Left err + where + diag = unsafeReadSCGDString str + check = checkFiniteDiagram diag + Just err = check + + -- | Unsafe version 'readSCGDFile' which does not check the structure of the resulting 'Diagram'. + unsafeReadSCGDFile :: String -> IO SCGD + unsafeReadSCGDFile path = do + raw <- readFile path + return (unsafeReadSCGDString raw) + + -- | Read a .scgd file and returns a diagram. A .scgd file obeys the following rules : + -- + -- 1. There is a line "\<SRC\>" and a line "\</SRC\>". + -- + -- 1.1 Between these two lines, the source composition graph is defined as in a scg file. + -- + -- 2. There is a line "\<TGT\>" and a line "\</TGT\>". + -- + -- 2.1 Between these two lines, the target composition graph is defined as in a scg file. + -- + -- 3. Outside of the two previously described sections, you can declare the maps between objects and morphisms. + -- + -- 3.1 You map an object to another with the following syntax : "object1 => object2". + -- + -- 3.2 You map a morphism to another with the following syntax : "objSrc1 -arrowSrc1-> objSrc2 => objTgt1 -arrowTgt1-> objTgt2". + -- + -- 4. You don't have to (and you shouldn't) specify maps from identities, nor maps from composite arrows. + readSCGDFile :: String -> IO (Either (DiagramError SCG (SCGMorphism Text Text) Text SCG (SCGMorphism Text Text) Text) SCGD) + readSCGDFile path = do + raw <- readFile path + return (readSCGDString raw) + + + -- | Transform a safe composition graph diagram into a string following the .scgd convention. + writeSCGDString :: (PrettyPrint a1, PrettyPrint b1, Eq a1, Eq b1, + PrettyPrint a2, PrettyPrint b2, Eq a2, Eq b2) => + Diagram (SafeCompositionGraph a1 b1) (SCGMorphism a1 b1) a1 (SafeCompositionGraph a2 b2) (SCGMorphism a2 b2) a2 -> String + writeSCGDString diag = srcString ++ tgtString ++ "\n" ++ omapString ++ "\n" ++ mmapString + where + srcString = "<SRC>\n"++writeSCGString (src diag)++"\n</SRC>\n" + tgtString = "<TGT>\n"++writeSCGString (tgt diag)++"</TGT>\n" + omapString = "#Object mapping\n" ++ (intercalate "\n" $ (\o -> (pprint o) ++ " => " ++ (pprint (diag ->$ o)) )<$> (setToList.ob.src $ diag)) ++ "\n" + mmapString = "#Morphism mapping\n" ++ (intercalate "\n" $ (\m -> pprint (source m) ++ " -" ++ pprint m ++ "-> " ++ pprint (target m)++ " => " ++ if isIdentity (tgt diag) (diag ->£ m) then "<ID/>" else pprint (source (diag ->£ m)) ++ " -" ++ pprint (diag ->£ m) ++ "-> " ++ pprint (target (diag ->£ m)))<$> (setToList.(Set.filter (isNotIdentity (src diag))).genArrows.src $ diag)) ++ "\n" + + -- | Saves a safe composition graph diagram into a file located at a given path. + writeSCGDFile :: (PrettyPrint a1, PrettyPrint b1, Eq a1, Eq b1, + PrettyPrint a2, PrettyPrint b2, Eq a2, Eq b2) => + Diagram (SafeCompositionGraph a1 b1) (SCGMorphism a1 b1) a1 (SafeCompositionGraph a2 b2) (SCGMorphism a2 b2) a2 -> String -> IO () + writeSCGDFile diag filepath = do + createDirectoryIfMissing True $ takeDirectory filepath + writeFile filepath $ writeSCGDString diag + + -- | Transform a 'CompositionGraph' into a 'SafeCompositionGraph' given a maximum number of loops. + safeCompositionGraphFromCompositionGraph :: Int -> CompositionGraph a b -> SafeCompositionGraph a b + safeCompositionGraphFromCompositionGraph i cg = SafeCompositionGraph{supportS = support cg, lawS = law cg, maxCycles = i} + + -- | Transform a 'SafeCompositionGraph' into a 'CompositionGraph'. + compositionGraphFromSafeCompositionGraph :: SafeCompositionGraph a b -> CompositionGraph a b + compositionGraphFromSafeCompositionGraph scg = unsafeCompositionGraph (supportS scg) (lawS scg) + + -- | Generates a random 'CompositionGraph' and transforms it into a 'SafeCompositionGraph' (see 'constructRandomCompositionGraph'). + constructRandomSafeCompositionGraph :: (RandomGen g) => Int -- ^ Number of arrows of the random composition graph. + -> Int -- ^ Number of monoidification attempts, a bigger number will produce more morphisms that will compose but the function will be slower. + -> Int -- ^ Perseverance : how much we pursure an attempt far away to find a law that works, a bigger number will make the attemps more successful, but slower. (When in doubt put 4.) + -> g -- ^ Random generator. + -> Int -- ^ The maximum number of loops of the SafeCompositionGraph + -> (SafeCompositionGraph Int Int, g) + constructRandomSafeCompositionGraph a b c g i = (safeCompositionGraphFromCompositionGraph i cg, g2) + where + (cg, g2) = constructRandomCompositionGraph a b c g + + -- | Creates a random safe composition graph with default random values. + -- + -- The number of arrows will be in the interval [1, 20]. + -- + -- The max number of loops is set to 100 as it is almost impossible to have a greater number of loops with monoidification attempts. + defaultConstructRandomSafeCompositionGraph :: (RandomGen g) => g -> (SafeCompositionGraph Int Int, g) + defaultConstructRandomSafeCompositionGraph g = (safeCompositionGraphFromCompositionGraph 100 cg, g2) + where + (cg,g2) = defaultConstructRandomCompositionGraph g + + -- | Constructs two random safe composition graphs and choose a random diagram between the two. + -- + -- The max number of loops is set to 100 as it is almost impossible to have a greater number of loops with monoidification attempts. + defaultConstructRandomSafeDiagram :: (RandomGen g) => g -> (Diagram (SafeCompositionGraph Int Int) (SCGMorphism Int Int) Int (SafeCompositionGraph Int Int) (SCGMorphism Int Int) Int, g) + defaultConstructRandomSafeDiagram g1 = pickRandomDiagram cat1 cat2 g3 + where + (nbArrows1, g2) = uniformR (1,8) g1 + (nbAttempts1, g3) = uniformR (0,nbArrows1+nbArrows1) g2 + (cat1, g4) = constructRandomSafeCompositionGraph nbArrows1 nbAttempts1 5 g3 100 + (nbArrows2, g5) = uniformR (1,11-nbArrows1) g4 + (nbAttempts2, g6) = uniformR (0,nbArrows2+nbArrows2) g5 + (cat2, g7) = constructRandomSafeCompositionGraph nbArrows2 nbAttempts2 5 g6 100
+ src/Math/FiniteCategories/SafeCompositionGraph/Example.hs view
@@ -0,0 +1,46 @@+{-| Module : FiniteCategories +Description : An example of 'SafeCompositionGraph' exported with GraphViz. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +An example of 'SafeCompositionGraph' exported with GraphViz. + +A 'SafeCompositionGraph' created from a string is also exported. + +A random 'SafeCompositionGraph' is also exported. + +Export the categories in the directory "OutputGraphViz\/Examples\/FiniteCategories\/SafeCompositionGraph". +-} +module Math.FiniteCategories.SafeCompositionGraph.Example +( + main +) +where + import qualified Data.WeakSet as Set + import Data.WeakSet.Safe + import Data.WeakMap.Safe + + import Math.FiniteCategory + import Math.Categories + import Math.FiniteCategories + import Math.IO.FiniteCategories.ExportGraphViz + import Math.IO.PrettyPrint + + import Numeric.Natural + import System.Random + + -- | An example of 'SafeCompositionGraph' exported with GraphViz. + main :: IO () + main = do + putStrLn "Start of Math.FiniteCategories.SafeCompositionGraph.Example" + catToPdf (unsafeSafeCompositionGraph (unsafeGraph (set [1 :: Int,2,3]) (set [Arrow{sourceArrow=1,targetArrow=1,labelArrow='a'},Arrow{sourceArrow=1,targetArrow=2,labelArrow='b'},Arrow{sourceArrow=2,targetArrow=3,labelArrow='c'}])) (weakMap [([Arrow{sourceArrow=1,targetArrow=1,labelArrow='a'},Arrow{sourceArrow=1,targetArrow=1,labelArrow='a'}],[Arrow{sourceArrow=1,targetArrow=1,labelArrow='a'}])]) 3) "OutputGraphViz/Examples/FiniteCategories/SafeCompositionGraph/SafeCompositionGraph" + catToPdf (unsafeSafeCompositionGraph (unsafeGraph (set [1 :: Int]) (set [Arrow{sourceArrow=1,targetArrow=1,labelArrow='a'}])) (weakMap []) 3) "OutputGraphViz/Examples/FiniteCategories/SafeCompositionGraph/SafeCompositionGraphOnFreeMonoid" + + catToPdf (fst.defaultConstructRandomSafeCompositionGraph $ (mkStdGen 123456)) "OutputGraphViz/Examples/FiniteCategories/SafeCompositionGraph/RandomSafeCompositionGraph" + + let (Right scg) = readSCGString "2\nA -f-> B -g-> C = A -h-> C" + catToPdf scg "OutputGraphViz/Examples/FiniteCategories/SafeCompositionGraph/SafeCompositionGraphFromString" + putStrLn "End of Math.FiniteCategories.SafeCompositionGraph.Example"
+ src/Math/FiniteCategories/Square.hs view
@@ -0,0 +1,131 @@+{-# LANGUAGE MultiParamTypeClasses #-} + +{-| Module : FiniteCategories +Description : The __'Square'__ category contains 4 generating arrows forming a square. It has 6 non identity arrows. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +The __'Square'__ category contains 4 generating arrows forming a square. It has 6 non identity arrows. +-} + +module Math.FiniteCategories.Square +( + SquareOb(..), + SquareAr(..), + Square(..) +) +where + import Math.FiniteCategory + import Math.IO.PrettyPrint + + import Data.WeakSet.Safe + + -- | Objects of the __'Square'__ category. + data SquareOb = SquareA | SquareB | SquareC | SquareD deriving (Eq, Show) + + -- | Morphisms of the __'Square'__ category. + data SquareAr = SquareIdA | SquareIdB | SquareIdC | SquareIdD | SquareF | SquareG | SquareH | SquareI | SquareFH | SquareGI deriving (Eq, Show) + + -- | The __'Square'__ category. + data Square = Square deriving (Eq, Show) + + instance Morphism SquareAr SquareOb where + source SquareIdA = SquareA + source SquareIdB = SquareB + source SquareIdC = SquareC + source SquareIdD = SquareD + source SquareF = SquareA + source SquareG = SquareA + source SquareH = SquareB + source SquareI = SquareC + source SquareFH = SquareA + source SquareGI = SquareA + + target SquareIdA = SquareA + target SquareIdB = SquareB + target SquareIdC = SquareC + target SquareIdD = SquareD + target SquareF = SquareB + target SquareG = SquareC + target SquareH = SquareD + target SquareI = SquareD + target SquareFH = SquareD + target SquareGI = SquareD + + (@?) SquareIdA SquareIdA = Just SquareIdA + (@?) SquareF SquareIdA = Just SquareF + (@?) SquareG SquareIdA = Just SquareG + (@?) SquareFH SquareIdA = Just SquareFH + (@?) SquareGI SquareIdA = Just SquareGI + (@?) SquareIdB SquareIdB = Just SquareIdB + (@?) SquareH SquareIdB = Just SquareH + (@?) SquareIdC SquareIdC = Just SquareIdC + (@?) SquareI SquareIdC = Just SquareI + (@?) SquareIdD SquareIdD = Just SquareIdD + (@?) SquareIdB SquareF = Just SquareF + (@?) SquareH SquareF = Just SquareFH + (@?) SquareIdC SquareG = Just SquareG + (@?) SquareI SquareG = Just SquareGI + (@?) SquareIdD SquareH = Just SquareH + (@?) SquareIdD SquareI = Just SquareI + (@?) SquareIdD SquareFH = Just SquareFH + (@?) SquareIdD SquareGI = Just SquareGI + (@?) _ _ = Nothing + + instance Category Square SquareAr SquareOb where + identity _ SquareA = SquareIdA + identity _ SquareB = SquareIdB + identity _ SquareC = SquareIdC + identity _ SquareD = SquareIdD + + ar _ SquareA SquareA = set [SquareIdA] + ar _ SquareA SquareB = set [SquareF] + ar _ SquareA SquareC = set [SquareG] + ar _ SquareA SquareD = set [SquareFH,SquareGI] + ar _ SquareB SquareB = set [SquareIdB] + ar _ SquareB SquareD = set [SquareH] + ar _ SquareC SquareC = set [SquareIdC] + ar _ SquareC SquareD = set [SquareI] + ar _ SquareD SquareD = set [SquareIdD] + ar _ _ _ = set [] + + genAr _ SquareA SquareA = set [SquareIdA] + genAr _ SquareA SquareB = set [SquareF] + genAr _ SquareA SquareC = set [SquareG] + genAr _ SquareB SquareB = set [SquareIdB] + genAr _ SquareB SquareD = set [SquareH] + genAr _ SquareC SquareC = set [SquareIdC] + genAr _ SquareC SquareD = set [SquareI] + genAr _ SquareD SquareD = set [SquareIdD] + genAr _ _ _ = set [] + + decompose _ SquareFH = [SquareH, SquareF] + decompose _ SquareGI = [SquareI, SquareG] + decompose _ x = [x] + + instance FiniteCategory Square SquareAr SquareOb where + ob _ = set [SquareA, SquareB, SquareC, SquareD] + + instance PrettyPrint SquareOb where + pprint SquareA = "A" + pprint SquareB = "B" + pprint SquareC = "C" + pprint SquareD = "D" + + instance PrettyPrint SquareAr where + pprint SquareIdA = "IdA" + pprint SquareIdB = "IdB" + pprint SquareIdC = "IdC" + pprint SquareIdD = "IdD" + pprint SquareF = "f" + pprint SquareG = "g" + pprint SquareH = "h" + pprint SquareI = "i" + pprint SquareFH = "h o f" + pprint SquareGI = "i o g" + + instance PrettyPrint Square where + pprint = show
+ src/Math/FiniteCategories/Square/Example.hs view
@@ -0,0 +1,28 @@+{-| Module : FiniteCategories +Description : __'Square'__ exported with GraphViz. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +__'Square'__ exported with GraphViz. + +Export the __'Square'__ category in the directory "OutputGraphViz\/Examples\/FiniteCategories\/Square". +-} +module Math.FiniteCategories.Square.Example +( + main +) +where + import Data.WeakSet.Safe + + import Math.FiniteCategories.Square + import Math.IO.FiniteCategories.ExportGraphViz + + -- | __'Square'__ exported with GraphViz. + main :: IO () + main = do + putStrLn "Start of Math.FiniteCategories.Square.Example" + catToPdf Square "OutputGraphViz/Examples/FiniteCategories/Square/Square" + putStrLn "End of Math.FiniteCategories.Square.Example"
+ src/Math/FiniteCategories/Subcategory.hs view
@@ -0,0 +1,209 @@+{-# LANGUAGE UndecidableInstances, FlexibleInstances, MultiParamTypeClasses #-} + +{-| Module : FiniteCategories +Description : A 'Subcategory' of a category /C/ is a category /D/ whose objects are objects in /C/ and whose morphisms are morphisms in /C/ with the same identities and composition of morphisms. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +A 'Subcategory' of a category /C/ is a category /D/ whose objects are objects in /C/ and whose morphisms are morphisms in /C/ with the same identities and composition of morphisms. + +We have to forget the generating set of morphisms of the original 'Category' as the generators are not always inheritable (see for example the full subcategory of __'Square'__ containing the objects A and D). + +If the generators are inheritable, you can use the constructor 'InheritedSubcategory' to inherit the generators of the original 'Category'. +-} + +module Math.FiniteCategories.Subcategory +( + -- * Subcategory + Subcategory, + -- ** Smart constructors + unsafeSubcategory, + subcategory, + -- ** Getter + originalCategory, + -- ** Interaction with 'Diagram' + embeddingToSubcategory, + fullDiagram, + fullNaturalTransformation, + -- * InheritedSubcategory + InheritedSubcategory, + -- ** Smart constructors + unsafeInheritedSubcategory, + inheritedSubcategory, + -- ** Getter + originalCategory2, + -- ** Interaction with 'Diagram' + embeddingToInheritedSubcategory, + fullDiagram2, + fullNaturalTransformation2, +) +where + import Math.FiniteCategory + import Math.FiniteCategoryError + import Math.Categories.FunctorCategory + 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 + + -- | A 'Subcategory' needs an original category, a set of objects and a set of morphisms selected in the category. + -- + -- The generators are forgotten, use 'InheritedSubcategory' if the generators are inheritable. + -- + -- 'Subcategory' is private because the subset of morphisms might not yield a valid 'FiniteCategory' if a composite morphism does not belong in the subset. + -- + -- Use the smart constructor 'subcategory' instead. + data Subcategory c m o = Subcategory c (Set o) (Set m) deriving (Eq) + + instance (Show c, Show m, Show o) => Show (Subcategory c m o) where + show (Subcategory c os ms) = "(unsafeSubcategory "++show c++" "++show os++" "++show ms++")" + + -- | Unsafe version of 'subcategory' which does not check the structure of the 'Subcategory' constructed. + unsafeSubcategory :: c -> (Set o) -> (Set m) -> Subcategory c m o + unsafeSubcategory c os ms = Subcategory c os ms + + -- | Smart constructor of 'Subcategory'. + -- + -- If the 'Subcategory' constructed is valid, return 'Right' the subcategory, otherwise return Left a 'FiniteCategoryError'. + subcategory :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> (Set o) -> (Set m) -> Either (FiniteCategoryError m o) (Subcategory c m o) + subcategory c ms os + | null check = Right r + | otherwise = Left err + where + r = Subcategory c ms os + check = checkFiniteCategory r + Just err = check + + -- | Return the original category the 'Subcategory' was taken from. + originalCategory :: Subcategory c m o -> c + originalCategory (Subcategory c _ _) = c + + instance (Category c m o, Eq o, Eq m) => Category (Subcategory c m o) m o where + identity (Subcategory c objs _) o + | o `isIn` objs = identity c o + | otherwise = error "Math.FiniteCategories.Subcategory.identity: object not in the subcategory" + ar (Subcategory c objs morphs) s t + | s `isIn` objs && t `isIn` objs = Set.filter (`isIn` morphs) $ ar c s t + | otherwise = error "Math.FiniteCategories.Subcategory.ar: source or target not in the subcategory" + + instance (Category c m o, Eq o, Eq m) => FiniteCategory (Subcategory c m o) m o where + ob (Subcategory _ o _) = o + + instance (PrettyPrint c, PrettyPrint m, PrettyPrint o, Eq o, Eq m) => PrettyPrint (Subcategory c m o) where + pprint (Subcategory c o m) = "FullSubcategory("++ pprint c ++ ","++ pprint o ++ "," ++ pprint m ++")" + + + + -- | An 'InheritedSubcategory' needs an original category, a set of objects and a set of morphisms selected in the category. + -- + -- The generators are inherited. + -- + -- 'InheritedSubcategory' is private because the subset of morphisms might not yield a valid 'FiniteCategory' if a composite morphism does not belong in the subset. + -- + -- Use the smart constructor 'inheritedSubcategory' instead. + data InheritedSubcategory c m o = InheritedSubcategory c (Set o) (Set m) deriving (Eq) + + instance (Show c, Show m, Show o) => Show (InheritedSubcategory c m o) where + show (InheritedSubcategory c os ms) = "(unsafeInheritedSubcategory "++show c++" "++show os++" "++show ms++")" + + -- | Unsafe version of 'inheritedSubcategory' which does not check the structure of the 'InheritedSubcategory' constructed. + unsafeInheritedSubcategory :: c -> (Set o) -> (Set m) -> InheritedSubcategory c m o + unsafeInheritedSubcategory c os ms = InheritedSubcategory c os ms + + -- | Smart constructor of 'InheritedSubcategory'. + -- + -- If the 'InheritedSubcategory' constructed is valid, return 'Right' the subcategory, otherwise return Left a 'FiniteCategoryError'. + inheritedSubcategory :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> (Set o) -> (Set m) -> Either (FiniteCategoryError m o) (InheritedSubcategory c m o) + inheritedSubcategory c ms os + | null check = Right r + | otherwise = Left err + where + r = InheritedSubcategory c ms os + check = checkFiniteCategory r + Just err = check + + -- | Return the original category the 'InheritedSubcategory' was taken from. + originalCategory2 :: InheritedSubcategory c m o -> c + originalCategory2 (InheritedSubcategory c _ _) = c + + instance (Category c m o, Eq o, Eq m) => Category (InheritedSubcategory c m o) m o where + identity (InheritedSubcategory c objs _) o + | o `isIn` objs = identity c o + | otherwise = error "Math.FiniteCategories.InheritedSubcategory.identity: object not in the subcategory" + ar (InheritedSubcategory c objs morphs) s t + | s `isIn` objs && t `isIn` objs = Set.filter (`isIn` morphs) $ ar c s t + | otherwise = error "Math.FiniteCategories.InheritedSubcategory.ar: source or target not in the subcategory" + genAr (InheritedSubcategory c objs morphs) s t + | s `isIn` objs && t `isIn` objs = Set.filter (`isIn` morphs) $ genAr c s t + | otherwise = error "Math.FiniteCategories.InheritedSubcategory.genAr: source or target not in the subcategory" + decompose (InheritedSubcategory c _ morphs) m + | m `isIn` morphs = decompose c m + | otherwise = error "Math.FiniteCategories.InheritedSubcategory.decompose: morphism not in the subcategory" + + instance (Category c m o, Eq o, Eq m) => FiniteCategory (InheritedSubcategory c m o) m o where + ob (InheritedSubcategory _ o _) = o + + instance (PrettyPrint c, PrettyPrint m, PrettyPrint o, Eq o, Eq m) => PrettyPrint (InheritedSubcategory c m o) where + pprint (InheritedSubcategory c o m) = "InheritedFullSubcategory("++ pprint c ++ ","++ pprint o ++ "," ++ pprint m ++")" + + + -- | Return the image 'Subcategory' of an embedding. + -- + -- An embedding is a faithful 'Diagram' injective on objects. + -- + -- Does not check that the 'Diagram' is an embedding. + embeddingToSubcategory :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1) => Diagram c1 m1 o1 c2 m2 o2 -> Subcategory c2 m2 o2 + embeddingToSubcategory diag = Subcategory (tgt diag) (image (omap diag)) (image (mmap diag)) + + -- | Return the image 'InheritedSubcategory' of an embedding. + -- + -- An embedding is a faithful 'Diagram' injective on objects. + -- + -- Does not check that the 'Diagram' is an embedding. + embeddingToInheritedSubcategory :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1) => Diagram c1 m1 o1 c2 m2 o2 -> InheritedSubcategory c2 m2 o2 + embeddingToInheritedSubcategory diag = InheritedSubcategory (tgt diag) (image (omap diag)) (image (mmap diag)) + + -- | Extracts a full and faithful diagram out of a faithful 'Diagram' injective on objects. + -- + -- Does not check that the 'Diagram' is an embedding. + fullDiagram :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1) => + Diagram c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 (Subcategory c2 m2 o2) m2 o2 + fullDiagram diag = Diagram {src = src diag, tgt = embeddingToSubcategory diag, omap = omap diag, mmap = mmap diag} + + -- | Extracts a full and faithful diagram out of a faithful 'Diagram' injective on objects. The target subcategory is inherited (see 'InheritedFullSubcategory'). + -- + -- Does not check that the 'Diagram' is an embedding. + fullDiagram2 :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1) => + Diagram c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 (InheritedSubcategory c2 m2 o2) m2 o2 + fullDiagram2 diag = Diagram {src = src diag, tgt = embeddingToInheritedSubcategory diag, omap = omap diag, mmap = mmap diag} + + -- | Extracts full and faithful diagrams out of the source and target 'Diagram's of a 'NaturalTransformation'. The 'Diagram's should be a faithful and injective on objects. + -- + -- Does not check that the 'Diagram's are embeddings. + fullNaturalTransformation :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + Category c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => + NaturalTransformation c1 m1 o1 c2 m2 o2 -> NaturalTransformation c1 m1 o1 (Subcategory c2 m2 o2) m2 o2 + fullNaturalTransformation nat = unsafeNaturalTransformation sourceDiag targetDiag (components nat) + where + targetCat = Subcategory (tgt (source nat)) ((image (omap (source nat))) ||| (image (omap (target nat)))) ((image (mmap (source nat))) ||| (image (mmap (target nat))) ||| (image (components nat))) + sourceDiag = Diagram{src=src (source nat), tgt=targetCat, omap=omap (source nat), mmap=mmap (source nat)} + targetDiag = Diagram{src=src (target nat), tgt=targetCat, omap=omap (target nat), mmap=mmap (target nat)} + + -- | Extracts full and faithful diagrams out of the source and target 'Diagram's of a 'NaturalTransformation'. The 'Diagram's should be a faithful and injective on objects. The target subcategory is inherited (see 'InheritedFullSubcategory'). + -- + -- Does not check that the 'Diagram's are embeddings. + fullNaturalTransformation2 :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + Category c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2) => + NaturalTransformation c1 m1 o1 c2 m2 o2 -> NaturalTransformation c1 m1 o1 (InheritedSubcategory c2 m2 o2) m2 o2 + fullNaturalTransformation2 nat = unsafeNaturalTransformation sourceDiag targetDiag (components nat) + where + targetCat = InheritedSubcategory (tgt (source nat)) ((image (omap (source nat))) ||| (image (omap (target nat)))) ((image (mmap (source nat))) ||| (image (mmap (target nat))) ||| (image (components nat))) + sourceDiag = Diagram{src=src (source nat), tgt=targetCat, omap=omap (source nat), mmap=mmap (source nat)} + targetDiag = Diagram{src=src (target nat), tgt=targetCat, omap=omap (target nat), mmap=mmap (target nat)}
+ src/Math/FiniteCategories/V.hs view
@@ -0,0 +1,83 @@+{-# LANGUAGE MultiParamTypeClasses #-} + +{-| Module : FiniteCategories +Description : The __'V'__ category contains two arrows pointing to the same object. It is the opposite of __'Hat'__. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +The __'V'__ category contains two arrows pointing to the same object. + +The shape of the __'V'__ category is the following : @`B` -`F`-> `A` <-`G`- `C`@ +-} + +module Math.FiniteCategories.V +( + VOb(..), + VAr(..), + V(..) +) +where + import Math.FiniteCategory + import Math.IO.PrettyPrint + + import Data.WeakSet.Safe + + -- | Objects of the __'V'__ category. + data VOb = VA | VB | VC deriving (Eq, Show) + + -- | Morphisms of the __'V'__ category. + data VAr = VIdA | VIdB | VIdC | VF | VG deriving (Eq, Show) + + -- | The __'V'__ category. + data V = V deriving (Eq, Show) + + instance Morphism VAr VOb where + source VIdA = VA + source VIdB = VB + source VIdC = VC + source VF = VB + source VG = VC + target VIdA = VA + target VIdB = VB + target VIdC = VC + target _ = VA + (@?) VIdA VIdA = Just VIdA + (@?) VIdB VIdB = Just VIdB + (@?) VF VIdB = Just VF + (@?) VG VIdC = Just VG + (@?) VIdC VIdC = Just VIdC + (@?) VIdA VF = Just VF + (@?) VIdA VG = Just VG + (@?) _ _ = Nothing + + instance Category V VAr VOb where + identity _ VA = VIdA + identity _ VB = VIdB + identity _ VC = VIdC + ar _ VA VA = set [VIdA] + ar _ VB VA = set [VF] + ar _ VB VB = set [VIdB] + ar _ VC VA = set [VG] + ar _ VC VC = set [VIdC] + ar _ _ _ = set [] + + instance FiniteCategory V VAr VOb where + ob _ = set [VA, VB, VC] + + instance PrettyPrint VOb where + pprint VA = "A" + pprint VB = "B" + pprint VC = "C" + + instance PrettyPrint VAr where + pprint VIdA = "IdA" + pprint VIdB = "IdB" + pprint VIdC = "IdC" + pprint VF = "f" + pprint VG = "g" + + instance PrettyPrint V where + pprint = show
+ src/Math/FiniteCategories/V/Example.hs view
@@ -0,0 +1,28 @@+{-| Module : FiniteCategories +Description : __'V'__ exported with GraphViz. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +__'V'__ exported with GraphViz. + +Export the __'V'__ category in the directory "OutputGraphViz\/Examples\/FiniteCategories\/V". +-} +module Math.FiniteCategories.V.Example +( + main +) +where + import Data.WeakSet.Safe + + import Math.FiniteCategories.V + import Math.IO.FiniteCategories.ExportGraphViz + + -- | __'V'__ exported with GraphViz. + main :: IO () + main = do + putStrLn "Start of Math.FiniteCategories.V.Example" + catToPdf V "OutputGraphViz/Examples/FiniteCategories/V/V" + putStrLn "End of Math.FiniteCategories.V.Example"
+ src/Math/FiniteCategory.hs view
@@ -0,0 +1,154 @@+{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-} + +{-| Module : FiniteCategories +Description : A 'FiniteCategory' is a 'Category' where the objects can be enumerated. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +A 'FiniteCategory' is a 'Category' where the objects can be enumerated. + +This module exports Math.Category so that you only have to import one of them. +-} + +module Math.FiniteCategory +( + -- * FiniteCategory + FiniteCategory(..), + -- ** Morphism enumeration + arrows, + arFrom, + arTo, + arFrom2, + arTo2, + identities, + -- ** Morphism predicates + isEpic, + isMonic, + -- ** Object predicates + isTerminal, + isInitial, + -- ** Find special objects + terminalObjects, + initialObjects, + -- * Generated finite category + -- ** Generator enumeration + genArrows, + genArFrom, + genArTo, + genArFrom2, + genArTo2, + -- ** Helper + bruteForceDecompose, + module Math.Category +) +where + import Data.WeakSet (Set) + import qualified Data.WeakSet as Set + import Data.WeakSet.Safe + import Data.List (elemIndex) + + import Math.Category + + import Control.Monad (join) + + + -- | A 'FiniteCategory' is a 'Category' which allows to enumerate its objects. + -- + -- It is assumed that the set of objects of the category is finite. + class (Category c m o) => FiniteCategory c m o | c -> m, m -> o where + -- | `ob` should return a set of objects. + ob :: c -> Set o + + -- | `arrows` returns the set of all unique morphisms of a category. + arrows :: (FiniteCategory c m o, Morphism m o) => c -> Set m + arrows c = join $ ar c <$> ob c <*> ob c + + -- | `arTo` returns the set of morphisms going to a specified target. + arTo :: (FiniteCategory c m o, Morphism m o) => c -> o -> Set m + arTo c t = join $ (\s -> ar c s t) <$> ob c + + -- | `arTo2` same as `arTo` but for multiple targets. + arTo2 :: (FiniteCategory c m o, Morphism m o) => c -> Set o -> Set m + arTo2 c ts = join $ ar c <$> ob c <*> ts + + -- | `arFrom` returns the list of unique morphisms going from a specified source. + arFrom :: (FiniteCategory c m o, Morphism m o) => c -> o -> Set m + arFrom c s = join $ ar c s <$> ob c + + -- | `arFrom2` same as `arFrom` but for multiple sources. + arFrom2 :: (FiniteCategory c m o, Morphism m o) => c -> Set o -> Set m + arFrom2 c ss = join $ ar c <$> ss <*> ob c + + -- | Same as `arrows` but only returns the generators. @genArrows c@ should be included in @arrows c@. + genArrows :: (FiniteCategory c m o, Morphism m o) => c -> Set m + genArrows c = join $ genAr c <$> ob c <*> ob c + + -- | Same as `arTo` but only returns the generators. @genArTo c t@ should be included in @arTo c t@. + genArTo :: (FiniteCategory c m o, Morphism m o) => c -> o -> Set m + genArTo c t = join $ (\s -> genAr c s t) <$> ob c + + -- | Same as `arTo2` but only returns the generators. @genArTo2 c (set [t])@ should be included in @arTo2 c (set [t])@. + genArTo2 :: (FiniteCategory c m o, Morphism m o) => c -> Set o -> Set m + genArTo2 c ts = join $ (genAr c) <$> ob c <*> ts + + -- | Same as `arFrom` but only returns the generators. @genArFrom c s@ should be included in @arFrom c s@. + genArFrom :: (FiniteCategory c m o, Morphism m o) => c -> o -> Set m + genArFrom c s = join $ (genAr c s) <$> ob c + + -- | Same as `arFrom2` but only returns the generators. @genArFrom2 c (set [s])@ should be included in @arFrom2 c (set [s])@. + genArFrom2 :: (FiniteCategory c m o, Morphism m o) => c -> Set o -> Set m + genArFrom2 c ss = join $ genAr c <$> ss <*> ob c + + -- | `identities` returns all the identities of a category. + identities :: (FiniteCategory c m o, Morphism m o) => c -> Set m + identities c = identity c <$> ob c + + -- | Return wether an object is initial in the category. + isInitial :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> o -> Bool + isInitial cat obj = let + morphisms t = setToList $ ar cat obj t + condition t = (not.null $ morphisms t) && (null.tail $ morphisms t) -- we avoid the usage of cardinal to test that the size of (ar cat obj t) is 1 for speed purposes + in + Set.and $ condition <$> ob cat + + -- | Return the set of intial objects in a category. + initialObjects :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> Set o + initialObjects cat = Set.filter (isInitial cat) (ob cat) + + -- | Return wether an object is terminal in the category. + isTerminal :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> o -> Bool + isTerminal cat obj = let + morphisms s = setToList $ ar cat s obj + condition s = (not.null $ morphisms s) && (null.tail $ morphisms s) -- we avoid the usage of cardinal to test that the size of (ar cat s obj) is 1 for speed purposes + in + Set.and $ condition <$> ob cat + + -- | Return the set of terminal objects in a category. + terminalObjects :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> Set o + terminalObjects cat = Set.filter (isTerminal cat) (ob cat) + + -- | Return wether a morphism is a monomorphism. + isMonic :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> m -> Bool + isMonic c f = and [f @ g /= f @ h || g == h| x <- setToList $ ob c, g <- setToList $ ar c x (source f), h <- setToList $ ar c x (source f)] + + -- | Return wether a morphism is an epimorphism. + isEpic :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> m -> Bool + isEpic c f = and [g @ f /= h @ f || g == h | x <- setToList $ ob c, g <- setToList $ ar c (target f) x, h <- setToList $ ar c (target f) x] + + -- | Helper function for `bruteForceDecompose`. + bruteForce :: (FiniteCategory c m o, Morphism m o, Eq m) => c -> m -> [[m]] -> [m] + bruteForce c m l = if index == Nothing then bruteForce c m (concat (pathToAugmentedPaths <$> l)) else l !! i where + index = elemIndex m (compose <$> l) + Just i = index + leavingMorph path = (setToList.(genArFrom c)) $ target.head $ path + pathToAugmentedPaths path = (leavingMorph path) >>= (\x -> [(x:path)] ) + + -- | If `genAr` is implemented, we can find the decomposition of a morphism by bruteforce search (we compose every arrow until we get the morphism we want). + -- + -- This method is meant to be used temporarly until a proper decompose method is implemented. (It is very slow.) + bruteForceDecompose :: (FiniteCategory c m o, Morphism m o, Eq m) => c -> m -> [m] + bruteForceDecompose c m = bruteForce c m ((:[]) <$> (setToList $ genArFrom c (source m))) +
+ src/Math/FiniteCategoryError.hs view
@@ -0,0 +1,72 @@+{-# LANGUAGE MultiParamTypeClasses #-} + +{-| Module : FiniteCategories +Description : Check the 'FiniteCategory' structure. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +Provide a function to test the structure of a 'FiniteCategory'. +-} + +module Math.FiniteCategoryError +( + -- * Check structure + FiniteCategoryError, + checkFiniteCategory +) +where + import Data.WeakSet (Set) + import qualified Data.WeakSet as Set + import Data.WeakSet.Safe + + import Math.FiniteCategory + + -- | A data type to represent an incoherence inside a finite category. + data FiniteCategoryError m o = + CompositionNotAssociative {f :: m, g :: m, h :: m, fg_h :: m, f_gh :: m} -- ^ @(h\@g)\@f /= h\@(g\@f)@ + | WrongSource {f :: m, realSource :: o} -- ^ `f` was found by using @'ar' c s t@ where @s /= 'source' f@. + | WrongTarget {f :: m, realTarget :: o} -- ^ `f` was found by using @'ar' c s t@ where @t /= 'target' f@. + | IdentityNotLeftNeutral {idL :: m, f :: m, foidL :: m} -- ^ `idL` is not a valid identity : @f \@ idL /= f@. + | IdentityNotRightNeutral {f :: m, idR :: m, idRof :: m} -- ^ `idR` is not a valid identity : @idR \@ f /= f@. + | MorphismsShouldNotBeEqual {f :: m, g :: m} -- ^ @f == g@ even though they don'y share the same source or target. + | NotTransitive {f :: m, g :: m} -- ^ @f\@g@ is not an element of @ar c (source g) (target g)@. + | GeneratorIsNotAMorphism {f :: m} -- ^ `f` is a generator but not a morphism. + | MorphismDoesntDecomposesIntoGenerators {f :: m, decomp :: [m], notGen :: m} -- ^ The morphism `f` decomposes into `decomp` where `notGen` is a non generating morphism. + | WrongDecomposition {f :: m, decomp :: [m], comp :: m} -- ^ @compose (decompose c f) /= f@. + deriving (Eq, Show) + + -- | Checks the category axioms for a 'FiniteCategory'. + -- + -- If an error is found in the category, 'Just' a `FiniteCategoryError` is returned. + -- Otherwise, 'Nothing' is returned. + checkFiniteCategory :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> Maybe (FiniteCategoryError m o) + checkFiniteCategory c + | (not.null) incoherentEq = Just MorphismsShouldNotBeEqual {f=(fst.head) incoherentEq, g=(snd.head) incoherentEq} + | (not.null) wrongSource = Just WrongSource {f = (fst.head) wrongSource, realSource = (snd.head) wrongSource} + | (not.null) wrongTarget = Just WrongTarget {f = (fst.head) wrongTarget, realTarget = (snd.head) wrongTarget} + | (not.null) idNotLNeutral = Just IdentityNotLeftNeutral {idL=(fst3.head) idNotLNeutral, f=(snd3.head) idNotLNeutral,foidL=(trd3.head) idNotLNeutral} + | (not.null) idNotRNeutral = Just IdentityNotRightNeutral {f=(fst3.head) idNotRNeutral, idR=(snd3.head) idNotRNeutral,idRof=(trd3.head) idNotRNeutral} + | (not.null) notAssociative = Just CompositionNotAssociative {f=(fst3.head) notAssociative,g=(snd3.head) notAssociative,h=(trd3.head) notAssociative, fg_h=(((fst3.head)notAssociative) @ ((snd3.head)notAssociative)) @ ((trd3.head)notAssociative), + f_gh=((fst3.head)notAssociative) @ (((snd3.head)notAssociative) @ ((trd3.head)notAssociative))} + | (not.null) notTransitive = Just NotTransitive {f=(fst.head) notTransitive, g=(snd.head) notTransitive} + | (not.(Set.null)) genNotMorph = Just GeneratorIsNotAMorphism {f=head.setToList $ genNotMorph} + | (not.null) decompIntoComposite = Just MorphismDoesntDecomposesIntoGenerators {f=(fst3.head) decompIntoComposite, decomp=(snd3.head) decompIntoComposite, notGen=(trd3.head) decompIntoComposite} + | (not.null) wrongDecomp = Just WrongDecomposition {f=(fst3.head) wrongDecomp, decomp=(snd3.head) wrongDecomp, comp=(trd3.head) wrongDecomp} + | otherwise = Nothing + where + incoherentEq = setToList $ Set.filter (\(f,g) -> f == g && (source f /= source g || target f /= target g)) (arrows c |*| arrows c) + wrongSource = [(f,s) | s <- setToList $ ob c, t <- setToList $ ob c, f <- setToList $ ar c s t, source f /= s] + wrongTarget = [(f,t) | s <- setToList $ ob c, t <- setToList $ ob c, f <- setToList $ ar c s t, target f /= t] + idNotLNeutral = [(identity c (source f),f,f @ identity c (source f)) | f <- setToList $ arrows c, f @ identity c (source f) /= f] + idNotRNeutral = [(f,identity c (target f), identity c (target f) @ f) | f <- setToList $ arrows c, identity c (target f) @ f /= f] + notAssociative = [(x,y,z) | z <- setToList $ arrows c, y <- setToList $ arFrom c (target z), x <- setToList $ arFrom c (target y), (x @ y) @ z /= x @ (y @ z)] + notTransitive = [(f,g) | g <- setToList $ arrows c, f <- setToList $ arFrom c (target g), not ((f @ g) `isIn` (ar c (source g) (target f)))] + genNotMorph = genArrows c |-| arrows c + decompIntoComposite = [(m,decompose c m,f) | m <- setToList $ arrows c, f <- decompose c m, not (f `isIn` (genAr c (source f) (target f)))] + wrongDecomp = [(f,decompose c f, compose (decompose c f)) | f <- setToList $ arrows c, compose (decompose c f) /= f] + fst3 (x,_,_) = x + snd3 (_,x,_) = x + trd3 (_,_,x) = x
+ src/Math/Functors.hs view
@@ -0,0 +1,25 @@+{-# LANGUAGE MultiParamTypeClasses #-} + +{-| Module : FiniteCategories +Description : This file exports all functors. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +This file exports all functors. +-} + +module Math.Functors ( + module Math.Functors.Adjunction, + module Math.Functors.DataMigration, + module Math.Functors.DiagonalFunctor, + module Math.Functors.KanExtension, + module Math.Functors.SetValued, +) where + import Math.Functors.Adjunction + import Math.Functors.DataMigration + import Math.Functors.DiagonalFunctor + import Math.Functors.KanExtension + import Math.Functors.SetValued
+ src/Math/Functors/Adjunction.hs view
@@ -0,0 +1,62 @@+{-# LANGUAGE MonadComprehensions, MultiParamTypeClasses #-} +{-| Module : FiniteCategories +Description : Adjoint functors. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +Adjunctions are all over the place in mathematics. +-} + +module Math.Functors.Adjunction +( + leftAdjoint, + rightAdjoint, +) +where + 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 Math.FiniteCategory + import Math.Categories.FunctorCategory + import Math.Categories.CommaCategory + + -- | 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 = om, + mmap = weakMapFromSet [(m, anElement (binding m)) | m <- arrows (tgt g), Map.member (source m) om && Map.member (target m) om && not (Set.null (binding m))] + } + where + universalMorphisms y = initialObjects (CommaCategory {rightDiagram = g, leftDiagram = (selectObject (tgt g) y)}) + yToUniversalMorphism = weakMapFromSet [(y, anElement.universalMorphisms $ y) | y <- ob (tgt g), not (Set.null (universalMorphisms y))] + om = Map.map indexTarget yToUniversalMorphism + yToEta = Map.map selectedArrow yToUniversalMorphism + binding m = [a | a <- ar (src g) (om |!| (source m)) (om |!| (target m)), ((yToEta |!| target m) @ m) == (g ->£ a) @ (yToEta |!| 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 = om, + mmap = weakMapFromSet [(m, anElement (binding m)) | m <- arrows (tgt f), (Map.member (source m) om) && (Map.member (target m) om) && not (Set.null (binding m))] + } + where + universalMorphisms x = terminalObjects (CommaCategory {leftDiagram = f, rightDiagram = (selectObject (tgt f) x)}) + xToUniversalMorphism = weakMapFromSet [(x, anElement.universalMorphisms $ x) | x <- ob (tgt f), not (Set.null (universalMorphisms x))] + om = Map.map indexSource xToUniversalMorphism + xToEps = Map.map selectedArrow xToUniversalMorphism + binding m = [a | a <- ar (src f) (om |!| (source m)) (om |!| (target m)), ((xToEps |!| target m) @ (f ->£ a)) == (m @ (xToEps |!| source m))]
+ src/Math/Functors/Adjunction/Example.hs view
@@ -0,0 +1,46 @@+{-| Module : FiniteCategories +Description : An exemple of 'leftAdjoint' and 'rightAdjoint' use exported with GraphViz. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +An exemple of 'leftAdjoint' and 'rightAdjoint' use exported with GraphViz. + +Export the lim functor of a discrete 'Diagram' in 'Ens' in the directory "OutputGraphViz\/Examples\/Functor\/Adjunction". +-} +module Math.Functors.Adjunction.Example +( + main +) +where + import Math.FiniteCategory + import Math.FiniteCategories.Ens + import Math.FiniteCategories.DiscreteCategory + import Math.Categories.FunctorCategory + import Math.Functors.Adjunction + import Math.Functors.DiagonalFunctor + import Math.IO.FiniteCategories.ExportGraphViz + + 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 + + -- | An exemple of 'leftAdjoint' and 'rightAdjoint' use exported with GraphViz. + main :: IO () + main = do + putStrLn "Start of Math.Functors.Adjunction.Example" + let universe = ens $ set [set [1 :: Int], set [3,4]] + let indexing = discreteCategory $ set [0 :: Int,1] + let diagFunct = diagonalFunctor indexing universe + let leftAdj = leftAdjoint diagFunct + let rightAdj = rightAdjoint diagFunct + catToPdf universe "OutputGraphViz/Examples/Functors/Adjunction/ens" + catToPdf indexing "OutputGraphViz/Examples/Functors/Adjunction/indexing" + diagToPdf2 (fst.anElement.(Map.mapToSet).omap $ leftAdj) "OutputGraphViz/Examples/Functors/Adjunction/diag" + diagToPdf2 (selectObject universe (snd.anElement.(Map.mapToSet).omap $ leftAdj)) "OutputGraphViz/Examples/Functors/Adjunction/limit" + putStrLn "End of Math.Functors.Adjunction.Example"
+ src/Math/Functors/DataMigration.hs view
@@ -0,0 +1,48 @@+{-# LANGUAGE MonadComprehensions, MultiParamTypeClasses #-} +{-| Module : FiniteCategories +Description : Data migration functors as defined by David Spivak in FQL. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +Data migration functors as defined by David Spivak in FQL. +-} + +module Math.Functors.DataMigration +( + deltaFunctor, + piFunctor, + sigmaFunctor +) +where + 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 Math.FiniteCategory + import Math.Categories.FunctorCategory + import Math.Functors.Adjunction + + -- | Precomposition functor. + deltaFunctor :: (FiniteCategory c1 m1 o1, Morphism m1 o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2, + FiniteCategory c3 m3 o3, Morphism m3 o3, Eq c3, Eq m3, Eq o3) => + c3 -> Diagram c1 m1 o1 c2 m2 o2 -> Diagram (FunctorCategory c2 m2 o2 c3 m3 o3) (NaturalTransformation c2 m2 o2 c3 m3 o3) (Diagram c2 m2 o2 c3 m3 o3) (FunctorCategory c1 m1 o1 c3 m3 o3) (NaturalTransformation c1 m1 o1 c3 m3 o3) (Diagram c1 m1 o1 c3 m3 o3) + deltaFunctor c diag = Diagram{src = s, tgt = t, + omap = memorizeFunction (<-@<- diag) (ob s), + mmap = memorizeFunction (<=@<- diag) (arrows s)} + where + s = FunctorCategory (tgt diag) c + t = FunctorCategory (src diag) c + + -- | Right adjoint of the precomposition functor. + piFunctor c = rightAdjoint.(deltaFunctor c) + + -- | Left adjoint of the precomposition functor. + sigmaFunctor c = leftAdjoint.(deltaFunctor c) +
+ src/Math/Functors/DataMigration/Example.hs view
@@ -0,0 +1,79 @@+{-| Module : FiniteCategories +Description : An exemple of a 'dataMigration' exported with GraphViz. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +An exemple of 'dataMigration' exported with GraphViz. + +Export a data migration in the directory "OutputGraphViz\/Examples\/Functor\/DataMigration". +-} +module Math.Functors.DataMigration.Example +( + main +) +where + import Math.FiniteCategory + import Math.FiniteCategories.SafeCompositionGraph + import Math.FiniteCategories + import Math.Functors.DataMigration + import Math.Categories.FinSet + import Math.IO.FiniteCategories.ExportGraphViz + + 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 + + -- | An exemple of 'DataMigration' exported with GraphViz. + main :: IO () + main = do + putStrLn "Start of Math.Functors.DataMigration.Example" + -- let Right graphSketch = readSCGString "3\nE -s-> V\nE -t-> V" + -- let Right autographSketch = readSCGString "3\nA -s-> A -s-> A = A -t-> A\nA -s-> A -t-> A = <ID>\nA -t-> A -s-> A = <ID>\n A -t-> A -t-> A = A -s-> A" + -- let f = (setToList $ ob (FunctorCategory graphSketch autographSketch)) !! 7 + -- --Diagram{src=graphSketch, tgt=autographSketch, omap=memorizeFunction (const.anElement.ob $ autographSketch) (ob graphSketch), mmap = weakMap (zip (setToList (arrows graphSketch)) (setToList (arrows autographSketch)))} + -- catToPdf graphSketch "OutputGraphViz/Examples/Functors/DataMigration/graphSketch" + -- catToPdf autographSketch "OutputGraphViz/Examples/Functors/DataMigration/autographSketch" + -- diagToPdf2 f "OutputGraphViz/Examples/Functors/DataMigration/f" + -- putStrLn (show f) + -- let universe = ens $ set [set [1 :: Int,2]] + -- let delta = (deltaFunctor universe f) + -- let anInstance = anElement (ob.source $ delta) + -- diagToPdf anInstance "OutputGraphViz/Examples/Functors/DataMigration/autograph1" + -- diagToPdf (delta ->$ anInstance) "OutputGraphViz/Examples/Functors/DataMigration/delta_autograph1" + + -- let universe = ens $ set [set[], set[1], set[1 :: Int,2]] + -- let pii = (piFunctor universe f) + -- let anInstance = (setToList.ob.source $ delta) !! 0 + -- diagToPdf anInstance "OutputGraphViz/Examples/Functors/DataMigration/graph1" + -- diagToPdf (pii ->$ anInstance) "OutputGraphViz/Examples/Functors/DataMigration/pi_graph1" + + -- let c = V + -- let d = numberCategory 2 + -- let f = completeDiagram Diagram{src=c,tgt=d,omap=weakMap [(VA,2),(VB,1),(VC,1)],mmap=weakMap [(VF,IsSmallerThan 1 2),(VG,IsSmallerThan 1 2)]} + let c = Parallel + let d = discreteCategory (set "A") + let f = completeDiagram Diagram{src=d,tgt=c,omap=weakMap [('A',ParallelA)],mmap = Map.empty} + diagToPdf f "OutputGraphViz/Examples/Functors/DataMigration/functor" + + let universe = ens $ set [set[], set [1 :: Int,2], set [1]] + let anInstance = completeDiagram Diagram{src=d,tgt=universe,omap=weakMap [('A',set [1])],mmap=Map.empty} + diagToPdf anInstance "OutputGraphViz/Examples/Functors/DataMigration/anInstance" + diagToPdf2 anInstance "OutputGraphViz/Examples/Functors/DataMigration/anInstance2" + + let pii = (piFunctor universe f) + diagToPdf (pii ->$ anInstance) "OutputGraphViz/Examples/Functors/DataMigration/pi_anInstance1" + diagToPdf2 (pii ->$ anInstance) "OutputGraphViz/Examples/Functors/DataMigration/pi_anInstance2" + putStrLn $ show (pii ->$ anInstance) + + let sigmaa = (sigmaFunctor universe f) + diagToPdf (sigmaa ->$ anInstance) "OutputGraphViz/Examples/Functors/DataMigration/sigma_anInstance1" + diagToPdf2 (sigmaa ->$ anInstance) "OutputGraphViz/Examples/Functors/DataMigration/sigma_anInstance2" + putStrLn $ show (sigmaa ->$ anInstance) + + putStrLn "End of Math.Functors.DataMigration.Example"
+ src/Math/Functors/DiagonalFunctor.hs view
@@ -0,0 +1,42 @@+{-# LANGUAGE MonadComprehensions, MultiParamTypeClasses #-} +{-| Module : FiniteCategories +Description : Diagonal functor. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +The diagonal functor sends each object to the constant functor on this object. +-} + +module Math.Functors.DiagonalFunctor +( + diagonalFunctor, +) +where + 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 Math.FiniteCategory + import Math.Categories.FunctorCategory + + -- | Given two categories /J/ and /C/, return the diagonal functor /C/ -> /C/^/J/. + -- + -- Let /J/ and /C/ be two categories, we consider the functor category /C/^/J/. + -- The diagonal functor /D/ : /C/ -> /C/^/J/ maps each object /x/ of /C/ to the constant diagram /D_x/ from /J/ to /C/. + -- It maps each morphism to the natural transformation between the two constant diagrams associated to the source and the target of the morphism. + diagonalFunctor :: (FiniteCategory c1 m1 o1, Morphism m1 o1, + FiniteCategory c2 m2 o2, Morphism m2 o2) => + c1 -- ^ /J/ + -> c2 -- ^ /C/ + -> Diagram c2 m2 o2 (FunctorCategory c1 m1 o1 c2 m2 o2) (NaturalTransformation c1 m1 o1 c2 m2 o2) (Diagram c1 m1 o1 c2 m2 o2) -- ^ /D/ : /C/ -> /C/^/J/ + diagonalFunctor j c = Diagram{src=c + , tgt=FunctorCategory j c + , omap=memorizeFunction (constantDiagram j c) (ob c) + , mmap=memorizeFunction (\f -> unsafeNaturalTransformation (constantDiagram j c (source f)) (constantDiagram j c (target f)) (memorizeFunction (\x->f) (ob j))) (arrows c)} +
+ src/Math/Functors/DiagonalFunctor/Example.hs view
@@ -0,0 +1,38 @@+{-| Module : FiniteCategories +Description : An exemple of a 'diagonalFunctor' exported with GraphViz. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +An exemple of 'diagonalFunctor' exported with GraphViz. + +Export a diagonal functor in the directory "OutputGraphViz\/Examples\/Functor\/DiagonalFunctor". +-} +module Math.Functors.DiagonalFunctor.Example +( + main +) +where + import Math.FiniteCategory + import Math.FiniteCategories.DiscreteCategory + import Math.FiniteCategories.V + import Math.Functors.DiagonalFunctor + import Math.IO.FiniteCategories.ExportGraphViz + + 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 + + -- | An exemple of 'diagonalFunctor' exported with GraphViz. + main :: IO () + main = do + putStrLn "Start of Math.Functors.DiagonalFunctor.Example" + catToPdf (discreteCategory (set [1 :: Int,2])) "OutputGraphViz/Examples/Functors/DiagonalFunctor/indexing" + catToPdf V "OutputGraphViz/Examples/Functors/DiagonalFunctor/target" + diagToPdf2 (diagonalFunctor (discreteCategory (set [1 :: Int,2])) V) "OutputGraphViz/Examples/Functors/DiagonalFunctor/diagonalFunctor" + putStrLn "End of Math.Functors.DiagonalFunctor.Example"
+ src/Math/Functors/Examples.hs view
@@ -0,0 +1,31 @@+{-| Module : FiniteCategories +Description : Run all functors examples. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +Run all functors examples. See results in the folder "OutputGraphViz\/Examples\/Functors". +-} + +module Math.Functors.Examples +( + main +) +where + import qualified Math.Functors.SetValued.Example as SetValued + import qualified Math.Functors.Adjunction.Example as Adjunction + import qualified Math.Functors.DiagonalFunctor.Example as DiagonalFunctor + import qualified Math.Functors.DataMigration.Example as DataMigration + import qualified Math.Functors.KanExtension.Example as KanExtension + import qualified Math.Functors.YonedaEmbedding.Example as Yoneda + + -- | Run all examples of the project. See results in the folder OutputGraphViz. + main = do + SetValued.main + KanExtension.main + DataMigration.main + Adjunction.main + DiagonalFunctor.main + Yoneda.main
+ src/Math/Functors/KanExtension.hs view
@@ -0,0 +1,161 @@+{-# LANGUAGE MonadComprehensions, MultiParamTypeClasses #-} +{-| Module : FiniteCategories +Description : Kan extensions for arbitrary functors. +Copyright : Guillaume Sabbagh 2023 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +Kan extensions for arbitrary functors. See 'Math.Functors.SetValued' for Kan extensions for set-valued functors. +-} + +module Math.Functors.KanExtension +( + leftKan, + rightKan, +) +where + 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 Math.FiniteCategory + import Math.Categories.FunctorCategory + import Math.Categories.CommaCategory + + + -- | KanObject is either a functor X : A -> C or a functor to be precomposed called RL : B -> C (R or L). + data KanObject c1 m1 o1 c2 m2 o2 c3 m3 o3 = X (Diagram c1 m1 o1 c3 m3 o3) | RL (Diagram c2 m2 o2 c3 m3 o3) deriving (Eq, Show) + + -- | RightKanMorphism is a natural transformation Delta between functors to be precomposed or a natural transformation Mu to X. + data RightKanMorphism c1 m1 o1 c2 m2 o2 c3 m3 o3 = Delta (NaturalTransformation c2 m2 o2 c3 m3 o3) (Diagram c1 m1 o1 c2 m2 o2) | Mu (NaturalTransformation c1 m1 o1 c3 m3 o3) deriving (Eq, Show) + + instance (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2, + Category c3 m3 o3, Morphism m3 o3, Eq c3, Eq m3, Eq o3) => + Morphism (RightKanMorphism c1 m1 o1 c2 m2 o2 c3 m3 o3) (KanObject c1 m1 o1 c2 m2 o2 c3 m3 o3) where + (@?) (Delta nat1 diag1) (Delta nat2 diag2) + | diag1 == diag2 = (\x -> Delta x diag1) <$> (nat1 @? nat2) + | otherwise = Nothing + (@?) (Mu nat2) (Delta nat1 diag) = Mu <$> (nat2 @? (nat1 <=@<- diag)) + (@?) (Mu nat1) (Mu nat2) = Mu <$> (nat1 @? nat2) + (@?) _ _ = Nothing + + source (Delta nat _) = RL (source nat) + source (Mu nat) = X (source nat) + + target (Delta nat _) = RL (target nat) + target (Mu nat) = X (target nat) + + -- | RightKanCategory is the category in which we want to take a comma category to find the terminal object. + data RightKanCategory c1 m1 o1 c2 m2 o2 c3 m3 o3 = RightKanCategory (Diagram c1 m1 o1 c2 m2 o2) (Diagram c1 m1 o1 c3 m3 o3) deriving (Eq, Show) + + instance (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2, + Category c3 m3 o3, Morphism m3 o3, Eq c3, Eq m3, Eq o3) => + Category (RightKanCategory c1 m1 o1 c2 m2 o2 c3 m3 o3) (RightKanMorphism c1 m1 o1 c2 m2 o2 c3 m3 o3) (KanObject c1 m1 o1 c2 m2 o2 c3 m3 o3) where + identity (RightKanCategory _ _) (X diag) = Mu (identity (FunctorCategory (src diag) (tgt diag)) diag) + identity (RightKanCategory f _) (RL diag) = Delta (identity (FunctorCategory (src diag) (tgt diag)) diag) f + + ar (RightKanCategory _ _) (X diag1) (X diag2) = Mu <$> ar (FunctorCategory (src diag1) (tgt diag1)) diag1 diag2 + ar (RightKanCategory f _) (RL diag1) (RL diag2) = (\x -> Delta x f) <$> ar (FunctorCategory (src diag1) (tgt diag1)) diag1 diag2 + ar (RightKanCategory f _) (RL diag1) (X diag2) = Mu <$> ar (FunctorCategory (src diag2) (tgt diag2)) (diag1 <-@<- f) diag2 + ar (RightKanCategory _ _) (X _) (RL _) = set [] + + instance (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2, + FiniteCategory c3 m3 o3, Morphism m3 o3, Eq c3, Eq m3, Eq o3) => + FiniteCategory (RightKanCategory c1 m1 o1 c2 m2 o2 c3 m3 o3) (RightKanMorphism c1 m1 o1 c2 m2 o2 c3 m3 o3) (KanObject c1 m1 o1 c2 m2 o2 c3 m3 o3) where + + ob (RightKanCategory f x) = Set.insert (X x) (RL <$> ob (FunctorCategory (tgt f) (tgt x))) + + + -- | Right Kan extension for two arbitrary functors. + + -- rightKan f x is the right Kan extension of x along f. + rightKan :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2, + FiniteCategory c3 m3 o3, Morphism m3 o3, Eq c3, Eq m3, Eq o3) => + Diagram c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 c3 m3 o3 -> Maybe (Diagram c2 m2 o2 c3 m3 o3, NaturalTransformation c1 m1 o1 c3 m3 o3) + rightKan f x = if Set.null terminals then Nothing else Just (terminalFunctor, terminalNat) + where + kanCat = RightKanCategory f x + functCat = FunctorCategory (tgt f) (tgt x) + t = Diagram{src=functCat, tgt=kanCat, omap=memorizeFunction RL (ob functCat), mmap = memorizeFunction (\x -> Delta x f) (arrows functCat)} + commaCat = CommaCategory{leftDiagram=t, rightDiagram=selectObject kanCat (X x)} + terminals = terminalObjects commaCat + aTerminal = anElement terminals + terminalFunctor = indexSource aTerminal + Mu terminalNat = selectedArrow aTerminal + + + + + + + + -- | LeftKanMorphism is a natural transformation Sigma between functors to be precomposed or a natural transformation Alpha from X. + data LeftKanMorphism c1 m1 o1 c2 m2 o2 c3 m3 o3 = Sigma (NaturalTransformation c2 m2 o2 c3 m3 o3) (Diagram c1 m1 o1 c2 m2 o2) | Alpha (NaturalTransformation c1 m1 o1 c3 m3 o3) deriving (Eq, Show) + + instance (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2, + Category c3 m3 o3, Morphism m3 o3, Eq c3, Eq m3, Eq o3) => + Morphism (LeftKanMorphism c1 m1 o1 c2 m2 o2 c3 m3 o3) (KanObject c1 m1 o1 c2 m2 o2 c3 m3 o3) where + (@?) (Sigma nat1 diag1) (Sigma nat2 diag2) + | diag1 == diag2 = (\x -> Sigma x diag1) <$> (nat1 @? nat2) + | otherwise = Nothing + (@?) (Sigma nat1 diag) (Alpha nat2) = Alpha <$> ((nat1 <=@<- diag) @? nat2) + (@?) (Alpha nat1) (Alpha nat2) = Alpha <$> (nat1 @? nat2) + (@?) _ _ = Nothing + + source (Sigma nat _) = RL (source nat) + source (Alpha nat) = X (source nat) + + target (Sigma nat _) = RL (target nat) + target (Alpha nat) = X (target nat) + + -- | LeftKanCategory is the category in which we want to take a comma category to find the initial object. + data LeftKanCategory c1 m1 o1 c2 m2 o2 c3 m3 o3 = LeftKanCategory (Diagram c1 m1 o1 c2 m2 o2) (Diagram c1 m1 o1 c3 m3 o3) deriving (Eq, Show) + + instance (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2, + Category c3 m3 o3, Morphism m3 o3, Eq c3, Eq m3, Eq o3) => + Category (LeftKanCategory c1 m1 o1 c2 m2 o2 c3 m3 o3) (LeftKanMorphism c1 m1 o1 c2 m2 o2 c3 m3 o3) (KanObject c1 m1 o1 c2 m2 o2 c3 m3 o3) where + identity (LeftKanCategory _ _) (X diag) = Alpha (identity (FunctorCategory (src diag) (tgt diag)) diag) + identity (LeftKanCategory f _) (RL diag) = Sigma (identity (FunctorCategory (src diag) (tgt diag)) diag) f + + ar (LeftKanCategory _ _) (X diag1) (X diag2) = Alpha <$> ar (FunctorCategory (src diag1) (tgt diag1)) diag1 diag2 + ar (LeftKanCategory f _) (RL diag1) (RL diag2) = (\x -> Sigma x f) <$> ar (FunctorCategory (src diag1) (tgt diag1)) diag1 diag2 + ar (LeftKanCategory f _) (X diag2) (RL diag1)= Alpha <$> ar (FunctorCategory (src diag2) (tgt diag2)) diag2 (diag1 <-@<- f) + ar _ _ _ = set [] + + instance (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2, + FiniteCategory c3 m3 o3, Morphism m3 o3, Eq c3, Eq m3, Eq o3) => + FiniteCategory (LeftKanCategory c1 m1 o1 c2 m2 o2 c3 m3 o3) (LeftKanMorphism c1 m1 o1 c2 m2 o2 c3 m3 o3) (KanObject c1 m1 o1 c2 m2 o2 c3 m3 o3) where + + ob (LeftKanCategory f x) = Set.insert (X x) (RL <$> ob (FunctorCategory (tgt f) (tgt x))) + + + -- | Left Kan extension for two arbitrary functors. + + -- leftKan f x is the left Kan extension of x along f. + leftKan :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq c2, Eq m2, Eq o2, + FiniteCategory c3 m3 o3, Morphism m3 o3, Eq c3, Eq m3, Eq o3) => + Diagram c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 c3 m3 o3 -> Maybe (Diagram c2 m2 o2 c3 m3 o3, NaturalTransformation c1 m1 o1 c3 m3 o3) + leftKan f x = if Set.null initials then Nothing else Just (initialFunctor, initialNat) + where + kanCat = LeftKanCategory f x + functCat = FunctorCategory (tgt f) (tgt x) + t = Diagram{src=functCat, tgt=kanCat, omap=memorizeFunction RL (ob functCat), mmap = memorizeFunction (\x -> Sigma x f) (arrows functCat)} + commaCat = CommaCategory{leftDiagram=selectObject kanCat (X x), rightDiagram=t} + initials = initialObjects commaCat + aInitial = anElement initials + initialFunctor = indexTarget aInitial + Alpha initialNat = selectedArrow aInitial +
+ src/Math/Functors/KanExtension/Example.hs view
@@ -0,0 +1,64 @@+{-| Module : FiniteCategories +Description : Examples of Kan extensions exported with GraphViz. +Copyright : Guillaume Sabbagh 2023 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +Examples of Kan extensions exported with GraphViz. + +Export extensions in the directory "OutputGraphViz\/Examples\/Functor\/KanExtension". +-} +module Math.Functors.KanExtension.Example +( + main +) +where + import Math.FiniteCategory + import Math.FiniteCategories + import Math.Functors.KanExtension + import Math.IO.FiniteCategories.ExportGraphViz + + 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 + + -- | Examples of Kan extensions exported with GraphViz. + main :: IO () + main = do + putStrLn "Start of Math.Functors.KanExtension.Example" + let d1 = (setToList $ ob (FunctorCategory (numberCategory 2) (numberCategory 4)))!! 3 + let d2 = (setToList $ ob (FunctorCategory (numberCategory 2) (numberCategory 3)))!! 2 + diagToPdf2 d1 "OutputGraphViz/Examples/Functors/KanExtension/F" + diagToPdf2 d2 "OutputGraphViz/Examples/Functors/KanExtension/X" + let Just (lk,lknat) = (leftKan d1 d2) + diagToPdf2 lk "OutputGraphViz/Examples/Functors/KanExtension/Lan_F(X)" + natToPdf lknat "OutputGraphViz/Examples/Functors/KanExtension/EtaLan_F(X)" + let Just (rk,rknat) = (rightKan d1 d2) + diagToPdf2 rk "OutputGraphViz/Examples/Functors/KanExtension/Ran_F(X)" + natToPdf rknat "OutputGraphViz/Examples/Functors/KanExtension/RhoRan_F(X)" + + let a = unsafeReadSCGString "2\nA\n" + catToPdf a "OutputGraphViz/Examples/Functors/KanExtension/NotPointwise/A" + let b = unsafeReadSCGString "2\nA -f-> B\n" + catToPdf b "OutputGraphViz/Examples/Functors/KanExtension/NotPointwise/B" + let c = unsafeReadSCGString "2\nA -f-> B -g-> A = <ID>\nB -g-> A -f-> B = <ID>\n" + catToPdf c "OutputGraphViz/Examples/Functors/KanExtension/NotPointwise/C" + let f = unsafeReadSCGDString "<SRC>\n2\nA\n</SRC>\n<TGT>\n2\nA -f-> B -g-> A = <ID>\nB -g-> A -f-> B = <ID>\n</TGT>\nA => A" + diagToPdf2 f "OutputGraphViz/Examples/Functors/KanExtension/NotPointwise/F" + let g = unsafeReadSCGDString "<SRC>\n2\nA\n</SRC>\n<TGT>\n2\nA -f-> B\n</TGT>\nA => A" + diagToPdf2 g "OutputGraphViz/Examples/Functors/KanExtension/NotPointwise/G" + + let Just (lk,lknat) = (leftKan f g) + diagToPdf2 lk "OutputGraphViz/Examples/Functors/KanExtension/NotPointwise/Lan_F(G)" + natToPdf lknat "OutputGraphViz/Examples/Functors/KanExtension/NotPointwise/EtaLan_F(G)" + + let Just (rk,rknat) = (rightKan f g) + diagToPdf2 rk "OutputGraphViz/Examples/Functors/KanExtension/NotPointwise/Ran_F(G)" + natToPdf rknat "OutputGraphViz/Examples/Functors/KanExtension/NotPointwise/EpsilonLan_F(G)" + + putStrLn "End of Math.Functors.KanExtension.Example"
+ src/Math/Functors/SetValued.hs view
@@ -0,0 +1,185 @@+{-# LANGUAGE MonadComprehensions, MultiParamTypeClasses #-} +{-| Module : FiniteCategories +Description : Utility functions for set-valued functors. +Copyright : Guillaume Sabbagh 2023 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +Kan extensions for set-valued functors. Inspired by DBC of M. Fleming, R. Gunther, R. Rosebrugh. +-} + +module Math.Functors.SetValued +( + -- * Right Kan extension + LimitObject(..), + rightKanSetValued, + -- ** Formatting + formatLimitObject, + formatSetOfLimitObjects, + formatFunctionOfLimitObjects, + -- * Left Kan extension + ColimitObject(..), + leftKanSetValued, + -- ** Formatting + formatColimitObject, + formatSetOfColimitObjects, + formatFunctionOfColimitObjects, +) +where + 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 (intercalate) + + import Math.FiniteCategory + import Math.Categories.FinSet + import Math.Categories.FunctorCategory + import Math.Categories.CommaCategory + import Math.FiniteCategories.One + import Math.IO.PrettyPrint + + -- | A 'LimitObject' is a map from a comma object to an element a, the maps should be seen as elements of the cartesian products indexed by comma objects. + type LimitObject o1 m2 a = Map (CommaObject One o1 m2) a + + -- | Format a 'LimitObject' to be readable. + formatLimitObject :: (Eq o1, Eq m2, Eq a, PrettyPrint a) => LimitObject o1 m2 a -> String + formatLimitObject mapping = "(" ++ intercalate "," [ (pprint v) | (k,v) <- Map.mapToList mapping] ++ ")" + + -- | Format a set of 'LimitObject's to be readable. + formatSetOfLimitObjects :: (Eq o1, Eq m2, Eq a, PrettyPrint a) => Set (LimitObject o1 m2 a) -> String + formatSetOfLimitObjects setOfMaps = "{" ++ intercalate "," (formatLimitObject <$> setToList setOfMaps) ++ "}" + + -- | Format a 'LimitObject' to be readable. + formatFunctionOfLimitObjects :: (Eq o1, Eq m2, Eq a, PrettyPrint a) => Function (LimitObject o1 m2 a) -> String + formatFunctionOfLimitObjects func = intercalate "," [(formatLimitObject k) ++ " -> " ++ (formatLimitObject v) | (k,v) <- (Map.mapToList (function func))] + + -- | Compute the image of the right Kan extension on an object of /B/. The image is a set of maps from the comma objects to elements a (you should see the maps as cartesian products indexed by comma objects). + rightKanSetValuedObjectwise :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2, + Eq a) => + Diagram c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 (FinSet a) (Function a) (Set a) -> o2 -> Set (LimitObject o1 m2 a) + rightKanSetValuedObjectwise f x b = filteredMaps + where + commaCat = CommaCategory{leftDiagram=selectObject (tgt f) b, rightDiagram=f} + allMaps = weakMap <$> (cartesianProductOfSets.setToList $ [[(a, elemXa) | elemXa <- (x ->$ (indexTarget a))] | a <- ob commaCat]) + filters = [\mapping -> ((x ->£(indexSecondArrow m)) ||!|| (mapping |!| (source m))) == (mapping |!| (target m)) | m <- setToList $ arrows commaCat] + filteredMaps = foldr Set.filter allMaps filters + + -- | Compute the image of the right Kan extension on a morphism of /B/. + rightKanSetValuedObjectwiseMorphism :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2, + Eq a) => + Diagram c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 (FinSet a) (Function a) (Set a) -> m2 -> Function (LimitObject o1 m2 a) + rightKanSetValuedObjectwiseMorphism f x m = result + where + precompose commaObj = unsafeCommaObject (indexSource commaObj) (indexTarget commaObj) ((selectedArrow commaObj) @ m) + imageSrc = rightKanSetValuedObjectwise f x (source m) + imageTgt = rightKanSetValuedObjectwise f x (target m) + commaCat2 = CommaCategory{leftDiagram=selectObject (tgt f) (target m), rightDiagram=f} + subsetIndexingObjects = ob commaCat2 + result = Function{function=weakMapFromSet [(mapping,anElement [mapping2 | mapping2 <- imageTgt, Map.isSubmapOf (Map.mapKeys precompose mapping2) mapping]) | mapping <- imageSrc], + codomain=imageTgt} + + -- | The right Kan extension of @X@ along @F@ where @X@ is a a set-valued functor. + -- + -- We transform the @X@ functor so that its target becomes @(FinSet (Map (CommaObject One o1 m2) a))@, each object @A@ of @c1@ is mapped to @{Delta : {<One,id,A>} -> e | e <- X(A)}@. + rightKanSetValued :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2, + Eq a) => + Diagram c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 (FinSet a) (Function a) (Set a) -> (Diagram c2 m2 o2 (FinSet (LimitObject o1 m2 a)) (Function (LimitObject o1 m2 a)) (Set (LimitObject o1 m2 a)), NaturalTransformation c1 m1 o1 (FinSet (LimitObject o1 m2 a)) (Function (LimitObject o1 m2 a)) (Set (LimitObject o1 m2 a))) + rightKanSetValued f x = (r,nat) + where + r = Diagram{src=tgt f,tgt=FinSet, omap=memorizeFunction (rightKanSetValuedObjectwise f x) (ob (tgt f)), mmap=memorizeFunction (rightKanSetValuedObjectwiseMorphism f x) (arrows (tgt f))} + rof = r <-@<- f + transformAIntoMap k a = weakMap [(unsafeCommaObject One k (identity (tgt f) (f ->$ k)), a)] + transformSetOfAIntoSetOfMap k v = [transformAIntoMap k e | e <- v] + transformFunctionOfAIntoFunctionOfMaps m1 func = Function{function=weakMap [(transformAIntoMap (source m1) t,transformAIntoMap (target m1) u) | (t,u) <- Map.mapToList (function func)], codomain=transformSetOfAIntoSetOfMap (target m1) (codomain func)} + newX = Diagram{src=src x, tgt=FinSet, omap=Map.mapWithKey transformSetOfAIntoSetOfMap (omap x), mmap=Map.mapWithKey transformFunctionOfAIntoFunctionOfMaps (mmap x)} + Right nat = naturalTransformation rof newX (weakMapFromSet [(o,Function{function=weakMapFromSet [(mapping,transformAIntoMap o ((snd.anElement) (Set.filter (\y -> (indexTarget.fst) y == o) (Map.mapToSet mapping))) ) | mapping <- (rof ->$ o)], codomain=newX ->$ o }) | o <- ob (src f)]) + + + + + + + + + + + + + + + + -- | A 'ColimitObject' is a set of couples (comma objects, elements a), the couples should be seen as elements of a disjoint union, the set of couples as equivalence classes of elements of a disjoint union. + type ColimitObject o1 m2 a = Set ((CommaObject o1 One m2), a) + + -- | Format a 'ColimitObject' to be readable. + formatColimitObject :: (PrettyPrint a) => ColimitObject o1 m2 a -> String + formatColimitObject = pprint.snd.anElement + + -- | Format a set of 'ColimitObject's to be readable. + formatSetOfColimitObjects :: (Eq o1, Eq m2, Eq a, PrettyPrint a) => Set (ColimitObject o1 m2 a) -> String + formatSetOfColimitObjects setOfEquivClasses = "{" ++ intercalate "," (formatColimitObject <$> setToList setOfEquivClasses) ++ "}" + + -- | Format a 'ColimitObject' to be readable. + formatFunctionOfColimitObjects :: (Eq o1, Eq m2, Eq a, PrettyPrint a) => Function (ColimitObject o1 m2 a) -> String + formatFunctionOfColimitObjects func = intercalate "," [(formatColimitObject k) ++ " -> " ++ (formatColimitObject v) | (k,v) <- (Map.mapToList (function func))] + + transformGraphToEquivRelation :: (Eq a) => Set (a,a) -> Set a -> Set (Set a) + transformGraphToEquivRelation couples initialNodes = Set.foldr (\candidate clusters -> if Set.any (isIn candidate) clusters then clusters else (Set.insert (Set.insert candidate (dfs candidate [candidate] (setToList initialNodes))) clusters)) (set []) initialNodes + where + dfs node blacklist [] = set [] + dfs node blacklist (candidate:nodes) + | elem candidate blacklist = (dfs node blacklist nodes) + | (node,candidate) `isIn` couples || (candidate,node) `isIn` couples = Set.insert candidate ((dfs node blacklist nodes) ||| (dfs candidate (node:blacklist) (setToList initialNodes))) + | otherwise = (dfs node blacklist nodes) + + -- | Compute the image of the left Kan extension on an object of /B/. The image is a set of set of couples (comma objects, elements a) (you should see the couples as element of a disjoint union, the set of couples as equivalence classes of elements). + leftKanSetValuedObjectwise :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2, + Eq a) => + Diagram c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 (FinSet a) (Function a) (Set a) -> o2 -> Set (ColimitObject o1 m2 a) + leftKanSetValuedObjectwise f x b = equivClasses + where + commaCat = CommaCategory{leftDiagram=f, rightDiagram=selectObject (tgt f) b} + allCouples = ((Set.unions).setToList $ [[(a, elemXa) | elemXa <- (x ->$ (indexSource a))] | a <- ob commaCat]) + graphRelations = Set.unions [[((source m,a),(target m,b)) | (a,b) <- (Map.mapToSet (function (x ->£(indexFirstArrow m))))] | m <- (setToList (arrows commaCat)), not (isIdentity commaCat m)] + equivClasses = transformGraphToEquivRelation graphRelations allCouples + + -- | Compute the image of the left Kan extension on a morphism of /B/. + leftKanSetValuedObjectwiseMorphism :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2, + Eq a) => + Diagram c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 (FinSet a) (Function a) (Set a) -> m2 -> Function (ColimitObject o1 m2 a) + leftKanSetValuedObjectwiseMorphism f x m = result + where + postcompose commaObj = unsafeCommaObject (indexSource commaObj) (indexTarget commaObj) (m @ (selectedArrow commaObj)) + imageSrc = leftKanSetValuedObjectwise f x (source m) + imageTgt = leftKanSetValuedObjectwise f x (target m) + result = Function{function=weakMapFromSet [(equivClass1, anElement [equivClass2 | equivClass2 <- imageTgt, Set.any (\(co, a) -> (postcompose co, a) `isIn` equivClass2) equivClass1 ]) | equivClass1 <- imageSrc], + codomain=imageTgt} + + -- | The left Kan extension of @X@ along @F@ where @X@ is a a set-valued functor. + -- + -- We transform the @X@ functor so that its target becomes @(FinSet (Set ((CommaObject One o1 m2), a)))@, each object @A@ of @c1@ is mapped to @{(<One,id,A>},e) | e <- X(A)}@. + leftKanSetValued :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq c1, Eq m1, Eq o1, + FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2, + Eq a) => + Diagram c1 m1 o1 c2 m2 o2 -> Diagram c1 m1 o1 (FinSet a) (Function a) (Set a) -> (Diagram c2 m2 o2 (FinSet (ColimitObject o1 m2 a)) (Function (ColimitObject o1 m2 a)) (Set (ColimitObject o1 m2 a)), NaturalTransformation c1 m1 o1 (FinSet (ColimitObject o1 m2 a)) (Function (ColimitObject o1 m2 a)) (Set (ColimitObject o1 m2 a))) + leftKanSetValued f x = (l,nat) + where + l = Diagram{src=tgt f,tgt=FinSet, omap=memorizeFunction (leftKanSetValuedObjectwise f x) (ob (tgt f)), mmap=memorizeFunction (leftKanSetValuedObjectwiseMorphism f x) (arrows (tgt f))} + lof = l <-@<- f + transformAIntoEquivClass k a = set [(unsafeCommaObject k One (identity (tgt f) (f ->$ k)), a)] + transformSetOfAIntoSetOfEquivClasses k v = [transformAIntoEquivClass k e | e <- v] + transformFunctionOfAIntoFunctionOfSetsOfEquivClasses m1 func = Function{function=weakMap [(transformAIntoEquivClass (source m1) t,transformAIntoEquivClass (target m1) u) | (t,u) <- Map.mapToList (function func)], codomain=transformSetOfAIntoSetOfEquivClasses (target m1) (codomain func)} + newX = Diagram{src=src x, tgt=FinSet, omap=Map.mapWithKey transformSetOfAIntoSetOfEquivClasses (omap x), mmap=Map.mapWithKey transformFunctionOfAIntoFunctionOfSetsOfEquivClasses (mmap x)} + Right nat = naturalTransformation newX lof (weakMapFromSet [(o,Function{function=weakMapFromSet [(equivClass,anElement [equivClass2 | equivClass2 <- (lof ->$ o), Set.any (\(co,a2) -> indexSource co == o && (snd.anElement $ equivClass) == a2) equivClass2]) | equivClass <- (newX ->$ o)], codomain=lof ->$ o }) | o <- ob (src f)]) + +
+ src/Math/Functors/SetValued/Example.hs view
@@ -0,0 +1,53 @@+{-| Module : FiniteCategories +Description : Examples of Kan extensions of set-valued functors exported with GraphViz. +Copyright : Guillaume Sabbagh 2023 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +Examples of Kan extensions of set-valued functors exported with GraphViz. + +Export extensions in the directory "OutputGraphViz\/Examples\/Functor\/SetValued". +-} +module Math.Functors.SetValued.Example +( + main +) +where + import Math.FiniteCategory + import Math.FiniteCategories + import Math.Categories.FinSet + import Math.Functors.SetValued + import Math.IO.FiniteCategories.ExportGraphViz + + 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.Text (pack) + + -- | Examples of Kan extensions of set-valued functors exported with GraphViz. + main :: IO () + main = do + putStrLn "Start of Math.Functors.SetValued.Example" + let c1 = unsafeReadSCGString "2\nA -f-> B\n" + catToPdf c1 "OutputGraphViz/Examples/Functors/SetValued/A" + let c2 = unsafeReadSCGString "2\nA -f-> B -g-> A = <ID>\nB -g-> A -f-> B = <ID>\n" + catToPdf c2 "OutputGraphViz/Examples/Functors/SetValued/B" + let f = unsafeReadSCGDString "<SRC>\n2\nA -f-> B\n</SRC>\n<TGT>\n2\nA -f-> B -g-> A = <ID>\nB -g-> A -f-> B = <ID>\n</TGT>\nA -f-> B => A -f-> B\n" + diagToPdf2 f "OutputGraphViz/Examples/Functors/SetValued/F" + let x = completeDiagram Diagram{src=c1,tgt=FinSet,omap=weakMap [(pack "A",set [0,1 :: Int]),(pack "B", set [2,3,4])], mmap=weakMap [(anElement (genAr c1 (pack "A") (pack "B")),Function{function=weakMap [(0,2),(1,2)], codomain = set [2,3,4]})]} + diagToPdf2 (fullDiagram2 x) "OutputGraphViz/Examples/Functors/SetValued/X" + let (ran, epsilon) = rightKanSetValued f x + diagToPdf (fullDiagram2 ran) "OutputGraphViz/Examples/Functors/SetValued/Ran2" + diagToPdf2Format (fullDiagram2 ran) formatSetOfLimitObjects formatFunctionOfLimitObjects "OutputGraphViz/Examples/Functors/SetValued/Ran" + natToPdfFormat (fullNaturalTransformation2 epsilon) formatSetOfLimitObjects formatFunctionOfLimitObjects "OutputGraphViz/Examples/Functors/SetValued/Epsilon" + let (lan, eta) = leftKanSetValued f x + diagToPdf (fullDiagram2 lan) "OutputGraphViz/Examples/Functors/SetValued/Lan2" + diagToPdf2Format (fullDiagram2 lan) formatSetOfColimitObjects formatFunctionOfColimitObjects "OutputGraphViz/Examples/Functors/SetValued/Lan" + natToPdfFormat (fullNaturalTransformation2 eta) formatSetOfColimitObjects formatFunctionOfColimitObjects "OutputGraphViz/Examples/Functors/SetValued/Eta" + putStrLn "End of Math.Functors.SetValued.Example"
+ src/Math/Functors/YonedaEmbedding/Example.hs view
@@ -0,0 +1,31 @@+{-| Module : FiniteCategories +Description : An example of 'yonedaEmbedding' exported with GraphViz. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +An example of 'yonedaEmbedding' exported with GraphViz. + +Export the diagram in the directory "OutputGraphViz\/Examples\/Functors\/YonedaEmbedding". +-} +module Math.Functors.YonedaEmbedding.Example +( + main +) +where + import Data.WeakSet (Set) + import Data.WeakSet.Safe + + import Math.FiniteCategories + import Math.Categories + import Math.IO.FiniteCategories.ExportGraphViz + + -- | 'yonedaEmbedding' exported with GraphViz. + main :: IO () + main = do + putStrLn "Start of Math.FiniteCategories.YonedaEmbedding.Example" + diagToPdf2 (fullDiagram.yonedaEmbedding $ Hat) "OutputGraphViz/Examples/FiniteCategories/YonedaEmbedding/YonedaEmbeddingHat" + diagToPdf2 (fullDiagram.yonedaEmbedding $ Square) "OutputGraphViz/Examples/FiniteCategories/YonedaEmbedding/YonedaEmbeddingSquare" + putStrLn "End of Math.FiniteCategories.YonedaEmbedding.Example"
+ src/Math/IO/FiniteCategories/ExportGraphViz.hs view
@@ -0,0 +1,487 @@+{-# LANGUAGE MonadComprehensions #-} + +{-| Module : FiniteCategories +Description : Visualize finite categories with GraphViz. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +This module is a way of exporting finite categories with GraphViz. + +Every function assumes that the 'FiniteCategory' is a 'FiniteCategory', if you want to export a category without implementing an instantiation of 'FiniteCategory', you can instantiate 'FiniteCategory' with the default functions 'defaultGenAr' and 'defaultDecompose'. +-} + +module Math.IO.FiniteCategories.ExportGraphViz +( + -- * Visualize categories + categoryToGraph, + catToDot, + catToPdf, + genToDot, + genToPdf, + categoryToGraphFormat, + catToDotFormat, + catToPdfFormat, + -- * Visualize diagrams + diagToDotCluster, + diagToPdfCluster, + diagToDot, + diagToPdf, + diagToDot2, + diagToPdf2, + diagToDot2Format, + diagToPdf2Format, + -- * Visualize natural transformations + natToDot, + natToPdf, + natToDotFormat, + natToPdfFormat, +) +where + import Math.FiniteCategory + import Math.FiniteCategories + import Math.IO.PrettyPrint + + import qualified Data.Text.Lazy as L (pack, Text) + import qualified Data.Text.Lazy.IO as IO (putStrLn, writeFile) + import Data.Graph.Inductive.Graph (mkGraph, Node, Edge, LNode, LEdge) + import Data.Graph.Inductive.PatriciaTree (Gr) + import Data.GraphViz (graphToDot, nonClusteredParams, fmtNode, fmtEdge, GraphvizParams(..), NodeCluster(..), blankParams,GraphID( Num ), Number(..)) + import Data.GraphViz.Attributes.Complete (Label(StrLabel), Attribute(Label)) + import Data.GraphViz.Attributes (X11Color(..), color) + import Data.GraphViz.Printing (renderDot, toDot) + import Data.Maybe (fromJust) + import Data.List (elemIndex,intercalate) + import Data.WeakSet.Safe + import qualified Data.WeakSet as Set + import Data.WeakMap.Safe + + import System.Process (callCommand) + import System.Directory (createDirectoryIfMissing) + import System.FilePath.Posix (takeDirectory) + + + + -- | Write lazy text to a file specified by a path, if the path leads to non existing directories, it creates the directories. Credits to wisn : https://stackoverflow.com/a/58685979 + createAndWriteFile :: FilePath -> L.Text -> IO () + createAndWriteFile path content = do + createDirectoryIfMissing True $ takeDirectory path + IO.writeFile path content + + -- | Transform an object of a category into a pure node. + objToNode :: (Eq o, FiniteCategory c m o) => c -> o -> Node + objToNode c o + | index == Nothing = error("Call objToNod on an object not in the category.") + | otherwise = i + where + Just i = index + index = elemIndex o (setToList.ob $ c) + + -- | Transform an object of a category into a labeled node. + objToLNode :: (Eq o, PrettyPrint o, FiniteCategory c m o) => c -> o -> LNode String + objToLNode c o = (objToNode c o, pprint o) + + -- | Transform an object of a category into a labeled node, using a custom function. + objToLNodeFormat :: (Eq o, FiniteCategory c m o) => c -> (o -> String) -> o -> LNode String + objToLNodeFormat c formatObj o = (objToNode c o, formatObj o) + + -- | Transform a morphism of a category into a pure edge. + arToEdge :: (Eq o, Morphism m o, FiniteCategory c m o) => c -> m -> Edge + arToEdge c m = ((objToNode c). source $ m, (objToNode c). target $ m) + + -- | Transform a morphism of a category into a labeled edge. + arToLEdge :: (Eq o, PrettyPrint o, PrettyPrint m, Morphism m o, FiniteCategory c m o) => c -> m -> LEdge String + arToLEdge c m = ((objToNode c). source $ m, (objToNode c). target $ m, pprint m) + + -- | Transform a morphism of a category into a labeled edge using a custom function. + arToLEdgeFormat :: (Eq o, Morphism m o, FiniteCategory c m o) => c -> (m -> String) -> m -> LEdge String + arToLEdgeFormat c formatMorph m = ((objToNode c). source $ m, (objToNode c). target $ m, formatMorph m) + + -- | Transform a category into an underlying inductive graph. + categoryToGraph :: (Eq o, PrettyPrint o, PrettyPrint m, Morphism m o, FiniteCategory c m o) => c -> Gr String String + categoryToGraph c = mkGraph (setToList (objToLNode c <$> (ob c))) (setToList (arToLEdge c <$> (arrows c))) + + -- | Transform a category into an underlying inductive graph using formatting functions. + categoryToGraphFormat :: (Eq o, Morphism m o, FiniteCategory c m o) => c -> (o -> String) -> (m -> String) -> Gr String String + categoryToGraphFormat c formatObj formatMorph = mkGraph (setToList (objToLNodeFormat c formatObj <$> (ob c))) (setToList (arToLEdgeFormat c formatMorph <$> (arrows c))) + + -- | Transform a dot representation of a graph into a pdf file. + dotToPdf :: IO () -> String -> IO () + dotToPdf dot path = dot >> callCommand ("dot "++path++" -o "++path++".pdf -T pdf") + + -- | Export a category with GraphViz. If the category is too large, use `genToDot` instead. + -- + -- The black arrows are generating arrows, grey one are generated arrows. + catToDot :: (Eq o, PrettyPrint o, PrettyPrint m, Morphism m o, FiniteCategory c m o) => c -> String -> IO () + catToDot c path = createAndWriteFile path $ renderDot $ toDot dot_file where + dot_file = graphToDot nonClusteredParams { fmtNode= \(n,label)-> [Label (StrLabel (L.pack label))], + fmtEdge= \(n1,n2,label)-> [Label (StrLabel (L.pack label)), + if label `isIn` generatorsLabels then color Black else color Gray80]} (categoryToGraph c) + generators = genArrows c + generatorsLabels = pprint <$> generators + + -- | Export a category with GraphViz, format the objects and the morphisms. If the category is too large, use `genToDot` instead. + -- + -- The black arrows are generating arrows, grey one are generated arrows. + catToDotFormat :: (Eq o, Morphism m o, FiniteCategory c m o) => c -> (o -> String) -> (m -> String) -> String -> IO () + catToDotFormat c formatObj formatMorph path = createAndWriteFile path $ renderDot $ toDot dot_file where + dot_file = graphToDot nonClusteredParams { fmtNode= \(n,label)-> [Label (StrLabel (L.pack label))], + fmtEdge= \(n1,n2,label)-> [Label (StrLabel (L.pack label)), + if label `isIn` generatorsLabels then color Black else color Gray80]} (categoryToGraphFormat c formatObj formatMorph) + generators = genArrows c + generatorsLabels = formatMorph <$> generators + + + -- | Export a category with GraphViz. If the category is too large, use `genToPdf` instead. + -- + -- The black arrows are generating arrows, grey one are generated arrows. + catToPdf :: (Eq o, PrettyPrint o, PrettyPrint m, Morphism m o, FiniteCategory c m o) => c -> String -> IO () + catToPdf c path = dotToPdf (catToDot c path) path + + -- | Export a category with GraphViz and format objects and arrows. If the category is too large, use `genToPdf` instead. + -- + -- The black arrows are generating arrows, grey one are generated arrows. + catToPdfFormat :: (Eq o, Morphism m o, FiniteCategory c m o) => c -> (o -> String) -> (m -> String) -> String -> IO () + catToPdfFormat c formatObj formatMorph path = dotToPdf (catToDotFormat c formatObj formatMorph path) path + + -- | Transforms a category into an inductive graph. + categoryToGeneratorGraph :: (Eq o, PrettyPrint o, PrettyPrint m, Morphism m o, FiniteCategory c m o) => c -> Gr String String + categoryToGeneratorGraph c = mkGraph (setToList (objToLNode c <$> (ob c))) (setToList (arToLEdge c <$> (genArrows c))) + + -- | Export the generator of a category with GraphViz. Use this when the category is too large to be fully exported. + genToDot :: (Eq o, PrettyPrint o, PrettyPrint m, Morphism m o, FiniteCategory c m o) => c -> String -> IO () + genToDot c path = createAndWriteFile path $ renderDot $ toDot dot_file where + dot_file = graphToDot nonClusteredParams { fmtNode= \(n,label)-> [Label (StrLabel (L.pack label))], + fmtEdge= \(n1,n2,label)-> [Label (StrLabel (L.pack label))]} (categoryToGeneratorGraph c) + + -- | Export the generator of a category with GraphViz. Use this when the category is to large to be fully exported. + genToPdf :: (Eq o, PrettyPrint o, PrettyPrint m, Morphism m o, FiniteCategory c m o) => c -> String -> IO () + genToPdf c path = dotToPdf (genToDot c path) path + + + -- __________________________________ + -- __________________________________ + -- + -- Diagram representation with cluster of objects mapped together + -- __________________________________ + -- __________________________________ + + + + -- | If the node is pair, then it is part of the source category, else it is part of the target category. + diagObjToNodeCluster :: (Eq o, FiniteCategory c m o) => c -> Bool -> o -> Node + diagObjToNodeCluster c b o + | index == Nothing = error("Call diagObjToNod on an object not in the category.") + | otherwise = if b then 2*i else 2*i+1 + where + Just i = index + index = elemIndex o (setToList (ob c)) + + diagObjToLNodeCluster :: (Eq o, PrettyPrint o, FiniteCategory c m o) => c -> Bool -> o -> LNode String + diagObjToLNodeCluster c b o = (diagObjToNodeCluster c b o, pprint o) + + diagArToEdgeCluster :: (Eq o, Morphism m o, FiniteCategory c m o) => c -> Bool -> m -> Edge + diagArToEdgeCluster c b m = ((diagObjToNodeCluster c b). source $ m, (diagObjToNodeCluster c b). target $ m) + + diagArToLEdgeCluster :: (Eq o, PrettyPrint o, PrettyPrint m, Morphism m o, FiniteCategory c m o) => c -> Bool -> m -> LEdge String + diagArToLEdgeCluster c b m = ((diagObjToNodeCluster c b). source $ m, (diagObjToNodeCluster c b). target $ m, pprint m) + + diagToGraphCluster :: (Eq c1, Eq o1, PrettyPrint o1, PrettyPrint m1, Morphism m1 o1, FiniteCategory c1 m1 o1, + Eq c2, Eq o2, PrettyPrint o2, PrettyPrint m2, Morphism m2 o2, FiniteCategory c2 m2 o2) => + Diagram c1 m1 o1 c2 m2 o2 -> Gr String String + diagToGraphCluster f = mkGraph (setToList ((diagObjToLNodeCluster (src f) True <$> (ob (src f))))++(setToList (diagObjToLNodeCluster (tgt f) False <$> (ob (tgt f))))) (setToList ((diagArToLEdgeCluster (src f) True <$> (genArrows (src f))))++(setToList (diagArToLEdgeCluster (tgt f) False <$> (genArrows (tgt f))))) + + -- | Export a functor with GraphViz such that the source category is in green, the target in blue, the objects mapped together are in the same cluster. + diagToDotCluster :: (Eq c1, Eq o1, PrettyPrint o1, PrettyPrint m1, Morphism m1 o1, FiniteCategory c1 m1 o1, + Eq c2, Eq o2, PrettyPrint o2, PrettyPrint m2, Morphism m2 o2, FiniteCategory c2 m2 o2) => + Diagram c1 m1 o1 c2 m2 o2 -> String -> IO () + diagToDotCluster f@Diagram{src=s,tgt=t,omap=om,mmap=fm} path = createAndWriteFile path $ renderDot $ toDot dot_file where + dot_file = graphToDot Params { + isDirected = True + ,globalAttributes = [] + ,clusterBy = (\(n,nl) -> if (n `mod` 2) == 0 then (C ((fromJust (elemIndex (om |!| ((setToList (ob s)) !! (n `div` 2))) (setToList (ob t))))) $ N (n,nl)) else (C (fromJust (elemIndex ((setToList (ob t)) !! (n `div` 2)) (setToList (ob t)))) $ N (n,nl))) + ,isDotCluster = const True + ,clusterID = Num . Int + ,fmtCluster = const [] + ,fmtNode = \(n,label)-> [Label (StrLabel (L.pack label)), if (n `mod` 2) == 0 then color Green else color Blue] + ,fmtEdge= \(n1,n2,label)-> [Label (StrLabel (L.pack label))] + } (diagToGraphCluster f) + + -- | Export a functor as a pdf with GraphViz such that the source category is in green, the target in blue, the objects mapped together are in the same cluster. + diagToPdfCluster :: (Eq c1, Eq o1, PrettyPrint o1, PrettyPrint m1, Morphism m1 o1, FiniteCategory c1 m1 o1, + Eq c2, Eq o2, PrettyPrint o2, PrettyPrint m2, Morphism m2 o2, FiniteCategory c2 m2 o2) => + Diagram c1 m1 o1 c2 m2 o2 -> String -> IO () + diagToPdfCluster f path = dotToPdf (diagToDotCluster f path) path + + + -- __________________________________ + -- __________________________________ + -- + -- Diagram representation with arrows between arrows + -- __________________________________ + -- __________________________________ + + indexAr :: (Morphism m o, FiniteCategory c m o, Eq o, Eq m) => c -> m -> Int + indexAr c m + | isIn m (arrows c) = fromJust $ elemIndex m (setToList (arrows c)) + | otherwise = error "indexAr of arrow not in category" + + indexOb :: (FiniteCategory c m o, Eq o) => c -> o -> Int + indexOb c o + | isIn o (ob c) = fromJust $ elemIndex o (setToList (ob c)) + | otherwise = error "indexOb of object not in category" + + -- | If the node%4 == 0, then it is part of the source category, else if node%4 == 1 it is part of the target category. + diagObjToNode :: (Eq o, FiniteCategory c m o) => c -> Bool -> o -> Node + diagObjToNode c b o + | index == Nothing = error("Call diagObjToNode on an object not in the category.") + | otherwise = if b then 4*i else 4*i+1 + where + Just i = index + index = elemIndex o (setToList (ob c)) + + diagObjToLNode :: (Eq o, PrettyPrint o, FiniteCategory c m o) => c -> Bool -> o -> LNode String + diagObjToLNode c b o = (diagObjToNode c b o, pprint o) + + -- Creates the invisible node associated to an arrow of the source category if the boolean is True, of the target category if the boolean is False. + invisNodeSrc :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrint m1, + Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrint m2) => + (Diagram c1 m1 o1 c2 m2 o2) -> m1 -> LNode String + invisNodeSrc f@Diagram{src=s,tgt=t,mmap=_,omap=_} m = (4*(indexAr s m)+2, pprint m) + + invisNodeTgt :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrint m1, + Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrint m2) => + (Diagram c1 m1 o1 c2 m2 o2) -> m2 -> LNode String + invisNodeTgt f@Diagram{src=s,tgt=t,mmap=_,omap=_} m = (4*(indexAr t m)+3, pprint m) + + diagArToLEdges :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrint m1, + Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrint m2) => + (Diagram c1 m1 o1 c2 m2 o2) -> Either m1 m2 -> [LEdge String] + diagArToLEdges f@Diagram{src=s,tgt=t,omap=_,mmap=_} (Left m) = [((diagObjToNode s True). source $ m, fst.(invisNodeSrc f) $ m, ""),(fst.(invisNodeSrc f) $ m,(diagObjToNode s True). target $ m, "")] + diagArToLEdges f@Diagram{src=s,tgt=t,omap=_,mmap=_} (Right m) = [((diagObjToNode t False). source $ m, fst.(invisNodeTgt f) $ m, ""),(fst.(invisNodeTgt f) $ m,(diagObjToNode t False). target $ m, "")] + + linkArrows :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrint m1, + Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrint m2) => + (Diagram c1 m1 o1 c2 m2 o2) -> [LEdge String] + linkArrows f@Diagram{src=s,tgt=t,omap=_,mmap=fm} = (\m->(fst(invisNodeSrc f m),fst(invisNodeTgt f (fm |!| m)),"")) <$> (setToList (arrows s)) + + linkObjects :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrint m1, + Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrint m2) => + (Diagram c1 m1 o1 c2 m2 o2) -> [LEdge String] + linkObjects f@Diagram{src=s,tgt=t,omap=om,mmap=_} = (\o->(diagObjToNode s True o,diagObjToNode t False (om |!| o),"")) <$> (setToList (ob s)) + + diagToGraph :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrint m1, PrettyPrint o1, + Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrint m2, PrettyPrint o2) => + (Diagram c1 m1 o1 c2 m2 o2) -> Gr String String + diagToGraph f = mkGraph ((diagObjToLNode (src f) True <$> (setToList (ob (src f))))++(diagObjToLNode (tgt f) False <$> (setToList (ob (tgt f))))++((invisNodeSrc f) <$> (setToList (arrows (src f))))++((invisNodeTgt f) <$> (setToList (arrows (tgt f))))) + ((Prelude.concat ((diagArToLEdges f <$> (Left <$> (setToList (arrows (src f)))))++(diagArToLEdges f <$> (Right <$> (setToList (arrows (tgt f)))))))++(linkArrows f)++(linkObjects f)) + + -- | Export a diagram with GraphViz such that the source category is in green, the target in blue, each morphism is represented by a node. + diagToDot :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrint m1, PrettyPrint o1, + Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrint m2, PrettyPrint o2) => + (Diagram c1 m1 o1 c2 m2 o2) -> String -> IO () + diagToDot f@Diagram{src=s,tgt=t,omap=om,mmap=fm} path = createAndWriteFile path $ renderDot $ toDot dot_file where + dot_file = graphToDot Params { + isDirected = True + ,globalAttributes = [] + ,clusterBy = (\(n,nl) -> case () of + _ | (n `mod` 2) == 0 -> (C 0 $ N (n,nl)) + | (n `mod` 2) == 1 -> (C 1 $ N (n,nl))) + ,isDotCluster = const True + ,clusterID = Num . Int + ,fmtCluster = const [] + ,fmtNode = \(n,label)-> [Label (StrLabel (L.pack label)), fmtColorN n] + ,fmtEdge= \e@(n1,n2,label)-> [Label (StrLabel (L.pack label)), fmtColorE e] + } (diagToGraph f) + where + fmtColorN n | n `mod` 4 == 0 = color Green + | n `mod` 4 == 1 = color Blue + | n `mod` 4 == 2 = color Red + | n `mod` 4 == 3 = color Pink + fmtColorE (s,t,_) | s `mod ` 4 == 0 = if t `mod` 2 == 1 then color Red else color Green + | t `mod ` 4 == 0 = color Green + | s `mod ` 4 == 1 = color Blue + | t `mod ` 4 == 1 = color Blue + | otherwise = color Black + + -- | Export a diagram as a pdf with GraphViz such that the source category is in green, the target in blue, each morphism is represented by a node. + diagToPdf :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrint m1, PrettyPrint o1, + Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrint m2, PrettyPrint o2) => + (Diagram c1 m1 o1 c2 m2 o2) -> String -> IO () + diagToPdf f path = dotToPdf (diagToDot f path) path + + + -- __________________________________ + -- __________________________________ + -- + -- Diagram representation as a selection of the target category + -- __________________________________ + -- __________________________________ + + -- | Export a diagram with GraphViz such that a node or an arrow is in orange if it is the target of the functor. + diagToDot2 :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrint m1, PrettyPrint o1, + Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrint m2, PrettyPrint o2) => + (Diagram c1 m1 o1 c2 m2 o2) -> String -> IO () + diagToDot2 f@Diagram{src=s,tgt=t,omap=om,mmap=fm} path = createAndWriteFile path $ renderDot $ toDot dot_file where + dot_file = graphToDot nonClusteredParams { fmtNode= \(n,label)-> [Label (StrLabel (L.pack label)), colorNode n], + fmtEdge= \(n1,n2,label)-> [Label (StrLabel (L.pack label)), colorEdge label]} (categoryToGraph t) + where + colorNode n = case () of + _ | countPredN == 0 -> color Black + | countPredN == 1 -> color Orange + | countPredN == 2 -> color Orange1 + | countPredN == 3 -> color Orange2 + | countPredN == 4 -> color Orange3 + | countPredN == 5 -> color Orange4 + | otherwise -> color OrangeRed4 + + where + countPredN = Prelude.length [1 | o <- (setToList (ob s)), (objToNode t (om |!| o)) == n] + colorEdge e = case () of + _ | countPredE == 0 -> color Black + | countPredE == 1 -> color Orange + | countPredE == 2 -> color Orange1 + | countPredE == 3 -> color Orange2 + | countPredE == 4 -> color Orange3 + | countPredE == 5 -> color Orange4 + | otherwise -> color OrangeRed4 + where + countPredE = Prelude.length [1 | m <- (setToList (arrows s)), (pprint (fm |!| m)) == e] + + -- | Export a diagram as a pdf with GraphViz such that a node or an arrow is in orange if it is the target of the functor. + diagToPdf2 :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrint m1, PrettyPrint o1, + Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrint m2, PrettyPrint o2) => + (Diagram c1 m1 o1 c2 m2 o2) -> String -> IO () + diagToPdf2 f path = dotToPdf (diagToDot2 f path) path + + -- | Export a diagram with GraphViz such that a node or an arrow is in orange if it is the target of the functor. + -- + -- Allows to format the name of the objects and of the morphisms. + diagToDot2Format :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrint m1, PrettyPrint o1, + Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrint m2, PrettyPrint o2) => + (Diagram c1 m1 o1 c2 m2 o2) -> (o2 -> String) -> (m2 -> String) -> String -> IO () + diagToDot2Format f@Diagram{src=s,tgt=t,omap=om,mmap=fm} formatObj formatMorph path = createAndWriteFile path $ renderDot $ toDot dot_file where + dot_file = graphToDot nonClusteredParams { fmtNode= \(n,label)-> [Label (StrLabel (L.pack label)), colorNode n], + fmtEdge= \(n1,n2,label)-> [Label (StrLabel (L.pack label)), colorEdge label]} (categoryToGraphFormat t formatObj formatMorph) + where + colorNode n = case () of + _ | countPredN == 0 -> color Black + | countPredN == 1 -> color Orange + | countPredN == 2 -> color Orange1 + | countPredN == 3 -> color Orange2 + | countPredN == 4 -> color Orange3 + | countPredN == 5 -> color Orange4 + | otherwise -> color OrangeRed4 + + where + countPredN = Prelude.length [1 | o <- (setToList (ob s)), (objToNode t (om |!| o)) == n] + colorEdge e = case () of + _ | countPredE == 0 -> color Black + | countPredE == 1 -> color Orange + | countPredE == 2 -> color Orange1 + | countPredE == 3 -> color Orange2 + | countPredE == 4 -> color Orange3 + | countPredE == 5 -> color Orange4 + | otherwise -> color OrangeRed4 + where + countPredE = Prelude.length [1 | m <- (setToList (arrows s)), (pprint (fm |!| m)) == e] + + -- | Export a diagram as a pdf with GraphViz such that a node or an arrow is in orange if it is the target of the functor. + -- + -- Allows to format the name of the objects and of the morphisms. + diagToPdf2Format :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, PrettyPrint m1, PrettyPrint o1, + Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, PrettyPrint m2, PrettyPrint o2) => + (Diagram c1 m1 o1 c2 m2 o2) -> (o2 -> String) -> (m2 -> String) -> String -> IO () + diagToPdf2Format f formatObj formatMorph path = dotToPdf (diagToDot2Format f formatObj formatMorph path) path + + + -- __________________________________ + -- __________________________________ + -- + -- Natural transformation representation as a translation in the target category. + -- __________________________________ + -- __________________________________ + + -- | Export a natural transformation with GraphViz such that the source diagram is in green, the target diagram is in blue and the translation is in yellow. + natToDot :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, Eq c1, PrettyPrint m1, PrettyPrint o1, + Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, Eq c2, PrettyPrint m2, PrettyPrint o2) => + (NaturalTransformation c1 m1 o1 c2 m2 o2) -> String -> IO () + natToDot nt path = createAndWriteFile path $ renderDot $ toDot dot_file where + s = source nt + t = target nt + c = components nt + dot_file = graphToDot nonClusteredParams { fmtNode= \(n,label)-> [Label (StrLabel (L.pack label)), colorNode n], + fmtEdge= \(n1,n2,label)-> [Label (StrLabel (L.pack label)), colorEdge label]} (categoryToGraph (tgt s)) + where + colorNode n = case () of + _ | predNSrc && predNTgt -> color Turquoise + | predNSrc -> color Green + | predNTgt -> color Blue + | otherwise -> color Black + where + predNSrc = Set.or [(objToNode (tgt s) ((omap s) |!| o)) == n | o <- (ob (src s))] + predNTgt = Set.or [(objToNode (tgt t) ((omap t) |!| o)) == n | o <- (ob (src t))] + colorEdge e = case () of + _ | predESrc && predETgt && predENat -> color Beige + | predESrc && predETgt -> color Turquoise + | predESrc && predENat -> color Orange + | predETgt && predENat -> color LightBlue + | predESrc -> color Green + | predETgt -> color Blue + | predENat -> color Yellow + | otherwise -> color Black + where + predESrc = Set.foldr (||) False [(pprint ((mmap s) |!| m)) == e | m <- (arrows (src s))] + predETgt = Set.foldr (||) False [(pprint ((mmap t) |!| m)) == e | m <- (arrows (src t))] + predENat = Set.foldr (||) False [(pprint (c |!| o)) == e | o <- (ob (src s))] + + -- | Export a natural transformation as pdf with GraphViz such that the source diagram is in green, the target diagram is in blue and the translation is in yellow. + natToPdf :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, Eq c1, PrettyPrint m1, PrettyPrint o1, + Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, Eq c2, PrettyPrint m2, PrettyPrint o2) => + (NaturalTransformation c1 m1 o1 c2 m2 o2) -> String -> IO () + natToPdf nt path = dotToPdf (natToDot nt path) path + + -- | Export a natural transformation with GraphViz such that the source diagram is in green, the target diagram is in blue and the translation is in yellow. + -- + -- Allows to format the name of the objects and of the morphisms. + natToDotFormat :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, Eq c1, PrettyPrint m1, PrettyPrint o1, + Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, Eq c2, PrettyPrint m2, PrettyPrint o2) => + (NaturalTransformation c1 m1 o1 c2 m2 o2) -> (o2 -> String) -> (m2 -> String) -> String -> IO () + natToDotFormat nt formatObj formatMorph path = createAndWriteFile path $ renderDot $ toDot dot_file where + s = source nt + t = target nt + c = components nt + dot_file = graphToDot nonClusteredParams { fmtNode= \(n,label)-> [Label (StrLabel (L.pack label)), colorNode n], + fmtEdge= \(n1,n2,label)-> [Label (StrLabel (L.pack label)), colorEdge label]} (categoryToGraphFormat (tgt s) formatObj formatMorph) + where + colorNode n = case () of + _ | predNSrc && predNTgt -> color Turquoise + | predNSrc -> color Green + | predNTgt -> color Blue + | otherwise -> color Black + where + predNSrc = Set.or [(objToNode (tgt s) ((omap s) |!| o)) == n | o <- (ob (src s))] + predNTgt = Set.or [(objToNode (tgt t) ((omap t) |!| o)) == n | o <- (ob (src t))] + colorEdge e = case () of + _ | predESrc && predETgt && predENat -> color Beige + | predESrc && predETgt -> color Turquoise + | predESrc && predENat -> color Orange + | predETgt && predENat -> color LightBlue + | predESrc -> color Green + | predETgt -> color Blue + | predENat -> color Yellow + | otherwise -> color Black + where + predESrc = Set.foldr (||) False [(pprint ((mmap s) |!| m)) == e | m <- (arrows (src s))] + predETgt = Set.foldr (||) False [(pprint ((mmap t) |!| m)) == e | m <- (arrows (src t))] + predENat = Set.foldr (||) False [(pprint (c |!| o)) == e | o <- (ob (src s))] + + -- | Export a natural transformation as pdf with GraphViz such that the source diagram is in green, the target diagram is in blue and the translation is in yellow. + -- + -- Allows to format the name of the objects and of the morphisms. + natToPdfFormat :: (Morphism m1 o1, FiniteCategory c1 m1 o1, Eq o1, Eq m1, Eq c1, PrettyPrint m1, PrettyPrint o1, + Morphism m2 o2, FiniteCategory c2 m2 o2, Eq o2, Eq m2, Eq c2, PrettyPrint m2, PrettyPrint o2) => + (NaturalTransformation c1 m1 o1 c2 m2 o2) -> (o2 -> String) -> (m2 -> String) -> String -> IO () + natToPdfFormat nt formatObj formatMorph path = dotToPdf (natToDotFormat nt formatObj formatMorph path) path
+ src/Math/IO/PrettyPrint.hs view
@@ -0,0 +1,71 @@+{-| Module : FiniteCategories +Description : A simple typeclass for things to be pretty printed. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +A simple typeclass for things to be pretty printed. Things should be pretty printable to be exported with graphviz. +Different objects should be pretty printed into different strings or the graphviz export might be wrong. +-} +module Math.IO.PrettyPrint +( + PrettyPrint(..), + pprintFunction +) +where + import Data.List (intercalate) + import qualified Data.Set as Set + import qualified Data.WeakSet as WSet + import qualified Data.WeakMap as WMap + import qualified Math.PureSet as PSet + import qualified Data.Text as Text + + import Numeric.Natural + + -- | The typeclass of things that can be pretty printed. + class PrettyPrint a where + pprint :: a -> String + + instance (PrettyPrint a) => PrettyPrint [a] where + pprint xs = "[" ++ intercalate "," (pprint <$> xs) ++ "]" + + + instance (PrettyPrint a, PrettyPrint b) => PrettyPrint (a,b) where + pprint (a,b) = "(" ++ pprint a ++ "," ++ pprint b ++ ")" + + instance (PrettyPrint a, PrettyPrint b, PrettyPrint c) => PrettyPrint (a,b,c) where + pprint (a,b,c) = "(" ++ pprint a ++ "," ++ pprint b ++ "," ++ pprint c ++ ")" + + instance (PrettyPrint a) => PrettyPrint (Set.Set a) where + pprint xs = "{" ++ intercalate "," (pprint <$> (Set.toList xs)) ++ "}" + + instance (PrettyPrint a, Eq a) => PrettyPrint (WSet.Set a) where + pprint xs = "{" ++ intercalate "," (pprint <$> (WSet.setToList xs)) ++ "}" + + instance (PrettyPrint a, Eq a, PrettyPrint b, Eq b) => PrettyPrint (WMap.Map a b) where + pprint m = "{" ++ intercalate "," ((\(k,v) -> (pprint k) ++ "->" ++ (pprint v)) <$> (WMap.mapToList m)) ++ "}" + + instance PrettyPrint PSet.PureSet where + pprint = PSet.formatPureSet + + instance PrettyPrint Int where + pprint = show + + instance PrettyPrint Double where + pprint = show + + instance PrettyPrint Natural where + pprint = show + + instance PrettyPrint Char where + pprint = (:[]) + + instance PrettyPrint Text.Text where + pprint = Text.unpack + + -- | Pretty print a function on a specific domain. + pprintFunction :: (PrettyPrint a, PrettyPrint b) => + (a -> b) -> [a] -> String + pprintFunction f xs = intercalate "\n" [pprint x ++" -> " ++ pprint (f x) | x <- xs]
− src/OppositeCategory/OppositeCategory.hs
@@ -1,57 +0,0 @@-{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-} - -{-| Module : FiniteCategories -Description : The opposite of a category. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -The opposite of a category is a category with reversed arrows. --} - -module OppositeCategory.OppositeCategory -( - OppositeMorphism(..), - OppositeCategory(..), - opOpMorph, - opOp -) -where - import FiniteCategory.FiniteCategory - import IO.PrettyPrint - - -- | Morphism in an opposite category. - data OppositeMorphism m o = OpMorph m deriving (Eq, Show, Ord) - - -- | Transforms back an opposite morphism into the original morphism. - opOpMorph :: OppositeMorphism m o -> m - opOpMorph (OpMorph m) = m - - instance (Morphism m o) => Morphism (OppositeMorphism m o) o where - source (OpMorph m) = target m - target (OpMorph m) = source m - (@) (OpMorph g) (OpMorph f) = OpMorph $ f @ g - - instance (PrettyPrintable m) => PrettyPrintable (OppositeMorphism m o) where - pprint (OpMorph m) = "Op "++(pprint m) - - -- | Opposite category of a given category. - data OppositeCategory c m o = Op c deriving (Eq, Show, Ord) - - -- | Transforms an opposite category into the original category. - opOp :: OppositeCategory c m o -> c - opOp (Op c) = c - - instance (FiniteCategory c m o, Morphism m o) => FiniteCategory (OppositeCategory c m o) (OppositeMorphism m o) o where - ob (Op c) = ob c - identity (Op c) o = OpMorph $ identity c o - ar (Op c) s t = OpMorph <$> ar c t s - - instance (GeneratedFiniteCategory c m o, Morphism m o) => GeneratedFiniteCategory (OppositeCategory c m o) (OppositeMorphism m o) o where - genAr (Op c) s t = OpMorph <$> genAr c t s - decompose (Op c) (OpMorph m) = OpMorph <$> decompose c m - - instance (PrettyPrintable c) => PrettyPrintable (OppositeCategory c m o) where - pprint (Op cat) = "Op "++(pprint cat)
− src/ProductCategory/ProductCategory.hs
@@ -1,91 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses #-} - -{-| Module : FiniteCategories -Description : Product category of two categories. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -Product category of two categories. --} -module ProductCategory.ProductCategory -( -firstObject, -firstMorphism, -firstCategory, -secondObject, -secondMorphism, -secondCategory, -ProductObject(..), -ProductMorphism(..), -ProductCategory(..), -) -where - import FiniteCategory.FiniteCategory - import Utils.CartesianProduct - import IO.PrettyPrint - - -- | Object in a product category. - data ProductObject o1 o2 = ProductObject o1 o2 deriving (Eq, Show, Ord) - - -- | Returns the first object of a product object. - firstObject :: ProductObject o1 o2 -> o1 - firstObject (ProductObject o1 _) = o1 - - -- | Returns the second object of a product object. - secondObject :: ProductObject o1 o2 -> o2 - secondObject (ProductObject _ o2) = o2 - - -- | Morphism in a product category. - data ProductMorphism m1 o1 m2 o2 = ProductMorphism m1 m2 deriving (Eq, Show, Ord) - - -- | Returns the first morphism of a product morphism. - firstMorphism :: ProductMorphism m1 o1 m2 o2 -> m1 - firstMorphism (ProductMorphism m1 _) = m1 - - -- | Returns the second morphism of a product morphism. - secondMorphism :: ProductMorphism m1 o1 m2 o2 -> m2 - secondMorphism (ProductMorphism _ m2) = m2 - - -- | Product category of two categories. - data ProductCategory c1 m1 o1 c2 m2 o2 = ProductCategory c1 c2 deriving (Eq, Show, Ord) - - -- | Returns the first category of a product category. - firstCategory :: ProductCategory c1 m1 o1 c2 m2 o2 -> c1 - firstCategory (ProductCategory c1 _) = c1 - - -- | Returns the second category of a product category. - secondCategory :: ProductCategory c1 m1 o1 c2 m2 o2 -> c2 - secondCategory (ProductCategory _ c2) = c2 - - instance (Morphism m1 o1, Morphism m2 o2) => Morphism (ProductMorphism m1 o1 m2 o2) (ProductObject o1 o2) where - source (ProductMorphism m1 m2) = ProductObject (source m1) (source m2) - target (ProductMorphism m1 m2) = ProductObject (target m1) (target m2) - (ProductMorphism g1 g2) @ (ProductMorphism f1 f2) = ProductMorphism (g1 @ f1) (g2 @ f2) - - instance (FiniteCategory c1 m1 o1, Morphism m1 o1, - FiniteCategory c2 m2 o2, Morphism m2 o2) => - FiniteCategory (ProductCategory c1 m1 o1 c2 m2 o2) (ProductMorphism m1 o1 m2 o2) (ProductObject o1 o2) where - ob (ProductCategory c1 c2) = [ProductObject a b | a <- (ob c1), b <- (ob c2)] - identity (ProductCategory c1 c2) (ProductObject a b) = ProductMorphism (identity c1 a) (identity c2 b) - ar (ProductCategory c1 c2) (ProductObject s1 s2) (ProductObject t1 t2) = [ProductMorphism m1 m2 | m1 <- ar c1 s1 t1, m2 <- ar c2 s2 t2] - - instance (GeneratedFiniteCategory c1 m1 o1, Morphism m1 o1, - GeneratedFiniteCategory c2 m2 o2, Morphism m2 o2) => - GeneratedFiniteCategory (ProductCategory c1 m1 o1 c2 m2 o2) (ProductMorphism m1 o1 m2 o2) (ProductObject o1 o2) where - genAr (ProductCategory c1 c2) (ProductObject s1 s2) (ProductObject t1 t2) = [ProductMorphism m1 m2 | m1 <- genAr c1 s1 t1, m2 <- genAr c2 s2 t2] - decompose (ProductCategory c1 c2) (ProductMorphism m1 m2) = [ProductMorphism d1 d2 | d1 <- decompoExtended1, d2 <- decompoExtended2] - where - decompo1 = decompose c1 m1 - decompo2 = decompose c2 m2 - decompoExtended1 = if ((length decompo1) < (length decompo2)) then (replicate ((length decompo2)-(length decompo1)) (identity c1 (target (head decompo1))))++decompo1 else decompo1 - decompoExtended2 = if ((length decompo2) < (length decompo1)) then (replicate ((length decompo1)-(length decompo2)) (identity c2 (target (head decompo2))))++decompo2 else decompo2 - - instance (PrettyPrintable o1, PrettyPrintable o2) => PrettyPrintable (ProductObject o1 o2) where - pprint (ProductObject a b) = "<"++(pprint a)++","++(pprint b)++">" - - - instance (PrettyPrintable m1, PrettyPrintable m2) => PrettyPrintable (ProductMorphism m1 o1 m2 o2) where - pprint (ProductMorphism f g) = "<"++(pprint f)++","++(pprint g)++">"
− src/RandomCompositionGraph/RandomCompositionGraph.hs
@@ -1,126 +0,0 @@-{-| Module : FiniteCategories -Description : Randomly generated composition graphs. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -This module provide functions to generate randomly composition graphs. -It is an easy and fast way to generate a lot of finite categories. -It can be used to test functions, to generate examples or to test hypothesis. --} - -module RandomCompositionGraph.RandomCompositionGraph -( - mkRandomCompositionGraph, - defaultMkRandomCompositionGraph -) -where - import FiniteCategory.FiniteCategory - import CompositionGraph.CompositionGraph (Graph(..), CGMorphism(..), CompositionLaw(..), CompositionGraph(..), Arrow(..), mkCompositionGraph, isGen, isComp) - import System.Random (RandomGen, uniformR) - import Data.Maybe (isNothing, fromJust) - import Utils.AssociationList - import Utils.Sample - import Utils.Tuple - - -- | Find first order composites arrows in a composition graph. - compositeMorphisms :: (Eq a, Eq b, Show a) => CompositionGraph a b -> [CGMorphism a b] - compositeMorphisms c = [g @ f | f <- genArrows c, g <- genArFrom c (target f), not (elem (g @ f) (genAr c (source f) (target g)))] - - -- | Merge two nodes. - mergeNodes :: (Eq a) => CompositionGraph a b -> a -> a -> CompositionGraph a b - mergeNodes cg@CompositionGraph{graph=g@(objs,ars),law=l} s t - | not (elem s objs) = error "mapped but not in rcg." - | not (elem t objs) = error "mapped to but not in rcg." - | s == t = cg - | otherwise = CompositionGraph {graph=(filter (/=s) objs,replaceArrow <$> ars), law=newLaw} - where - replace x = if x == s then t else x - replaceArrow (s1,t1,l1) = (replace s1, replace t1, l1) - newLaw = (\(k,v) -> (replaceArrow <$> k, replaceArrow <$> v)) <$> l - - -- | Merge two morphisms of a composition graph, the morphism mapped should be composite, the morphism mapped to should be a generator. - mergeMorphisms :: (Eq a, Eq b) => CompositionGraph a b -> CGMorphism a b -> CGMorphism a b -> CompositionGraph a b - mergeMorphisms cg@CompositionGraph{graph=g,law=l} s@CGMorphism{path=p1@(s1,rp1,t1),compositionLaw=l1} t@CGMorphism{path=p2@(s2,rp2,t2),compositionLaw=l2} - | (isGen s) = error "Generator at the start of a merge" - | (isComp t) = error "Composite at the end of a merge" - | s1 == t1 = mergeNodes CompositionGraph{graph=g, law=newLaw} (source s) (source t) - | s1 == t2 = mergeNodes (mergeNodes CompositionGraph{graph=g, law=newLaw} (source s) (source t)) (target s) (source t) - | otherwise = mergeNodes (mergeNodes CompositionGraph{graph=g, law=newLaw} (source s) (source t)) (target s) (target t) where - newLaw = ((replaceArrow <$> rp1,replaceArrow <$> rp2):((\(k,v) -> (replaceArrow <$> k, replaceArrow <$> v)) <$> l)) - where - replace x = if x == s1 then s2 else (if x == t1 then t2 else x) - replaceArrow (s3,t3,l3) = (replace s3, replace t3, l3) - - -- | Checks associativity of a composition graph. - checkAssociativity :: (Eq a, Eq b, Show a) => CompositionGraph a b -> Bool - checkAssociativity cg = foldr (&&) True [checkTriplet (f,g,h) | f <- genArrows cg, g <- genArFrom cg (target f), h <- genArFrom cg (target g)] - where - checkTriplet (f,g,h) = (h @ g) @ f == h @ (g @ f) - - -- | Find all composite arrows and try to map them to generating arrows. - identifyCompositeToGen :: (RandomGen g, Eq a, Eq b, Show a) => CompositionGraph a b -> Int -> g -> (Maybe (CompositionGraph a b), g) - identifyCompositeToGen _ 0 rGen = (Nothing, rGen) - identifyCompositeToGen cg n rGen - | not (checkAssociativity cg) = (Nothing, rGen) - | null compositeMorphs = (Just cg, rGen) - | otherwise = if isNothing newCG then identifyCompositeToGen cg (n `div` 2) newGen2 else (newCG, newGen2) - where - compositeMorphs = compositeMorphisms cg - morphToMap = (head compositeMorphs) - (selectedGen,newGen1) = if (source morphToMap == target morphToMap) then pickOne [fs | obj <- ob cg, fs <- (genAr cg obj obj)] rGen else pickOne (genArrows cg) rGen - (newCG,newGen2) = identifyCompositeToGen (mergeMorphisms cg morphToMap selectedGen) n newGen1 - - -- | Algorithm described in `mkRandomCompositionGraph`. - monoidificationAttempt :: (RandomGen g, Eq a, Eq b, Show a) => CompositionGraph a b -> Int -> g -> (CompositionGraph a b, g, [a]) - monoidificationAttempt cg p g = if isNothing result then (cg,finalGen,[]) else (fromJust result, finalGen, [s,t]) - where - ([s,t],newGen) = if ((length (ob cg)) > 1) then sample (ob cg) 2 g else (ob cg ++ ob cg,g) - newCG = mergeNodes cg s t - (result,finalGen) = identifyCompositeToGen newCG p newGen - - -- | Initialize a composition graph with all arrows seperated. - initRandomCG :: Int -> CompositionGraph Int Int - initRandomCG n = CompositionGraph{graph=([0..n+n-1],[((i+i),(i+i+1), i) | i <- [0..n]]),law=[]} - - -- | Generates a random composition graph. - -- - -- We use the fact that a category is a generalized monoid. - -- - -- We try to create a composition law of a monoid greedily. - -- - -- To get a category, we begin with a category with all arrows seperated and not composing with each other. - -- It is equivalent to the monoid with an empty composition law. - -- - -- Then, a monoidification attempt is the following algorihm : - -- - -- 1. Pick two objects, merge them. - -- 2. While there are composite morphisms, try to merge them with generating arrows. - -- 3. If it fails, don't change the composition graph. - -- 4. Else return the new composition graph - -- - -- A monoidification attempt takes a valid category and outputs a valid category, furthermore, the number of arrows is constant - -- and the number of objects is decreasing (not strictly). - mkRandomCompositionGraph :: (RandomGen g) => Int -- ^ Number of arrows of the random composition graph. - -> Int -- ^ Number of monoidification attempts, a bigger number will produce more morphisms that will compose but the function will be slower. - -> Int -- ^ Perseverance : how much we pursure an attempt far away to find a law that works, a bigger number will make the attemps more successful, but slower. (When in doubt put 4.) - -> g -- ^ Random generator. - -> (CompositionGraph Int Int, g) - mkRandomCompositionGraph nbAr nbAttempts perseverance gen = attempt (initRandomCG nbAr) nbAttempts perseverance gen - where - attempt cg 0 _ gen = (cg, gen) - attempt cg n p gen = attempt newCG (n-1) p newGen - where - (newCG, newGen,_) = (monoidificationAttempt cg p gen) - - -- | Creates a random composition graph with default random values. - -- - -- The number of arrows will be in the interval [1, 20]. - defaultMkRandomCompositionGraph :: (RandomGen g) => g -> (CompositionGraph Int Int, g) - defaultMkRandomCompositionGraph g1 = mkRandomCompositionGraph nbArrows (min nbAttempts 20) 4 g3 - where - (nbArrows, g2) = uniformR (1,20) g1 - (nbAttempts, g3) = uniformR (0,nbArrows+nbArrows) g2 -
− src/RandomDiagram/RandomDiagram.hs
@@ -1,45 +0,0 @@-{-| Module : FiniteCategories -Description : Select a random diagram in a category. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -This module provide functions to generate random diagrams. -It can be used to test functions, to generate examples or to test hypothesis. --} - -module RandomDiagram.RandomDiagram -( - mkRandomDiagram, - defaultMkRandomDiagram -) -where - import FiniteCategory.FiniteCategory - import CompositionGraph.CompositionGraph - import RandomCompositionGraph.RandomCompositionGraph - import System.Random (RandomGen, uniformR) - import Data.Maybe (isNothing, fromJust) - import Utils.Sample - import FunctorCategory.FunctorCategory - import Diagram.Diagram - - -- | Choose a random diagram in the functor category of an index category and an image category. - mkRandomDiagram :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1, - FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2, - RandomGen g) => c1 -> c2 -> g -> (Diagram c1 m1 o1 c2 m2 o2, g) - mkRandomDiagram index cat gen = pickOne (ob FunctorCategory{sourceCat=index, targetCat=cat}) gen - - - -- | Constructs two random composition graphs and choose a random diagram between the two. - defaultMkRandomDiagram :: (RandomGen g) => g -> (Diagram (CompositionGraph Int Int) (CGMorphism Int Int) Int (CompositionGraph Int Int) (CGMorphism Int Int) Int, g) - defaultMkRandomDiagram g1 = mkRandomDiagram cat1 cat2 g3 - where - (nbArrows1, g2) = uniformR (1,8) g1 - (nbAttempts1, g3) = uniformR (0,nbArrows1+nbArrows1) g2 - (cat1, g4) = mkRandomCompositionGraph nbArrows1 nbAttempts1 5 g3 - (nbArrows2, g5) = uniformR (1,11-nbArrows1) g4 - (nbAttempts2, g6) = uniformR (0,nbArrows2+nbArrows2) g5 - (cat2, g7) = mkRandomCompositionGraph nbArrows2 nbAttempts2 5 g6 -
− src/Set/FinOrdSet.hs
@@ -1,96 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses #-} - -{-| Module : FiniteCategories -Description : The category of finite sets of elements you can order (it is optimized with the Data.Set type). -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -Same as `FinOrdSet` but using Data.Set as objects, it is more optimized but needs its elements to be ordered. --} - -module Set.FinOrdSet -( - -- * The morphism of the category : `FinOrdMap` - FinOrdMap(..), - -- * The category itself : `FinOrdSet` - FinOrdSet(..), - powerFinOrdSet -) -where - import qualified Data.Map as Map (Map, (!), fromList, keys) - import qualified Data.Set as Set (Set, fromList, toList, powerSet, null, size, findMin) - import Data.List (intercalate, nub) - import FiniteCategory.FiniteCategory (FiniteCategory(..), GeneratedFiniteCategory(..), Morphism(..), bruteForceDecompose) - import Control.Monad (filterM) - import Utils.CartesianProduct ((|^|)) - import IO.PrettyPrint - - - -- | `FinOrdMap` is the morphism of the `FinOrdSet` category. - -- - -- It is represented by a `Data.Map`. The domain is the list of /keys/. - -- We need to store the codomain of the map in order to differentiate different maps which would be the same if we couldn't compare codomains. - -- For example, @f : {1,2,3} -> {1,2,3}@ and @g : {1,2,3} -> {1,2,3,4}@ would have the same `Data.Map` but are different. - data FinOrdMap a = FinOrdMap {codomain :: Set.Set a, function :: Map.Map a a} deriving (Eq, Show) - - instance (Ord a) => Morphism (FinOrdMap a) (Set.Set a) where - (@) g f = FinOrdMap {codomain=codomain g, function=Map.fromList[(k,(function g)Map.!((function f) Map.! k))| k <- Map.keys (function f)]} - source = Set.fromList.(Map.keys).function - target = codomain - - instance (PrettyPrintable a, Ord a) => PrettyPrintable (FinOrdMap a) where - pprint f = pprint (source f) ++ " -> " ++ pprint (target f) ++ "\n" ++ pprint (function f) - - -- | `FinOrdSet` stores the sets which constitutes its objects. - data (FinOrdSet a) = FinOrdSet {sets :: [Set.Set a]} deriving (Show) - - instance (Ord a) => FiniteCategory (FinOrdSet a) (FinOrdMap a) (Set.Set a) where - ob = nub.sets - identity c s - | elem s (ob c) = FinOrdMap {codomain=s, function=Map.fromList [(o,o)| o <- (Set.toList s)]} - | otherwise = error("Trying to get identity of an object not in the Set category.") - ar c s t - | Set.null s = [FinOrdMap {codomain=t, function=Map.fromList []}] - | Set.null t = [] - | otherwise = (\x -> FinOrdMap {codomain=t, function=Map.fromList x}) <$> [zip domain i | i <- images] where - domain = Set.toList s - codomain = Set.toList t - images = (codomain |^| (length domain)) - - instance (Ord a) => GeneratedFiniteCategory (FinOrdSet a) (FinOrdMap a) (Set.Set a) where - genAr c s t - | Set.null s = [FinOrdMap {codomain=t, function= Map.fromList []}] - | Set.null t = [] - | Set.size s == 1 = [FinOrdMap {codomain=t, function=injectiv}] - | Set.size t == 1 = [FinOrdMap {codomain=t, function=surjectiv}] - | s == t = nub $ (\m -> FinOrdMap {codomain=t, function=m}) <$> [transpose,rotate,project] - | length s < length t = [FinOrdMap {codomain=t, function=injectiv}] - | otherwise = [FinOrdMap {codomain=t, function=surjectiv}] - where - domain = Set.toList s - codomain = Set.toList t - transpose = Map.fromList ([(domain !! 0, domain !! 1),(domain !! 1, domain !! 0)]++[(o,o) | o <- drop 2 domain]) - rotatedDomain = (tail domain) ++ [(head domain)] - rotate = Map.fromList (zip domain rotatedDomain) - project = Map.fromList ((domain !! 0, domain !! 1):[(o,o) | o <- tail domain]) - injectiv = Map.fromList (zip domain codomain) - surjectiv = Map.fromList (zip domain ((replicate ((length s)-(length t)+1) (head codomain))++codomain)) - - decompose = bruteForceDecompose - - instance (Ord a) => Eq (FinOrdSet a) where - FinOrdSet {sets=ss1} == FinOrdSet {sets=ss2} = if ss1 == [] then ss2 == [] else (isIncluded ss1 ss2) && (isIncluded ss2 ss1) - where - isIncluded [] ss2 = True - isIncluded (s:ss1) ss2 = (elem s ss2) && (isIncluded ss1 ss2) - - instance (PrettyPrintable a) => PrettyPrintable (FinOrdSet a) where - pprint FinOrdSet {sets=ss} = "FinOrdSet of "++ pprint ss - - -- | Returns the `FinOrdSet` category such that every subset of the set given is an object of the category. - powerFinOrdSet :: (Ord a) => Set.Set a -> FinOrdSet a - powerFinOrdSet x = FinOrdSet {sets = (Set.toList).(Set.powerSet) $ x} -
− src/Set/FinSet.hs
@@ -1,203 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses #-} - -{-| Module : FiniteCategories -Description : The category of finite sets. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -The __FinSet__ category has as objects finite sets and as morphisms maps between them. -It is a full subcategory of the __Set__ category. -It is itself a large category (therefore not a finite one), -we only construct finite subcategories of the mathematical infinite __FinSet__ category. -`FinSet` is the type of full finite subcategories of __FinSet__. - -To instantiate it, use the `FinSet` constructor on a list of sets. - -For example, see Example.ExampleSet --} - -module Set.FinSet where - import Data.List (intersect, nub, intercalate, subsequences) - import Utils.SetList - import Utils.AssociationList - import FiniteCategory.FiniteCategory - import Utils.CartesianProduct ((|^|)) - import IO.PrettyPrint - - import Diagram.Diagram - import ConeCategory.ConeCategory - import UsualCategories.One - - -- | When constructing a set, the following rules should be respected : - -- - -- - An elem is always a leaf construct. - -- - -- - There should be no duplicate in a Collection. - -- - -- - The root construct is always a Collection. - -- - -- This set construction does not require the ord constraint. - data FinSet a = Elem a - | Collection [FinSet a] - deriving (Show) - - instance (Eq a) => Eq (FinSet a) where - (Elem a) == (Elem b) = a == b - (Collection s1) == (Collection s2) = doubleInclusion s1 s2 - _ == _ = False - - instance Functor FinSet where - fmap f (Elem a) = Elem (f a) - fmap f (Collection xs) = Collection (fmap f <$> xs) - - -- | Constructs the empty set. - emptyFinSet :: FinSet a - emptyFinSet = Collection [] - - -- | Constructs a singleton set. - singleton :: a -> FinSet a - singleton x = Collection [Elem x] - - -- | Extract a list from a set. - toList :: FinSet a -> [FinSet a] - toList (Collection list) = list - - -- | Transforms a list of sets into a set. - fromList :: (Eq a) => [FinSet a] -> FinSet a - fromList xs = Collection $ nub xs - - -- | Union of two sets. - (|||) :: (Eq a) => FinSet a -> FinSet a -> FinSet a - (|||) (Collection l1) (Collection l2) = Collection $ nub (l1++l2) - - -- | Union of a list of sets. - union :: (Eq a) => [FinSet a] -> FinSet a - union sets = foldr (|||) emptyFinSet sets - - -- | Intersection of two sets. - (&&&) :: (Eq a) => FinSet a -> FinSet a -> FinSet a - (&&&) (Collection l1) (Collection l2) = Collection $ intersect l1 l2 - - -- | Intersection of a list of sets. - intersection :: (Eq a) => [FinSet a] -> FinSet a - intersection [] = error "Cannot make an intersection of no set." - intersection sets = foldr1 (&&&) sets - - -- | Returns wether a set is in another one. - isIn :: (Eq a) => FinSet a -> FinSet a -> Bool - isIn e (Collection es) = elem e es - - -- | Returns wether a set is included in another one. - includedIn :: (Eq a) => FinSet a -> FinSet a -> Bool - includedIn (Collection l1) (Collection l2) = isIncludedIn l1 l2 - - -- | Returns the size of a set. - card :: FinSet a -> Int - card (Collection xs) = length xs - - -- | Generalizes a set of @a@ so that it can contain elements of type @a@ or @b@. - generalizeType :: FinSet a -> FinSet (Either a b) - generalizeType = fmap Left - - instance (PrettyPrintable a) => PrettyPrintable (FinSet a) where - pprint (Elem a) = pprint a - pprint (Collection elems) = "{"++ (intercalate "," (pprint <$> elems)) ++ "}" - - -- | `FinMap` is the morphism of the `FinSetCat` category. - -- - -- We need to keep the codomain because it would not be present in a non-surjective map. - -- - -- It is represented by an association list and a codomain. - data FinMap a = FinMap { finMap :: (AssociationList (FinSet a) (FinSet a)) - , codomain :: (FinSet a) - } - deriving (Eq, Show) - - instance (Eq a) => Morphism (FinMap a) (FinSet a) where - (@) g f = FinMap { finMap = [(k,((finMap g) !-! v)) | (k,v) <- (finMap f)] - , codomain = (codomain g) - } - source m = Collection $ nub (keys (finMap m)) - target = codomain - - instance (PrettyPrintable a, Eq a) => PrettyPrintable (FinMap a) where - pprint f = pprint (source f) ++ " -> " ++ pprint (target f) ++ "\n" ++ pprint (finMap f) - - -- | `FinSetCat` is the type for the category of `FinSet`. - -- Its elements are the sets considered in the Set category. - data FinSetCat a = FinSetCat [FinSet a] deriving (Eq, Show) - - instance (Eq a) => FiniteCategory (FinSetCat a) (FinMap a) (FinSet a) where - ob (FinSetCat xs) = xs - identity c s - | elem s (ob c) = FinMap{ finMap = [(e,e) | e <- toList s] - , codomain = s - } - | otherwise = error("Trying to get identity of an object not in the Set category.") - ar _ s t - | s == emptyFinSet = [FinMap{finMap=[],codomain=t}] - | t == emptyFinSet = [] - | otherwise = (\x -> FinMap {codomain=t, finMap=x}) <$> [zip domain i | i <- images] where - domain = toList s - codomain = toList t - images = (codomain |^| (length domain)) - - instance (Eq a) => GeneratedFiniteCategory (FinSetCat a) (FinMap a) (FinSet a) where - genAr _ s t - | s == emptyFinSet = [FinMap{finMap=[],codomain=t}] - | t == emptyFinSet = [] - | card s == 1 = [FinMap {codomain=t, finMap=injectiv}] - | card t == 1 = [FinMap {codomain=t, finMap=surjectiv}] - | s == t = nub $ (\m -> FinMap {codomain=t, finMap=m}) <$> [transpose,rotate,project] - | card s < card t = [FinMap {codomain=t, finMap=injectiv}] - | otherwise = [FinMap {codomain=t, finMap=surjectiv}] - where - domain = toList s - codomain = toList t - transpose = [(domain !! 0, domain !! 1),(domain !! 1, domain !! 0)]++[(o,o) | o <- drop 2 domain] - rotatedDomain = (tail domain) ++ [(head domain)] - rotate = zip domain rotatedDomain - project = (domain !! 0, domain !! 1):[(o,o) | o <- tail domain] - injectiv = zip domain codomain - surjectiv = zip domain ((replicate ((card s)-(card t)+1) (head codomain))++codomain) - - decompose = bruteForceDecompose - - instance (PrettyPrintable a) => PrettyPrintable (FinSetCat a) where - pprint (FinSetCat xs) = "FinSetCat "++(pprint xs) - - -- | Returns the `FinSet` category such that every subset of the set given is an object of the category. - powerFinSet :: FinSet a -> FinSet a - powerFinSet (Collection xs) = Collection (Collection <$> subsequences xs) - - -- | Add a set to the target FinSetCat such that the given diagram has a limit. The diagram must not be the empty diagram from @0@ to @0@. - -- - -- Returns an insertion functor from the previous set category to the new one, an updated diagram which has a limit, and the new limit object. - constructLimit :: (FiniteCategory c m o, Morphism m o, Eq a, Eq c, Eq m, Eq o) => Diagram c m o (FinSetCat a) (FinMap a) (FinSet a) -> (Diagram (FinSetCat a) (FinMap a) (FinSet a) (FinSetCat a) (FinMap a) (FinSet a), Diagram c m o (FinSetCat a) (FinMap a) (FinSet a), (FinSet a)) - constructLimit diag = (insertionFunctor, newDiagram, newLimitObject) - where - cat@(FinSetCat sets) = tgt diag - singletonAlreadyHere = or $ (\s -> card s == 1) <$> sets - singleton2 = if singletonAlreadyHere - then - head [s | s <- sets, card s == 1] - else - Collection [head sets] -- we make a singleton out of the first set - newSetCat = if singletonAlreadyHere - then - cat - else - FinSetCat (singleton2:sets) - newDiag = Diagram {src = src diag, tgt = newSetCat, omap = omap diag, mmap = mmap diag} - newLimitObject = Collection $ [(iterate (\x -> Collection [x]) singleton2) !! i | i <- [1..(length (conesOfApex newDiag singleton2))]] - newTargetCat = FinSetCat (newLimitObject:sets) - insertionFunctor = Diagram {src = cat, tgt = newTargetCat, omap = functToAssocList id (ob cat) - , mmap = functToAssocList id (arrows cat)} - newDiagram = insertionFunctor `composeDiag` diag - - -- | Generalizes a set category of @a@ so that it can contain elements of type @a@ or @b@. - generalizeTypeSetCat :: FinSetCat a -> FinSetCat (Either a b) - generalizeTypeSetCat (FinSetCat xs) = FinSetCat $ (fmap Left) <$> xs
− src/Subcategories/FreeSubcategory.hs
@@ -1,50 +0,0 @@-{-# LANGUAGE UndecidableInstances, FlexibleInstances, MultiParamTypeClasses #-} - -{-| Module : FiniteCategories -Description : Free subcategory generated by a subset of morphisms of a category C. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -Free subcategory generated by a subset of morphisms of a category @C@. --} -module Subcategories.FreeSubcategory -( -FreeSubcategory(..) -) -where - import FiniteCategory.FiniteCategory - import Data.List (nub) - import Utils.SetList - - -- | The free subcategory generated by a subset of morphisms of a category @C@. - data FreeSubcategory c m o = FreeSubcategory c [m] - - -- | Compose a list of morphisms with generator morphisms to generated new morphisms. - composeOnce :: (Morphism m o, Eq m, Eq o) => [m] -> [m] -> [m] - composeOnce m g = nub [m2 @ m1| m1 <- m, m2 <- g, (target m1) == (source m2)] - - -- | Compose a list of generator morphisms until it's useless. - composeUntilEnd :: (Morphism m o, Eq m, Eq o) => [m] -> [m] - composeUntilEnd g = composeRecursive g g - where composeRecursive ms g - | doubleInclusion nextStep ms = ms - | otherwise = composeRecursive nextStep g - where - nextStep = composeOnce ms g - allArrows :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => FreeSubcategory c m o -> [m] - allArrows sc@(FreeSubcategory c morphs) = composeUntilEnd $ nub $ morphs++(identities sc) - - instance (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => FiniteCategory (FreeSubcategory c m o) m o where - ob (FreeSubcategory _ morphs) = nub $ [source m | m <- morphs]++[target m | m <- morphs] - identity (FreeSubcategory c morphs) obj = identity c obj - ar sc s t = filter (\x -> (source x) == s && (target x) == t) (allArrows sc) - arrows = allArrows - - instance (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => GeneratedFiniteCategory (FreeSubcategory c m o) m o where - genAr (FreeSubcategory _ morphs) s t = filter (\x -> (source x) == s && (target x) == t) morphs - decompose = bruteForceDecompose - genArrows (FreeSubcategory _ morphs) = morphs -
− src/Subcategories/FullSubcategory.hs
@@ -1,36 +0,0 @@-{-# LANGUAGE UndecidableInstances, FlexibleInstances, MultiParamTypeClasses #-} - -{-| Module : FiniteCategories -Description : Full subcategory a category C. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -Full subcategory a category C. --} -module Subcategories.FullSubcategory -( -FullSubcategory(..) -) -where - import FiniteCategory.FiniteCategory - import Data.List (nub) - import Utils.SetList - import IO.PrettyPrint - - -- | The datatype for full subcategories of a given category containing given objects. - data FullSubcategory c m o = FullSubcategory c [o] deriving (Eq, Show) - - instance (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => FiniteCategory (FullSubcategory c m o) m o where - ob (FullSubcategory _ objs) = nub $ objs - identity (FullSubcategory c objs) obj = if elem obj objs then identity c obj else error "Cannot create identity of an object not in the category." - ar (FullSubcategory c objs) s t = if elem s objs && elem t objs then ar c s t else error "Cannot create morphisms between objects not in the category." - - instance (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => GeneratedFiniteCategory (FullSubcategory c m o) m o where - genAr = defaultGenAr - decompose = defaultDecompose - - instance (PrettyPrintable c, PrettyPrintable o) => PrettyPrintable (FullSubcategory c m o) where - pprint (FullSubcategory c o) = "Full subcategory of "++pprint c++" containing "++pprint o
− src/Subcategories/Subcategory.hs
@@ -1,54 +0,0 @@-{-# LANGUAGE UndecidableInstances, FlexibleInstances, MultiParamTypeClasses #-} - -{-| Module : FiniteCategories -Description : A subcategory is the image of a faithful functor. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -A subcategory is the image of a faithful functor. --} - -module Subcategories.Subcategory where - import FiniteCategory.FiniteCategory - import Diagram.Diagram - import Utils.AssociationList - import Data.List (nub) - import Subcategories.FullSubcategory - - -- | The type to view a faithful diagram as a subcategory. - -- - -- It is your responsability to check that the diagram is faithful. - data Subcategory c1 m1 o1 c2 m2 o2 = Subcategory (Diagram c1 m1 o1 c2 m2 o2) - - instance (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1 - , FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2) => - FiniteCategory (Subcategory c1 m1 o1 c2 m2 o2) m2 o2 where - ob (Subcategory diag) = nub $ ((omap diag) !-!) <$> (ob (src diag)) - identity (Subcategory diag) o = identity (tgt diag) o - ar (Subcategory diag) s t = nub $ ((mmap diag) !-!) <$> ar (src diag) ((inverse.omap $ diag) !-! s) ((inverse.omap $ diag) !-! t) - - instance (GeneratedFiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1 - , GeneratedFiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2) => - GeneratedFiniteCategory (Subcategory c1 m1 o1 c2 m2 o2) m2 o2 where - genAr (Subcategory diag) s t = nub $ ((mmap diag) !-!) <$> genAr (src diag) ((inverse.omap $ diag) !-! s) ((inverse.omap $ diag) !-! t) - decompose (Subcategory diag) m = nub $ ((mmap diag) !-!) <$> decompose (src diag) ((inverse.mmap $ diag) !-! m) - - -- | Extracts a full and faithful diagram out of a faithful diagram. - fullDiagram :: ( 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 c1 m1 o1 (Subcategory c1 m1 o1 c2 m2 o2) m2 o2 - fullDiagram diag = Diagram {src = src diag, tgt = Subcategory diag, omap = omap diag, mmap = mmap diag} - - -- | Strips the target of a diagram so that only given objects remain. - stripDiagram :: ( 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 -> [o2] -> Diagram c1 m1 o1 (FullSubcategory c2 m2 o2) m2 o2 - stripDiagram diag keep = Diagram { - src = src diag, - tgt = FullSubcategory (tgt diag) keep, - omap = omap diag, - mmap = mmap diag - }
− src/UsualCategories/DiscreteCategory.hs
@@ -1,54 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses #-} - -{-| Module : FiniteCategories -Description : A discrete category is a category with no morphism other than identities. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -A discrete category is a category with no morphism other than identities. --} - -module UsualCategories.DiscreteCategory -( - DiscreteObject(..), - DiscreteIdentity(..), - DiscreteCategory(..) -) -where - import FiniteCategory.FiniteCategory - import IO.PrettyPrint - - -- | A discrete object is just an usual object. - data DiscreteObject a = DiscreteObject a deriving (Eq, Show) - - instance (PrettyPrintable a) => PrettyPrintable (DiscreteObject a) where - pprint (DiscreteObject x) = pprint x - - -- | `DiscreteIdentity` is the morphism of the discrete category. - data DiscreteIdentity a = DiscreteIdentity a deriving (Eq, Show) - - instance (Eq a) => Morphism (DiscreteIdentity a) (DiscreteObject a) where - source (DiscreteIdentity x) = DiscreteObject x - target (DiscreteIdentity x) = DiscreteObject x - (@) = (\x y -> if x /= y then error "Composition of incompatible discrete morphisms" else x) - - instance (PrettyPrintable a) => PrettyPrintable (DiscreteIdentity a) where - pprint (DiscreteIdentity x) = "Id"++pprint x - - -- | The discrete category is just a list of objects. - data DiscreteCategory a = DiscreteCategory [a] deriving (Eq, Show) - - instance (Eq a) => FiniteCategory (DiscreteCategory a) (DiscreteIdentity a) (DiscreteObject a) where - ob (DiscreteCategory objs) = DiscreteObject <$> objs - identity (DiscreteCategory objs) (DiscreteObject o) = if elem o objs then DiscreteIdentity o else error "Identity of an object not in the discrete category." - ar c x y = if x /= y then [] else [identity c x] - - instance (Eq a) => GeneratedFiniteCategory (DiscreteCategory a) (DiscreteIdentity a) (DiscreteObject a) where - genAr = defaultGenAr - decompose = defaultDecompose - - instance (PrettyPrintable a) => PrettyPrintable (DiscreteCategory a) where - pprint (DiscreteCategory xs) = "DiscreteCategory of " ++pprint xs
− src/UsualCategories/Hat.hs
@@ -1,74 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses #-} - -{-| Module : FiniteCategories -Description : The Hat category contains two arrows coming from the same object. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -The Hat category contains two arrows coming from the same object. --} - -module UsualCategories.Hat -( - HatOb(..), - HatAr(..), - Hat(..) -) -where - import FiniteCategory.FiniteCategory - import IO.PrettyPrint - - -- | Object of the Hat category. - data HatOb = A | B | C deriving (Eq, Show) - - -- | Morphism of the Hat category. - data HatAr = IdA | IdB | IdC | F | G deriving (Eq, Show) - - -- | The Hat category. - data Hat = Hat deriving (Eq, Show) - - instance Morphism HatAr HatOb where - source IdA = A - source IdB = B - source IdC = C - source _ = A - target IdA = A - target IdB = B - target IdC = C - target F = B - target G = C - (@) IdA IdA = IdA - (@) F IdA = F - (@) G IdA = G - (@) IdB IdB = IdB - (@) IdC IdC = IdC - (@) IdB F = F - (@) IdC G = G - - instance FiniteCategory Hat HatAr HatOb where - ob = const [A,B,C] - identity _ A = IdA - identity _ B = IdB - identity _ C = IdC - ar _ A A = [IdA] - ar _ B B = [IdB] - ar _ C C = [IdC] - ar _ A B = [F] - ar _ A C = [G] - ar _ _ _ = [] - - instance GeneratedFiniteCategory Hat HatAr HatOb where - genAr = defaultGenAr - decompose = defaultDecompose - - instance PrettyPrintable HatOb where - pprint = show - - instance PrettyPrintable HatAr where - pprint = show - - instance PrettyPrintable Hat where - pprint = show
− src/UsualCategories/One.hs
@@ -1,40 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses #-} - -{-| Module : FiniteCategories -Description : The __1__ category contains a unique object and its identity. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -The __1__ category contains a unique object and its identity. --} - -module UsualCategories.One -( - One(..) -) -where - import FiniteCategory.FiniteCategory - import IO.PrettyPrint - - -- | A type that serves the purpose of being the __1__ category, its object and its identity. - data One = One deriving (Eq, Show) - - instance Morphism One One where - source One = One - target One = One - (@) = const.const $ One - - instance FiniteCategory One One One where - ob = const [One] - identity = const.id - ar = const.const.const $ [One] - - instance GeneratedFiniteCategory One One One where - genAr = defaultGenAr - decompose = defaultDecompose - - instance PrettyPrintable One where - pprint One = "1"
− src/UsualCategories/Parallel.hs
@@ -1,67 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses #-} - -{-| Module : FiniteCategories -Description : The parallel category contains two parallel arrows. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -The parallel category contains two objects `A` and `B` and two morphisms @`F` : `A` -> `B`@ and @`G` : `A` -> `B`@. --} - -module UsualCategories.Parallel -( - ParallelOb(..), - ParallelAr(..), - Parallel(..) -) -where - import FiniteCategory.FiniteCategory - import IO.PrettyPrint - - -- | Object of the parallel category. - data ParallelOb = A | B deriving (Eq, Show) - - -- | Morphism of the parallel category. - data ParallelAr = IdA | IdB | F | G deriving (Eq, Show) - - -- | The parallel category. - data Parallel = Parallel deriving (Eq, Show) - - instance Morphism ParallelAr ParallelOb where - source IdA = A - source IdB = B - source _ = A - target IdA = A - target IdB = B - target _ = B - (@) IdA IdA = IdA - (@) F IdA = F - (@) G IdA = G - (@) IdB IdB = IdB - (@) IdB F = F - (@) IdB G = G - - instance FiniteCategory Parallel ParallelAr ParallelOb where - ob = const [A,B] - identity _ A = IdA - identity _ B = IdB - ar _ A A = [IdA] - ar _ A B = [F,G] - ar _ B B = [IdB] - ar _ _ _ = [] - - instance GeneratedFiniteCategory Parallel ParallelAr ParallelOb where - genAr = defaultGenAr - decompose = defaultDecompose - - instance PrettyPrintable ParallelOb where - pprint = show - - instance PrettyPrintable ParallelAr where - pprint = show - - instance PrettyPrintable Parallel where - pprint = show
− src/UsualCategories/Square.hs
@@ -1,101 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses #-} - -{-| Module : FiniteCategories -Description : The square category contains 4 generating arrows forming a square. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -The square category contains 4 generating arrows forming a square. --} - -module UsualCategories.Square -( - SquareOb(..), - SquareAr(..), - Square(..) -) -where - import FiniteCategory.FiniteCategory - import IO.PrettyPrint - - -- | Object of the Square category. - data SquareOb = A | B | C | D deriving (Eq, Show) - - -- | Morphism of the Square category. - data SquareAr = IdA | IdB | IdC | IdD | F | G | H | I | FH | GI deriving (Eq, Show) - - -- | The Square category. - data Square = Square deriving (Eq, Show) - - instance Morphism SquareAr SquareOb where - source IdA = A - source IdB = B - source IdC = C - source IdD = D - source F = A - source G = A - source H = B - source I = C - source FH = A - source GI = A - target IdA = A - target IdB = B - target IdC = C - target IdD = D - target F = B - target G = C - target H = D - target I = D - target FH = D - target GI = D - (@) IdA IdA = IdA - (@) F IdA = F - (@) G IdA = G - (@) FH IdA = FH - (@) GI IdA = GI - (@) IdB IdB = IdB - (@) H IdB = H - (@) IdC IdC = IdC - (@) I IdC = I - (@) IdD IdD = IdD - (@) IdB F = F - (@) H F = FH - (@) IdC G = G - (@) I G = GI - (@) IdD H = H - (@) IdD I = I - (@) IdD FH = FH - (@) IdD GI = GI - - instance FiniteCategory Square SquareAr SquareOb where - ob = const [A,B,C,D] - identity _ A = IdA - identity _ B = IdB - identity _ C = IdC - identity _ D = IdD - ar _ A A = [IdA] - ar _ A B = [F] - ar _ A C = [G] - ar _ A D = [FH,GI] - ar _ B B = [IdB] - ar _ B D = [H] - ar _ C C = [IdC] - ar _ C D = [I] - ar _ D D = [IdD] - ar _ _ _ = [] - - instance GeneratedFiniteCategory Square SquareAr SquareOb where - genAr = defaultGenAr - decompose = defaultDecompose - - instance PrettyPrintable SquareOb where - pprint = show - - instance PrettyPrintable SquareAr where - pprint = show - - instance PrettyPrintable Square where - pprint = show
− src/UsualCategories/Three.hs
@@ -1,84 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses #-} - -{-| Module : FiniteCategories -Description : The __3__ category contains three object `A`, `B` and `C` and three morphisms @`F` : `A` -> `B`@, @`G` : `B` -> `C`@, @`G`*`F` : `A` -> `C`@. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -The __3__ category contains three object `A`, `B` and `C` and three morphisms @`F` : `A` -> `B`@, @`G` : `B` -> `C`@, @`G`*`F` : `A` -> `C`@ (and of course three identities). --} - -module UsualCategories.Three -( - ThreeOb(..), - ThreeAr(..), - Three(..) -) -where - import FiniteCategory.FiniteCategory - import IO.PrettyPrint - - -- | Object of the __3__ category. - data ThreeOb = A | B | C deriving (Eq, Show) - - -- | Morphism of the __3__ category. - data ThreeAr = IdA | IdB | IdC | F | G | GF deriving (Eq,Show) - - -- | The __3__ category. - data Three = Three deriving (Eq,Show) - - instance Morphism ThreeAr ThreeOb where - source IdA = A - source IdB = B - source IdC = C - source F = A - source G = B - source GF = A - target IdA = A - target IdB = B - target IdC = C - target F = B - target G = C - target GF = C - (@) IdA IdA = IdA - (@) F IdA = F - (@) GF IdA = GF - (@) IdB IdB = IdB - (@) G IdB = G - (@) IdC IdC = IdC - (@) IdB F = F - (@) G F = GF - (@) IdC G = G - (@) IdC GF = GF - (@) x y = error ("Invalid composition of ThreeMorph : "++show x++" * "++show y) - - instance FiniteCategory Three ThreeAr ThreeOb where - ob = const [A,B,C] - identity _ A = IdA - identity _ B = IdB - identity _ C = IdC - ar _ A A = [IdA] - ar _ A B = [F] - ar _ A C = [GF] - ar _ B B = [IdB] - ar _ B C = [G] - ar _ C C = [IdC] - ar _ _ _ = [] - - instance GeneratedFiniteCategory Three ThreeAr ThreeOb where - genAr _ A C = [] - genAr c x y = defaultGenAr c x y - decompose _ GF = [G,F] - decompose c m = defaultDecompose c m - - instance PrettyPrintable ThreeOb where - pprint = show - - instance PrettyPrintable ThreeAr where - pprint = show - - instance PrettyPrintable Three where - pprint = show
− src/UsualCategories/Two.hs
@@ -1,67 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses #-} - -{-| Module : FiniteCategories -Description : The __2__ category contains two object `A` and `B` and a morphism @`F` : `A` -> `B`@. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -The __2__ category contains two object `A` and `B` and a morphism @f : `A` -> `B`@ (and of course two identities). --} - -module UsualCategories.Two -( - TwoOb(..), - TwoAr(..), - Two(..) -) -where - import FiniteCategory.FiniteCategory - import IO.PrettyPrint - - -- | Object of the __2__ category. - data TwoOb = A | B deriving (Eq, Show) - - -- | Morphism of the __2__ category. - data TwoAr = IdA | IdB | F deriving (Eq,Show) - - -- | The __2__ category. - data Two = Two deriving (Eq,Show) - - instance Morphism TwoAr TwoOb where - source IdA = A - source IdB = B - source F = A - target IdA = A - target IdB = B - target F = B - (@) IdA IdA = IdA - (@) IdB IdB = IdB - (@) F IdA = F - (@) IdB F = F - (@) x y = error ("Invalid composition of TwoMorph : "++show x++" * "++show y) - - instance FiniteCategory Two TwoAr TwoOb where - ob = const [A,B] - identity _ A = IdA - identity _ B = IdB - ar _ A A = [IdA] - ar _ A B = [F] - ar _ B B = [IdB] - ar _ _ _ = [] - - instance GeneratedFiniteCategory Two TwoAr TwoOb where - genAr = defaultGenAr - decompose = defaultDecompose - - instance PrettyPrintable TwoOb where - pprint = show - - instance PrettyPrintable TwoAr where - pprint = show - - instance PrettyPrintable Two where - pprint = show -
− src/UsualCategories/V.hs
@@ -1,74 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses #-} - -{-| Module : FiniteCategories -Description : The V category contains two arrows pointing to the same object. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -The V category contains two arrows pointing to the same object. --} - -module UsualCategories.V -( - VOb(..), - VAr(..), - V(..) -) -where - import FiniteCategory.FiniteCategory - import IO.PrettyPrint - - -- | Object of the V category. - data VOb = A | B | C deriving (Eq, Show) - - -- | Morphism of the V category. - data VAr = IdA | IdB | IdC | F | G deriving (Eq, Show) - - -- | The V category. - data V = V deriving (Eq, Show) - - instance Morphism VAr VOb where - source IdA = A - source IdB = B - source IdC = C - source F = A - source G = B - target IdA = A - target IdB = B - target IdC = C - target _ = C - (@) IdA IdA = IdA - (@) F IdA = F - (@) IdB IdB = IdB - (@) G IdB = G - (@) IdC F = F - (@) IdC G = G - (@) IdC IdC = IdC - - instance FiniteCategory V VAr VOb where - ob = const [A,B,C] - identity _ A = IdA - identity _ B = IdB - identity _ C = IdC - ar _ A A = [IdA] - ar _ A C = [F] - ar _ B B = [IdB] - ar _ B C = [G] - ar _ C C = [IdC] - ar _ _ _ = [] - - instance GeneratedFiniteCategory V VAr VOb where - genAr = defaultGenAr - decompose = defaultDecompose - - instance PrettyPrintable VOb where - pprint = show - - instance PrettyPrintable VAr where - pprint = show - - instance PrettyPrintable V where - pprint = show
− src/UsualCategories/Zero.hs
@@ -1,40 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses #-} - -{-| Module : FiniteCategories -Description : The __0__ category contains no object and no morphism. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -The __0__ category contains no object and no morphism. --} - -module UsualCategories.Zero -( - Zero(..) -) -where - import FiniteCategory.FiniteCategory - import IO.PrettyPrint - - -- | The __0__ category. - data Zero = Zero deriving (Eq, Show) - - instance Morphism Zero Zero where - source _ = error "No morphism in the zero category." - target _ = error "No morphism in the zero category." - (@) _ _ = error "No morphism in the zero category." - - instance FiniteCategory Zero Zero Zero where - ob = const [] - identity _ _ = error "No object in the zero category." - ar = const.const.const $ [] - - instance GeneratedFiniteCategory Zero Zero Zero where - genAr = ar - decompose _ _ = error "No morphism in the zero category." - - instance PrettyPrintable Zero where - pprint = show
− src/Utils/AssociationList.hs
@@ -1,108 +0,0 @@-{-| Module : FiniteCategories -Description : The type for association lists. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -The type for association lists. - -It is used when the 'Ord' constraint of `Data.Map` is too restrictive. --} - -module Utils.AssociationList -( - AssociationList, - keys, - values, - (!-), - (!-!), - (!-?), - (!-.), - mkAssocListIdentity, - enumAssocLists, - functToAssocList, - assocListToFunct, - inverse, - removeKey, - removeValue, -) -where - import Utils.CartesianProduct - import Data.Tuple (swap) - - -- | The type of association lists (a list of couples). - type AssociationList a b = [(a, b)] - - -- | Returns the keys of the association list. - keys :: (AssociationList a b) -> [a] - keys = fmap fst - - -- | Returns the values of the association list. - values :: (AssociationList a b) -> [b] - values = fmap snd - - -- | If the key is in the association list, returns Just the value associated, otherwise Nothing. - -- - -- Same as lookup in `Data.Map`. - (!-) :: (Eq a) => a -> (AssociationList a b) -> Maybe b - (!-) _ [] = Nothing - (!-) k ((a,b):xs) - | a == k = Just b - | otherwise = k !- xs - - -- | If the key is in the association list, returns the value associated, otherwise throws an error. - -- - -- Same as (!) in `Data.Map`. - (!-!) :: (Eq a) => (AssociationList a b) -> a -> b - (!-!) [] _ = error "Key not in association list." - (!-!) ((a,b):xs) k - | a == k = b - | otherwise = xs !-! k - - -- | If the key is in the association list, returns the value associated, otherwise returns a default value. - -- - -- Same as /findWithDefault/ in `Data.Map`. - (!-?) :: (Eq a) => b -> a -> (AssociationList a b) -> b - (!-?) d _ [] = d - (!-?) d k ((a,b):xs) - | a == k = b - | otherwise = (!-?) d k xs - - -- | Composition of association lists. - (!-.) :: (Eq a, Eq b) => (AssociationList b c) -> (AssociationList a b) -> (AssociationList a c) - (!-.) al2 al1 = [(k, al2 !-! (al1 !-! k)) | k <- keys al1, elem (al1 !-! k) (keys al2)] - - -- | Constructs the identity association list of a list of values. - -- - -- For example, @ mkAssocListIdentity [1,2,3] = [(1,1),(2,2),(3,3)]@ - mkAssocListIdentity :: [a] -> AssociationList a a - mkAssocListIdentity xs = [(o,o) | o <- xs] - - -- | Enumerates all association lists possible between a domain and a codomain. - enumAssocLists :: [a] -> [b] -> [AssociationList a b] - enumAssocLists dom codom = [zip dom im | im <- (codom |^| (length dom))] - - -- | Transforms a function and a domain into an association list. - functToAssocList :: (a -> b) -> [a] -> (AssociationList a b) - functToAssocList f d = [(o, f o) | o <- d] - - -- | Transforms an association list to a function. - assocListToFunct :: (Eq a) => (AssociationList a b) -> a -> b - assocListToFunct [] _ = error "Can't transform an empty list into a function." - assocListToFunct ((k,v):xs) x - | k == x = v - | otherwise = assocListToFunct xs x - - -- | Inverse of an association list - inverse :: (AssociationList a b) -> (AssociationList b a) - inverse kvs = swap <$> kvs - - -- | Remove all couples with a certain key - removeKey :: (Eq a) => (AssociationList a b) -> a -> (AssociationList a b) - removeKey al key = [c | c@(k,_) <- al, k /= key] - - -- | Remove all couples with a certain value - removeValue :: (Eq b) => (AssociationList a b) -> b -> (AssociationList a b) - removeValue al value = [c | c@(_,v) <- al, v /= value]
− src/Utils/CartesianProduct.hs
@@ -1,38 +0,0 @@-{-| Module : FiniteCategories -Description : Simple functions to compute cartesian products of finite lists. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -Simple functions to compute cartesian products of finite lists. --} - -module Utils.CartesianProduct -( - cartesianProduct, - cartesianPower, - (|*|), - (|^|) -) -where - import Data.List (replicate) - - -- | Returns the cartesian product of the finite lists. - -- - -- cartesianProduct [A,B,C,...] = A x B x C x ... - cartesianProduct :: [[a]] -> [[a]] - cartesianProduct [] = [[]] - cartesianProduct (x:xs) = concat ((\l -> [e:l | e <- x]) <$> (cartesianProduct xs)) - - -- | Returns the cartesian product of two lists - (|*|) :: [a] -> [a] -> [[a]] - x |*| y = cartesianProduct [x,y] - - -- | Returns the cartesian product of a list by itself /k/ times. - cartesianPower :: [a] -> Int -> [[a]] - cartesianPower l k = cartesianProduct $ replicate k l - - -- | Infix alias for `cartesianPower` - (|^|) = cartesianPower
− src/Utils/EnumerateMaps.hs
@@ -1,23 +0,0 @@-{-| Module : FiniteCategories -Description : Enumerate all maps between two lists. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -Enumerate all maps between two lists. --} -module Utils.EnumerateMaps -( - enumMaps -) -where - import Utils.CartesianProduct - import Utils.AssociationList - - -- | Returns all association lists from a domain to a codomain. - enumMaps :: [a] -- ^ Domain. - -> [b] -- ^ Codomain. - -> [AssociationList a b] -- ^ All association lists from domain to codomain. - enumMaps dom codom = zip dom <$> codom |^| (length dom)
− src/Utils/Sample.hs
@@ -1,38 +0,0 @@-{-| Module : FiniteCategories -Description : Sample randomly a list. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -Sample randomly a list. --} - -module Utils.Sample -( - pickOne, - sample -) -where - import System.Random (RandomGen, uniformR) - - -- | Pick one element of a list randomly. - pickOne :: (RandomGen g) => [a] -> g -> (a,g) - pickOne [] g = error "pickOne in an empty list." - pickOne l g = ((l !! index),newGen) where - (index,newGen) = (uniformR (0,(length l)-1) g) - - listWithoutNthElem :: [a] -> Int -> [a] - listWithoutNthElem [] _ = [] - listWithoutNthElem (x:xs) 0 = xs - listWithoutNthElem (x:xs) k = x:(listWithoutNthElem xs (k-1)) - - -- | Sample /n/ elements of a list randomly. - sample :: (RandomGen g) => [a] -> Int -> g -> ([a],g) - sample _ 0 g = ([],g) - sample [] k g = error "Sample size bigger than the list size." - sample l n g = ((l !! index):rest,finalGen) where - (index,newGen) = (uniformR (0,(length l)-1) g) - new_l = listWithoutNthElem l index - (rest,finalGen) = sample new_l (n-1) newGen
− src/Utils/SetList.hs
@@ -1,34 +0,0 @@-{-| Module : FiniteCategories -Description : Utilitary functions for sets with list as underlying representation. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -Utilitary functions for sets with list as underlying representation. - -It has the advantage of not requiring the Ord typeclass at all. --} - -module Utils.SetList -( - isIncludedIn, - doubleInclusion, - powerList -) where - -- | Returns a boolean indicating if the set of elements of a list are included in an another. - isIncludedIn :: (Eq a) => [a] -> [a] -> Bool - [] `isIncludedIn` _ = True - (x:xs) `isIncludedIn` l2 - | x `elem` l2 = xs `isIncludedIn` l2 - | otherwise = False - - -- | Returns a boolean indicating if the set of elements of two lists are equal. - doubleInclusion :: (Eq a) => [a] -> [a] -> Bool - l1 `doubleInclusion` l2 = (l1 `isIncludedIn` l2) && (l2 `isIncludedIn` l1) - - -- | Returns the list of all sublists of a list. - powerList :: (Eq a) => [a] -> [[a]] - powerList [] = [[]] - powerList (x:xs) = (powerList xs) ++ ((x:) <$> (powerList xs))
− src/Utils/Tuple.hs
@@ -1,34 +0,0 @@-{-| Module : FiniteCategories -Description : Utilitary functions for tuples. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -Utilitary functions for tuples. --} - -module Utils.Tuple -( -fst3, -snd3, -trd3, -uncurry3 -) -where - -- | Returns the first element of a triplet. - fst3 :: (a,b,c) -> a - fst3 (x,_,_) = x - - -- | Returns the second element of a triplet. - snd3 :: (a,b,c) -> b - snd3 (_,x,_) = x - - -- | Returns the third element of a triplet. - trd3 :: (a,b,c) -> c - trd3 (_,_,x) = x - - -- | Uncurry 3 arguments. - uncurry3 :: (a -> b -> c -> d) -> (a,b,c) -> d - uncurry3 f (a,b,c) = f a b c
− src/YonedaEmbedding/YonedaEmbedding.hs
@@ -1,69 +0,0 @@--- {-# LANGUAGE FlexibleContexts, MultiParamTypeClasses #-} - -{-| Module : FiniteCategories -Description : The Yoneda embedding of a category. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -The Yoneda embedding of a category. --} - -module YonedaEmbedding.YonedaEmbedding where - import FiniteCategory.FiniteCategory - import FunctorCategory.FunctorCategory - import Diagram.Diagram - import OppositeCategory.OppositeCategory - import Set.FinSet - import Utils.AssociationList - import Subcategories.Subcategory - import Currying.Currying - import OppositeCategory.OppositeCategory - import Limit.Limit - import ConeCategory.ConeCategory - import DiagonalFunctor.DiagonalFunctor - import Utils.Tuple - - import IO.PrettyPrint - - -- | A presheaf on a category @C@ is a diagram from @C^op@ to __Set__. - type PreSheaf c m o = Diagram (OppositeCategory c m o) (OppositeMorphism m o) o (FinSetCat m) (FinMap m) (FinSet m) - - -- | Natural transformation between presheaves. - type PreSheavesNatTransfo c m o = NaturalTransformation (OppositeCategory c m o) (OppositeMorphism m o) o (FinSetCat m) (FinMap m) (FinSet m) - - -- | The type of the category of presheaves. - type PreSheavesCategory c m o = FunctorCategory (OppositeCategory c m o) (OppositeMorphism m o) o (FinSetCat m) (FinMap m) (FinSet m) - - -- | Returns the presheaf category generated by a Yoneda embedding and an insertion functor full and faithful. - yonedaEmbedding :: (FiniteCategory c m o, Morphism m o, Eq m, Eq o) => c -> (PreSheavesCategory c m o, Diagram c m o (PreSheavesCategory c m o) (PreSheavesNatTransfo c m o) (PreSheaf c m o)) - yonedaEmbedding cat = (presheavesCat, functor) - where - hom x = fromList $ fromList <$> (\s -> Elem <$> ar cat s x) <$> (ob cat) - omapPresheaf x s = fromList $ Elem <$> ar cat s x - mmapPresheaf x m = FinMap{codomain = omapPresheaf x (target m) - , finMap = zip (toList (omapPresheaf x (source m))) ((\f -> fmap (@ (opOpMorph m)) f) <$> (toList (omapPresheaf x (source m))))} - presheaf x = Diagram { src = Op cat - , tgt = FinSetCat $ toList $ union $ hom <$> ob cat - , omap = functToAssocList (omapPresheaf x) (ob (Op cat)) - , mmap = functToAssocList (mmapPresheaf x) (arrows (Op cat))} - - ntFromMorph m o = FinMap {codomain = (omap $ presheaf (target m)) !-! o - , finMap = zip (toList domain) (toList postcom) } - where - domain = (omap $ presheaf (source m)) !-! o - postcom = (m @) `fmap` domain - mmapFunctor m = NaturalTransformation { srcNT = presheaf (source m) - , tgtNT = presheaf (target m) - , component = ntFromMorph m} - - presheavesCat = FunctorCategory { sourceCat = Op cat - , targetCat = FinSetCat $ concat (toList <$> (hom <$> ob cat))} - functor = Diagram { src = cat - , tgt = presheavesCat - , omap = functToAssocList presheaf (ob cat) - , mmap = functToAssocList mmapFunctor (arrows cat) - } -
+ test/CheckAllFiniteCategories.hs view
@@ -0,0 +1,69 @@+{-| Module : FiniteCategories +Description : Check the structure of every finite categories defined in this package. +Copyright : Guillaume Sabbagh 2021 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +Check the structure of every finite categories defined in this package. +-} +module CheckAllFiniteCategories +( + main +) +where + import Math.FiniteCategory + import Math.FiniteCategoryError + import Math.Categories + import Math.FiniteCategories + + 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 Math.PureSet + import Data.Text (Text, pack) + import Data.Maybe (fromJust) + + import Numeric.Natural + + assert :: (Show c, Show m, Show o, Eq m, Eq o, FiniteCategory c m o, Morphism m o) => c -> IO () + assert cat + | null check = putStrLn $ (show cat)++" passed" + | otherwise = do + putStrLn $ (show cat)++" failed: "++(show err) + error "Assertion failed" + where + check = checkFiniteCategory cat + Just err = check + + -- | Check the structure of every finite categories defined in this package. + main = do + putStrLn "Start of CheckAllFiniteCategories" + assert $ V + assert $ Hat + assert $ Parallel + assert $ discreteCategory $ set [1,2,3,4 :: Int] + assert $ numberCategory 5 + assert $ Square + assert $ ens.(Set.powerSet).set $ "ABC" + assert $ (FullSubcategory FinGrph $ (underlyingGraphFormat id (const.pack $ "")).numberCategory <$> set [0..2] :: FullSubcategory (FinGrph Natural Text) (GraphHomomorphism Natural Text) (Graph Natural Text)) + assert $ (Op (ens.(Set.powerSet).set $ "ABC")) + assert $ (FullSubcategory FinCat (numberCategory <$> (set [0..3])) :: FullSubcategory (FinCat NumberCategory NumberCategoryMorphism Natural) (FinFunctor NumberCategory NumberCategoryMorphism Natural) NumberCategory) + assert $ FunctorCategory (numberCategory 2) (numberCategory 4) + assert $ (unsafeCompositionGraph (unsafeGraph (set [1 :: Int,2,3]) (set [Arrow{sourceArrow=1,targetArrow=1,labelArrow='a'},Arrow{sourceArrow=1,targetArrow=2,labelArrow='b'},Arrow{sourceArrow=2,targetArrow=3,labelArrow='c'}])) (weakMap [([Arrow{sourceArrow=1,targetArrow=1,labelArrow='a'},Arrow{sourceArrow=1,targetArrow=1,labelArrow='a'}],[Arrow{sourceArrow=1,targetArrow=1,labelArrow='a'}])])) + assert $ (tgt (finiteCategoryToCompositionGraph (ens.(Set.powerSet).set $ "AB"))) + assert $ (unsafeSafeCompositionGraph (unsafeGraph (set [1 :: Int]) (set [Arrow{sourceArrow=1,targetArrow=1,labelArrow='a'}])) (weakMap []) 3) + assert $ fromJust $ sliceCategory (numberCategory 4) 2 + assert $ fromJust $ cosliceCategory (numberCategory 4) 2 + assert $ arrowCategory (numberCategory 4) + assert $ One + let diag = completeDiagram Diagram{src=V,tgt=Square,omap=weakMap [(VA,SquareD),(VB,SquareB),(VC,SquareC)], mmap=weakMap [(VF,SquareH),(VG,SquareI)]} + assert $ coneCategory diag + let diag2 = completeDiagram Diagram{src=Hat,tgt=Square,omap=weakMap [(HatA,SquareA),(HatB,SquareB),(HatC,SquareC)], mmap=weakMap [(HatF,SquareF),(HatG,SquareG)]} + assert $ coconeCategory diag2 + assert $ (embeddingToSubcategory.yonedaEmbedding $ Square) + putStrLn "End of CheckAllFiniteCategories"
− test/ExampleAdjunction/ExampleAdjunction.hs
@@ -1,44 +0,0 @@-{-| Module : FiniteCategories -Description : An example of adjunction. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of adjunction. --} -module ExampleAdjunction.ExampleAdjunction -( - main -) -where - import ExportGraphViz.ExportGraphViz (catToPdf,genToPdf, diagToPdf, diagToPdf2, natToPdf) - import Diagram.Diagram - import Limit.Limit - import UsualCategories.DiscreteCategory - import Utils.AssociationList - import CompositionGraph.CompositionGraph - import IO.Parsers.Lexer - import IO.Parsers.SafeCompositionGraph - import IO.Parsers.SafeCompositionGraphFunctor - import FunctorCategory.FunctorCategory - import FiniteCategory.FiniteCategory - import ConeCategory.ConeCategory - - -- | Export the categories defined above as pdf with GraphViz. - main = do - putStrLn "Start of ExampleAdjunction" - cg <- readSCGFile "test/ExampleAdjunction/ExampleAdjunction.scg" - catToPdf cg "OutputGraphViz/Examples/Adjunction/category" - diag1 <- readFSCGFile "test/ExampleAdjunction/ExampleAdjunctionDiag1.fscg" - diagToPdf2 diag1 "OutputGraphViz/Examples/Adjunction/diag1" - diag2 <- readFSCGFile "test/ExampleAdjunction/ExampleAdjunctionDiag2.fscg" - diagToPdf2 diag2 "OutputGraphViz/Examples/Adjunction/diag2" - catToPdf (mkConeCategory diag1) "OutputGraphViz/Examples/Adjunction/coneCat1" - catToPdf (mkConeCategory diag2) "OutputGraphViz/Examples/Adjunction/coneCat2" - putStrLn $ show $ (omap (limitFunctor (src diag1) (tgt diag1))) !-! diag1 - putStrLn $ show $ (omap (limitFunctor (src diag2) (tgt diag2))) !-! diag2 - putStrLn $ show $ (mmap (limitFunctor (src diag1) (tgt diag1))) !-! (head (ar FunctorCategory{sourceCat = src diag1, targetCat = tgt diag1} diag1 diag2)) - putStrLn "End of ExampleAdjunction" -
− test/ExampleAdjunction/ExampleAdjunction.scg
@@ -1,14 +0,0 @@-6 - - -A -1-> B -B -5-> E -A -2-> C -C -6-> F -D -3-> E -D -4-> F -A -7-> D - - -A -7-> D -4-> F = A -2-> C -6-> F -A -7-> D -3-> E = A -1-> B -5-> E
− test/ExampleAdjunction/ExampleAdjunctionDiag1.fscg
@@ -1,21 +0,0 @@-<SRC> -6 -0 -1 -</SRC> - -<TGT> -6 -A -1-> B -B -5-> E -A -2-> C -C -6-> F -D -3-> E -D -4-> F -A -7-> D -A -7-> D -4-> F = A -2-> C -6-> F -A -7-> D -3-> E = A -1-> B -5-> E -</TGT> - -0 => B -1 => C
− test/ExampleAdjunction/ExampleAdjunctionDiag2.fscg
@@ -1,21 +0,0 @@-<SRC> -6 -0 -1 -</SRC> - -<TGT> -6 -A -1-> B -B -5-> E -A -2-> C -C -6-> F -D -3-> E -D -4-> F -A -7-> D -A -7-> D -4-> F = A -2-> C -6-> F -A -7-> D -3-> E = A -1-> B -5-> E -</TGT> - -0 => E -1 => F
− test/ExampleCat/ExampleCat.hs
@@ -1,41 +0,0 @@-{-| Module : FiniteCategories -Description : An example of a category of categories. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of category of categories. --} -module ExampleCat.ExampleCat -( - set1, set2, cat, - main -) -where - import Prelude hiding (fmap, Functor) - import Cat.FinCat (FinCat(..)) - import Set.FinOrdSet (FinOrdSet(..)) - import Data.Set (fromList) - import ExportGraphViz.ExportGraphViz (catToPdf,genToPdf) - import Cat.FinCat - import FiniteCategory.FiniteCategory - - -- | A category with {1,2} and {3} as object and applications as morphisms. - set1 = FinOrdSet [fromList [1, 2], fromList [3]] :: FinOrdSet Int - -- | A category with {1,2} as object and applications as morphisms. - set2 = FinOrdSet [fromList [1,2]] :: FinOrdSet Int - - -- | A category with the two previous categories as objects - cat = FinCat [set1,set2] - - -- | Export all the previously defined categories as pdf with GraphViz. - main = do - putStrLn "Start of ExampleCat" - catToPdf set1 "OutputGraphViz/Examples/Cat/CatOfSet/set1" - catToPdf set2 "OutputGraphViz/Examples/Cat/CatOfSet/set2" - catToPdf cat "OutputGraphViz/Examples/Cat/CatOfSet/cat" - putStrLn "End of ExampleCat" - -
− test/ExampleCat/ExampleFunctor.hs
@@ -1,41 +0,0 @@-{-| Module : FiniteCategories -Description : An example of functor. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of functor. --} -module ExampleCat.ExampleFunctor -( - funct, - main -) -where - import Cat.FinCat (FinCat(..)) - import FiniteCategory.FiniteCategory - import RandomCompositionGraph.RandomCompositionGraph - import CompositionGraph.CompositionGraph - import System.Random - import ExportGraphViz.ExportGraphViz (catToPdf,genToPdf,diagToPdf,diagToPdf2) - import Cat.FinCat - import Diagram.Conversion - - (rcg1,newGen) = (mkRandomCompositionGraph 5 10 5 (mkStdGen 8)) - - cat = FinCat [rcg1] - - -- | An arbitrary functor from the random composition graph to itself. - funct = (arrows cat) !! 51 - - -- | Export the category of finCat containing a random composition graph as a pdf with GraphViz. - main = do - putStrLn "Start of ExampleFunctor" - catToPdf rcg1 "OutputGraphViz/Examples/Cat/Functor/rcg1" - catToPdf cat "OutputGraphViz/Examples/Cat/Functor/catRCG" - diagToPdf (finFunctorToDiagram funct) "OutputGraphViz/Examples/Cat/Functor/functor" - diagToPdf2 (finFunctorToDiagram funct) "OutputGraphViz/Examples/Cat/Functor/diag" - putStrLn "End of ExampleFunctor" -
− test/ExampleCat/ExamplePartialFinCat.hs
@@ -1,40 +0,0 @@-{-| Module : FiniteCategories -Description : An example of a category of categories with partial functors. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of category of categories with partial functors. --} -module ExampleCat.ExamplePartialFinCat -( - set1, set2, cat, - main -) -where - import Prelude hiding (fmap, Functor) - import Cat.PartialFinCat (PartialFinCat(..)) - import Set.FinOrdSet (FinOrdSet(..)) - import Data.Set (fromList) - import ExportGraphViz.ExportGraphViz (catToPdf,genToPdf) - import FiniteCategory.FiniteCategory - - -- | A category with {1,2} and {3} as object and applications as morphisms. - set1 = FinOrdSet [fromList [1]] :: FinOrdSet Int - -- | A category with {1,2} as object and applications as morphisms. - set2 = FinOrdSet [fromList [1,2]] :: FinOrdSet Int - - -- | A category with the two previous categories as objects - cat = PartialFinCat [set1,set2] - - -- | Export all the previously defined categories as pdf with GraphViz. - main = do - putStrLn "Start of ExamplePartialFinCat" - catToPdf set1 "OutputGraphViz/Examples/Cat/PartialFinCat/set1" - catToPdf set2 "OutputGraphViz/Examples/Cat/PartialFinCat/set2" - catToPdf cat "OutputGraphViz/Examples/Cat/PartialFinCat/catOfCat" - putStrLn "End of ExamplePartialFinCat" - -
− test/ExampleCommaCategory/ExampleArrowCategory.hs
@@ -1,34 +0,0 @@-{-| Module : FiniteCategories -Description : An example of arrow category. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of arrow category. --} -module ExampleCommaCategory.ExampleArrowCategory -( - arrowCategory, - main -) -where - import RandomCompositionGraph.RandomCompositionGraph - import System.Random - import ExportGraphViz.ExportGraphViz (catToPdf,diagToPdf,diagToPdf2) - import FiniteCategory.FiniteCategory - import CommaCategory.CommaCategory - - (rcg1,newGen) = (mkRandomCompositionGraph 5 10 3 (mkStdGen 8789)) - - -- | The category of arrows of a random composition graph. - arrowCategory = mkArrowCategory rcg1 - - -- | Export the arrow category as a pdf with GraphViz. - main = do - putStrLn "Start of ExampleArrowCategory" - catToPdf rcg1 "OutputGraphViz/Examples/CommaCategory/ArrowCategory/rcg" - catToPdf arrowCategory "OutputGraphViz/Examples/CommaCategory/ArrowCategory/arrow" - putStrLn "End of ExampleArrowCategory" -
− test/ExampleCommaCategory/ExampleCosliceCategory.hs
@@ -1,37 +0,0 @@-{-| Module : FiniteCategories -Description : An example of coslice category. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of coslice category. --} -module ExampleCommaCategory.ExampleCosliceCategory -( - cosliceCategory, - main -) -where - import RandomCompositionGraph.RandomCompositionGraph - import System.Random - import ExportGraphViz.ExportGraphViz (catToPdf,diagToPdf,diagToPdf2) - import Diagram.Diagram (mkIdentityDiagram) - import FiniteCategory.FiniteCategory - import CommaCategory.CommaCategory - import Utils.Sample - import Data.Maybe - - (rcg1,newGen) = (defaultMkRandomCompositionGraph (mkStdGen 834589)) - - -- | The category of objects under a random one. - cosliceCategory = fromJust $ mkCosliceCategory rcg1 (fst (pickOne (ob rcg1) newGen)) - - -- | Export the coslice category as a pdf with GraphViz. - main = do - putStrLn "Start of ExampleCosliceCategory" - catToPdf rcg1 "OutputGraphViz/Examples/CommaCategory/CosliceCategory/rcg" - catToPdf cosliceCategory "OutputGraphViz/Examples/CommaCategory/CosliceCategory/coslice" - putStrLn "End of ExampleCosliceCategory" -
− test/ExampleCommaCategory/ExampleSliceCategory.hs
@@ -1,37 +0,0 @@-{-| Module : FiniteCategories -Description : An example of slice category. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of slice category. --} -module ExampleCommaCategory.ExampleSliceCategory -( - sliceCategory, - main -) -where - import RandomCompositionGraph.RandomCompositionGraph - import System.Random - import ExportGraphViz.ExportGraphViz (catToPdf,diagToPdf,diagToPdf2) - import Diagram.Diagram (mkIdentityDiagram) - import FiniteCategory.FiniteCategory - import CommaCategory.CommaCategory - import Utils.Sample - import Data.Maybe - - (rcg1,newGen) = (defaultMkRandomCompositionGraph (mkStdGen 83456789)) - - -- | The category of objects over a random one. - sliceCategory = fromJust $ mkSliceCategory rcg1 (fst (pickOne (ob rcg1) newGen)) - - -- | Export the slice category as a pdf with GraphViz. - main = do - putStrLn "Start of ExampleSliceCategory" - catToPdf rcg1 "OutputGraphViz/Examples/CommaCategory/SliceCategory/rcg" - catToPdf sliceCategory "OutputGraphViz/Examples/CommaCategory/SliceCategory/slice" - putStrLn "End of ExampleSliceCategory" -
− test/ExampleCompositionGraph/ExampleCompositionGraph.hs
@@ -1,44 +0,0 @@-{-| Module : FiniteCategories -Description : An example of composition graph. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of composition graph. --} -module ExampleCompositionGraph.ExampleCompositionGraph -( - square, main -) -where - import CompositionGraph.CompositionGraph - import ExportGraphViz.ExportGraphViz (catToPdf) - import qualified FiniteCategory.FiniteCategory as FinCat (FiniteCategoryError(..)) - import Data.Text (Text, pack) - - f = (0, 1, pack "f") :: Arrow Int Text - g = (1, 2, pack "g") :: Arrow Int Text - h = (0, 3, pack "h") :: Arrow Int Text - i = (3, 2, pack "i") :: Arrow Int Text - - -- | A composition law defined by hand. - myLaw = [([g,f],[i,h])] - - myGraph = ([0, 1, 2, 3], [f,g,h,i]) - -- | An example of a composition graph - Right square = mkCompositionGraph myGraph myLaw - - my_sub_graph = ([0, 1, 3], [f,g,h,i]) - -- | A composition subgraph of the previous composition graph. - csg = mkCompositionGraph my_sub_graph myLaw - - -- | Exports the composition graphs as pdf files with GraphViz. - main = main_ square csg where - main_ _ (Left err) = putStrLn.show $ err - main_ square (Right csg) = do - putStrLn "Start of ExampleCompositionGraph" - catToPdf square "OutputGraphViz/Examples/CompositionGraph/CompositionGraph/compositionGraph" - catToPdf csg "OutputGraphViz/Examples/CompositionGraph/CompositionGraph/compositionGraph2" - putStrLn "End of ExampleCompositionGraph"
− test/ExampleCompositionGraph/ExampleCompositionGraphConstruction.hs
@@ -1,80 +0,0 @@-{-| Module : FiniteCategories -Description : An example of `CompositionGraph` construction with insertion, modification and deletion. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of `CompositionGraph` construction with insertion, modification and deletion. --} -module ExampleCompositionGraph.ExampleCompositionGraphConstruction -( - main -) -where - import CompositionGraph.CompositionGraph - import ExportGraphViz.ExportGraphViz - import Diagram.Diagram - import FiniteCategory.FiniteCategory - import Data.Text (Text, pack) - import Data.List ((\\)) - import Diagram.Conversion - - cg1 = mkEmptyCompositionGraph :: CompositionGraph Text Text - (cg2,funct2) = insertObject cg1 (pack "1") - (cg3,funct3) = insertObject cg2 (pack "2") - Right (cg4,funct4) = insertMorphism cg3 ((pack "1")) ((pack "2")) (pack "f") - Right (cg5,funct5) = insertMorphism cg4 ((pack "1")) ((pack "1")) (pack "g") - Right (cg6,funct6) = identifyMorphisms cg5 ((head [f | f <- genAr cg5 ((pack "1")) ((pack "1")), isNotIdentity cg5 f]) @ (head [f | f <- genAr cg5 ((pack "1")) ((pack "1")), isNotIdentity cg5 f])) (head [f | f <- genAr cg5 ((pack "1")) ((pack "1")), isNotIdentity cg5 f]) - Right (cg7,funct7) = replaceObject cg6 (pack "2") (pack "3") - Right (cg8,funct8) = replaceMorphism cg7 (head (ar cg7 (pack "1") (pack "3"))) (pack "h") - (cg9,funct9) = insertObject cg8 (pack "4") - Right (cg10,funct10) = insertMorphism cg9 ((pack "3")) ((pack "4")) (pack "i") - Right (cg11,funct11) = insertMorphism cg10 ((pack "1")) ((pack "4")) (pack "j") - Right (cg12,funct12) = identifyMorphisms cg11 (((ar cg11 (pack "1") (pack "4")) \\ (genAr cg11 (pack "1") (pack "4")))!!1) (head (genAr cg11 (pack "1") (pack "4"))) - Right (cg13,funct13) = deleteMorphism cg12 (head (genAr cg12 (pack "1") (pack "4"))) - Right (cg14,funct14) = deleteObject cg13 (pack "4") - Right (cg15,funct15) = identifyMorphisms cg14 ((ar cg14 (pack "1") (pack "3"))!!1) ((ar cg14 (pack "1") (pack "3"))!!0) - Right (cg16,funct16) = unidentifyMorphism cg15 ((ar cg15 (pack "1") (pack "3"))!!0) - - Just diag2 = partialFunctorToDiagram funct2 - Just diag3 = partialFunctorToDiagram funct3 - Just diag4 = partialFunctorToDiagram funct4 - -- we don't create diag5 and diag6 because their are not showable as categories are infinite. - Just diag7 = partialFunctorToDiagram funct7 - Just diag8 = partialFunctorToDiagram funct8 - Just diag9 = partialFunctorToDiagram funct9 - Just diag10 = partialFunctorToDiagram funct10 - Just diag11 = partialFunctorToDiagram funct11 - -- we don't create diag12, diag13, diag14 and diag15 because they are not total. - Just diag16 = partialFunctorToDiagram funct16 - - -- | Exports the composition graphs and insertion functors as pdf file with GraphViz. - main = do - putStrLn "Start of ExampleCompositionGraphConstruction" - catToPdf cg1 "OutputGraphViz/Examples/CompositionGraph/CompositionGraphConstruction/cat1" - catToPdf cg2 "OutputGraphViz/Examples/CompositionGraph/CompositionGraphConstruction/cat2" - catToPdf cg3 "OutputGraphViz/Examples/CompositionGraph/CompositionGraphConstruction/cat3" - catToPdf cg4 "OutputGraphViz/Examples/CompositionGraph/CompositionGraphConstruction/cat4" - catToPdf cg6 "OutputGraphViz/Examples/CompositionGraph/CompositionGraphConstruction/cat6" - catToPdf cg7 "OutputGraphViz/Examples/CompositionGraph/CompositionGraphConstruction/cat7" - catToPdf cg8 "OutputGraphViz/Examples/CompositionGraph/CompositionGraphConstruction/cat8" - catToPdf cg9 "OutputGraphViz/Examples/CompositionGraph/CompositionGraphConstruction/cat9" - catToPdf cg10 "OutputGraphViz/Examples/CompositionGraph/CompositionGraphConstruction/cat10" - catToPdf cg11 "OutputGraphViz/Examples/CompositionGraph/CompositionGraphConstruction/cat11" - catToPdf cg12 "OutputGraphViz/Examples/CompositionGraph/CompositionGraphConstruction/cat12" - catToPdf cg13 "OutputGraphViz/Examples/CompositionGraph/CompositionGraphConstruction/cat13" - catToPdf cg14 "OutputGraphViz/Examples/CompositionGraph/CompositionGraphConstruction/cat14" - catToPdf cg15 "OutputGraphViz/Examples/CompositionGraph/CompositionGraphConstruction/cat15" - catToPdf cg16 "OutputGraphViz/Examples/CompositionGraph/CompositionGraphConstruction/cat16" - diagToPdf diag2 "OutputGraphViz/Examples/CompositionGraph/CompositionGraphConstruction/funct2" - diagToPdf diag3 "OutputGraphViz/Examples/CompositionGraph/CompositionGraphConstruction/funct3" - diagToPdf diag4 "OutputGraphViz/Examples/CompositionGraph/CompositionGraphConstruction/funct4" - diagToPdf diag7 "OutputGraphViz/Examples/CompositionGraph/CompositionGraphConstruction/funct7" - diagToPdf diag8 "OutputGraphViz/Examples/CompositionGraph/CompositionGraphConstruction/funct8" - diagToPdf diag9 "OutputGraphViz/Examples/CompositionGraph/CompositionGraphConstruction/funct9" - diagToPdf diag10 "OutputGraphViz/Examples/CompositionGraph/CompositionGraphConstruction/funct10" - diagToPdf diag11 "OutputGraphViz/Examples/CompositionGraph/CompositionGraphConstruction/funct11" - diagToPdf diag16 "OutputGraphViz/Examples/CompositionGraph/CompositionGraphConstruction/funct16" - putStrLn "End of ExampleCompositionGraphConstruction"
− test/ExampleCompositionGraph/ExampleFinSetToCompositionGraph.hs
@@ -1,34 +0,0 @@-{-| Module : FiniteCategories -Description : An example of conversion from a `FinOrdSet` category to a `CompositionGraph`. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of conversion from a `FinOrdSet` category to a `CompositionGraph`. --} -module ExampleCompositionGraph.ExampleFinSetToCompositionGraph -( - main -) -where - import CompositionGraph.CompositionGraph - import Set.FinOrdSet - import Data.Set (fromList) - import ExportGraphViz.ExportGraphViz - import qualified FiniteCategory.FiniteCategory as FinCat (FiniteCategoryError(..)) - import Data.Text (Text, pack) - - finSet = FinOrdSet [fromList [1,2], fromList [3]] :: FinOrdSet Int - - (cg, iso) = generatedFiniteCategoryToCompositionGraph finSet - - -- | Exports the composition graph as pdf file with GraphViz. - main = do - putStrLn "Start of ExampleFinSetToCompositionGraph" - catToPdf finSet "OutputGraphViz/Examples/CompositionGraph/FinSetToCompositionGraph/finSet" - catToPdf cg "OutputGraphViz/Examples/CompositionGraph/FinSetToCompositionGraph/compositionGraph" - diagToPdf iso "OutputGraphViz/Examples/CompositionGraph/FinSetToCompositionGraph/funct" - diagToPdf2 iso "OutputGraphViz/Examples/CompositionGraph/FinSetToCompositionGraph/diag" - putStrLn "End of ExampleFinSetToCompositionGraph"
− test/ExampleCompositionGraph/ExampleSafeCompositionGraph.hs
@@ -1,47 +0,0 @@-{-| Module : FiniteCategories -Description : An example of safe composition graph. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of safe composition graph. --} -module ExampleCompositionGraph.ExampleSafeCompositionGraph -( - squareS, main -) -where - import CompositionGraph.CompositionGraph - import CompositionGraph.SafeCompositionGraph - import ExportGraphViz.ExportGraphViz (catToPdf) - import qualified FiniteCategory.FiniteCategory as FinCat (FiniteCategoryError(..)) - import Data.Text (Text, pack) - - f = (0, 1, pack "f") :: Arrow Int Text - g = (1, 2, pack "g") :: Arrow Int Text - h = (0, 3, pack "h") :: Arrow Int Text - i = (3, 2, pack "i") :: Arrow Int Text - j = (3, 3, pack "j") :: Arrow Int Text - - -- | A composition law defined by hand. - myLaw = [([g,f],[i,h])] - - myGraph = ([0, 1, 2, 3], [f,g,h,i,j]) - -- | An example of a composition graph - squareS = mkSafeCompositionGraph myGraph myLaw 3 - - my_sub_graph = ([0, 1, 2], [f,j]) - -- | A composition subgraph of the previous composition graph. - csg = mkSafeCompositionGraph my_sub_graph myLaw 2 - - -- | Exports the composition graphs as pdf files with GraphViz. - main = main_ squareS csg where - main_ (Left err) _ = putStrLn.show $ err - main_ _ (Left err) = putStrLn.show $ err - main_ (Right squareS) (Right csg) = do - putStrLn "Start of ExampleSafeCompositionGraph" - catToPdf squareS "OutputGraphViz/Examples/CompositionGraph/SafeCompositionGraph/compositionGraph" - catToPdf csg "OutputGraphViz/Examples/CompositionGraph/SafeCompositionGraph/compositionGraph2" - putStrLn "End of ExampleSafeCompositionGraph"
− test/ExampleConeCategory/ExampleCoconeCategory.hs
@@ -1,44 +0,0 @@-{-| Module : FiniteCategories -Description : An example of cocone category. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of cocone category. --} -module ExampleConeCategory.ExampleCoconeCategory -( - main -) -where - import RandomCompositionGraph.RandomCompositionGraph - import System.Random - import ExportGraphViz.ExportGraphViz - import FiniteCategory.FiniteCategory - import FunctorCategory.FunctorCategory - import Diagram.Diagram - import UsualCategories.Three - import Utils.Sample - import Data.Maybe - import ConeCategory.ConeCategory - import IO.PrettyPrint - - (rcg,newGen) = (mkRandomCompositionGraph 20 25 5 (mkStdGen 878)) - - (diag,newGen1) = (pickOne (ob FunctorCategory{sourceCat=Three, targetCat=rcg}) newGen) - - coconeCategory = mkCoconeCategory diag - - -- | Export the cocone category as a pdf with GraphViz. - main = do - putStrLn "Start of ExampleCoconeCategory" - catToPdf rcg "OutputGraphViz/Examples/ConeCategory/Cocone/rcg" - diagToPdf diag "OutputGraphViz/Examples/ConeCategory/Cocone/funct" - diagToPdf2 diag "OutputGraphViz/Examples/ConeCategory/Cocone/diag" - catToPdf coconeCategory "OutputGraphViz/Examples/ConeCategory/Cocone/coconeCategory" - putStrLn "Colimits : " - putStrLn $ pprint $ initialObjects coconeCategory - putStrLn "End of ExampleCoconeCategory" -
− test/ExampleConeCategory/ExampleColimit.hs
@@ -1,46 +0,0 @@-{-| Module : FiniteCategories -Description : An example of colimits of a diagram. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of colimits of a diagram. --} -module ExampleConeCategory.ExampleColimit -( - main -) -where - import RandomCompositionGraph.RandomCompositionGraph - import System.Random - import ExportGraphViz.ExportGraphViz - import FiniteCategory.FiniteCategory - import FunctorCategory.FunctorCategory - import Diagram.Diagram - import UsualCategories.Three - import Utils.Sample - import ConeCategory.ConeCategory - - (rcg,newGen) = (mkRandomCompositionGraph 20 25 5 (mkStdGen 878)) - - (diag,newGen1) = (pickOne (ob FunctorCategory{sourceCat=Three, targetCat=rcg}) newGen) - - colimit = colimits diag - - recuNatToPdf [] = putStrLn "End of natural transformation export" - recuNatToPdf (x:xs) = do - natToPdf (coconeToNaturalTransformation x) ("OutputGraphViz/Examples/ConeCategory/Colimit/nat"++show (length xs)) - putStrLn $ show $ (naturalTransformationToCocone (coconeToNaturalTransformation x)) == x - recuNatToPdf xs - - -- | Export the colimits as a pdf with GraphViz. - main = do - putStrLn "Start of ExampleColimit" - catToPdf rcg "OutputGraphViz/Examples/ConeCategory/Colimit/rcg" - diagToPdf diag "OutputGraphViz/Examples/ConeCategory/Colimit/funct" - diagToPdf2 diag "OutputGraphViz/Examples/ConeCategory/Colimit/diag" - recuNatToPdf colimit - putStrLn "End of ExampleColimit" -
− test/ExampleConeCategory/ExampleConeCategory.hs
@@ -1,42 +0,0 @@-{-| Module : FiniteCategories -Description : An example of cone category. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of cone category. --} -module ExampleConeCategory.ExampleConeCategory -( - main -) -where - import RandomCompositionGraph.RandomCompositionGraph - import System.Random - import ExportGraphViz.ExportGraphViz - import FiniteCategory.FiniteCategory - import FunctorCategory.FunctorCategory - import Diagram.Diagram - import UsualCategories.Three - import Utils.Sample - import Data.Maybe - import ConeCategory.ConeCategory - import CommaCategory.CommaCategory - import IO.PrettyPrint - import RandomDiagram.RandomDiagram - import IO.Parsers.SafeCompositionGraphFunctor - - -- | Export the cone category as a pdf with GraphViz. - main = do - putStrLn "Start of ExampleConeCategory" - diag <- readFSCGFile "test/ExampleConeCategory/diagram.fscg" - let coneCategory = mkConeCategory diag - catToPdf (tgt diag) "OutputGraphViz/Examples/ConeCategory/Cone/category" - diagToPdf diag "OutputGraphViz/Examples/ConeCategory/Cone/funct" - diagToPdf2 diag "OutputGraphViz/Examples/ConeCategory/Cone/diag" - catToPdf coneCategory "OutputGraphViz/Examples/ConeCategory/Cone/coneCategory" - sequence $ (\(x,y) -> natToPdf (arrow x) ("OutputGraphViz/Examples/ConeCategory/Cone/cone"++(show y))) <$> (zip (ob coneCategory) [1..]) - putStrLn "End of ExampleConeCategory" -
− test/ExampleConeCategory/ExampleLeftCone.hs
@@ -1,40 +0,0 @@-{-| Module : FiniteCategories -Description : An example of cone category. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of cone category. --} -module ExampleConeCategory.ExampleLeftCone -( - main -) -where - import System.Random - import ExportGraphViz.ExportGraphViz - import ConeCategory.LeftCone - import Diagram.Diagram - import FiniteCategory.FiniteCategory - import IO.Parsers.SafeCompositionGraphFunctor - - -- | Export the cone category as a pdf with GraphViz. - main = do - putStrLn "Start of ExampleLeftCone" - diag <- readFSCGFile "test/ExampleConeCategory/diagram.fscg" - let leftCone = LeftCone (src diag) - let inclusionLeftCone = inclusionFunctor leftCone - let coneCat = ConeCategory diag - catToPdf (src diag) "OutputGraphViz/Examples/ConeCategory/LeftCone/I" - catToPdf leftCone "OutputGraphViz/Examples/ConeCategory/LeftCone/leftCone" - diagToPdf inclusionLeftCone "OutputGraphViz/Examples/ConeCategory/LeftCone/inclusionFunctor" - diagToPdf2 inclusionLeftCone "OutputGraphViz/Examples/ConeCategory/LeftCone/inclusionDiagram" - diagToPdf diag "OutputGraphViz/Examples/ConeCategory/LeftCone/diagAsFunct" - diagToPdf2 diag "OutputGraphViz/Examples/ConeCategory/LeftCone/diag" - catToPdf coneCat "OutputGraphViz/Examples/ConeCategory/LeftCone/coneCategory" - diagToPdf ((ob coneCat) !! 0) "OutputGraphViz/Examples/ConeCategory/LeftCone/exampleOfCone" - diagToPdf2 ((ob coneCat) !! 0) "OutputGraphViz/Examples/ConeCategory/LeftCone/exampleOfConeAsDiag" - putStrLn "End of ExampleLeftCone" -
− test/ExampleConeCategory/ExampleLimit.hs
@@ -1,45 +0,0 @@-{-| Module : FiniteCategories -Description : An example of limits of a diagram. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of limits of a diagram. --} -module ExampleConeCategory.ExampleLimit -( - main -) -where - import RandomCompositionGraph.RandomCompositionGraph - import System.Random - import ExportGraphViz.ExportGraphViz - import FiniteCategory.FiniteCategory - import FunctorCategory.FunctorCategory - import Diagram.Diagram - import UsualCategories.Three - import Utils.Sample - import ConeCategory.ConeCategory - - (rcg,newGen) = (mkRandomCompositionGraph 20 25 5 (mkStdGen 878)) - - (diag,newGen1) = (pickOne (ob FunctorCategory{sourceCat=Three, targetCat=rcg}) newGen) - - limit = limits diag - - recuNatToPdf [] = putStrLn "End of natural transformation export" - recuNatToPdf (x:xs) = do - natToPdf (coneToNaturalTransformation x) ("OutputGraphViz/Examples/ConeCategory/Limit/nat"++show (length xs)) - recuNatToPdf xs - - -- | Export the limits as a pdf with GraphViz. - main = do - putStrLn "Start of ExampleLimit" - catToPdf rcg "OutputGraphViz/Examples/ConeCategory/Limit/rcg" - diagToPdf diag "OutputGraphViz/Examples/ConeCategory/Limit/funct" - diagToPdf2 diag "OutputGraphViz/Examples/ConeCategory/Limit/diag" - recuNatToPdf limit - putStrLn "End of ExampleLimit" -
− test/ExampleCurrying/ExampleCurrying.hs
@@ -1,43 +0,0 @@-{-| Module : FiniteCategories -Description : An example of currying a functor. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of currying a functor. --} -module ExampleCurrying.ExampleCurrying -( - main -) -where - import ExportGraphViz.ExportGraphViz (catToPdf,genToPdf, diagToPdf2) - import FiniteCategory.FiniteCategory - import UsualCategories.Square - import YonedaEmbedding.YonedaEmbedding - import Diagram.Diagram - import Subcategories.Subcategory - import Currying.Currying - - -- | We select A and D in the Square category. - Just diag = mkDiscreteDiagram Square [A,D] - -- Just diag = mkSelect2 Square FH - - -- | We Yoneda embed the Square category. - (yoneda,embedding) = yonedaEmbedding Square - - -- | We compose diag and embedding. - curriedDiag = composeDiag embedding diag - - -- | Export all the previously defined categories as pdf with GraphViz. - main = do - putStrLn "Start of ExampleCurrying" - diagToPdf2 (fullDiagram curriedDiag) "OutputGraphViz/Examples/ExampleCurrying/yonedaEmbedding" - diagToPdf2 (fullDiagram (uncurryDiagram curriedDiag)) "OutputGraphViz/Examples/ExampleCurrying/uncurriedYonedaEmbedding" - diagToPdf2 (fullDiagram (curryDiagram (uncurryDiagram curriedDiag))) "OutputGraphViz/Examples/ExampleCurrying/curriedUncurriedYonedaEmbedding" - diagToPdf2 (fullDiagram (switchArg curriedDiag)) "OutputGraphViz/Examples/ExampleCurrying/switchArgYoneda" - putStrLn "End of ExampleCurrying" - -
− test/ExampleDiagonalFunctor/ExampleDiagonalFunctor.hs
@@ -1,51 +0,0 @@-{-| Module : FiniteCategories -Description : An example of diagonal functor. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of diagonal functor. --} -module ExampleDiagonalFunctor.ExampleDiagonalFunctor -( - diagonalFunctor, - main -) -where - import RandomCompositionGraph.RandomCompositionGraph - import System.Random - import ExportGraphViz.ExportGraphViz - import FiniteCategory.FiniteCategory - import Diagram.Diagram - import UsualCategories.Three - import UsualCategories.Two - import DiagonalFunctor.DiagonalFunctor - import FunctorCategory.FunctorCategory - import CompositionGraph.CompositionGraph - - (rcg1,newGen) = (mkRandomCompositionGraph 6 10 4 (mkStdGen 10987654)) - - -- | A diagonal functor. - diagonalFunctor = mkDiagonalFunctor Two rcg1 - - recuNatToPdf [] = putStrLn "End of natural transformation export" - recuNatToPdf (x:xs) = do - natToPdf x ("OutputGraphViz/Examples/DiagonalFunctor/nat"++show (length xs)) - recuNatToPdf xs - - recuDiagToPdf [] = putStrLn "End of diagrams export" - recuDiagToPdf (x:xs) = do - diagToPdf2 x ("OutputGraphViz/Examples/DiagonalFunctor/diag"++show (length xs)) - recuDiagToPdf xs - - -- | Export the diagonal functor as a pdf with GraphViz. - main = do - putStrLn "Start of ExampleDiagonalFunctor" - catToPdf rcg1 "OutputGraphViz/Examples/DiagonalFunctor/rcg1" - recuDiagToPdf (ob.tgt $ diagonalFunctor) - recuNatToPdf (arrows.tgt $ diagonalFunctor) - diagToPdf2 diagonalFunctor "OutputGraphViz/Examples/DiagonalFunctor/diagonalFunctor" - putStrLn "End of ExampleDiagonalFunctor" -
− test/ExampleDiagram/ExampleConstantDiagram.hs
@@ -1,40 +0,0 @@-{-| Module : FiniteCategories -Description : An example of constant diagram. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of constant diagram. --} -module ExampleDiagram.ExampleConstantDiagram -( - constantDiag, - main -) -where - import RandomCompositionGraph.RandomCompositionGraph - import System.Random - import ExportGraphViz.ExportGraphViz (catToPdf,diagToPdf,diagToPdf2) - import Diagram.Diagram (mkConstantDiagram) - import CompositionGraph.CompositionGraph - import Utils.Sample - import FiniteCategory.FiniteCategory - import Data.Maybe (fromJust) - - (rcg1,newGen) = (defaultMkRandomCompositionGraph (mkStdGen 8)) - (rcg2,newGen1) = (defaultMkRandomCompositionGraph newGen) - - -- | The constant diagram from a random composition graph to a random object. - constantDiag = fromJust $ mkConstantDiagram rcg1 rcg2 (fst (pickOne (ob rcg2) newGen1)) - - -- | Export the constant diagram as a pdf with GraphViz. - main = do - putStrLn "Start of ExampleConstantDiagram" - catToPdf rcg1 "OutputGraphViz/Examples/Diagram/ConstantDiagram/rcg1" - catToPdf rcg2 "OutputGraphViz/Examples/Diagram/ConstantDiagram/rcg2" - diagToPdf constantDiag "OutputGraphViz/Examples/Diagram/ConstantDiagram/functor" - diagToPdf2 constantDiag "OutputGraphViz/Examples/Diagram/ConstantDiagram/diag" - putStrLn "End of ExampleConstantDiagram" -
− test/ExampleDiagram/ExampleConversion.hs
@@ -1,36 +0,0 @@-{-| Module : FiniteCategories -Description : Examples of functor conversion. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -Examples of functor conversion. --} -module ExampleDiagram.ExampleConversion -( - main -) -where - import RandomDiagram.RandomDiagram - import Diagram.Conversion - import ExportGraphViz.ExportGraphViz - import System.Random - import Data.Maybe - - (diag,newGen) = (defaultMkRandomDiagram (mkStdGen 745678)) - finFunct = diagramToFinFunctor diag - partialFunct = diagramToPartialFunctor diag - Just finFunct2 = partialFunctorToFinFunctor partialFunct - partialFunct2 = finFunctorToPartialFunctor finFunct - - -- | Export the diagram as a pdf with GraphViz. - main = do - putStrLn "Start of ExampleConversion" - diagToPdf diag "OutputGraphViz/Examples/Diagram/Conversion/diag" - diagToPdf (finFunctorToDiagram finFunct) "OutputGraphViz/Examples/Diagram/Conversion/finFunct" - diagToPdf (fromJust $ partialFunctorToDiagram partialFunct) "OutputGraphViz/Examples/Diagram/Conversion/partialFunct" - diagToPdf (finFunctorToDiagram finFunct2) "OutputGraphViz/Examples/Diagram/Conversion/finFunct2" - diagToPdf (fromJust $ partialFunctorToDiagram partialFunct2) "OutputGraphViz/Examples/Diagram/Conversion/partialFunct2" - putStrLn "End of ExampleConversion"
− test/ExampleDiagram/ExampleDiagram.hs
@@ -1,53 +0,0 @@-{-| Module : FiniteCategories -Description : An example of an arbitray diagram. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of an arbitray diagram. We select a square in a random composition graph. --} -module ExampleDiagram.ExampleDiagram -( - diag, - main -) -where - import RandomCompositionGraph.RandomCompositionGraph - import System.Random - import ExportGraphViz.ExportGraphViz (catToPdf,diagToPdf,diagToPdf2) - import Diagram.Diagram (mkDiagram, src, completeMmap) - import CompositionGraph.CompositionGraph - import Utils.Sample - import FiniteCategory.FiniteCategory hiding (FiniteCategoryError(..)) - import Data.Maybe (fromJust) - import Data.Map (Map, fromList) - import ExampleCompositionGraph.ExampleCompositionGraph (square) - import Utils.AssociationList - - (rcg1,newGen) = (mkRandomCompositionGraph 20 25 3 (mkStdGen 12345)) - - -- | We select a square in the random category. - diag = fromJust $ mkDiagram square rcg1 (functToAssocList om (ob square)) fm - where - om 0 = 30 - om 1 = 20 - om 2 = 31 - om 3 = 29 - fm = completeMmap square rcg1 (functToAssocList om (ob square)) (functToAssocList fm_ (arrows square)) - where - fm_ x - | x == (head (genAr square 0 1)) = head $ genAr rcg1 30 20 - | x == (head (genAr square 1 2)) = head $ genAr rcg1 20 31 - | x == (head (genAr square 0 3)) = head $ genAr rcg1 30 29 - | x == (head (genAr square 3 2)) = head $ genAr rcg1 29 31 - - -- | Export the diagram as a pdf with GraphViz. - main = do - putStrLn "Start of ExampleDiagram" - catToPdf rcg1 "OutputGraphViz/Examples/Diagram/Diagram/rcg1" - catToPdf square "OutputGraphViz/Examples/Diagram/Diagram/square" - diagToPdf diag "OutputGraphViz/Examples/Diagram/Diagram/functor" - diagToPdf2 diag "OutputGraphViz/Examples/Diagram/Diagram/diag" - putStrLn "End of ExampleDiagram"
− test/ExampleDiagram/ExampleDiscreteDiagram.hs
@@ -1,37 +0,0 @@-{-| Module : FiniteCategories -Description : An example of discrete diagram. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of discrete diagram. --} -module ExampleDiagram.ExampleDiscreteDiagram -( - discreteDiag, - main -) -where - import RandomCompositionGraph.RandomCompositionGraph - import System.Random - import ExportGraphViz.ExportGraphViz (catToPdf,diagToPdf,diagToPdf2) - import Diagram.Diagram (mkDiscreteDiagram) - import CompositionGraph.CompositionGraph - import Utils.Sample - import FiniteCategory.FiniteCategory - import Data.Maybe (fromJust) - - (rcg1,newGen) = (mkRandomCompositionGraph 10 10 3 (mkStdGen 567)) - - -- | The discrete diagram to a random composition graph where we select a few random objects. - discreteDiag = fromJust $ mkDiscreteDiagram rcg1 (fst (sample (ob rcg1) 4 newGen)) - - -- | Export the discrete diagram as a pdf with GraphViz. - main = do - putStrLn "Start of ExampleDiscreteDiagram" - catToPdf rcg1 "OutputGraphViz/Examples/Diagram/DiscreteDiagram/rcg1" - diagToPdf discreteDiag "OutputGraphViz/Examples/Diagram/DiscreteDiagram/functor" - diagToPdf2 discreteDiag "OutputGraphViz/Examples/Diagram/DiscreteDiagram/diag" - putStrLn "End of ExampleDiscreteDiagram"
− test/ExampleDiagram/ExampleIdentityDiagram.hs
@@ -1,35 +0,0 @@-{-| Module : FiniteCategories -Description : An example of identity diagram. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of identity diagram. --} -module ExampleDiagram.ExampleIdentityDiagram -( - identityDiag, - main -) -where - import RandomCompositionGraph.RandomCompositionGraph - import System.Random - import ExportGraphViz.ExportGraphViz (catToPdf,diagToPdf,diagToPdf2) - import Diagram.Diagram (mkIdentityDiagram) - import FiniteCategory.FiniteCategory - - (rcg1,newGen) = (defaultMkRandomCompositionGraph (mkStdGen 83456789)) - - -- | The identity diagram on a random composition graph. - identityDiag = mkIdentityDiagram rcg1 - - -- | Export the constant diagram as a pdf with GraphViz. - main = do - putStrLn "Start of ExampleIdentityDiagram" - catToPdf rcg1 "OutputGraphViz/Examples/Diagram/IdentityDiagram/rcg1" - diagToPdf identityDiag "OutputGraphViz/Examples/Diagram/IdentityDiagram/functor" - diagToPdf2 identityDiag "OutputGraphViz/Examples/Diagram/IdentityDiagram/diag" - putStrLn "End of ExampleIdentityDiagram" -
− test/ExampleDiagram/ExampleParallelDiagram.hs
@@ -1,40 +0,0 @@-{-| Module : FiniteCategories -Description : An example of parallel diagram. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of parallel diagram. --} -module ExampleDiagram.ExampleParallelDiagram -( - parallelDiag, - main -) -where - import RandomCompositionGraph.RandomCompositionGraph - import System.Random - import ExportGraphViz.ExportGraphViz (catToPdf,diagToPdf,diagToPdf2) - import Diagram.Diagram (mkParallel, src) - import Utils.Sample - import FiniteCategory.FiniteCategory hiding (FiniteCategoryError(..)) - import Data.Maybe (fromJust) - - (rcg1,newGen) = (mkRandomCompositionGraph 10 15 3 (mkStdGen 1234)) - - (arToPickFrom,newGen2) = (pickOne [ar rcg1 a b|a <- ob rcg1, b <- ob rcg1, length (ar rcg1 a b) > 1, a/=b] newGen) - ([f,g],newGen3) = (sample arToPickFrom 2 newGen2) - - -- | We select a two parallel morphism in a random category. - parallelDiag = fromJust $ (mkParallel rcg1 f g) - - -- | Export the diagram as a pdf with GraphViz. - main = do - putStrLn "Start of ExampleParallelDiagram" - catToPdf rcg1 "OutputGraphViz/Examples/Diagram/ParallelDiagram/rcg1" - catToPdf (src parallelDiag) "OutputGraphViz/Examples/Diagram/ParallelDiagram/Parallel" - diagToPdf parallelDiag "OutputGraphViz/Examples/Diagram/ParallelDiagram/functor" - diagToPdf2 parallelDiag "OutputGraphViz/Examples/Diagram/ParallelDiagram/diag" - putStrLn "End of ExampleParallelDiagram"
− test/ExampleDiagram/ExampleSelectOneDiagram.hs
@@ -1,39 +0,0 @@-{-| Module : FiniteCategories -Description : An example of select1 diagram. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of select1 diagram. --} -module ExampleDiagram.ExampleSelectOneDiagram -( - selectOne, - main -) -where - import RandomCompositionGraph.RandomCompositionGraph - import System.Random - import ExportGraphViz.ExportGraphViz (catToPdf,diagToPdf,diagToPdf2) - import Diagram.Diagram (mkSelect1, src) - import Utils.Sample - import FiniteCategory.FiniteCategory - import Data.Maybe (fromJust) - - (rcg1,newGen) = (mkRandomCompositionGraph 10 10 3 (mkStdGen 567678)) - - -- | We select one object in a random category. - selectOne = fromJust $ mkSelect1 rcg1 (fst (pickOne (ob rcg1) newGen)) - - -- | Export the diagram as a pdf with GraphViz. - main = do - putStrLn "Start of ExampleSelectOneDiagram" - catToPdf rcg1 "OutputGraphViz/Examples/Diagram/SelectOneDiagram/rcg1" - catToPdf (src selectOne) "OutputGraphViz/Examples/Diagram/SelectOneDiagram/One" - diagToPdf selectOne "OutputGraphViz/Examples/Diagram/SelectOneDiagram/functor" - diagToPdf2 selectOne "OutputGraphViz/Examples/Diagram/SelectOneDiagram/diag" - putStrLn "End of ExampleSelectOneDiagram" - -
− test/ExampleDiagram/ExampleSelectThreeDiagram.hs
@@ -1,41 +0,0 @@-{-| Module : FiniteCategories -Description : An example of select3 diagram. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of select3 diagram. --} -module ExampleDiagram.ExampleSelectThreeDiagram -( - selectThree, - main -) -where - import RandomCompositionGraph.RandomCompositionGraph - import System.Random - import ExportGraphViz.ExportGraphViz (catToPdf,diagToPdf,diagToPdf2) - import Diagram.Diagram (mkSelect3, src) - import Utils.Sample - import FiniteCategory.FiniteCategory hiding (FiniteCategoryError(..)) - import Data.List ((\\)) - import Data.Maybe (fromJust) - - (rcg1,newGen) = (mkRandomCompositionGraph 10 15 3 (mkStdGen 1234)) - - (f,newGen2) = (pickOne ((arrows rcg1)\\(identities rcg1)) newGen) - (g,newGen3) = (pickOne ((arFrom rcg1 (target f))) newGen2) - - -- | We select a triangle in a random category. - selectThree = fromJust $ (mkSelect3 rcg1 f g) - - -- | Export the diagram as a pdf with GraphViz. - main = do - putStrLn "Start of ExampleSelectThreeDiagram" - catToPdf rcg1 "OutputGraphViz/Examples/Diagram/SelectThreeDiagram/rcg1" - catToPdf (src selectThree) "OutputGraphViz/Examples/Diagram/SelectThreeDiagram/Three" - diagToPdf selectThree "OutputGraphViz/Examples/Diagram/SelectThreeDiagram/functor" - diagToPdf2 selectThree "OutputGraphViz/Examples/Diagram/SelectThreeDiagram/diag" - putStrLn "End of ExampleSelectThreeDiagram"
− test/ExampleDiagram/ExampleSelectTwoDiagram.hs
@@ -1,38 +0,0 @@-{-| Module : FiniteCategories -Description : An example of select2 diagram. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of select2 diagram. --} -module ExampleDiagram.ExampleSelectTwoDiagram -( - selectTwo, - main -) -where - import RandomCompositionGraph.RandomCompositionGraph - import System.Random - import ExportGraphViz.ExportGraphViz (catToPdf,diagToPdf,diagToPdf2) - import Diagram.Diagram (mkSelect2, src) - import Utils.Sample - import FiniteCategory.FiniteCategory - import Data.List ((\\)) - import Data.Maybe (fromJust) - - (rcg1,newGen) = (mkRandomCompositionGraph 10 10 3 (mkStdGen 56767898)) - - -- | We select an arrow in the category. - selectTwo = fromJust $ mkSelect2 rcg1 (fst (pickOne ((arrows rcg1)\\(identities rcg1)) newGen)) - - -- | Export the diagram as a pdf with GraphViz. - main = do - putStrLn "Start of ExampleSelectTwoDiagram" - catToPdf rcg1 "OutputGraphViz/Examples/Diagram/SelectTwoDiagram/rcg1" - catToPdf (src selectTwo) "OutputGraphViz/Examples/Diagram/SelectTwoDiagram/Two" - diagToPdf selectTwo "OutputGraphViz/Examples/Diagram/SelectTwoDiagram/functor" - diagToPdf2 selectTwo "OutputGraphViz/Examples/Diagram/SelectTwoDiagram/diag" - putStrLn "End of ExampleSelectTwoDiagram"
− test/ExampleDiagram/ExampleSelectZeroDiagram.hs
@@ -1,36 +0,0 @@-{-| Module : FiniteCategories -Description : An example of select0 diagram. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of select0 diagram. --} -module ExampleDiagram.ExampleSelectZeroDiagram -( - selectZero, - main -) -where - import RandomCompositionGraph.RandomCompositionGraph - import System.Random - import ExportGraphViz.ExportGraphViz (catToPdf,diagToPdf,diagToPdf2) - import Diagram.Diagram (mkSelect0, src) - - (rcg1,newGen) = (mkRandomCompositionGraph 10 10 3 (mkStdGen 56)) - - -- | We select no object in the category. - selectZero = mkSelect0 rcg1 - - -- | Export the diagram as a pdf with GraphViz. - main = do - putStrLn "Start of ExampleSelectZeroDiagram" - catToPdf rcg1 "OutputGraphViz/Examples/Diagram/SelectZeroDiagram/rcg1" - catToPdf (src selectZero) "OutputGraphViz/Examples/Diagram/SelectZeroDiagram/Zero" - diagToPdf selectZero "OutputGraphViz/Examples/Diagram/SelectZeroDiagram/functor" - diagToPdf2 selectZero "OutputGraphViz/Examples/Diagram/SelectZeroDiagram/diag" - putStrLn "End of ExampleSelectZeroDiagram" - -
− test/ExampleFunctorCategory/ExampleFunctorCategory.hs
@@ -1,47 +0,0 @@-{-| Module : FiniteCategories -Description : An example of functor category. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of functor category. --} -module ExampleFunctorCategory.ExampleFunctorCategory -( - functorCategory, - main -) -where - import RandomCompositionGraph.RandomCompositionGraph - import System.Random - import ExportGraphViz.ExportGraphViz - import FiniteCategory.FiniteCategory - import FunctorCategory.FunctorCategory - import Diagram.Diagram - import UsualCategories.One - import Utils.Sample - import Data.Maybe - - (rcg1,newGen) = (mkRandomCompositionGraph 5 10 3 (mkStdGen 87819)) - - (ob1,newGen1) = (pickOne (ob rcg1) newGen) - -- diag1 = fromJust (mkSelect1 rcg1 ob1) - -- diag2 = mkIdentityDiagram rcg1 - -- | The functor category C^1 - functorCategory = FunctorCategory{sourceCat=One, targetCat=rcg1} - - recuNatToPdf [] = putStrLn "End of natural transformation export" - recuNatToPdf (x:xs) = do - natToPdf x ("OutputGraphViz/Examples/FunctorCategory/nat"++show (length xs)) - recuNatToPdf xs - - -- | Export the arrow category as a pdf with GraphViz. - main = do - putStrLn "Start of ExampleFunctorCategory" - catToPdf rcg1 "OutputGraphViz/Examples/FunctorCategory/rcg" - catToPdf functorCategory "OutputGraphViz/Examples/FunctorCategory/functorCategory" - recuNatToPdf (arrows functorCategory) - putStrLn "End of ExampleFunctorCategory" -
− test/ExampleOppositeCategory/ExampleOppositeCategory.hs
@@ -1,30 +0,0 @@-{-| Module : FiniteCategories -Description : An example of opposite category. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of opposite category. --} -module ExampleOppositeCategory.ExampleOppositeCategory -( - opSet, - main -) -where - import ExportGraphViz.ExportGraphViz (catToPdf,genToPdf) - import ExampleCat.ExampleCat (set1) - import OppositeCategory.OppositeCategory - -- | The opposite category of set1. - opSet = Op set1 - - -- | Export all the previously defined categories as pdf with GraphViz. - main = do - putStrLn "Start of ExampleOppositeCategory" - catToPdf set1 "OutputGraphViz/Examples/OppositeCategory/set1" - catToPdf opSet "OutputGraphViz/Examples/OppositeCategory/opposite" - putStrLn "End of ExampleOppositeCategory" - -
− test/ExampleParsers/Example.fscg
@@ -1,13 +0,0 @@-<SRC> -4 -1 -a-> 2 -2 -b-> 3 -</SRC> - -<TGT> -4 -Earth -gives birth to-> Apple tree -produces-> Apple -rots into-> Earth = <ID> -</TGT> - -1 -a-> 2 => Earth -gives birth to-> Apple tree -2 -b-> 3 => Apple tree -produces-> Apple
− test/ExampleParsers/Example.scg
@@ -1,2 +0,0 @@-4 -Earth -gives birth to-> Apple tree -produces-> Apple -rots into-> Earth = <ID>
− test/ExampleParsers/Example2.scg
@@ -1,21 +0,0 @@-#Max number of cycles : -4 - -#Objects : -Apple -Apple tree -Earth - -# Arrows : -#Apple -rots into-> Earth -gives birth to-> Apple tree -produces-> Apple -#Apple -rots into-> Earth -gives birth to-> Apple tree -Apple -rots into-> Earth -Apple tree -produces-> Apple -#Apple tree -produces-> Apple -rots into-> Earth -gives birth to-> Apple tree -produces-> Apple -#Apple tree -produces-> Apple -rots into-> Earth -gives birth to-> Apple tree -#Apple tree -produces-> Apple -rots into-> Earth -#Earth -gives birth to-> Apple tree -produces-> Apple -Earth -gives birth to-> Apple tree - -# Composition law : -Earth -gives birth to-> Apple tree -produces-> Apple -rots into-> Earth = <ID>
− test/ExampleParsers/ExampleSafeCompositionGraph.hs
@@ -1,30 +0,0 @@-{-| Module : FiniteCategories -Description : Tests the parsing of scg files. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -Tests the parsing of scg files. --} -module ExampleParsers.ExampleSafeCompositionGraph -( - main -) -where - import IO.Parsers.Lexer - import IO.Parsers.SafeCompositionGraph - import CompositionGraph.SafeCompositionGraph - import ExportGraphViz.ExportGraphViz - - -- | Tests the parsing of scg files. - main = do - putStrLn "Start of ExampleParsers.ExampleSafeCompositionGraph" - cg <- readSCGFile "test/ExampleParsers/Example.scg" - catToPdf cg "OutputGraphViz/Examples/Parsers/safeCompositionGraph" - writeSCGFile cg "test/ExampleParsers/Example2.scg" - cg2 <- readSCGFile "test/ExampleParsers/Example2.scg" - catToPdf cg2 "OutputGraphViz/Examples/Parsers/safeCompositionGraph2" - putStrLn "End of ExampleParsers.ExampleSafeCompositionGraph" -
− test/ExampleParsers/ExampleSafeCompositionGraphFunctor.hs
@@ -1,32 +0,0 @@-{-| Module : FiniteCategories -Description : Tests the parsing of fscg files. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -Tests the parsing of fscg files. --} -module ExampleParsers.ExampleSafeCompositionGraphFunctor -( - main -) -where - import IO.Parsers.Lexer - import IO.Parsers.SafeCompositionGraphFunctor - import CompositionGraph.SafeCompositionGraph - import ExportGraphViz.ExportGraphViz - import Diagram.Conversion - import Diagram.Diagram - import IO.PrettyPrint - - -- | Export the arrow category as a pdf with GraphViz. - main = do - putStrLn "Start of ExampleSafeCompositionGraphFunctor" - diag <- readFSCGFile "test/ExampleParsers/Example.fscg" - putStrLn $ pprint diag - diagToPdf2 diag "OutputGraphViz/Examples/Parsers/SafeCompositionGraphFunctor/diag" - putStrLn "End of ExampleSafeCompositionGraphFunctor" - -
− test/ExampleProductCategory/ExampleProductCategory.hs
@@ -1,51 +0,0 @@-{-| Module : FiniteCategories -Description : An example of product category. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of product category. --} -module ExampleProductCategory.ExampleProductCategory -( - main -) -where - import CompositionGraph.CompositionGraph - import ExportGraphViz.ExportGraphViz (catToPdf, diagToPdf, diagToPdf2) - import FiniteCategory.FiniteCategory hiding (f,g,h,i,j) - import Data.Text (Text, pack) - import ProductCategory.ProductCategory - - - f = (pack "A", pack "B", 1) :: Arrow Text Int - g = (pack "A", pack "C", 2) :: Arrow Text Int - h = (pack "B", pack "D", 3) :: Arrow Text Int - i = (pack "C", pack "D", 4) :: Arrow Text Int - - -- | A composition law defined by hand. - myLaw = [] - - myGraph = (pack.pure <$> ['A'..'D'], [f,g,h,i]) - -- | An example of a composition graph - Right square = mkCompositionGraph myGraph myLaw - - j = (pack "X", pack "Y", 9) :: Arrow Text Int - -- | A composition law defined by hand. - myLaw2 = [] - - myGraph2 = (pack.pure <$> ['X'..'Y'], [j]) - -- | An example of a composition graph - Right arrow = mkCompositionGraph myGraph2 myLaw2 - - prod = ProductCategory square arrow - - -- | Exports the composition graphs and its Yoneda embedding as pdf files with GraphViz. - main = do - putStrLn "Start of ExampleProductCategory" - catToPdf square "OutputGraphViz/Examples/ProductCategory/square" - catToPdf arrow "OutputGraphViz/Examples/ProductCategory/arrow" - catToPdf prod "OutputGraphViz/Examples/ProductCategory/prod" - putStrLn "End of ExampleProductCategory"
− test/ExampleRandomCompositionGraph/ExampleRandomCompositionGraph.hs
@@ -1,41 +0,0 @@-{-| Module : FiniteCategories -Description : Examples of random composition graphs. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -This example shows how to use `mkRandomCompositionGraph`. --} - -module ExampleRandomCompositionGraph.ExampleRandomCompositionGraph -( -main -) -where - import CompositionGraph.CompositionGraph - import RandomCompositionGraph.RandomCompositionGraph - import System.Random - import ExportGraphViz.ExportGraphViz - - generateRGCs :: (RandomGen g) => Int -> g -> [CompositionGraph Int Int] -> ([CompositionGraph Int Int], g) - generateRGCs 0 gen cgs = (cgs,gen) - generateRGCs n gen cgs = ((newCG:end), finalGen) - where - (newCG,newGen) = (mkRandomCompositionGraph 10 15 5 gen) - (end,finalGen) = generateRGCs (n-1) newGen cgs - - exportRCG :: [CompositionGraph Int Int] -> IO () - exportRCG [] = putStrLn "End of ExampleRandomCompositionGraph" - exportRCG (cg:cgs) = do - putStrLn (show (length cgs)++" rcg remaining...") - catToPdf cg ("OutputGraphViz/Examples/RandomCompositionGraph/RCG"++show (length cgs)) - exportRCG cgs - - -- | Exports 10 random composition graphs as pdf. - main = do - putStrLn "Start of ExampleRandomCompositionGraph" - exportRCG cgs - where - (cgs, g) = generateRGCs 10 (mkStdGen 745678765434567) []
− test/ExampleRandomDiagram/ExampleRandomDiagram.hs
@@ -1,44 +0,0 @@-{-| Module : FiniteCategories -Description : Examples of random diagrams. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -This example shows how to use `mkRandomDiagram`. --} - -module ExampleRandomDiagram.ExampleRandomDiagram -( - main -) -where - import CompositionGraph.CompositionGraph - import RandomCompositionGraph.RandomCompositionGraph - import RandomDiagram.RandomDiagram - import System.Random - import ExportGraphViz.ExportGraphViz - import Diagram.Diagram - - generateRDiags 0 gen diags = (diags,gen) - generateRDiags n gen diags = ((diag:end), finalGen) - where - (diag,newGen) = (defaultMkRandomDiagram gen) - (end,finalGen) = generateRDiags (n-1) newGen diags - - exportDiags [] = putStrLn "End of ExampleRandomDiagram" - exportDiags (diag:diags) = do - putStrLn (show (length diags)++" random diagrams remaining...") - catToPdf (src diag) ("OutputGraphViz/Examples/RandomDiagram/RandomDefaultDiagram/src"++show (length diags)) - catToPdf (tgt diag) ("OutputGraphViz/Examples/RandomDiagram/RandomDefaultDiagram/tgt"++show (length diags)) - diagToPdf diag ("OutputGraphViz/Examples/RandomDiagram/RandomDefaultDiagram/funct"++show (length diags)) - diagToPdf2 diag ("OutputGraphViz/Examples/RandomDiagram/RandomDefaultDiagram/diag"++show (length diags)) - exportDiags diags - - -- | Exports 5 random composition graphs as pdf. - main = do - putStrLn "Start of ExampleRandomDiagram" - exportDiags diags - where - (diags, g) = generateRDiags 5 (mkStdGen 745678765434567) []
− test/ExampleRandomDiagram/ExampleRandomTriangle.hs
@@ -1,43 +0,0 @@-{-| Module : FiniteCategories -Description : Examples of random triangle diagrams. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -This example shows how to use `mkRandomDiagram`. --} - -module ExampleRandomDiagram.ExampleRandomTriangle -( - main -) -where - import CompositionGraph.CompositionGraph - import RandomCompositionGraph.RandomCompositionGraph - import RandomDiagram.RandomDiagram - import System.Random - import ExportGraphViz.ExportGraphViz - import UsualCategories.Three - - generateRDiags 0 gen diags = (diags,gen) - generateRDiags n gen diags = ((diag:end), finalGen) - where - (newCG,newGen) = (defaultMkRandomCompositionGraph gen) - (diag,newGen2) = (mkRandomDiagram Three newCG newGen) - (end,finalGen) = generateRDiags (n-1) newGen2 diags - - exportDiags [] = putStrLn "End of ExampleRandomTriangle" - exportDiags (diag:diags) = do - putStrLn (show (length diags)++" random triangles remaining...") - diagToPdf diag ("OutputGraphViz/Examples/RandomDiagram/RandomTriangles/funct"++show (length diags)) - diagToPdf2 diag ("OutputGraphViz/Examples/RandomDiagram/RandomTriangles/diag"++show (length diags)) - exportDiags diags - - -- | Exports 5 random composition graphs as pdf. - main = do - putStrLn "Start of ExampleRandomTriangle" - exportDiags diags - where - (diags, g) = generateRDiags 5 (mkStdGen 745678765434567) []
− test/ExampleSet/ExampleCompletion.hs
@@ -1,39 +0,0 @@-{-| Module : FiniteCategories -Description : An example of set cat completion. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of set cat completion. --} -module ExampleSet.ExampleCompletion -( - main -) -where - import Set.FinSet - import ConeCategory.ConeCategory - import ExportGraphViz.ExportGraphViz - import Diagram.Diagram - - -- | Constructs the limit of an arbitrary diagram in a set category. - main = do - putStrLn "Start of ExampleCompletion" - let set = Collection $ [singleton 1, singleton 2] :: FinSet Int - let c = FinSetCat $ toList set - - let Just diag = mkDiscreteDiagram c [singleton 1, singleton 2] - diagToPdf2 diag "OutputGraphViz/Examples/Set/diag" - - let coneCat = mkConeCategory diag - catToPdf coneCat "OutputGraphViz/Examples/Set/Completion/coneCat" - let (insertionFunctor, newDiag, newLimit) = constructLimit diag - diagToPdf2 newDiag "OutputGraphViz/Examples/Set/Completion/newDiag" - let newConeCat = mkConeCategory newDiag - catToPdf newConeCat "OutputGraphViz/Examples/Set/Completion/newConeCat" - let lim = limits newDiag - sequence $ (uncurry coneToPdf) <$> zip (coneToNaturalTransformation <$> lim) (("OutputGraphViz/Examples/Set/Completion/limit"++).show <$> [1..(length lim)]) - putStrLn "End of ExampleCompletion" -
− test/ExampleSet/ExampleOrdSet.hs
@@ -1,30 +0,0 @@-{-| Module : FiniteCategories -Description : An example of set category. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of set category. --} -module ExampleSet.ExampleOrdSet -( - set, - main -) -where - import Set.FinOrdSet (FinOrdSet(..)) - import Data.Set (fromList) - import ExportGraphViz.ExportGraphViz (catToPdf,genToPdf) - - -- | A category with {1,2} and {1,2,3} as objects and applications as morphisms. - set = FinOrdSet [fromList [1,2], fromList [1,2,3]] :: FinOrdSet Int - - -- | Export the category @set@ as a pdf with GraphViz. - main = do - putStrLn "Start of ExampleOrdSet" - catToPdf set "OutputGraphViz/Examples/Set/ordSet" - genToPdf set "OutputGraphViz/Examples/Set/ordSetGen" - putStrLn "End of ExampleOrdSet" -
− test/ExampleSet/ExamplePowerOrdSet.hs
@@ -1,30 +0,0 @@-{-| Module : FiniteCategories -Description : An example of a power set category. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of power set category. --} - -module ExampleSet.ExamplePowerOrdSet -( - power, - main -) -where - import Set.FinOrdSet (FinOrdSet(..), powerFinOrdSet) - import Data.Set (Set(..), fromList) - import ExportGraphViz.ExportGraphViz (catToPdf,genToPdf) - - -- | A category with all subsets of {1,2,3} as objects and applications as morphisms. - power = powerFinOrdSet $ fromList [1..3] :: FinOrdSet Int - - -- | Export the power set of {1,2,3} as a pdf with GraphViz. - main = do - putStrLn "Start of ExamplePowerOrdSet" - catToPdf power "OutputGraphViz/Examples/Set/powerOrdSet" - putStrLn "End of ExamplePowerOrdSet" -
− test/ExampleSet/ExamplePowerSet.hs
@@ -1,30 +0,0 @@-{-| Module : FiniteCategories -Description : An example of a power set category. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of power set category. --} - -module ExampleSet.ExamplePowerSet -( - powerSet, - main -) -where - import Set.FinSet - import ExportGraphViz.ExportGraphViz (catToPdf,genToPdf) - - -- | A category with all subsets of {1,2,3} as objects and applications as morphisms. - powerSet = powerFinSet $ Collection $ Elem <$> [1..3] :: FinSet Int - powerSetCat = FinSetCat $ toList powerSet - - -- | Export the power set of {1,2,3} as a pdf with GraphViz. - main = do - putStrLn "Start of ExamplePowerSet" - catToPdf powerSetCat "OutputGraphViz/Examples/Set/powerSet" - putStrLn "End of ExamplePowerSet" -
− test/ExampleSet/ExampleSet.hs
@@ -1,33 +0,0 @@-{-| Module : FiniteCategories -Description : An example of set category. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of set category. --} -module ExampleSet.ExampleSet -( - set, - setCat, - main -) -where - import Set.FinSet - import ExportGraphViz.ExportGraphViz (catToPdf,genToPdf) - - -- | A set containing {1,2} and {1,2,3}. - set = Collection [Collection $ Elem <$> [1,2], Collection $ Elem <$> [1,2,3]] :: FinSet Int - - -- | The category containing {1,2} and {1,2,3} as objects. - setCat = FinSetCat $ toList set - - -- | Export the category @set@ as a pdf with GraphViz. - main = do - putStrLn "Start of ExampleSet" - catToPdf setCat "OutputGraphViz/Examples/Set/set" - genToPdf setCat "OutputGraphViz/Examples/Set/setGen" - putStrLn "End of ExampleSet" -
− test/ExampleSubcategories/ExampleFreeSubcategory.hs
@@ -1,30 +0,0 @@-{-| Module : FiniteCategories -Description : An example of free subcategory. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of free subcategory. --} -module ExampleSubcategories.ExampleFreeSubcategory -( - freeSubcategory, - main -) where - import ExampleSet.ExamplePowerOrdSet (power) - import Subcategories.FreeSubcategory - import Set.FinOrdSet - import ExportGraphViz.ExportGraphViz - import Data.Set - import FiniteCategory.FiniteCategory - - -- | Free subcategory generated by three maps in the set category containing {1,2}, {2,3} and {1,3}. - freeSubcategory = FreeSubcategory power [(ar power (fromList [1,2]) (fromList [2,3])) !! 0,(ar power (fromList [2,3]) (fromList [1,3])) !! 0,(ar power (fromList [1,3]) (fromList [1,2])) !! 0] :: FreeSubcategory (FinOrdSet Int) (FinOrdMap Int) (Set Int) - - -- | Exports previously defined categories as pdf files with GraphViz. - main = do - putStrLn "Start of ExampleFreeSubcategory" - catToPdf freeSubcategory "OutputGraphViz/Examples/Subcategories/freeSubcategory" - putStrLn "End of ExampleFreeSubcategory"
− test/ExampleYonedaEmbedding/ExampleYonedaEmbedding.hs
@@ -1,60 +0,0 @@-{-| Module : FiniteCategories -Description : An example of Yoneda embedding. -Copyright : Guillaume Sabbagh 2021 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -An example of Yoneda embedding. --} -module ExampleYonedaEmbedding.ExampleYonedaEmbedding -( - main -) -where - import CompositionGraph.CompositionGraph - import ExportGraphViz.ExportGraphViz (catToPdf, diagToPdf, diagToPdf2) - import FiniteCategory.FiniteCategory hiding (f,g,h,i) - import Data.Text (Text, pack) - import YonedaEmbedding.YonedaEmbedding - import IO.PrettyPrint - import Subcategories.Subcategory - import Subcategories.FullSubcategory - import Diagram.Diagram - import Utils.AssociationList - - import Set.FinSet - - import OppositeCategory.OppositeCategory - - f = (pack "A", pack "B", 1) :: Arrow Text Int - g = (pack "A", pack "C", 2) :: Arrow Text Int - h = (pack "B", pack "D", 3) :: Arrow Text Int - i = (pack "C", pack "D", 4) :: Arrow Text Int - - -- | A composition law defined by hand. - myLaw = [] - - myGraph = (pack.pure <$> ['A'..'D'], [f,g,h,i]) - -- | An example of a composition graph - Right square = mkCompositionGraph myGraph myLaw - - (yoneda, funct) = yonedaEmbedding square - - type YC = (CompositionGraph Text Int) - type YM = (CGMorphism Text Int) - type YO = Text - - emptySheaf = Diagram {src = Op square, tgt = tgt ((ob yoneda) !! 0), omap = functToAssocList (const emptyFinSet) (ob square), mmap = functToAssocList (const FinMap{codomain = emptyFinSet, finMap = []}) (arrows (Op square))} - - subTarget = (FullSubcategory (tgt funct) (emptySheaf:(((omap funct) !-!) <$> (ob (src funct))))) :: FullSubcategory (PreSheavesCategory YC YM YO) (PreSheavesNatTransfo YC YM YO) (PreSheaf YC YM YO) - - -- | Exports the composition graphs and its Yoneda embedding as pdf files with GraphViz. - main = do - putStrLn "Start of ExampleYonedaEmbedding" - catToPdf square "OutputGraphViz/Examples/YonedaEmbedding/square" - -- diagToPdf (minimalDiagram funct) "OutputGraphViz/Examples/YonedaEmbedding/yonedaEmbeddingAsFunct" - diagToPdf2 (fullDiagram funct) "OutputGraphViz/Examples/YonedaEmbedding/yonedaEmbedding" - catToPdf subTarget "OutputGraphViz/Examples/YonedaEmbedding/fullYonedaEmbedding" - putStrLn "End of ExampleYonedaEmbedding"
test/RunAllExamples.hs view
@@ -1,6 +1,6 @@ {-| Module : FiniteCategories Description : Run all examples of the project. -Copyright : Guillaume Sabbagh 2021 +Copyright : Guillaume Sabbagh 2022 License : GPL-3 Maintainer : guillaumesabbagh@protonmail.com Stability : experimental @@ -14,94 +14,12 @@ main ) where - import qualified ExampleCompositionGraph.ExampleCompositionGraph as ECG - import qualified ExampleSet.ExampleOrdSet as OSET - import qualified ExampleSet.ExamplePowerOrdSet as POSET - import qualified ExampleRandomCompositionGraph.ExampleRandomCompositionGraph as RCG - import qualified ExampleCat.ExampleCat as CAT - import qualified ExampleCat.ExamplePartialFinCat as PCAT - import qualified ExampleCat.ExampleFunctor as FUNCT - import qualified ExampleDiagram.ExampleConstantDiagram as CONSTDIAG - import qualified ExampleDiagram.ExampleDiscreteDiagram as DISCRETEDIAG - import qualified ExampleDiagram.ExampleSelectOneDiagram as SELECTONEDIAG - import qualified ExampleDiagram.ExampleSelectTwoDiagram as SELECTTWODIAG - import qualified ExampleDiagram.ExampleSelectThreeDiagram as SELECTTHREEDIAG - import qualified ExampleDiagram.ExampleSelectZeroDiagram as SELECTZERODIAG - import qualified ExampleDiagram.ExampleParallelDiagram as PARDIAG - import qualified ExampleDiagram.ExampleDiagram as DIAG - import qualified ExampleDiagram.ExampleIdentityDiagram as IDDIAG - import qualified ExampleCommaCategory.ExampleSliceCategory as SLICE - import qualified ExampleCommaCategory.ExampleCosliceCategory as COSLICE - import qualified ExampleCommaCategory.ExampleArrowCategory as ARROWCAT - import qualified ExampleFunctorCategory.ExampleFunctorCategory as FUNCTCAT - import qualified ExampleDiagonalFunctor.ExampleDiagonalFunctor as DIAGONAL - import qualified ExampleConeCategory.ExampleConeCategory as CONE - import qualified ExampleConeCategory.ExampleCoconeCategory as COCONE - import qualified ExampleConeCategory.ExampleLimit as LIMIT - import qualified ExampleConeCategory.ExampleColimit as COLIMIT - import qualified ExampleRandomDiagram.ExampleRandomDiagram as RANDDIAG - import qualified ExampleRandomDiagram.ExampleRandomTriangle as RANDTRIANGLE - import qualified ExampleCompositionGraph.ExampleFinSetToCompositionGraph as SETTOCG - import qualified ExampleCompositionGraph.ExampleCompositionGraphConstruction as CGCONSTRUCT - import qualified ExampleDiagram.ExampleConversion as CONVERT - import qualified ExampleCompositionGraph.ExampleSafeCompositionGraph as SCG - import qualified ExampleSubcategories.ExampleFreeSubcategory as FSC - import qualified ExampleParsers.ExampleSafeCompositionGraph as PSCG - import qualified ExampleParsers.ExampleSafeCompositionGraphFunctor as PFSCG - import qualified ExampleConeCategory.ExampleLeftCone as LCONE - import qualified ExampleOppositeCategory.ExampleOppositeCategory as OP - import qualified ExampleSet.ExamplePowerSet as PSET - import qualified ExampleSet.ExampleSet as SET - import qualified ExampleYonedaEmbedding.ExampleYonedaEmbedding as YONEDA - import qualified ExampleSet.ExampleCompletion as COMP - import qualified ExampleProductCategory.ExampleProductCategory as PROD - import qualified ExampleCurrying.ExampleCurrying as CURRY - import qualified ExampleAdjunction.ExampleAdjunction as ADJ - + import qualified Math.FiniteCategories.Examples as FINCAT + import qualified Math.Functors.Examples as FUNCTORS + import qualified CheckAllFiniteCategories as CHECK + -- | Run all examples of the project. See results in the folder OutputGraphViz. main = do - ADJ.main - CURRY.main - PROD.main - COMP.main - YONEDA.main - SET.main - PSET.main - OP.main - LCONE.main - PFSCG.main - PSCG.main - FSC.main - SCG.main - CONVERT.main - CGCONSTRUCT.main - SETTOCG.main - PCAT.main - RCG.main - COLIMIT.main - LIMIT.main - COCONE.main - CONE.main - DIAGONAL.main - FUNCTCAT.main - ARROWCAT.main - COSLICE.main - SLICE.main - IDDIAG.main - DIAG.main - PARDIAG.main - SELECTZERODIAG.main - SELECTTHREEDIAG.main - SELECTTWODIAG.main - SELECTONEDIAG.main - DISCRETEDIAG.main - CONSTDIAG.main - FUNCT.main - CAT.main - ECG.main - OSET.main - POSET.main - RANDTRIANGLE.main - RANDDIAG.main - - + FUNCTORS.main + FINCAT.main + CHECK.main