module Data.EnumSet (
T(Cons, decons),
fromEnum,
fromEnums,
toEnums,
intToEnums,
null,
empty,
(.&.),
(.|.),
xor,
unions,
get,
put,
set,
clear,
flip,
fromBool,
) where
import qualified Data.Bits as B
import Data.Bits (Bits, )
import qualified Foreign.Storable.Newtype as Store
import Foreign.Storable (Storable(..), )
import qualified Prelude as P
import Prelude hiding (fromEnum, toEnum, null, flip, )
newtype T word enum = Cons {decons :: word}
deriving (Eq)
instance (Storable word, Enum enum) => Storable (T word enum) where
sizeOf = Store.sizeOf decons
alignment = Store.alignment decons
peek = Store.peek Cons
poke = Store.poke decons
fromEnum :: (Enum a, Bits w) => a -> T w a
fromEnum = Cons . B.bit . P.fromEnum
fromEnums :: (Enum a, Bits w) => [a] -> T w a
fromEnums = Cons . foldl B.setBit 0 . map P.fromEnum
toEnums :: (Enum a, Bits w) => T w a -> [a]
toEnums =
map fst . filter (P.flip B.testBit 0 . snd) .
zip [P.toEnum 0 ..] . iterate (P.flip B.shiftR 1) .
decons
intToEnums :: (Enum a, Integral w) => T w a -> [a]
intToEnums =
map fst . filter (odd . snd) .
zip [P.toEnum 0 ..] . iterate (P.flip div 2) .
decons
null :: (Enum a, Bits w) => T w a -> Bool
null (Cons x) = x==0
empty :: (Enum a, Bits w) => T w a
empty = Cons 0
lift2 :: (w -> w -> w) -> (T w a -> T w a -> T w a)
lift2 f (Cons x) (Cons y) = Cons (f x y)
infixl 7 .&.
infixl 5 .|.
(.&.), (.|.), xor :: (Enum a, Bits w) => T w a -> T w a -> T w a
(.&.) = lift2 (B..&.)
(.|.) = lift2 (B..|.)
xor = lift2 B.xor
unions :: (Enum a, Bits w) => [T w a] -> T w a
unions = foldl (.|.) empty
get :: (Enum a, Bits w) => a -> T w a -> Bool
get n = P.flip B.testBit (P.fromEnum n) . decons
put :: (Enum a, Bits w) => a -> Bool -> T w a -> T w a
put n b s =
fromBool n b .|. clear n s
lift1 ::
(Enum a, Bits w) =>
(w -> Int -> w) -> (a -> T w a -> T w a)
lift1 f n (Cons vec) = Cons (f vec (P.fromEnum n))
set :: (Enum a, Bits w) => a -> T w a -> T w a
set = lift1 B.setBit
clear :: (Enum a, Bits w) => a -> T w a -> T w a
clear = lift1 B.clearBit
flip :: (Enum a, Bits w) => a -> T w a -> T w a
flip = lift1 B.complementBit
fromBool :: (Enum a, Bits w) => a -> Bool -> T w a
fromBool n b =
Cons (B.shiftL (fromIntegral $ P.fromEnum b) (P.fromEnum n))