module Data.IntSet.EnumSet2 where

import qualified Data.IntSet as S
import qualified Data.List as L (map)
import Data.Semigroup as Sem

newtype EnumSet e = EnumSet {EnumSet e -> IntSet
unEnumSet :: S.IntSet}
  deriving (EnumSet e -> EnumSet e -> Bool
(EnumSet e -> EnumSet e -> Bool)
-> (EnumSet e -> EnumSet e -> Bool) -> Eq (EnumSet e)
forall e. EnumSet e -> EnumSet e -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: EnumSet e -> EnumSet e -> Bool
$c/= :: forall e. EnumSet e -> EnumSet e -> Bool
== :: EnumSet e -> EnumSet e -> Bool
$c== :: forall e. EnumSet e -> EnumSet e -> Bool
Eq,Eq (EnumSet e)
Eq (EnumSet e) =>
(EnumSet e -> EnumSet e -> Ordering)
-> (EnumSet e -> EnumSet e -> Bool)
-> (EnumSet e -> EnumSet e -> Bool)
-> (EnumSet e -> EnumSet e -> Bool)
-> (EnumSet e -> EnumSet e -> Bool)
-> (EnumSet e -> EnumSet e -> EnumSet e)
-> (EnumSet e -> EnumSet e -> EnumSet e)
-> Ord (EnumSet e)
EnumSet e -> EnumSet e -> Bool
EnumSet e -> EnumSet e -> Ordering
EnumSet e -> EnumSet e -> EnumSet e
forall e. Eq (EnumSet e)
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall e. EnumSet e -> EnumSet e -> Bool
forall e. EnumSet e -> EnumSet e -> Ordering
forall e. EnumSet e -> EnumSet e -> EnumSet e
min :: EnumSet e -> EnumSet e -> EnumSet e
$cmin :: forall e. EnumSet e -> EnumSet e -> EnumSet e
max :: EnumSet e -> EnumSet e -> EnumSet e
$cmax :: forall e. EnumSet e -> EnumSet e -> EnumSet e
>= :: EnumSet e -> EnumSet e -> Bool
$c>= :: forall e. EnumSet e -> EnumSet e -> Bool
> :: EnumSet e -> EnumSet e -> Bool
$c> :: forall e. EnumSet e -> EnumSet e -> Bool
<= :: EnumSet e -> EnumSet e -> Bool
$c<= :: forall e. EnumSet e -> EnumSet e -> Bool
< :: EnumSet e -> EnumSet e -> Bool
$c< :: forall e. EnumSet e -> EnumSet e -> Bool
compare :: EnumSet e -> EnumSet e -> Ordering
$ccompare :: forall e. EnumSet e -> EnumSet e -> Ordering
$cp1Ord :: forall e. Eq (EnumSet e)
Ord,ReadPrec [EnumSet e]
ReadPrec (EnumSet e)
Int -> ReadS (EnumSet e)
ReadS [EnumSet e]
(Int -> ReadS (EnumSet e))
-> ReadS [EnumSet e]
-> ReadPrec (EnumSet e)
-> ReadPrec [EnumSet e]
-> Read (EnumSet e)
forall e. ReadPrec [EnumSet e]
forall e. ReadPrec (EnumSet e)
forall e. Int -> ReadS (EnumSet e)
forall e. ReadS [EnumSet e]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [EnumSet e]
$creadListPrec :: forall e. ReadPrec [EnumSet e]
readPrec :: ReadPrec (EnumSet e)
$creadPrec :: forall e. ReadPrec (EnumSet e)
readList :: ReadS [EnumSet e]
$creadList :: forall e. ReadS [EnumSet e]
readsPrec :: Int -> ReadS (EnumSet e)
$creadsPrec :: forall e. Int -> ReadS (EnumSet e)
Read,Int -> EnumSet e -> ShowS
[EnumSet e] -> ShowS
EnumSet e -> String
(Int -> EnumSet e -> ShowS)
-> (EnumSet e -> String)
-> ([EnumSet e] -> ShowS)
-> Show (EnumSet e)
forall e. Int -> EnumSet e -> ShowS
forall e. [EnumSet e] -> ShowS
forall e. EnumSet e -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [EnumSet e] -> ShowS
$cshowList :: forall e. [EnumSet e] -> ShowS
show :: EnumSet e -> String
$cshow :: forall e. EnumSet e -> String
showsPrec :: Int -> EnumSet e -> ShowS
$cshowsPrec :: forall e. Int -> EnumSet e -> ShowS
Show)

instance Sem.Semigroup (EnumSet e) where
  EnumSet x :: IntSet
x <> :: EnumSet e -> EnumSet e -> EnumSet e
<> EnumSet y :: IntSet
y = IntSet -> EnumSet e
forall e. IntSet -> EnumSet e
EnumSet (IntSet
x IntSet -> IntSet -> IntSet
forall a. Monoid a => a -> a -> a
`mappend` IntSet
y)

instance Monoid (EnumSet e) where
  mempty :: EnumSet e
mempty = IntSet -> EnumSet e
forall e. IntSet -> EnumSet e
EnumSet IntSet
forall a. Monoid a => a
mempty
  mappend :: EnumSet e -> EnumSet e -> EnumSet e
mappend = EnumSet e -> EnumSet e -> EnumSet e
forall a. Semigroup a => a -> a -> a
(<>)

(\\) :: (Enum e) => EnumSet e -> EnumSet e -> EnumSet e
\\ :: EnumSet e -> EnumSet e -> EnumSet e
(\\) (EnumSet s1 :: IntSet
s1) (EnumSet s2 :: IntSet
s2) = IntSet -> EnumSet e
forall e. IntSet -> EnumSet e
EnumSet (IntSet -> IntSet -> IntSet
(S.\\) IntSet
s1 IntSet
s2)

null :: (Enum e) => EnumSet e -> Bool
null :: EnumSet e -> Bool
null (EnumSet s :: IntSet
s) = IntSet -> Bool
S.null IntSet
s

size :: (Enum e) => EnumSet e -> Int
size :: EnumSet e -> Int
size (EnumSet s :: IntSet
s) = IntSet -> Int
S.size IntSet
s

member :: (Enum e) => e -> EnumSet e -> Bool
member :: e -> EnumSet e -> Bool
member e :: e
e (EnumSet s :: IntSet
s) = Int -> IntSet -> Bool
S.member (e -> Int
forall a. Enum a => a -> Int
fromEnum e
e) IntSet
s

notMember :: (Enum e) => Int -> EnumSet e -> Bool
notMember :: Int -> EnumSet e -> Bool
notMember e :: Int
e (EnumSet s :: IntSet
s) = Int -> IntSet -> Bool
S.notMember (Int -> Int
forall a. Enum a => a -> Int
fromEnum Int
e) IntSet
s

isSubsetOf :: (Enum e) => EnumSet e -> EnumSet e -> Bool
isSubsetOf :: EnumSet e -> EnumSet e -> Bool
isSubsetOf (EnumSet e1 :: IntSet
e1) (EnumSet e2 :: IntSet
e2) = IntSet -> IntSet -> Bool
S.isSubsetOf IntSet
e1 IntSet
e2

isProperSubsetOf :: (Enum e) => EnumSet e -> EnumSet e -> Bool
isProperSubsetOf :: EnumSet e -> EnumSet e -> Bool
isProperSubsetOf (EnumSet e1 :: IntSet
e1) (EnumSet e2 :: IntSet
e2) = IntSet -> IntSet -> Bool
S.isProperSubsetOf IntSet
e1 IntSet
e2

empty :: (Enum e) => EnumSet e
empty :: EnumSet e
empty = IntSet -> EnumSet e
forall e. IntSet -> EnumSet e
EnumSet (IntSet
S.empty)

singleton :: (Enum e) => e -> EnumSet e
singleton :: e -> EnumSet e
singleton e :: e
e = IntSet -> EnumSet e
forall e. IntSet -> EnumSet e
EnumSet (Int -> IntSet
S.singleton (e -> Int
forall a. Enum a => a -> Int
fromEnum e
e))

insert :: (Enum e) => e -> EnumSet e -> EnumSet e
insert :: e -> EnumSet e -> EnumSet e
insert e :: e
e (EnumSet s :: IntSet
s) = IntSet -> EnumSet e
forall e. IntSet -> EnumSet e
EnumSet (Int -> IntSet -> IntSet
S.insert (e -> Int
forall a. Enum a => a -> Int
fromEnum e
e) IntSet
s)

delete :: (Enum e) => e -> EnumSet e -> EnumSet e
delete :: e -> EnumSet e -> EnumSet e
delete e :: e
e (EnumSet s :: IntSet
s) = IntSet -> EnumSet e
forall e. IntSet -> EnumSet e
EnumSet (Int -> IntSet -> IntSet
S.delete (e -> Int
forall a. Enum a => a -> Int
fromEnum e
e) IntSet
s)

union :: (Enum e) => EnumSet e -> EnumSet e -> EnumSet e
union :: EnumSet e -> EnumSet e -> EnumSet e
union (EnumSet s1 :: IntSet
s1) (EnumSet s2 :: IntSet
s2) = IntSet -> EnumSet e
forall e. IntSet -> EnumSet e
EnumSet (IntSet -> IntSet -> IntSet
S.union IntSet
s1 IntSet
s2)

unions :: (Enum e) => [EnumSet e] -> EnumSet e
unions :: [EnumSet e] -> EnumSet e
unions es :: [EnumSet e]
es = IntSet -> EnumSet e
forall e. IntSet -> EnumSet e
EnumSet ([IntSet] -> IntSet
forall (f :: * -> *). Foldable f => f IntSet -> IntSet
S.unions ((EnumSet e -> IntSet) -> [EnumSet e] -> [IntSet]
forall a b. (a -> b) -> [a] -> [b]
L.map EnumSet e -> IntSet
forall e. EnumSet e -> IntSet
unEnumSet [EnumSet e]
es))

difference :: (Enum e) => EnumSet e -> EnumSet e -> EnumSet e
difference :: EnumSet e -> EnumSet e -> EnumSet e
difference (EnumSet e1 :: IntSet
e1) (EnumSet e2 :: IntSet
e2) = IntSet -> EnumSet e
forall e. IntSet -> EnumSet e
EnumSet (IntSet -> IntSet -> IntSet
S.difference IntSet
e1 IntSet
e2)

intersection :: (Enum e) => EnumSet e -> EnumSet e -> EnumSet e
intersection :: EnumSet e -> EnumSet e -> EnumSet e
intersection (EnumSet e1 :: IntSet
e1) (EnumSet e2 :: IntSet
e2) = IntSet -> EnumSet e
forall e. IntSet -> EnumSet e
EnumSet (IntSet -> IntSet -> IntSet
S.intersection IntSet
e1 IntSet
e2)

filter :: (Enum e) => (e -> Bool) -> EnumSet e -> EnumSet e
filter :: (e -> Bool) -> EnumSet e -> EnumSet e
filter f :: e -> Bool
f (EnumSet s :: IntSet
s) = IntSet -> EnumSet e
forall e. IntSet -> EnumSet e
EnumSet ((Int -> Bool) -> IntSet -> IntSet
S.filter Int -> Bool
f' IntSet
s)
  where f' :: Int -> Bool
f' b :: Int
b = e -> Bool
f (Int -> e
forall a. Enum a => Int -> a
toEnum Int
b)

partition :: (Enum e) => (e -> Bool) -> EnumSet e -> (EnumSet e, EnumSet e)
partition :: (e -> Bool) -> EnumSet e -> (EnumSet e, EnumSet e)
partition f :: e -> Bool
f (EnumSet s :: IntSet
s) = (IntSet -> EnumSet e
forall e. IntSet -> EnumSet e
EnumSet IntSet
s1', IntSet -> EnumSet e
forall e. IntSet -> EnumSet e
EnumSet IntSet
s2')
  where (s1' :: IntSet
s1',s2' :: IntSet
s2') = (Int -> Bool) -> IntSet -> (IntSet, IntSet)
S.partition Int -> Bool
f' IntSet
s
        f' :: Int -> Bool
f' b :: Int
b = e -> Bool
f (Int -> e
forall a. Enum a => Int -> a
toEnum Int
b)

split :: (Enum e) => e -> EnumSet e -> (EnumSet e, EnumSet e)
split :: e -> EnumSet e -> (EnumSet e, EnumSet e)
split e :: e
e (EnumSet s :: IntSet
s) = (IntSet -> EnumSet e
forall e. IntSet -> EnumSet e
EnumSet IntSet
s1', IntSet -> EnumSet e
forall e. IntSet -> EnumSet e
EnumSet IntSet
s2')
  where (s1' :: IntSet
s1',s2' :: IntSet
s2') = Int -> IntSet -> (IntSet, IntSet)
S.split (e -> Int
forall a. Enum a => a -> Int
fromEnum e
e) IntSet
s

splitMember :: (Enum e) => e -> EnumSet e -> (EnumSet e, Bool, EnumSet e)
splitMember :: e -> EnumSet e -> (EnumSet e, Bool, EnumSet e)
splitMember e :: e
e (EnumSet s :: IntSet
s) = (IntSet -> EnumSet e
forall e. IntSet -> EnumSet e
EnumSet IntSet
s1',Bool
a,IntSet -> EnumSet e
forall e. IntSet -> EnumSet e
EnumSet IntSet
s2')
  where (s1' :: IntSet
s1',a :: Bool
a,s2' :: IntSet
s2') = Int -> IntSet -> (IntSet, Bool, IntSet)
S.splitMember (e -> Int
forall a. Enum a => a -> Int
fromEnum e
e) IntSet
s

map :: (Enum e) => (e -> e) -> EnumSet e -> EnumSet e
map :: (e -> e) -> EnumSet e -> EnumSet e
map f :: e -> e
f (EnumSet s :: IntSet
s) = IntSet -> EnumSet e
forall e. IntSet -> EnumSet e
EnumSet ((Int -> Int) -> IntSet -> IntSet
S.map Int -> Int
f' IntSet
s)
  where f' :: Int -> Int
f' b :: Int
b = e -> Int
forall a. Enum a => a -> Int
fromEnum (e -> e
f (Int -> e
forall a. Enum a => Int -> a
toEnum Int
b))

fold :: (Enum e) => (e -> b -> b) -> b -> EnumSet e -> b
fold :: (e -> b -> b) -> b -> EnumSet e -> b
fold f :: e -> b -> b
f a :: b
a (EnumSet s :: IntSet
s) = (Int -> b -> b) -> b -> IntSet -> b
forall b. (Int -> b -> b) -> b -> IntSet -> b
S.fold Int -> b -> b
f' b
a IntSet
s
  where f' :: Int -> b -> b
f' b :: Int
b a1 :: b
a1 = e -> b -> b
f (Int -> e
forall a. Enum a => Int -> a
toEnum Int
b) b
a1

elems :: (Enum e) => EnumSet e -> [e]
elems :: EnumSet e -> [e]
elems (EnumSet s :: IntSet
s) = (Int -> e) -> [Int] -> [e]
forall a b. (a -> b) -> [a] -> [b]
L.map Int -> e
forall a. Enum a => Int -> a
toEnum (IntSet -> [Int]
S.elems IntSet
s)

toList :: (Enum e) => EnumSet e -> [e]
toList :: EnumSet e -> [e]
toList (EnumSet s :: IntSet
s) = (Int -> e) -> [Int] -> [e]
forall a b. (a -> b) -> [a] -> [b]
L.map Int -> e
forall a. Enum a => Int -> a
toEnum (IntSet -> [Int]
S.toList IntSet
s)

fromList :: (Enum e) => [e] -> EnumSet e
fromList :: [e] -> EnumSet e
fromList es :: [e]
es = IntSet -> EnumSet e
forall e. IntSet -> EnumSet e
EnumSet ([Int] -> IntSet
S.fromList ((e -> Int) -> [e] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
L.map e -> Int
forall a. Enum a => a -> Int
fromEnum [e]
es))

toAscList :: (Enum e) => EnumSet e -> [e]
toAscList :: EnumSet e -> [e]
toAscList (EnumSet s :: IntSet
s) = (Int -> e) -> [Int] -> [e]
forall a b. (a -> b) -> [a] -> [b]
L.map Int -> e
forall a. Enum a => Int -> a
toEnum (IntSet -> [Int]
S.toAscList IntSet
s)

fromAscList :: (Enum e) => [e] -> EnumSet e
fromAscList :: [e] -> EnumSet e
fromAscList es :: [e]
es = IntSet -> EnumSet e
forall e. IntSet -> EnumSet e
EnumSet ([Int] -> IntSet
S.fromAscList ((e -> Int) -> [e] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
L.map e -> Int
forall a. Enum a => a -> Int
fromEnum [e]
es))

fromDistinctAscList :: (Enum e) => [e] -> EnumSet e
fromDistinctAscList :: [e] -> EnumSet e
fromDistinctAscList es :: [e]
es = IntSet -> EnumSet e
forall e. IntSet -> EnumSet e
EnumSet ([Int] -> IntSet
S.fromDistinctAscList ((e -> Int) -> [e] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
L.map e -> Int
forall a. Enum a => a -> Int
fromEnum [e]
es))

showTree :: (Enum e) => EnumSet e -> String
showTree :: EnumSet e -> String
showTree (EnumSet s :: IntSet
s) = IntSet -> String
S.showTree IntSet
s

showTreeWith :: (Enum e) => Bool -> Bool -> EnumSet e -> String
showTreeWith :: Bool -> Bool -> EnumSet e -> String
showTreeWith a1 :: Bool
a1 a2 :: Bool
a2 (EnumSet s :: IntSet
s) = Bool -> Bool -> IntSet -> String
S.showTreeWith Bool
a1 Bool
a2 IntSet
s