diff --git a/EnumContainers.cabal b/EnumContainers.cabal
new file mode 100644
--- /dev/null
+++ b/EnumContainers.cabal
@@ -0,0 +1,23 @@
+Name:                EnumContainers
+Version:             0.1
+Synopsis:            Simple Enum-class-based int containers
+License:             BSD3
+License-file:        LICENSE
+Author:              Eyal Lotem
+Maintainer:          eyal.lotem@gmail.com
+Category:            Data
+Build-type:          Simple
+-- Extra-source-files:
+Cabal-version:       >=1.2
+
+Library
+  hs-source-dirs:  src
+  Exposed-modules: Data.EnumIntMap,
+                   Data.EnumIntSet
+  Build-depends:   base >= 4 && < 5, containers >= 0.3 && < 0.4, deepseq >= 1.1 && < 1.2
+
+  -- Modules not exported by this package.
+  -- Other-modules:
+
+  -- Extra tools (e.g. alex, hsc2hs, ...) needed to build the source.
+  -- Build-tools:
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c)2010, Eyal Lotem
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Eyal Lotem nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/src/Data/EnumIntMap.hs b/src/Data/EnumIntMap.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/EnumIntMap.hs
@@ -0,0 +1,55 @@
+module Data.EnumIntMap(EnumIntMap, lookup, findWithDefault, (!), fromList, fromListBy, keys, elems, toList, empty, elementsFromMap) where
+
+import Prelude hiding (lookup)
+import Control.Arrow(first, (&&&))
+import Data.Maybe(fromMaybe)
+import qualified Data.IntMap as IntMap
+import Data.IntMap(IntMap)
+import Data.Monoid(Monoid(..))
+import Control.DeepSeq (NFData, rnf)
+
+newtype EnumIntMap k v = EnumIntMap { unEnumIntMap :: IntMap v }
+  deriving (Show, Read, Eq, Ord)
+
+inEnumIntMap :: (IntMap v -> IntMap v') -> EnumIntMap k v -> EnumIntMap k v'
+inEnumIntMap f = EnumIntMap . f . unEnumIntMap
+
+inEnumIntMap2 :: (IntMap v -> IntMap v' -> IntMap v'') -> EnumIntMap k v -> EnumIntMap k v' -> EnumIntMap k v''
+inEnumIntMap2 f = inEnumIntMap . f . unEnumIntMap
+
+instance (Enum a, NFData b) => NFData (EnumIntMap a b) where
+  rnf = rnf . unEnumIntMap
+
+instance Monoid (EnumIntMap k v) where
+  mempty = EnumIntMap mempty
+  mappend = inEnumIntMap2 mappend
+
+empty :: Enum k => EnumIntMap k v
+empty = mempty
+
+lookup :: Enum k => k -> EnumIntMap k v -> Maybe v
+k `lookup` EnumIntMap intMap = IntMap.lookup (fromEnum k) intMap
+
+findWithDefault :: Enum k => v -> k -> EnumIntMap k v -> v
+findWithDefault v k (EnumIntMap intMap) = IntMap.findWithDefault v (fromEnum k) intMap
+
+(!) :: Enum k => EnumIntMap k v -> k -> v
+em ! k = fromMaybe (error "EnumIntMap.! no such key") $ lookup k em
+
+fromList :: Enum k => [(k, v)] -> EnumIntMap k v
+fromList = EnumIntMap . IntMap.fromList . (map . first) fromEnum
+
+fromListBy :: Enum k => (v -> k) -> [v] -> EnumIntMap k v
+fromListBy f = fromList . map (f &&& id)
+
+toList :: Enum k => EnumIntMap k v -> [(k, v)]
+toList = (map . first) toEnum . IntMap.toList . unEnumIntMap
+
+elems :: Enum k => EnumIntMap k v -> [v]
+elems = map snd . toList
+
+keys :: Enum k => EnumIntMap k v -> [k]
+keys = map fst . toList
+
+elementsFromMap :: (Enum k) => [k] -> EnumIntMap k b -> [b]
+elementsFromMap ks m = map (m !) ks
diff --git a/src/Data/EnumIntSet.hs b/src/Data/EnumIntSet.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/EnumIntSet.hs
@@ -0,0 +1,45 @@
+module Data.EnumIntSet(EnumIntSet, empty, union,
+                       unions, fromList, toList, elems,
+                       member, notMember) where
+
+import Prelude hiding (lookup)
+import qualified Data.IntSet as IntSet
+import Data.IntSet(IntSet)
+import Data.Monoid(Monoid(..))
+
+newtype EnumIntSet k = EnumIntSet { unEnumIntSet :: IntSet }
+  deriving (Show, Read, Eq, Ord)
+
+inEnumIntSet :: (IntSet -> IntSet) -> EnumIntSet k -> EnumIntSet k'
+inEnumIntSet f = EnumIntSet . f . unEnumIntSet
+
+inEnumIntSet2 :: (IntSet -> IntSet -> IntSet) -> EnumIntSet k -> EnumIntSet k' -> EnumIntSet k''
+inEnumIntSet2 f = inEnumIntSet . f . unEnumIntSet
+
+instance Monoid (EnumIntSet k) where
+  mempty = EnumIntSet mempty
+  mappend = inEnumIntSet2 mappend
+
+empty :: Enum k => EnumIntSet k
+empty = mempty
+
+union :: EnumIntSet k -> EnumIntSet k -> EnumIntSet k
+union = mappend
+
+unions :: [EnumIntSet k] -> EnumIntSet k
+unions = mconcat
+
+fromList :: Enum k => [k] -> EnumIntSet k
+fromList = EnumIntSet . IntSet.fromList . map fromEnum
+
+toList :: Enum k => EnumIntSet k -> [k]
+toList = map toEnum . IntSet.toList . unEnumIntSet
+
+elems :: Enum k => EnumIntSet k -> [k]
+elems = toList
+
+member :: Enum k => k -> EnumIntSet k -> Bool
+member k = IntSet.member (fromEnum k) . unEnumIntSet
+
+notMember :: Enum k => k -> EnumIntSet k -> Bool
+notMember k = not . member k
