diff --git a/enumset.cabal b/enumset.cabal
--- a/enumset.cabal
+++ b/enumset.cabal
@@ -1,5 +1,6 @@
+-- would also be useful as type-safe alternative in wx, wxcore
 Name:             enumset
-Version:          0.0.1
+Version:          0.0.2
 License:          BSD3
 License-File:     LICENSE
 Author:           Henning Thielemann <haskell@henning-thielemann.de>
@@ -14,17 +15,16 @@
   represents a flag set stored in a Word16
   that supports the flags @LT@, @EQ@, @GT@.
   .
-  This package is similar to the @bitset@ package
-  the @Data.Edison.Coll.EnumSet@ module in the edison package,
+  This package is similar to the @bitset@ package and
+  the @Data.Edison.Coll.EnumSet@ module in the @edison@ package,
   however our implementation allows you to choose the embedding type
   and thus the maximum size of the set.
--- Portability:      Haskell98
-Cabal-Version:    >=1.6
+Cabal-Version:    >=1.10
 Tested-With:      GHC==6.10.4, GHC==6.12.3
 Build-Type:       Simple
 
 Source-Repository this
-  Tag:         0.0.1
+  Tag:         0.0.2
   Type:        darcs
   Location:    http://code.haskell.org/~thielema/enumset/
 
@@ -33,7 +33,9 @@
   Location:    http://code.haskell.org/~thielema/enumset/
 
 Library
+  Default-Language: Haskell98
   Build-Depends:
+    data-accessor >=0.2.1 && <0.3,
     storable-record >=0.0.1 && <0.1,
     base >= 4 && <5
 
@@ -42,3 +44,4 @@
   Exposed-Modules:
     Data.EnumSet
     Data.EnumSet.PackedEnum
+    Data.FlagSet
diff --git a/src/Data/EnumSet.hs b/src/Data/EnumSet.hs
--- a/src/Data/EnumSet.hs
+++ b/src/Data/EnumSet.hs
@@ -2,6 +2,9 @@
 Similar to Data.Edison.Coll.EnumSet
 but it allows to choose the underlying type for bit storage.
 This is really a low-level module for type-safe foreign function interfaces.
+
+The integer representation of the enumeration type
+is the bit position of the flag within the bitvector.
 -}
 module Data.EnumSet (
    T(Cons, decons),
@@ -9,14 +12,20 @@
    fromEnums,
    toEnums,
    intToEnums,
+   mostSignificantPosition,
+   singletonByPosition,
    null,
    empty,
+   singleton,
+   disjoint,
    (.&.),
+   (.-.),
    (.|.),
    xor,
    unions,
    get,
    put,
+   accessor,
    set,
    clear,
    flip,
@@ -26,23 +35,36 @@
 import qualified Data.Bits as B
 import Data.Bits (Bits, )
 
+import Data.Monoid (Monoid(mempty, mappend), )
+
 import qualified Foreign.Storable.Newtype as Store
-import Foreign.Storable (Storable(..), )
+import Foreign.Storable (Storable(sizeOf, alignment, peek, poke), )
 
+import qualified Data.Accessor.Basic as Acc
+
 import qualified Prelude as P
 import Prelude hiding (fromEnum, toEnum, null, flip, )
 
 
-newtype T word enum = Cons {decons :: word}
+newtype T word index = Cons {decons :: word}
    deriving (Eq)
 
-instance (Storable word, Enum enum) => Storable (T word enum) where
+instance (Enum a, Storable w) => Storable (T w a) where
    sizeOf = Store.sizeOf decons
    alignment = Store.alignment decons
    peek = Store.peek Cons
    poke = Store.poke decons
 
+{- |
+Since this data type is intended for constructing flags,
+we choose the set union as mappend.
+For intersection we would also not have a canonical identity element.
+-}
+instance (Enum a, Bits w) => Monoid (T w a) where
+   mempty = empty
+   mappend = (.|.)
 
+
 fromEnum :: (Enum a, Bits w) => a -> T w a
 fromEnum = Cons . B.bit . P.fromEnum
 
@@ -62,24 +84,59 @@
    decons
 
 
+{- |
+floor of binary logarithm -
+Intended for getting the position of a single set bit.
+This in turn is intended for implementing an 'Enum' instance
+if you only know masks but no bit positions.
+-}
+{-# INLINE mostSignificantPosition #-}
+mostSignificantPosition :: (Bits w, Storable w) => T w a -> Int
+mostSignificantPosition (Cons x) =
+   snd $
+   foldl
+      (\(x0,pos) testPos ->
+         let x1 = B.shiftR x0 testPos
+         in  if x1 == 0
+               then (x0, pos)
+               else (x1, pos+testPos))
+      (x,0) $
+   reverse $
+   takeWhile (< sizeOf x * 8) $
+   iterate (2*) 1
+
+{- |
+set a bit -
+Intended for implementing an 'Enum' instance
+if you only know masks but no bit positions.
+-}
+{-# INLINE singletonByPosition #-}
+singletonByPosition :: (Bits w) => Int -> T w a
+singletonByPosition = Cons . B.setBit 0
+
+
 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
 
+disjoint :: (Enum a, Bits w) => T w a -> T w a -> Bool
+disjoint x y = null (x .&. y)
 
+
 {-# INLINE lift2 #-}
 lift2 :: (w -> w -> w) -> (T w a -> T w a -> T w a)
 lift2 f (Cons x) (Cons y) = Cons (f x y)
 
 -- fixities like in Data.Bits
-infixl 7 .&.
+infixl 7 .&., .-.
 infixl 5 .|.
 
-(.&.), (.|.), xor :: (Enum a, Bits w) => T w a -> T w a -> T w a
+(.&.), (.-.), (.|.), xor :: (Enum a, Bits w) => T w a -> T w a -> T w a
 (.&.) = lift2 (B..&.)
 (.|.) = lift2 (B..|.)
+(.-.) = lift2 (\x y -> x B..&. B.complement y)
 xor   = lift2 B.xor
 
 unions :: (Enum a, Bits w) => [T w a] -> T w a
@@ -93,12 +150,18 @@
 put n b s =
    fromBool n b .|. clear n s
 
+accessor :: (Enum a, Bits w) => a -> Acc.T (T w a) Bool
+accessor x = Acc.fromSetGet (put x) (get x)
 
+
 {-# INLINE lift1 #-}
 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))
+
+singleton :: (Enum a, Bits w) => a -> T w a
+singleton = P.flip set empty
 
 set :: (Enum a, Bits w) => a -> T w a -> T w a
 set = lift1 B.setBit
diff --git a/src/Data/EnumSet/PackedEnum.hs b/src/Data/EnumSet/PackedEnum.hs
--- a/src/Data/EnumSet/PackedEnum.hs
+++ b/src/Data/EnumSet/PackedEnum.hs
@@ -1,7 +1,10 @@
 {- |
 Extract and inject an Enum value into an EnumSet.
 -}
-module Data.EnumSet.PackedEnum (T(Cons), unpack, pack, clear, put, ) where
+module Data.EnumSet.PackedEnum
+   {-# DEPRECATED "use Data.FlagSet instead" #-}
+   (T(Cons), unpack, pack, clear, put, )
+   where
 
 import qualified Data.EnumSet as ES
 
diff --git a/src/Data/FlagSet.hs b/src/Data/FlagSet.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/FlagSet.hs
@@ -0,0 +1,142 @@
+{- |
+A bit vector that represents a record in a bit-packed way.
+-}
+module Data.FlagSet (
+   T(Cons, decons),
+   fromMaskedValue, match,
+   Enum(fromEnum),
+   compose, decompose,
+   Mask(Mask, unmask), maskValue,
+   Value(Value, unvalue),
+   MaskedValue(MaskedValue),
+   get, put, accessor,
+   ) where
+
+import qualified Data.Bits as B
+import Data.Bits (Bits, (.&.), (.|.), )
+
+import Data.Monoid (Monoid(mempty, mappend, mconcat), )
+
+import qualified Foreign.Storable.Newtype as Store
+import Foreign.Storable (Storable(sizeOf, alignment, peek, poke), )
+
+import qualified Data.Accessor.Basic as Acc
+
+import qualified Prelude as P
+import Prelude hiding (Enum, fromEnum, toEnum, null, flip, )
+
+
+{- |
+The basic bit vector data type.
+It does not provide a lot of functionality,
+since that could not be done in a safe way.
+
+The type @a@ identifies the maintained flags.
+It may be an empty type
+but it may also be an enumeration
+of record fields with concrete values.
+In the latter case you are encouraged to define an 'Enum' instance
+for this enumeration.
+Be aware that it is different from 'P.Enum' of Prelude.
+-}
+newtype T word a = Cons {decons :: word}
+   deriving (Eq)
+
+instance (Storable w) => Storable (T w a) where
+   sizeOf = Store.sizeOf decons
+   alignment = Store.alignment decons
+   peek = Store.peek Cons
+   poke = Store.poke decons
+
+
+{- |
+@Mask w a b@ describes a field of a @T w a@ that has type @Value w b@.
+On the machine level a 'Mask' value is a vector of bits,
+where set bits represent the bits belonging to one record field.
+There must be only one mask value for every pair of types @(a,b)@.
+-}
+newtype Mask w a b = Mask {unmask :: w}
+   deriving (Eq, Show)
+
+newtype Value w b = Value {unvalue :: w}
+   deriving (Eq, Show)
+
+
+get :: (Enum a, Bits w) => Mask w a b -> T w a -> Value w b
+get (Mask m) (Cons fs) = Value (m .&. fs)
+
+put :: (Enum a, Bits w) => Mask w a b -> Value w b -> T w a -> T w a
+put (Mask m) (Value v) (Cons fs) =
+   Cons $ (fs .-. m) .|. v
+
+accessor :: (Enum a, Bits w) => Mask w a b -> Acc.T (T w a) (Value w b)
+accessor m = Acc.fromSetGet (put m) (get m)
+
+
+
+{- |
+Combines a mask with a value, that matches this mask.
+In @MaskedValue mask value@, @value@ must be a subset of @mask@.
+-}
+data MaskedValue w a = MaskedValue w w
+   deriving (Eq, Show)
+
+
+fromMaskedValue :: MaskedValue w a -> T w a
+fromMaskedValue (MaskedValue _m v) = Cons v
+
+match :: (Bits w) => T w a -> MaskedValue w a -> Bool
+match (Cons fs) (MaskedValue m v) =
+   m .&. fs  ==  v
+
+
+maskValue :: Mask w a b -> Value w b -> MaskedValue w a
+maskValue (Mask m) (Value v) = MaskedValue m v
+
+
+{- |
+@mappend a b@ means that values stored in @b@ overwrite corresponding values in @a@.
+-}
+instance (Bits w) => Monoid (MaskedValue w a) where
+   mempty = MaskedValue 0 0
+   mappend (MaskedValue mx vx) (MaskedValue my vy) =
+      MaskedValue (mx .|. my) (vx .-. my  .|.  vy)
+
+
+class Enum a where
+   {- |
+   'P.fromEnum' should return an integer
+   that represents the position of the @a@ value
+   in the list of all enumeration items.
+   In contrast to that,
+   'fromEnum' must return the according bit pattern.
+   -}
+   fromEnum :: (Bits w) => a -> MaskedValue w a
+
+{- |
+Decompose a flag set into flags.
+The flags are generated using the 'Bounded' and 'Enum' instance.
+We do not recommend to use the result list for further processing,
+since testing of flags is much faster using 'match'.
+However you may find it useful to 'show' the list.
+-}
+decompose :: (Bounded a, Enum a, P.Enum a, Bits w) => T w a -> [a]
+decompose x =
+   filter (match x . fromEnum) [minBound .. maxBound]
+
+{- |
+Compose a flag set from a list of flags.
+However you may prefer to assemble flags
+using 'mconcat' or 'mappend' on 'MaskedValue's.
+-}
+compose :: (Enum a, P.Enum a, Bits w) => [a] -> T w a
+compose xs =
+   fromMaskedValue $ mconcat $ map fromEnum xs
+
+
+
+-- fixity like .&.
+infixl 7 .-.
+
+(.-.) :: (Bits w) => w -> w -> w
+x .-. y = x .&. B.complement y
