diff --git a/WeakSets.cabal b/WeakSets.cabal
--- a/WeakSets.cabal
+++ b/WeakSets.cabal
@@ -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:
diff --git a/src/Data/WeakSets/HomogeneousSet.hs b/src/Data/WeakSets/HomogeneousSet.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/WeakSets/HomogeneousSet.hs
@@ -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]
+    
diff --git a/src/HomogeneousSet.hs b/src/HomogeneousSet.hs
deleted file mode 100644
--- a/src/HomogeneousSet.hs
+++ /dev/null
@@ -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]
-    
diff --git a/src/Math/WeakSets/PureSet.hs b/src/Math/WeakSets/PureSet.hs
new file mode 100644
--- /dev/null
+++ b/src/Math/WeakSets/PureSet.hs
@@ -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
+    
+    
diff --git a/src/PureSet.hs b/src/PureSet.hs
deleted file mode 100644
--- a/src/PureSet.hs
+++ /dev/null
@@ -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
-    
-    
diff --git a/test/TestHomogeneousSet.hs b/test/TestHomogeneousSet.hs
--- a/test/TestHomogeneousSet.hs
+++ b/test/TestHomogeneousSet.hs
@@ -1,5 +1,5 @@
 module TestHomogeneousSet where
-    import HomogeneousSet
+    import Data.WeakSets.HomogeneousSet
     
     -- | Tests all functions related to homogeneous sets.
     main :: IO ()
diff --git a/test/TestPureSet.hs b/test/TestPureSet.hs
--- a/test/TestPureSet.hs
+++ b/test/TestPureSet.hs
@@ -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.
