{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Data.EnumSet
( EnumSet
, intSetToEnumSet
, enumSetToIntSet
, (\\)
, null
, size
, member
, notMember
, lookupLT
, lookupGT
, lookupLE
, lookupGE
, isSubsetOf
, isProperSubsetOf
, empty
, singleton
, insert
, delete
, union
, unions
, difference
, intersection
, filter
, partition
, split
, splitMember
, map
, foldr
, foldl
, foldr'
, foldl'
, fold
, findMin
, findMax
, deleteMin
, deleteMax
, deleteFindMin
, deleteFindMax
, maxView
, minView
, elems
, toList
, fromList
, toAscList
, toDescList
, fromAscList
, fromDistinctAscList
) where
import Prelude hiding ( filter, foldl, foldr, lookup, map, null )
import qualified Prelude as P
import Data.IntSet ( IntSet )
import qualified Data.IntSet as I
import Control.Arrow ( (***) )
import Control.DeepSeq ( NFData )
import Data.Monoid ( Monoid )
import Data.Semigroup ( Semigroup )
import Data.Typeable ( Typeable )
import Text.Read
newtype EnumSet k = EnumSet { unWrap :: IntSet }
deriving (Eq, Semigroup, Monoid, Ord, Typeable, NFData)
instance (Enum k, Show k) => Show (EnumSet k) where
showsPrec p ks = showParen (p > 10) $
showString "fromList " . shows (toList ks)
instance (Enum k, Read k) => Read (EnumSet k) where
readPrec = parens . prec 10 $ do
Ident "fromList" <- lexP
list <- readPrec
return (fromList list)
intSetToEnumSet :: IntSet -> EnumSet k
intSetToEnumSet = EnumSet
{-# INLINE intSetToEnumSet #-}
enumSetToIntSet :: EnumSet k -> IntSet
enumSetToIntSet = unWrap
{-# INLINE enumSetToIntSet #-}
(\\) :: EnumSet k -> EnumSet k -> EnumSet k
(EnumSet is1) \\ (EnumSet is2) = EnumSet $ is1 I.\\ is2
{-# INLINE (\\) #-}
null :: EnumSet k -> Bool
null = I.null . unWrap
{-# INLINE null #-}
size :: EnumSet k -> Int
size = I.size . unWrap
{-# INLINE size #-}
member :: (Enum k) => k -> EnumSet k -> Bool
member k = I.member (fromEnum k) . unWrap
{-# INLINE member #-}
notMember :: (Enum k) => k -> EnumSet k -> Bool
notMember k = I.notMember (fromEnum k) . unWrap
{-# INLINE notMember #-}
lookupLT :: (Enum k) => k -> EnumSet k -> Maybe k
lookupLT k = fmap toEnum . I.lookupLT (fromEnum k) . unWrap
{-# INLINE lookupLT #-}
lookupGT :: (Enum k) => k -> EnumSet k -> Maybe k
lookupGT k = fmap toEnum . I.lookupGT (fromEnum k) . unWrap
{-# INLINE lookupGT #-}
lookupLE :: (Enum k) => k -> EnumSet k -> Maybe k
lookupLE k = fmap toEnum . I.lookupLE (fromEnum k) . unWrap
{-# INLINE lookupLE #-}
lookupGE :: (Enum k) => k -> EnumSet k -> Maybe k
lookupGE k = fmap toEnum . I.lookupGE (fromEnum k) . unWrap
{-# INLINE lookupGE #-}
empty :: EnumSet k
empty = EnumSet I.empty
{-# INLINE empty #-}
singleton :: (Enum k) => k -> EnumSet k
singleton = EnumSet . I.singleton . fromEnum
{-# INLINE singleton #-}
insert :: (Enum k) => k -> EnumSet k -> EnumSet k
insert k = EnumSet . I.insert (fromEnum k) . unWrap
{-# INLINE insert #-}
delete :: (Enum k) => k -> EnumSet k -> EnumSet k
delete k = EnumSet . I.delete (fromEnum k) . unWrap
{-# INLINE delete #-}
unions :: [EnumSet k] -> EnumSet k
unions = EnumSet . I.unions . P.map unWrap
{-# INLINE unions #-}
union :: EnumSet k -> EnumSet k -> EnumSet k
union (EnumSet is1) (EnumSet is2) = EnumSet $ I.union is1 is2
{-# INLINE union #-}
difference :: EnumSet k -> EnumSet k -> EnumSet k
difference (EnumSet is1) (EnumSet is2) = EnumSet $ I.difference is1 is2
{-# INLINE difference #-}
intersection :: EnumSet k -> EnumSet k -> EnumSet k
intersection (EnumSet is1) (EnumSet is2) = EnumSet $ I.intersection is1 is2
{-# INLINE intersection #-}
isProperSubsetOf :: EnumSet k -> EnumSet k -> Bool
isProperSubsetOf (EnumSet is1) (EnumSet is2) = I.isProperSubsetOf is1 is2
{-# INLINE isProperSubsetOf #-}
isSubsetOf :: EnumSet k -> EnumSet k -> Bool
isSubsetOf (EnumSet is1) (EnumSet is2) = I.isSubsetOf is1 is2
{-# INLINE isSubsetOf #-}
filter :: (Enum k) => (k -> Bool) -> EnumSet k -> EnumSet k
filter f = EnumSet . I.filter (f . toEnum) . unWrap
{-# INLINE filter #-}
partition :: (Enum k) => (k -> Bool) -> EnumSet k -> (EnumSet k, EnumSet k)
partition f = (EnumSet *** EnumSet) . I.partition (f . toEnum) . unWrap
{-# INLINE partition #-}
split :: (Enum k) => k -> EnumSet k -> (EnumSet k, EnumSet k)
split k = (EnumSet *** EnumSet) . I.split (fromEnum k) . unWrap
{-# INLINE split #-}
splitMember :: (Enum k) => k -> EnumSet k -> (EnumSet k, Bool, EnumSet k)
splitMember k = wrap . I.splitMember (fromEnum k) . unWrap
where
wrap (is1, b, is2) = (EnumSet is1, b, EnumSet is2)
{-# INLINE splitMember #-}
maxView :: (Enum k) => EnumSet k -> Maybe (k, EnumSet k)
maxView = fmap (toEnum *** EnumSet) . I.maxView . unWrap
{-# INLINE maxView #-}
minView :: (Enum k) => EnumSet k -> Maybe (k, EnumSet k)
minView = fmap (toEnum *** EnumSet) . I.minView . unWrap
{-# INLINE minView #-}
deleteFindMin :: (Enum k) => EnumSet k -> (k, EnumSet k)
deleteFindMin = (toEnum *** EnumSet) . I.deleteFindMin . unWrap
{-# INLINE deleteFindMin #-}
deleteFindMax :: (Enum k) => EnumSet k -> (k, EnumSet k)
deleteFindMax = (toEnum *** EnumSet) . I.deleteFindMax . unWrap
{-# INLINE deleteFindMax #-}
findMin :: (Enum k) => EnumSet k -> k
findMin = toEnum . I.findMin . unWrap
{-# INLINE findMin #-}
findMax :: (Enum k) => EnumSet k -> k
findMax = toEnum . I.findMax . unWrap
{-# INLINE findMax #-}
deleteMin :: EnumSet k -> EnumSet k
deleteMin = EnumSet . I.deleteMin . unWrap
{-# INLINE deleteMin #-}
deleteMax :: EnumSet k -> EnumSet k
deleteMax = EnumSet . I.deleteMax . unWrap
{-# INLINE deleteMax #-}
map :: (Enum k) => (k -> k) -> EnumSet k -> EnumSet k
map f = EnumSet . I.map (fromEnum . f . toEnum) . unWrap
{-# INLINE map #-}
foldr :: (Enum k) => (k -> b -> b) -> b -> EnumSet k -> b
foldr f acc = I.foldr (f . toEnum) acc . unWrap
{-# INLINE foldr #-}
foldl :: (Enum k) => (a -> k -> a) -> a -> EnumSet k -> a
foldl f acc = I.foldl (\a -> f a . toEnum) acc . unWrap
{-# INLINE foldl #-}
foldr' :: (Enum k) => (k -> b -> b) -> b -> EnumSet k -> b
foldr' f acc = I.foldr' (f . toEnum) acc . unWrap
{-# INLINE foldr' #-}
foldl' :: (Enum k) => (a -> k -> a) -> a -> EnumSet k -> a
foldl' f acc = I.foldl' (\a -> f a . toEnum) acc . unWrap
{-# INLINE foldl' #-}
fold :: (Enum k) => (k -> b -> b) -> b -> EnumSet k -> b
fold f acc = I.fold (f . toEnum) acc . unWrap
{-# INLINE fold #-}
elems :: (Enum k) => EnumSet k -> [k]
elems = P.map toEnum . I.elems . unWrap
{-# INLINE elems #-}
toList :: (Enum k) => EnumSet k -> [k]
toList = P.map toEnum . I.toList . unWrap
{-# INLINE toList #-}
toAscList :: (Enum k) => EnumSet k -> [k]
toAscList = P.map toEnum . I.toAscList . unWrap
{-# INLINE toAscList #-}
toDescList :: (Enum k) => EnumSet k -> [k]
toDescList = P.map toEnum . I.toDescList . unWrap
{-# INLINE toDescList #-}
fromList :: (Enum k) => [k] -> EnumSet k
fromList = EnumSet . I.fromList . P.map fromEnum
{-# INLINE fromList #-}
fromAscList :: (Enum k) => [k] -> EnumSet k
fromAscList = EnumSet . I.fromAscList . P.map fromEnum
{-# INLINE fromAscList #-}
fromDistinctAscList :: (Enum k) => [k] -> EnumSet k
fromDistinctAscList = EnumSet . I.fromDistinctAscList . P.map fromEnum
{-# INLINE fromDistinctAscList #-}