WeakSets 0.2.0.0 → 0.3.0.0
raw patch · 7 files changed
+380/−379 lines, 7 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- HomogeneousSet: (|!|) :: Eq a => Function a b -> a -> b
- HomogeneousSet: (|$|) :: Eq a => Function a b -> a -> Maybe b
- HomogeneousSet: (|&|) :: Eq a => Set a -> Set a -> Set a
- HomogeneousSet: (|*|) :: Set a -> Set b -> Set (a, b)
- HomogeneousSet: (|+|) :: Set a -> Set b -> Set (Either a b)
- HomogeneousSet: (|-|) :: Eq a => Set a -> Set a -> Set a
- HomogeneousSet: (|.|) :: (Eq a, Eq b) => Function b c -> Function a b -> Function a c
- HomogeneousSet: (|^|) :: (Num a, Eq a) => Set a -> a -> Set [a]
- HomogeneousSet: (|||) :: Set a -> Set a -> Set a
- HomogeneousSet: cardinal :: Eq a => Set a -> Int
- HomogeneousSet: catMaybesToSet :: Set (Maybe a) -> Set a
- HomogeneousSet: data Function a b
- HomogeneousSet: data Set a
- HomogeneousSet: domain :: Function a b -> Set a
- HomogeneousSet: filterSet :: (a -> Bool) -> Set a -> Set a
- HomogeneousSet: findWithDefault :: Eq a => Function a b -> b -> a -> b
- HomogeneousSet: function :: AssociationList a b -> Function a b
- HomogeneousSet: functionToSet :: Eq a => Function a b -> Set (a, b)
- HomogeneousSet: image :: Function a b -> Set b
- HomogeneousSet: instance (GHC.Classes.Eq a, GHC.Classes.Eq b) => GHC.Classes.Eq (HomogeneousSet.Function a b)
- HomogeneousSet: instance (GHC.Show.Show a, GHC.Show.Show b) => GHC.Show.Show (HomogeneousSet.Function a b)
- HomogeneousSet: instance Data.Foldable.Foldable HomogeneousSet.Set
- HomogeneousSet: instance GHC.Base.Applicative HomogeneousSet.Set
- HomogeneousSet: instance GHC.Base.Functor HomogeneousSet.Set
- HomogeneousSet: instance GHC.Base.Monad HomogeneousSet.Set
- HomogeneousSet: instance GHC.Classes.Eq a => GHC.Base.Monoid (HomogeneousSet.Set a)
- HomogeneousSet: instance GHC.Classes.Eq a => GHC.Base.Semigroup (HomogeneousSet.Set a)
- HomogeneousSet: instance GHC.Classes.Eq a => GHC.Classes.Eq (HomogeneousSet.Set a)
- HomogeneousSet: instance GHC.Show.Show a => GHC.Show.Show (HomogeneousSet.Set a)
- HomogeneousSet: isIn :: Eq a => a -> Set a -> Bool
- HomogeneousSet: isIncludedIn :: Eq a => Set a -> Set a -> Bool
- HomogeneousSet: mapMaybeToSet :: (a -> Maybe b) -> Set a -> Set b
- HomogeneousSet: maybeToSet :: Maybe a -> Set a
- HomogeneousSet: memorizeFunction :: (a -> b) -> Set a -> Function a b
- HomogeneousSet: powerSet :: Set a -> Set (Set a)
- HomogeneousSet: set :: [a] -> Set a
- HomogeneousSet: setToList :: Eq a => Set a -> [a]
- HomogeneousSet: setToMaybe :: Set a -> Maybe a
- HomogeneousSet: type AssociationList a b = [(a, b)]
- PureSet: (&&&&) :: PureSet -> PureSet -> PureSet
- PureSet: (||||) :: PureSet -> PureSet -> PureSet
- PureSet: PureSet :: Set PureSet -> PureSet
- PureSet: card :: PureSet -> Int
- PureSet: cartesianProduct :: PureSet -> PureSet -> PureSet
- PureSet: data PureSet
- PureSet: emptySet :: PureSet
- PureSet: formatPureSet :: PureSet -> String
- PureSet: instance GHC.Classes.Eq PureSet.PureSet
- PureSet: instance GHC.Show.Show PureSet.PureSet
- PureSet: isInP :: PureSet -> PureSet -> Bool
- PureSet: isIncludedInP :: PureSet -> PureSet -> Bool
- PureSet: numberToSet :: (Num a, Eq a) => a -> PureSet
- PureSet: pair :: PureSet -> PureSet -> PureSet
- PureSet: powerSetP :: PureSet -> PureSet
- PureSet: prettify :: PureSet -> String
- PureSet: pureSet :: [PureSet] -> PureSet
- PureSet: singleton :: PureSet -> PureSet
+ Data.WeakSets.HomogeneousSet: (|!|) :: Eq a => Function a b -> a -> b
+ Data.WeakSets.HomogeneousSet: (|$|) :: Eq a => Function a b -> a -> Maybe b
+ Data.WeakSets.HomogeneousSet: (|&|) :: Eq a => Set a -> Set a -> Set a
+ Data.WeakSets.HomogeneousSet: (|*|) :: Set a -> Set b -> Set (a, b)
+ Data.WeakSets.HomogeneousSet: (|+|) :: Set a -> Set b -> Set (Either a b)
+ Data.WeakSets.HomogeneousSet: (|-|) :: Eq a => Set a -> Set a -> Set a
+ Data.WeakSets.HomogeneousSet: (|.|) :: (Eq a, Eq b) => Function b c -> Function a b -> Function a c
+ Data.WeakSets.HomogeneousSet: (|^|) :: (Num a, Eq a) => Set a -> a -> Set [a]
+ Data.WeakSets.HomogeneousSet: (|||) :: Set a -> Set a -> Set a
+ Data.WeakSets.HomogeneousSet: cardinal :: Eq a => Set a -> Int
+ Data.WeakSets.HomogeneousSet: catMaybesToSet :: Set (Maybe a) -> Set a
+ Data.WeakSets.HomogeneousSet: data Function a b
+ Data.WeakSets.HomogeneousSet: data Set a
+ Data.WeakSets.HomogeneousSet: domain :: Function a b -> Set a
+ Data.WeakSets.HomogeneousSet: filterSet :: (a -> Bool) -> Set a -> Set a
+ Data.WeakSets.HomogeneousSet: findWithDefault :: Eq a => Function a b -> b -> a -> b
+ Data.WeakSets.HomogeneousSet: function :: AssociationList a b -> Function a b
+ Data.WeakSets.HomogeneousSet: functionToSet :: Eq a => Function a b -> Set (a, b)
+ Data.WeakSets.HomogeneousSet: image :: Function a b -> Set b
+ Data.WeakSets.HomogeneousSet: instance (GHC.Classes.Eq a, GHC.Classes.Eq b) => GHC.Classes.Eq (Data.WeakSets.HomogeneousSet.Function a b)
+ Data.WeakSets.HomogeneousSet: instance (GHC.Show.Show a, GHC.Show.Show b) => GHC.Show.Show (Data.WeakSets.HomogeneousSet.Function a b)
+ Data.WeakSets.HomogeneousSet: instance Data.Foldable.Foldable Data.WeakSets.HomogeneousSet.Set
+ Data.WeakSets.HomogeneousSet: instance GHC.Base.Applicative Data.WeakSets.HomogeneousSet.Set
+ Data.WeakSets.HomogeneousSet: instance GHC.Base.Functor Data.WeakSets.HomogeneousSet.Set
+ Data.WeakSets.HomogeneousSet: instance GHC.Base.Monad Data.WeakSets.HomogeneousSet.Set
+ Data.WeakSets.HomogeneousSet: instance GHC.Classes.Eq a => GHC.Base.Monoid (Data.WeakSets.HomogeneousSet.Set a)
+ Data.WeakSets.HomogeneousSet: instance GHC.Classes.Eq a => GHC.Base.Semigroup (Data.WeakSets.HomogeneousSet.Set a)
+ Data.WeakSets.HomogeneousSet: instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.WeakSets.HomogeneousSet.Set a)
+ Data.WeakSets.HomogeneousSet: instance GHC.Show.Show a => GHC.Show.Show (Data.WeakSets.HomogeneousSet.Set a)
+ Data.WeakSets.HomogeneousSet: isIn :: Eq a => a -> Set a -> Bool
+ Data.WeakSets.HomogeneousSet: isIncludedIn :: Eq a => Set a -> Set a -> Bool
+ Data.WeakSets.HomogeneousSet: mapMaybeToSet :: (a -> Maybe b) -> Set a -> Set b
+ Data.WeakSets.HomogeneousSet: maybeToSet :: Maybe a -> Set a
+ Data.WeakSets.HomogeneousSet: memorizeFunction :: (a -> b) -> Set a -> Function a b
+ Data.WeakSets.HomogeneousSet: powerSet :: Set a -> Set (Set a)
+ Data.WeakSets.HomogeneousSet: set :: [a] -> Set a
+ Data.WeakSets.HomogeneousSet: setToList :: Eq a => Set a -> [a]
+ Data.WeakSets.HomogeneousSet: setToMaybe :: Set a -> Maybe a
+ Data.WeakSets.HomogeneousSet: type AssociationList a b = [(a, b)]
+ Math.WeakSets.PureSet: (&&&&) :: PureSet -> PureSet -> PureSet
+ Math.WeakSets.PureSet: (||||) :: PureSet -> PureSet -> PureSet
+ Math.WeakSets.PureSet: PureSet :: Set PureSet -> PureSet
+ Math.WeakSets.PureSet: card :: PureSet -> Int
+ Math.WeakSets.PureSet: cartesianProduct :: PureSet -> PureSet -> PureSet
+ Math.WeakSets.PureSet: data PureSet
+ Math.WeakSets.PureSet: emptySet :: PureSet
+ Math.WeakSets.PureSet: formatPureSet :: PureSet -> String
+ Math.WeakSets.PureSet: instance GHC.Classes.Eq Math.WeakSets.PureSet.PureSet
+ Math.WeakSets.PureSet: instance GHC.Show.Show Math.WeakSets.PureSet.PureSet
+ Math.WeakSets.PureSet: isInP :: PureSet -> PureSet -> Bool
+ Math.WeakSets.PureSet: isIncludedInP :: PureSet -> PureSet -> Bool
+ Math.WeakSets.PureSet: numberToSet :: (Num a, Eq a) => a -> PureSet
+ Math.WeakSets.PureSet: pair :: PureSet -> PureSet -> PureSet
+ Math.WeakSets.PureSet: powerSetP :: PureSet -> PureSet
+ Math.WeakSets.PureSet: prettify :: PureSet -> String
+ Math.WeakSets.PureSet: pureSet :: [PureSet] -> PureSet
+ Math.WeakSets.PureSet: singleton :: PureSet -> PureSet
Files
- WeakSets.cabal +3/−3
- src/Data/WeakSets/HomogeneousSet.hs +238/−0
- src/HomogeneousSet.hs +0/−237
- src/Math/WeakSets/PureSet.hs +136/−0
- src/PureSet.hs +0/−136
- test/TestHomogeneousSet.hs +1/−1
- test/TestPureSet.hs +2/−2
WeakSets.cabal view
@@ -14,7 +14,7 @@ -- PVP summary: +-+------- breaking API changes -- | | +----- non-breaking API additions -- | | | +--- code changes with no API change -version: 0.2.0.0 +version: 0.3.0.0 -- A short (one-line) description of the package. synopsis: @@ -43,7 +43,7 @@ -- A copyright notice. -- copyright: -category: Math, Data +category: Data, Math -- Extra files to be distributed with the package, such as examples or a README. extra-source-files: @@ -52,7 +52,7 @@ library -- Modules exported by the library. - exposed-modules: HomogeneousSet, PureSet + exposed-modules: Data.WeakSets.HomogeneousSet, Math.WeakSets.PureSet -- Modules included in this library but not exported. -- other-modules:
+ src/Data/WeakSets/HomogeneousSet.hs view
@@ -0,0 +1,238 @@+{-| Module : WeakSets +Description : Homogeneous sets are sets which can contain only one type of values. They are more flexible than Data.Set because they do not require the objects contained to be orderable. +Copyright : Guillaume Sabbagh 2022 +License : LGPL-3.0-or-later +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +Homogeneous sets are sets which can contain only one type of values. + +They are more flexible than Data.Set because they do not require the objects contained to be orderable. + +The datatype only assumes its components are equatable, it is therefore slower than the Data.Set datatype. + +We use this datatype because most of the datatypes we care about are not orderable. + +Inline functions related to homogeneous sets are written between pipes @|@. + +Function names should not collide with Prelude but should collide with Data.Set. +-} + +module Data.WeakSets.HomogeneousSet +( + -- * Set datatype and smart constructor + Set, -- abstract type, the smart constructor is `set` + set, -- the smart constructor for `Set` + -- * Set related functions + setToList, + isIncludedIn, + cardinal, + isIn, + (|&|), + (|||), + (|*|), + (|+|), + (|-|), + (|^|), + powerSet, + filterSet, + -- * Functions to work with `Maybe` + setToMaybe, + maybeToSet, + catMaybesToSet, + mapMaybeToSet, + -- * Function datatype and smart constructor + AssociationList(..), + Function, -- abstract type, the smart constructor is `function` + function, -- the smart constructor for `Function` + -- * Function related functions + functionToSet, + domain, + image, + (|$|), + (|!|), + findWithDefault, + (|.|), + memorizeFunction, +) +where + import Data.List (intercalate, nub, nubBy, intersect, union, (\\), subsequences) + import Data.Maybe + + -- | A homogeneous set is a list of values. + -- + -- The only differences are that we don't want duplicate elements and we don't need the order of the list elements. + -- + -- To force these constraints, the `Set` constructor is abstract and is not exported. The only way to construct a set is to use the smart constructor `set` which ensures the previous conditions. + data Set a = Set [a] + + -- | The smart constructor of sets. This is the only way of instantiating a `Set`. + -- + -- If several elements are equal, they are kept until the user wants a list back. + set :: [a] -> Set a + set xs = Set xs + + instance (Show a) => Show (Set a) where + show (Set xs) = "(set "++show xs++")" + + -- | Return a boolean indicating if a `Set` is included in another one. + isIncludedIn :: (Eq a) => Set a -> Set a -> Bool + (Set []) `isIncludedIn` _ = True + (Set (x:xs)) `isIncludedIn` (Set ys) + | x `elem` ys = (Set xs) `isIncludedIn` (Set ys) + | otherwise = False + + instance (Eq a) => Eq (Set a) where + x == y = x `isIncludedIn` y && y `isIncludedIn` x + + instance (Eq a) => Semigroup (Set a) where + (Set xs) <> (Set ys) = set $ xs <> ys + + instance (Eq a) => Monoid (Set a) where + mempty = Set [] + + instance Foldable Set where + foldr f d (Set xs) = foldr f d xs + + instance Functor Set where + fmap f (Set xs) = Set $ f <$> xs + + instance Applicative Set where + pure x = Set [x] + (<*>) (Set fs) (Set xs) = Set $ fs <*> xs + + instance Monad Set where + (>>=) (Set xs) f = Set $ xs >>= (unsafeSetToList.f) + + -- | Transform a `Set` back into a list, the list returned does not have duplicate elements, the order of the original list holds. + setToList :: (Eq a) => Set a -> [a] + setToList (Set xs) = nub xs + + -- | Gives the underlying list of a set without removing duplicates, this function is not exported. + unsafeSetToList :: Set a -> [a] + unsafeSetToList (Set xs) = xs + + -- | Size of a set. + cardinal :: (Eq a) => Set a -> Int + cardinal = length.setToList + + -- | Return wether an element is in a set. + isIn :: (Eq a) => a -> Set a -> Bool + isIn x = (elem x).unsafeSetToList + + -- | Return the intersection of two sets. + (|&|) :: (Eq a) => Set a -> Set a -> Set a + (|&|) (Set xs) (Set ys) = Set $ xs `intersect` ys + + -- | Return the union of two sets. + (|||) :: Set a -> Set a -> Set a + (|||) (Set xs) (Set ys) = Set $ xs ++ ys + + -- | Return the cartesian product of two sets. + (|*|) :: Set a -> Set b -> Set (a,b) + (|*|) (Set xs) (Set ys) = Set $ [(x,y) | x <- xs, y <- ys] + + -- | Return the disjoint union of two sets. + (|+|) :: Set a -> Set b -> Set (Either a b) + (|+|) (Set xs) (Set ys) = Set $ [Left x | x <- xs] ++ [Right y | y <- ys] + + -- | Returns the cartesian product of a set with itself n times. + (|^|) :: (Num a, Eq a) => Set a -> a -> Set [a] + (|^|) _ 0 = Set [[]] + (|^|) s n = (:) <$> s <*> (s |^| (n-1)) + + -- | Return the difference of two sets. + (|-|) :: (Eq a) => Set a -> Set a -> Set a + (|-|) (Set xs) (Set ys) = Set $ xs \\ ys + + -- | Return the set of all subsets of a given set. + powerSet :: Set a -> Set (Set a) + powerSet (Set xs) = Set $ Set <$> subsequences xs + + -- | Filter a set according to a condition. + filterSet :: (a -> Bool) -> Set a -> Set a + filterSet f (Set xs) = Set $ filter f xs + + -- | Set version of listToMaybe. + setToMaybe :: Set a -> Maybe a + setToMaybe = listToMaybe.unsafeSetToList + + -- | Set version of maybeToList. + maybeToSet :: Maybe a -> Set a + maybeToSet x = Set $ maybeToList x + + -- | Set version of catMaybes. + catMaybesToSet :: Set (Maybe a) -> Set a + catMaybesToSet = set.catMaybes.unsafeSetToList + + -- | Set version of mapMaybe. + mapMaybeToSet :: (a -> Maybe b) -> Set a -> Set b + mapMaybeToSet f = set.(mapMaybe f).unsafeSetToList + + -- | A function of homogeneous sets. It is a set of pairs (key,value) such that their should only be one pair with a given key. + -- + -- It is an abstract type, the smart constructor is `function`. + data Function a b = Function (Set (a,b)) deriving (Eq) + + instance (Show a, Show b) => Show (Function a b) where + show (Function al) = "(function "++show al++")" + + -- | An association list is a list of pairs (key,value). + type AssociationList a b = [(a,b)] + + -- | The smart constructor of functions. This is the only way of instantiating a `Function`. + -- + -- Takes an association list and returns a function which maps to each key the value associated. + -- + -- If several pairs have the same keys, they are kept until the user wants an association list back. + function :: AssociationList a b -> Function a b + function al = Function $ Set $ al + + -- | Transform a function back into its underlying association list. + functionToSet :: (Eq a) => Function a b -> Set (a,b) + functionToSet (Function (Set al)) = Set $ nubBy (\x y -> (fst x) == (fst y)) al + + -- | Return the domain of a function. + domain :: Function a b -> Set a + domain (Function al) = fst <$> al + + -- | Return the image of a function. The image of a function is the set of values which are reachable by applying the function. + image :: Function a b -> Set b + image (Function al) = snd <$> al + + -- | Apply a function to a given value. If the function is not defined on the given value returns `Nothing`, otherwise returns `Just` the image. + -- + -- This function is like `lookup` in Data.Map for function (the order of the argument are reversed though). + (|$|) :: (Eq a) => Function a b -> a -> Maybe b + (|$|) (Function (Set [])) _ = Nothing + (|$|) (Function (Set ((k,v):xs))) x + | x == k = Just v + | otherwise = (Function (Set xs)) |$| x + + -- | Unsafe version of `(|$|)`. + -- + -- This function is like `(!)` in Data.Map for function. + (|!|) :: (Eq a) => Function a b -> a -> b + (|!|) (Function (Set [])) _ = error "Function applied on a value not in the domain." + (|!|) (Function (Set ((k,v):xs))) x + | x == k = v + | otherwise = (Function (Set xs)) |!| x + + -- | Apply a function to a given value, if the value is in the domain returns the image, otherwise return a default value. + -- + -- This function is like `findWithDefault` in Data.Map for function (the order of the argument are reversed though). + findWithDefault :: (Eq a) => Function a b -> b -> a -> b + findWithDefault (Function (Set [])) d _ = d + findWithDefault (Function (Set ((k,v):xs))) d x + | x == k = v + | otherwise = findWithDefault (Function (Set xs)) d x + + -- | Compose two functions. If the two functions are not composable, strips the functions until they can compose. + (|.|) :: (Eq a, Eq b) => Function b c -> Function a b -> Function a c + (|.|) f2 f1 = Function $ Set [(k,(f2 |!| (f1 |!| k))) | k <- (setToList.domain $ f1), f1 |!| k `isIn` (domain f2)] + + -- | Memorize a Haskell function on a given finite domain. + memorizeFunction :: (a -> b) -> Set a -> Function a b + memorizeFunction f (Set xs) = Function $ Set [(k, f k) | k <- xs] +
− src/HomogeneousSet.hs
@@ -1,237 +0,0 @@-{-| Module : WeakSets -Description : Homogeneous sets are sets which can contain only one type of values. They are more flexible than Data.Set because they do not require the objects contained to be orderable. -Copyright : Guillaume Sabbagh 2022 -License : LGPL-3.0-or-later -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -Homogeneous sets are sets which can contain only one type of values. - -They are more flexible than Data.Set because they do not require the objects contained to be orderable. - -The datatype only assumes its components are equatable, it is therefore slower than the Data.Set datatype. - -We use this datatype because most of the datatypes we care about are not orderable. - -Inline functions related to homogeneous sets are written between pipes @|@. - -Function names should not collide with Prelude but should collide with Data.Set. --} - -module HomogeneousSet -( - -- * Set datatype and smart constructor - Set, -- abstract type, the smart constructor is `set` - set, -- the smart constructor for `Set` - -- * Set related functions - setToList, - isIncludedIn, - cardinal, - isIn, - (|&|), - (|||), - (|*|), - (|+|), - (|-|), - (|^|), - powerSet, - filterSet, - setToMaybe, - maybeToSet, - catMaybesToSet, - mapMaybeToSet, - -- * Function datatype and smart constructor - AssociationList(..), - Function, -- abstract type, the smart constructor is `function` - function, -- the smart constructor for `Function` - -- * Function related functions - functionToSet, - domain, - image, - (|$|), - (|!|), - findWithDefault, - (|.|), - memorizeFunction, -) -where - import Data.List (intercalate, nub, nubBy, intersect, union, (\\), subsequences) - import Data.Maybe - - -- | A homogeneous set is a list of values. - -- - -- The only differences are that we don't want duplicate elements and we don't need the order of the list elements. - -- - -- To force these constraints, the `Set` constructor is abstract and is not exported. The only way to construct a set is to use the smart constructor `set` which ensures the previous conditions. - data Set a = Set [a] - - -- | The smart constructor of sets. This is the only way of instantiating a `Set`. - -- - -- If several elements are equal, they are kept until the user wants a list back. - set :: [a] -> Set a - set xs = Set xs - - instance (Show a) => Show (Set a) where - show (Set xs) = "(set "++show xs++")" - - -- | Return a boolean indicating if a `Set` is included in another one. - isIncludedIn :: (Eq a) => Set a -> Set a -> Bool - (Set []) `isIncludedIn` _ = True - (Set (x:xs)) `isIncludedIn` (Set ys) - | x `elem` ys = (Set xs) `isIncludedIn` (Set ys) - | otherwise = False - - instance (Eq a) => Eq (Set a) where - x == y = x `isIncludedIn` y && y `isIncludedIn` x - - instance (Eq a) => Semigroup (Set a) where - (Set xs) <> (Set ys) = set $ xs <> ys - - instance (Eq a) => Monoid (Set a) where - mempty = Set [] - - instance Foldable Set where - foldr f d (Set xs) = foldr f d xs - - instance Functor Set where - fmap f (Set xs) = Set $ f <$> xs - - instance Applicative Set where - pure x = Set [x] - (<*>) (Set fs) (Set xs) = Set $ fs <*> xs - - instance Monad Set where - (>>=) (Set xs) f = Set $ xs >>= (unsafeSetToList.f) - - -- | Transform a `Set` back into a list, the list returned does not have duplicate elements, the order of the original list holds. - setToList :: (Eq a) => Set a -> [a] - setToList (Set xs) = nub xs - - -- | Gives the underlying list of a set without removing duplicates, this function is not exported. - unsafeSetToList :: Set a -> [a] - unsafeSetToList (Set xs) = xs - - -- | Size of a set. - cardinal :: (Eq a) => Set a -> Int - cardinal = length.setToList - - -- | Return wether an element is in a set. - isIn :: (Eq a) => a -> Set a -> Bool - isIn x = (elem x).unsafeSetToList - - -- | Return the intersection of two sets. - (|&|) :: (Eq a) => Set a -> Set a -> Set a - (|&|) (Set xs) (Set ys) = Set $ xs `intersect` ys - - -- | Return the union of two sets. - (|||) :: Set a -> Set a -> Set a - (|||) (Set xs) (Set ys) = Set $ xs ++ ys - - -- | Return the cartesian product of two sets. - (|*|) :: Set a -> Set b -> Set (a,b) - (|*|) (Set xs) (Set ys) = Set $ [(x,y) | x <- xs, y <- ys] - - -- | Return the disjoint union of two sets. - (|+|) :: Set a -> Set b -> Set (Either a b) - (|+|) (Set xs) (Set ys) = Set $ [Left x | x <- xs] ++ [Right y | y <- ys] - - -- | Returns the cartesian product of a set with itself n times. - (|^|) :: (Num a, Eq a) => Set a -> a -> Set [a] - (|^|) _ 0 = Set [[]] - (|^|) s n = (:) <$> s <*> (s |^| (n-1)) - - -- | Return the difference of two sets. - (|-|) :: (Eq a) => Set a -> Set a -> Set a - (|-|) (Set xs) (Set ys) = Set $ xs \\ ys - - -- | Return the set of all subsets of a given set. - powerSet :: Set a -> Set (Set a) - powerSet (Set xs) = Set $ Set <$> subsequences xs - - -- | Filter a set according to a condition. - filterSet :: (a -> Bool) -> Set a -> Set a - filterSet f (Set xs) = Set $ filter f xs - - -- | Set version of listToMaybe. - setToMaybe :: Set a -> Maybe a - setToMaybe = listToMaybe.unsafeSetToList - - -- | Set version of maybeToList. - maybeToSet :: Maybe a -> Set a - maybeToSet x = Set $ maybeToList x - - -- | Set version of catMaybes. - catMaybesToSet :: Set (Maybe a) -> Set a - catMaybesToSet = set.catMaybes.unsafeSetToList - - -- | Set version of mapMaybe. - mapMaybeToSet :: (a -> Maybe b) -> Set a -> Set b - mapMaybeToSet f = set.(mapMaybe f).unsafeSetToList - - -- | A function of homogeneous sets. It is a set of pairs (key,value) such that their should only be one pair with a given key. - -- - -- It is an abstract type, the smart constructor is `function`. - data Function a b = Function (Set (a,b)) deriving (Eq) - - instance (Show a, Show b) => Show (Function a b) where - show (Function al) = "(function "++show al++")" - - -- | An association list is a list of pairs (key,value). - type AssociationList a b = [(a,b)] - - -- | The smart constructor of functions. This is the only way of instantiating a `Function`. - -- - -- Takes an association list and returns a function which maps to each key the value associated. - -- - -- If several pairs have the same keys, they are kept until the user wants an association list back. - function :: AssociationList a b -> Function a b - function al = Function $ Set $ al - - -- | Transform a function back into its underlying association list. - functionToSet :: (Eq a) => Function a b -> Set (a,b) - functionToSet (Function (Set al)) = Set $ nubBy (\x y -> (fst x) == (fst y)) al - - -- | Return the domain of a function. - domain :: Function a b -> Set a - domain (Function al) = fst <$> al - - -- | Return the image of a function. The image of a function is the set of values which are reachable by applying the function. - image :: Function a b -> Set b - image (Function al) = snd <$> al - - -- | Apply a function to a given value. If the function is not defined on the given value returns `Nothing`, otherwise returns `Just` the image. - -- - -- This function is like `lookup` in Data.Map for function (the order of the argument are reversed though). - (|$|) :: (Eq a) => Function a b -> a -> Maybe b - (|$|) (Function (Set [])) _ = Nothing - (|$|) (Function (Set ((k,v):xs))) x - | x == k = Just v - | otherwise = (Function (Set xs)) |$| x - - -- | Unsafe version of `(|$|)`. - -- - -- This function is like `(!)` in Data.Map for function. - (|!|) :: (Eq a) => Function a b -> a -> b - (|!|) (Function (Set [])) _ = error "Function applied on a value not in the domain." - (|!|) (Function (Set ((k,v):xs))) x - | x == k = v - | otherwise = (Function (Set xs)) |!| x - - -- | Apply a function to a given value, if the value is in the domain returns the image, otherwise return a default value. - -- - -- This function is like `findWithDefault` in Data.Map for function (the order of the argument are reversed though). - findWithDefault :: (Eq a) => Function a b -> b -> a -> b - findWithDefault (Function (Set [])) d _ = d - findWithDefault (Function (Set ((k,v):xs))) d x - | x == k = v - | otherwise = findWithDefault (Function (Set xs)) d x - - -- | Compose two functions. If the two functions are not composable, strips the functions until they can compose. - (|.|) :: (Eq a, Eq b) => Function b c -> Function a b -> Function a c - (|.|) f2 f1 = Function $ Set [(k,(f2 |!| (f1 |!| k))) | k <- (setToList.domain $ f1), f1 |!| k `isIn` (domain f2)] - - -- | Memorize a Haskell function on a given finite domain. - memorizeFunction :: (a -> b) -> Set a -> Function a b - memorizeFunction f (Set xs) = Function $ Set [(k, f k) | k <- xs] -
+ src/Math/WeakSets/PureSet.hs view
@@ -0,0 +1,136 @@+{-| Module : WeakSets +Description : Pure sets are nested sets which only contain other sets all the way down. They allow to explore basic set theory. +Copyright : Guillaume Sabbagh 2022 +License : GPL-3 +Maintainer : guillaumesabbagh@protonmail.com +Stability : experimental +Portability : portable + +Pure sets are nested sets which only contain other sets all the way down. They allow to explore basic set theory. + +Every mathematical object is a set, usual constructions such as Von Neumann numbers and Kuratowski pairs are implemented. + +It is a tree where the order of the branches does not matter. + +Functions with the same name as homogeneous set functions are suffixed with the letter 'P' for pure to avoid name collision. +-} + +module Math.WeakSets.PureSet +( + -- * `PureSet` datatype + PureSet(..), + pureSet, + -- * Mathematical constructions using sets + emptySet, + singleton, + pair, + cartesianProduct, + numberToSet, + (||||), + (&&&&), + isInP, + isIncludedInP, + card, + powerSetP, + -- * Formatting functions + prettify, + formatPureSet, +) +where + import Data.WeakSets.HomogeneousSet + import Data.List (intersect, nub, intercalate, subsequences) + import Data.Maybe (fromJust, catMaybes) + + -- | A `PureSet` is a `Set` of other pure sets. + data PureSet = PureSet (Set PureSet) deriving (Eq) + + instance Show PureSet where + show (PureSet xs) = "(pureSet "++ show (setToList xs) ++")" + + -- | Construct a `PureSet` from a list of pure sets. + pureSet :: [PureSet] -> PureSet + pureSet = (PureSet).set + + -- | Peel a `PureSet` into a `Set`. + pureSetToSet :: PureSet -> Set PureSet + pureSetToSet (PureSet xs) = xs + + -- | Construct the empty set. + emptySet :: PureSet + emptySet = pureSet [] + + -- | Construct the singleton containing a given set. + singleton :: PureSet -> PureSet + singleton x = pureSet $ [x] + + -- | Construct an ordered pair from two sets according to Kuratowski's definition of a tuple. + pair :: PureSet -> PureSet -> PureSet + pair x y = PureSet $ set [singleton x, pureSet $ [x,y]] + + -- | Construct the cartesian product of two sets. + cartesianProduct :: PureSet -> PureSet -> PureSet + cartesianProduct (PureSet xs) (PureSet ys) = pureSet $ [pair x y | x <- setToList xs, y <- setToList ys] + + -- | Union of two pure sets. + (||||) :: PureSet -> PureSet -> PureSet + (||||) (PureSet xs) (PureSet ys) = PureSet $ xs ||| ys + + -- | Intersection of two pure sets. + (&&&&) :: PureSet -> PureSet -> PureSet + (&&&&) (PureSet xs) (PureSet ys) = PureSet $ xs |&| ys + + -- | Difference of two pure sets. + (\\\\) :: PureSet -> PureSet -> PureSet + (\\\\) (PureSet xs) (PureSet ys) = PureSet $ xs |-| ys + + -- | Transform a number into its Von Neumann construction + numberToSet :: (Num a, Eq a) => a -> PureSet + numberToSet 0 = emptySet + numberToSet n = (numberToSet (n-1)) |||| (singleton (numberToSet (n-1))) + + -- | Return wether a pure set is in another one. + isInP :: PureSet -> PureSet -> Bool + isInP x (PureSet xs) = x `isIn` xs + + -- | Return wether a pure set is included in another one. + isIncludedInP :: PureSet -> PureSet -> Bool + isIncludedInP (PureSet xs) (PureSet ys) = xs `isIncludedIn` ys + + -- | Return the size of a pure set. + card :: PureSet -> Int + card (PureSet xs) = cardinal xs + + -- | Return the set of subsets of a given set. + powerSetP :: PureSet -> PureSet + powerSetP (PureSet xs) = PureSet $ PureSet <$> powerSet xs + + -- | Prettiffy a pure set according to usual mathematical notation. + prettify :: PureSet -> String + prettify (PureSet xs) + | cardinal xs == 0 = "{}" + | otherwise = "{" ++ (intercalate ", " $ prettify <$> setToList xs) ++ "}" + + -- | Format pure sets such that if numbers are recognized, they are transformed into integer and if pairs are recognized, they are transformed into pairs. + formatPureSet :: PureSet -> String + formatPureSet x + | (not.null) $ toNumber x = show.fromJust $ toNumber x + | (not.null) $ toPair x = fromJust.toPair $ x + | otherwise = "{"++intercalate "," (formatPureSet <$> (setToList.pureSetToSet $ x))++"}" + where + toNumber s@(PureSet xs) + | s == emptySet = Just 0 + | otherwise = let + numbers = setToList $ toNumber <$> xs + anyMissing = null $ foldr1 (>>) numbers + maxNb = maximum $ catMaybes numbers + in + if (not anyMissing) && (set (Just <$> [0..maxNb])) == (set numbers) then Just (maxNb + 1) else Nothing + toPair (PureSet xs) + | cardinal xs == 2 = + case () of + () | ((card $ (setToList xs) !! 0) == 1 && (card $ (setToList xs) !! 1) == 2) && ((setToList xs) !! 0) `isInP` ((setToList xs) !! 1) -> Just $ "(" ++ (formatPureSet.head.setToList.pureSetToSet $ ((setToList xs) !! 0)) ++ "," ++ (formatPureSet.head.setToList.pureSetToSet $ (((setToList xs) !! 1) \\\\ ((setToList xs) !! 0))) ++ ")" + | ((card $ (setToList xs) !! 1) == 1 && (card $ (setToList xs) !! 0) == 2) && ((setToList xs) !! 1) `isInP` ((setToList xs) !! 0) -> Just $ "(" ++ (formatPureSet.head.setToList.pureSetToSet $ ((setToList xs) !! 1)) ++ "," ++ (formatPureSet.head.setToList.pureSetToSet $ (((setToList xs) !! 0) \\\\ ((setToList xs) !! 1))) ++ ")" + | otherwise -> Nothing + | otherwise = Nothing + +
− src/PureSet.hs
@@ -1,136 +0,0 @@-{-| Module : WeakSets -Description : Pure sets are nested sets which only contain other sets all the way down. They allow to explore basic set theory. -Copyright : Guillaume Sabbagh 2022 -License : GPL-3 -Maintainer : guillaumesabbagh@protonmail.com -Stability : experimental -Portability : portable - -Pure sets are nested sets which only contain other sets all the way down. They allow to explore basic set theory. - -Every mathematical object is a set, usual constructions such as Von Neumann numbers and Kuratowski pairs are implemented. - -It is a tree where the order of the branches does not matter. - -Functions with the same name as homogeneous set functions are suffixed with the letter 'P' for pure to avoid name collision. --} - -module PureSet -( - -- * `PureSet` datatype - PureSet(..), - pureSet, - -- * Mathematical constructions using sets - emptySet, - singleton, - pair, - cartesianProduct, - numberToSet, - (||||), - (&&&&), - isInP, - isIncludedInP, - card, - powerSetP, - -- * Formatting functions - prettify, - formatPureSet, -) -where - import HomogeneousSet - import Data.List (intersect, nub, intercalate, subsequences) - import Data.Maybe (fromJust, catMaybes) - - -- | A `PureSet` is a `Set` of other pure sets. - data PureSet = PureSet (Set PureSet) deriving (Eq) - - instance Show PureSet where - show (PureSet xs) = "(pureSet "++ show (setToList xs) ++")" - - -- | Construct a `PureSet` from a list of pure sets. - pureSet :: [PureSet] -> PureSet - pureSet = (PureSet).set - - -- | Peel a `PureSet` into a `Set`. - pureSetToSet :: PureSet -> Set PureSet - pureSetToSet (PureSet xs) = xs - - -- | Construct the empty set. - emptySet :: PureSet - emptySet = pureSet [] - - -- | Construct the singleton containing a given set. - singleton :: PureSet -> PureSet - singleton x = pureSet $ [x] - - -- | Construct an ordered pair from two sets according to Kuratowski's definition of a tuple. - pair :: PureSet -> PureSet -> PureSet - pair x y = PureSet $ set [singleton x, pureSet $ [x,y]] - - -- | Construct the cartesian product of two sets. - cartesianProduct :: PureSet -> PureSet -> PureSet - cartesianProduct (PureSet xs) (PureSet ys) = pureSet $ [pair x y | x <- setToList xs, y <- setToList ys] - - -- | Union of two pure sets. - (||||) :: PureSet -> PureSet -> PureSet - (||||) (PureSet xs) (PureSet ys) = PureSet $ xs ||| ys - - -- | Intersection of two pure sets. - (&&&&) :: PureSet -> PureSet -> PureSet - (&&&&) (PureSet xs) (PureSet ys) = PureSet $ xs |&| ys - - -- | Difference of two pure sets. - (\\\\) :: PureSet -> PureSet -> PureSet - (\\\\) (PureSet xs) (PureSet ys) = PureSet $ xs |-| ys - - -- | Transform a number into its Von Neumann construction - numberToSet :: (Num a, Eq a) => a -> PureSet - numberToSet 0 = emptySet - numberToSet n = (numberToSet (n-1)) |||| (singleton (numberToSet (n-1))) - - -- | Return wether a pure set is in another one. - isInP :: PureSet -> PureSet -> Bool - isInP x (PureSet xs) = x `isIn` xs - - -- | Return wether a pure set is included in another one. - isIncludedInP :: PureSet -> PureSet -> Bool - isIncludedInP (PureSet xs) (PureSet ys) = xs `isIncludedIn` ys - - -- | Return the size of a pure set. - card :: PureSet -> Int - card (PureSet xs) = cardinal xs - - -- | Return the set of subsets of a given set. - powerSetP :: PureSet -> PureSet - powerSetP (PureSet xs) = PureSet $ PureSet <$> powerSet xs - - -- | Prettiffy a pure set according to usual mathematical notation. - prettify :: PureSet -> String - prettify (PureSet xs) - | cardinal xs == 0 = "{}" - | otherwise = "{" ++ (intercalate ", " $ prettify <$> setToList xs) ++ "}" - - -- | Format pure sets such that if numbers are recognized, they are transformed into integer and if pairs are recognized, they are transformed into pairs. - formatPureSet :: PureSet -> String - formatPureSet x - | (not.null) $ toNumber x = show.fromJust $ toNumber x - | (not.null) $ toPair x = fromJust.toPair $ x - | otherwise = "{"++intercalate "," (formatPureSet <$> (setToList.pureSetToSet $ x))++"}" - where - toNumber s@(PureSet xs) - | s == emptySet = Just 0 - | otherwise = let - numbers = setToList $ toNumber <$> xs - anyMissing = null $ foldr1 (>>) numbers - maxNb = maximum $ catMaybes numbers - in - if (not anyMissing) && (set (Just <$> [0..maxNb])) == (set numbers) then Just (maxNb + 1) else Nothing - toPair (PureSet xs) - | cardinal xs == 2 = - case () of - () | ((card $ (setToList xs) !! 0) == 1 && (card $ (setToList xs) !! 1) == 2) && ((setToList xs) !! 0) `isInP` ((setToList xs) !! 1) -> Just $ "(" ++ (formatPureSet.head.setToList.pureSetToSet $ ((setToList xs) !! 0)) ++ "," ++ (formatPureSet.head.setToList.pureSetToSet $ (((setToList xs) !! 1) \\\\ ((setToList xs) !! 0))) ++ ")" - | ((card $ (setToList xs) !! 1) == 1 && (card $ (setToList xs) !! 0) == 2) && ((setToList xs) !! 1) `isInP` ((setToList xs) !! 0) -> Just $ "(" ++ (formatPureSet.head.setToList.pureSetToSet $ ((setToList xs) !! 1)) ++ "," ++ (formatPureSet.head.setToList.pureSetToSet $ (((setToList xs) !! 0) \\\\ ((setToList xs) !! 1))) ++ ")" - | otherwise -> Nothing - | otherwise = Nothing - -
test/TestHomogeneousSet.hs view
@@ -1,5 +1,5 @@ module TestHomogeneousSet where - import HomogeneousSet + import Data.WeakSets.HomogeneousSet -- | Tests all functions related to homogeneous sets. main :: IO ()
test/TestPureSet.hs view
@@ -1,6 +1,6 @@ module TestPureSet where - import HomogeneousSet - import PureSet + import Data.WeakSets.HomogeneousSet + import Math.WeakSets.PureSet import Data.List (intercalate) -- | Tests all functions related to pure sets.