    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 {forall e. 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
    $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
    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
    $ccompare :: forall e. EnumSet e -> EnumSet e -> Ordering
    compare :: EnumSet e -> EnumSet e -> Ordering
    $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
    >= :: EnumSet e -> EnumSet e -> Bool
    $cmax :: forall e. EnumSet e -> EnumSet e -> EnumSet e
    max :: EnumSet e -> EnumSet e -> EnumSet e
    $cmin :: forall e. EnumSet e -> EnumSet e -> EnumSet e
    min :: EnumSet e -> EnumSet e -> 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
    $creadsPrec :: forall e. Int -> ReadS (EnumSet e)
    readsPrec :: Int -> ReadS (EnumSet e)
    $creadList :: forall e. ReadS [EnumSet e]
    readList :: ReadS [EnumSet e]
    $creadPrec :: forall e. ReadPrec (EnumSet e)
    readPrec :: ReadPrec (EnumSet e)
    $creadListPrec :: forall e. ReadPrec [EnumSet e]
    readListPrec :: ReadPrec [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
    $cshowsPrec :: forall e. Int -> EnumSet e -> ShowS
    showsPrec :: Int -> EnumSet e -> ShowS
    $cshow :: forall e. EnumSet e -> String
    show :: EnumSet e -> String
    $cshowList :: forall e. [EnumSet e] -> ShowS
    showList :: [EnumSet e] -> ShowS
    Show)

    instance Sem.Semigroup (EnumSet e) where
      EnumSet IntSet
    x <> :: EnumSet e -> EnumSet e -> EnumSet e
    <> EnumSet 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
    \\ :: forall e. Enum e => EnumSet e -> EnumSet e -> EnumSet e
    (\\) (EnumSet IntSet
    s1) (EnumSet 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 :: forall e. Enum e => EnumSet e -> Bool
    null (EnumSet IntSet
    s) = IntSet -> Bool
    S.null IntSet
    s

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

    member :: (Enum e) => e -> EnumSet e -> Bool
    member :: forall e. Enum e => e -> EnumSet e -> Bool
    member e
    e (EnumSet 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 :: forall e. Enum e => Int -> EnumSet e -> Bool
    notMember Int
    e (EnumSet 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 :: forall e. Enum e => EnumSet e -> EnumSet e -> Bool
    isSubsetOf (EnumSet IntSet
    e1) (EnumSet IntSet
    e2) = IntSet -> IntSet -> Bool
    S.isSubsetOf IntSet
    e1 IntSet
    e2

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

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

    singleton :: (Enum e) => e -> EnumSet e
    singleton :: forall e. Enum e => e -> EnumSet e
    singleton 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 :: forall e. Enum e => e -> EnumSet e -> EnumSet e
    insert e
    e (EnumSet 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 :: forall e. Enum e => e -> EnumSet e -> EnumSet e
    delete e
    e (EnumSet 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 :: forall e. Enum e => EnumSet e -> EnumSet e -> EnumSet e
    union (EnumSet IntSet
    s1) (EnumSet 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 :: forall e. Enum e => [EnumSet e] -> EnumSet e
    unions [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 :: forall e. Enum e => EnumSet e -> EnumSet e -> EnumSet e
    difference (EnumSet IntSet
    e1) (EnumSet 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 :: forall e. Enum e => EnumSet e -> EnumSet e -> EnumSet e
    intersection (EnumSet IntSet
    e1) (EnumSet 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 :: forall e. Enum e => (e -> Bool) -> EnumSet e -> EnumSet e
    filter e -> Bool
    f (EnumSet 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' 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 :: forall e.
    Enum e =>
    (e -> Bool) -> EnumSet e -> (EnumSet e, EnumSet e)
    partition e -> Bool
    f (EnumSet 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 (IntSet
    s1',IntSet
    s2') = (Int -> Bool) -> IntSet -> (IntSet, IntSet)
    S.partition Int -> Bool
    f' IntSet
    s
            f' :: Int -> Bool
    f' 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 :: forall e. Enum e => e -> EnumSet e -> (EnumSet e, EnumSet e)
    split e
    e (EnumSet 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 (IntSet
    s1',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 :: forall e. Enum e => e -> EnumSet e -> (EnumSet e, Bool, EnumSet e)
    splitMember e
    e (EnumSet 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 (IntSet
    s1',Bool
    a,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 :: forall e. Enum e => (e -> e) -> EnumSet e -> EnumSet e
    map e -> e
    f (EnumSet 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' 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 :: forall e b. Enum e => (e -> b -> b) -> b -> EnumSet e -> b
    fold e -> b -> b
    f b
    a (EnumSet 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' Int
    b 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 :: forall e. Enum e => EnumSet e -> [e]
    elems (EnumSet 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 :: forall e. Enum e => EnumSet e -> [e]
    toList (EnumSet 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 :: forall e. Enum e => [e] -> EnumSet e
    fromList [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 :: forall e. Enum e => EnumSet e -> [e]
    toAscList (EnumSet 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 :: forall e. Enum e => [e] -> EnumSet e
    fromAscList [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 :: forall e. Enum e => [e] -> EnumSet e
    fromDistinctAscList [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 :: forall e. Enum e => EnumSet e -> String
    showTree (EnumSet IntSet
    s) = IntSet -> String
    S.showTree IntSet
    s

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