Data.HashSet
Introduction
HashSet
allows you to store unique elements, providing efficient insertion,
lookups, and deletion. A HashSet
makes no guarantees as to the order of its
elements.
If you are storing sets of Data.Ints consider using Data.IntSet from the containers package.
Examples
All the examples below assume HashSet
is imported qualified, and uses the following dataStructures
set.
>>>
import qualified Data.HashSet as HashSet
>>>
let dataStructures = HashSet.fromList ["Set", "Map", "Graph", "Sequence"]
Basic Operations
Check membership in a set:
>>>
-- Check if "Map" and "Trie" are in the set of data structures.
>>>
HashSet.member "Map" dataStructures
True>>>
HashSet.member "Trie" dataStructures
False
Add a new entry to the set:
>>>
let moreDataStructures = HashSet.insert "Trie" dataStructures
>>>
HashSet.member "Trie" moreDataStructures
> True
Remove the "Graph"
entry from the set of data structures.
>>>
let fewerDataStructures = HashSet.delete "Graph" dataStructures
>>>
HashSet.toList fewerDataStructures
["Map","Set","Sequence"]
Create a new set and combine it with our original set.
>>>
let unorderedDataStructures = HashSet.fromList ["HashSet", "HashMap"]
>>>
HashSet.union dataStructures unorderedDataStructures
fromList ["Map","HashSet","Graph","HashMap","Set","Sequence"]
Using custom data with HashSet
To create a HashSet
of your custom type, the type must have instances for
Eq
and Hashable
. The Hashable
typeclass is defined in the
hashable package, see the
documentation for information on how to make your type an instance of
Hashable
.
We'll start by setting up our custom data type:
>>>
:set -XDeriveGeneric
>>>
import GHC.Generics (Generic)
>>>
import Data.Hashable
>>>
data Person = Person { name :: String, likesDogs :: Bool } deriving (Show, Eq, Generic)
>>>
instance Hashable Person
And now we'll use it!
>>>
let people = HashSet.fromList [Person "Lana" True, Person "Joe" False, Person "Simon" True]
>>>
HashSet.filter likesDogs people
fromList [Person {name = "Simon", likesDogs = True},Person {name = "Lana", likesDogs = True}]
Performance
The implementation is based on hash array mapped tries. A
HashSet
is often faster than other Ord
-based set types,
especially when value comparisons are expensive, as in the case of
strings.
Many operations have a average-case complexity of
Documentation
A set of values. A set cannot contain duplicate values.
Instances
Foldable HashSet Source # | |
Defined in Data.HashSet.Internal Methods fold :: Monoid m => HashSet m -> m Source # foldMap :: Monoid m => (a -> m) -> HashSet a -> m Source # foldMap' :: Monoid m => (a -> m) -> HashSet a -> m Source # foldr :: (a -> b -> b) -> b -> HashSet a -> b Source # foldr' :: (a -> b -> b) -> b -> HashSet a -> b Source # foldl :: (b -> a -> b) -> b -> HashSet a -> b Source # foldl' :: (b -> a -> b) -> b -> HashSet a -> b Source # foldr1 :: (a -> a -> a) -> HashSet a -> a Source # foldl1 :: (a -> a -> a) -> HashSet a -> a Source # toList :: HashSet a -> [a] Source # null :: HashSet a -> Bool Source # length :: HashSet a -> Int Source # elem :: Eq a => a -> HashSet a -> Bool Source # maximum :: Ord a => HashSet a -> a Source # minimum :: Ord a => HashSet a -> a Source # | |
Eq1 HashSet Source # | |
Ord1 HashSet Source # | |
Defined in Data.HashSet.Internal | |
Show1 HashSet Source # | |
NFData1 HashSet Source # | Since: 0.2.14.0 |
Defined in Data.HashSet.Internal | |
Hashable1 HashSet Source # | |
Defined in Data.HashSet.Internal | |
Lift a => Lift (HashSet a :: Type) Source # | Since: 0.2.17.0 |
(Data a, Eq a, Hashable a) => Data (HashSet a) Source # | |
Defined in Data.HashSet.Internal Methods gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> HashSet a -> c (HashSet a) Source # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (HashSet a) Source # toConstr :: HashSet a -> Constr Source # dataTypeOf :: HashSet a -> DataType Source # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c (HashSet a)) Source # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (HashSet a)) Source # gmapT :: (forall b. Data b => b -> b) -> HashSet a -> HashSet a Source # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> HashSet a -> r Source # gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> HashSet a -> r Source # gmapQ :: (forall d. Data d => d -> u) -> HashSet a -> [u] Source # gmapQi :: Int -> (forall d. Data d => d -> u) -> HashSet a -> u Source # gmapM :: Monad m => (forall d. Data d => d -> m d) -> HashSet a -> m (HashSet a) Source # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> HashSet a -> m (HashSet a) Source # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> HashSet a -> m (HashSet a) Source # | |
(Hashable a, Eq a) => Monoid (HashSet a) Source # | To obtain good performance, the smaller set must be presented as the first argument. Examples
|
(Hashable a, Eq a) => Semigroup (HashSet a) Source # | To obtain good performance, the smaller set must be presented as the first argument. Examples
|
(Eq a, Hashable a) => IsList (HashSet a) Source # | |
(Eq a, Hashable a, Read a) => Read (HashSet a) Source # | |
Show a => Show (HashSet a) Source # | |
NFData a => NFData (HashSet a) Source # | |
Defined in Data.HashSet.Internal | |
Eq a => Eq (HashSet a) Source # | Note that, in the presence of hash collisions, equal
In general, the lack of substitutivity can be observed with any function that depends on the key ordering, such as folds and traversals. |
Ord a => Ord (HashSet a) Source # | |
Defined in Data.HashSet.Internal | |
Hashable a => Hashable (HashSet a) Source # | |
type Item (HashSet a) Source # | |
Defined in Data.HashSet.Internal |
Construction
singleton :: Hashable a => a -> HashSet a Source #
>>>
HashSet.singleton 1
fromList [1]
Combine
union :: (Eq a, Hashable a) => HashSet a -> HashSet a -> HashSet a Source #
To obtain good performance, the smaller set must be presented as the first argument.
>>>
union (fromList [1,2]) (fromList [2,3])
fromList [1,2,3]
unions :: (Eq a, Hashable a) => [HashSet a] -> HashSet a Source #
Construct a set containing all elements from a list of sets.
Basic interface
size :: HashSet a -> Int Source #
>>>
HashSet.size HashSet.empty
0>>>
HashSet.size (HashSet.fromList [1,2,3])
3
insert :: (Eq a, Hashable a) => a -> HashSet a -> HashSet a Source #
>>>
HashSet.insert 1 HashSet.empty
fromList [1]
delete :: (Eq a, Hashable a) => a -> HashSet a -> HashSet a Source #
>>>
HashSet.delete 1 (HashSet.fromList [1,2,3])
fromList [2,3]>>>
HashSet.delete 1 (HashSet.fromList [4,5,6])
fromList [4,5,6]
isSubsetOf :: (Eq a, Hashable a) => HashSet a -> HashSet a -> Bool Source #
Examples
>>>
fromList [1,3] `isSubsetOf` fromList [1,2,3]
True
>>>
fromList [1,2] `isSubsetOf` fromList [1,3]
False
Since: 0.2.12
Transformations
map :: (Hashable b, Eq b) => (a -> b) -> HashSet a -> HashSet b Source #
>>>
HashSet.map show (HashSet.fromList [1,2,3])
HashSet.fromList ["1","2","3"]
Difference and intersection
difference :: (Eq a, Hashable a) => HashSet a -> HashSet a -> HashSet a Source #
>>>
HashSet.difference (HashSet.fromList [1,2,3]) (HashSet.fromList [2,3,4])
fromList [1]
intersection :: (Eq a, Hashable a) => HashSet a -> HashSet a -> HashSet a Source #
>>>
HashSet.intersection (HashSet.fromList [1,2,3]) (HashSet.fromList [2,3,4])
fromList [2,3]
Folds
foldl' :: (a -> b -> a) -> a -> HashSet b -> a Source #
foldr :: (b -> a -> a) -> a -> HashSet b -> a Source #
Filter
filter :: (a -> Bool) -> HashSet a -> HashSet a Source #
Conversions
Lists
toList :: HashSet a -> [a] Source #
fromList :: (Eq a, Hashable a) => [a] -> HashSet a Source #