linkedhashmap-0.1.0.0: src/Data/LinkedHashSet.hs
module Data.LinkedHashSet
(
LinkedHashSet
-- * Construction
, empty
, singleton
-- * Combine
-- , union
-- , unions
-- * Basic interface
, null
, size
, member
, insert
, delete
-- * Transformations
-- , map
-- * Difference and intersection
-- , difference
-- , intersection
-- * Folds
-- , foldl'
-- , foldr
-- * Filter
-- , filter
-- ** Lists
, toList
, fromList
) where
import Prelude hiding (null, lookup)
import Control.DeepSeq (NFData(rnf))
import Data.Hashable (Hashable)
import qualified Data.List as L
import qualified Data.LinkedHashMap.Seq as M
-- | A set of values. A set cannot contain duplicate values.
newtype LinkedHashSet a = LinkedHashSet {
asMap :: M.LinkedHashMap a ()
}
instance (Show a) => Show (LinkedHashSet a) where
showsPrec d m = showParen (d > 10) $
showString "fromList " . shows (toList m)
-- | /O(1)/ Construct an empty set.
empty :: LinkedHashSet a
empty = LinkedHashSet M.empty
-- | /O(1)/ Construct a set with a single element.
singleton :: (Eq a, Hashable a) => a -> LinkedHashSet a
singleton a = LinkedHashSet (M.singleton a ())
{-# INLINABLE singleton #-}
-- -- | /O(n+m)/ Construct a set containing all elements from both sets.
-- --
-- -- To obtain good performance, the smaller set must be presented as
-- -- the first argument.
-- union :: (Eq a, Hashable a) => LinkedHashSet a -> LinkedHashSet a -> LinkedHashSet a
-- union s1 s2 = LinkedHashSet $ M.union (asMap s1) (asMap s2)
-- {-# INLINE union #-}
-- -- | Construct a set containing all elements from a list of sets.
-- unions :: (Eq a, Hashable a) => [LinkedHashSet a] -> LinkedHashSet a
-- unions = List.foldl' union empty
-- {-# INLINE unions #-}
-- | /O(1)/ Return 'True' if this set is empty, 'False' otherwise.
null :: LinkedHashSet a -> Bool
null = M.null . asMap
{-# INLINE null #-}
-- | /O(1)/ Return the number of elements in this set.
size :: LinkedHashSet a -> Int
size = M.size . asMap
{-# INLINE size #-}
-- | /O(min(n,W))/ Return 'True' if the given value is present in this
-- set, 'False' otherwise.
member :: (Eq a, Hashable a) => a -> LinkedHashSet a -> Bool
member a s = case M.lookup a (asMap s) of
Just _ -> True
_ -> False
{-# INLINABLE member #-}
-- | /O(min(n,W))/ Add the specified value to this set.
insert :: (Eq a, Hashable a) => a -> LinkedHashSet a -> LinkedHashSet a
insert a = LinkedHashSet . M.insert a () . asMap
{-# INLINABLE insert #-}
-- | /O(min(n,W))/ Remove the specified value from this set if
-- present.
delete :: (Eq a, Hashable a) => a -> LinkedHashSet a -> LinkedHashSet a
delete a = LinkedHashSet . M.delete a . asMap
{-# INLINABLE delete #-}
-- -- | /O(n)/ Transform this set by applying a function to every value.
-- -- The resulting set may be smaller than the source.
-- map :: (Hashable b, Eq b) => (a -> b) -> LinkedHashSet a -> LinkedHashSet b
-- map f = fromList . List.map f . toList
-- {-# INLINE map #-}
-- -- | /O(n)/ Difference of two sets. Return elements of the first set
-- -- not existing in the second.
-- difference :: (Eq a, Hashable a) => LinkedHashSet a -> LinkedHashSet a -> LinkedHashSet a
-- difference (LinkedHashSet a) (LinkedHashSet b) = LinkedHashSet (M.difference a b)
-- {-# INLINABLE difference #-}
-- -- | /O(n)/ Intersection of two sets. Return elements present in both
-- -- the first set and the second.
-- intersection :: (Eq a, Hashable a) => LinkedHashSet a -> LinkedHashSet a -> LinkedHashSet a
-- intersection (LinkedHashSet a) (LinkedHashSet b) = LinkedHashSet (M.intersection a b)
-- {-# INLINABLE intersection #-}
-- -- | /O(n)/ Reduce this set by applying a binary operator to all
-- -- elements, using the given starting value (typically the
-- -- left-identity of the operator). Each application of the operator
-- -- is evaluated before before using the result in the next
-- -- application. This function is strict in the starting value.
-- foldl' :: (a -> b -> a) -> a -> LinkedHashSet b -> a
-- foldl' f z0 = M.foldlWithKey' g z0 . asMap
-- where g z k _ = f z k
-- {-# INLINE foldl' #-}
-- -- | /O(n)/ Reduce this set by applying a binary operator to all
-- -- elements, using the given starting value (typically the
-- -- right-identity of the operator).
-- foldr :: (b -> a -> a) -> a -> LinkedHashSet b -> a
-- foldr f z0 = foldrWithKey g z0 . asMap
-- where g k _ z = f k z
-- {-# INLINE foldr #-}
-- -- | /O(n)/ Filter this set by retaining only elements satisfying a
-- -- predicate.
-- filter :: (a -> Bool) -> LinkedHashSet a -> LinkedHashSet a
-- filter p = LinkedHashSet . H.filterWithKey q . asMap
-- where q k _ = p k
-- {-# INLINE filter #-}
-- | /O(n)/ Return a list of this set's elements. The list is produced lazily.
toList :: LinkedHashSet a -> [a]
toList t = map (\(k, _) -> k) $ M.toList (asMap t)
{-# INLINE toList #-}
-- | /O(n*min(W, n))/ Construct a set from a list of elements.
fromList :: (Eq a, Hashable a) => [a] -> LinkedHashSet a
fromList as = LinkedHashSet $ M.fromList $ zip as $ cycle [()]
{-# INLINE fromList #-}
instance (NFData a) => NFData (LinkedHashSet a) where
rnf = rnf . asMap