{-# LANGUAGE GeneralizedNewtypeDeriving #-} {- | Module : ELynx.Data.Tree.Subset Description : A subset is a set of elements Copyright : (c) Dominik Schrempf 2019 License : GPL-3 Maintainer : dominik.schrempf@gmail.com Stability : unstable Portability : portable Creation date: Fri Dec 13 11:02:43 2019. -} module ELynx.Data.Tree.Subset ( Subset () , sfromset , sfromlist , smap , snull , sempty , ssingleton , sunion , sunions , sdifference , sintersection , sdisjoint , smember , sshow ) where import Data.List (intercalate) import qualified Data.Set as S -- | A 'Subset' is a set of elements of type a. For example, on phylogenetic -- trees, a 'Subset' is a set of leaves. In this case, a 'Subset' is induced, -- for example, by a node on the (rooted) tree. The 'Subset's of leaf nodes are -- singletons. The 'Subset's of the root node is the set of all leaves. -- 'Subset's are the building blocks of partitions. Each branch on the tree -- induces a bipartition, or a pair of 'Subset's, see -- 'ELynx.Data.Tree.Bipartition'. Multifurcations induce multipartitions, see -- 'ELynx.Data.Tree.Multipartition'. -- -- Internally, a subset is just an 'S.Set', since the order of elements -- within the subset is not important, but the uniqueness of elements is. newtype Subset a = SS {subset :: S.Set a} deriving (Show, Read, Eq, Ord, Semigroup, Monoid, Foldable) -- | Create a subset from a set. sfromset :: S.Set a -> Subset a sfromset = SS -- | Create a subset from a list. Throws an error if duplicate elements are -- present in the list. sfromlist :: Ord a => [a] -> Subset a sfromlist l = if S.size s == length l then sfromset s else error "pfromlist: List contains duplicate elements." where s = S.fromList l -- | Map a function over all elements in a subset. smap :: Ord b => (a -> b) -> Subset a -> Subset b smap f = SS . S.map f . subset -- | Is the subset empty? snull :: Subset a -> Bool snull = S.null . subset -- | The empty subset. sempty :: Subset a sempty = SS S.empty -- | A subset with one element. ssingleton :: a -> Subset a ssingleton = SS . S.singleton -- | Unite two subsets. sunion :: Ord a => Subset a -> Subset a -> Subset a sunion p q = SS $ subset q `S.union` subset p -- | Unite a list of subsets. sunions :: Ord a => [Subset a] -> Subset a sunions = SS . S.unions . map subset -- | Difference of two subsets. sdifference :: Ord a => Subset a -> Subset a -> Subset a sdifference p q = SS $ subset p S.\\ subset q -- | Intersection of two subsets. sintersection :: Ord a => Subset a -> Subset a -> Subset a sintersection p q = SS $ S.intersection (subset p) (subset q) -- | Are two subsets disjoint? sdisjoint :: Ord a => Subset a -> Subset a -> Bool sdisjoint p q = S.disjoint (subset p) (subset q) -- | Check if an element is member of a subset. smember :: Ord a => a -> Subset a -> Bool smember x = S.member x . subset -- | Show the elements of a subset in a human readable way. sshow :: (a -> String) -> Subset a -> String sshow f = intercalate "," . map f . S.toList . subset