{-# LANGUAGE BangPatterns #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE TypeFamilies #-} {-# OPTIONS_GHC -O2 #-} module Data.Set.Unlifted ( Set , singleton , member , size ) where import Data.Primitive.UnliftedArray (UnliftedArray, PrimUnlifted(..)) import Data.Semigroup (Semigroup) import qualified Data.Foldable as F import qualified Data.Semigroup as SG import qualified GHC.Exts as E import qualified Data.Set.Internal as I -- | A set of elements. newtype Set a = Set (I.Set UnliftedArray a) instance PrimUnlifted (Set a) where toArrayArray# (Set x) = toArrayArray# x fromArrayArray# y = Set (fromArrayArray# y) instance (PrimUnlifted a, Ord a) => Semigroup (Set a) where Set x <> Set y = Set (I.append x y) stimes = SG.stimesIdempotentMonoid sconcat xs = Set (I.concat (E.coerce (F.toList xs))) instance (PrimUnlifted a, Ord a) => Monoid (Set a) where mempty = Set I.empty mappend = (SG.<>) mconcat xs = Set (I.concat (E.coerce xs)) instance (PrimUnlifted a, Eq a) => Eq (Set a) where Set x == Set y = I.equals x y instance (PrimUnlifted a, Ord a) => Ord (Set a) where compare (Set x) (Set y) = I.compare x y -- | The functions that convert a list to a 'Set' are asymptotically -- better that using @'foldMap' 'singleton'@, with a cost of /O(n*log n)/ -- rather than /O(n^2)/. If the input list is sorted, even if duplicate -- elements are present, the algorithm further improves to /O(n)/. The -- fastest option available is calling 'fromListN' on a presorted list -- and passing the correct size size of the resulting 'Set'. However, even -- if an incorrect size is given to this function, -- it will still correctly convert the list into a 'Set'. instance (PrimUnlifted a, Ord a) => E.IsList (Set a) where type Item (Set a) = a fromListN n = Set . I.fromListN n fromList = Set . I.fromList toList (Set s) = I.toList s instance (PrimUnlifted a, Show a) => Show (Set a) where showsPrec p (Set s) = I.showsPrec p s -- | Test for membership in the set. member :: (PrimUnlifted a, Ord a) => a -> Set a -> Bool member a (Set s) = I.member a s -- | Construct a set with a single element. singleton :: PrimUnlifted a => a -> Set a singleton = Set . I.singleton -- | The number of elements in the set. size :: PrimUnlifted a => Set a -> Int size (Set s) = I.size s