diff --git a/Data/Map/MultiKey.hs b/Data/Map/MultiKey.hs
new file mode 100644
--- /dev/null
+++ b/Data/Map/MultiKey.hs
@@ -0,0 +1,75 @@
+{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+
+module Data.Map.MultiKey 
+  ( MultiKey(..)
+  , MultiKeyable(..)
+  , delete
+  , deleteKey
+  , fromList
+  , insert
+  , insertList
+  , key
+  , lookup
+  , null
+  , toList
+  , updateKey
+  ) where
+
+import           Data.List             (foldl')
+import           Data.Map              (Map)
+import qualified Data.Map       as     M
+import           Data.Typeable
+import           Prelude        hiding (lookup, null)
+
+data Key a = forall k . (Typeable k, Ord k) => 
+    Key (Map k a) (a -> k) deriving Typeable
+
+data MultiKey a = MultiKey [Key a] deriving Typeable
+
+class MultiKeyable a where
+    empty :: MultiKey a
+
+key :: (Typeable k, Ord k) => (a -> k) -> Key a
+key f = Key M.empty f
+
+lookup :: (Typeable a, Typeable k) => k -> MultiKey a -> Maybe a
+lookup k mk@(MultiKey keys) = lookup' keys
+  where
+    lookup' [] = error $ "MultiKey: there is no key of type " 
+                 ++ (show $ typeOf k) ++ " in " ++ (show $ typeOf mk)
+    lookup' (Key m _:ks) = maybe (lookup' ks) (`M.lookup` m) $ cast k
+
+insertIntoKey :: a -> Key a -> Key a
+insertIntoKey x (Key m getIdx) = Key (M.insert (getIdx x) x m) getIdx
+
+insert :: a -> MultiKey a -> MultiKey a
+insert x (MultiKey indexes) = MultiKey $ map (insertIntoKey x) indexes
+
+insertList :: MultiKeyable a => [a] -> MultiKey a -> MultiKey a
+insertList xs (MultiKey keys) = MultiKey $ map f keys
+  where
+    f key = foldl' (flip insertIntoKey) key xs
+
+deleteFromKey :: a -> Key a -> Key a
+deleteFromKey x (Key m getIdx) = Key (M.delete (getIdx x) m) getIdx
+
+delete :: a -> MultiKey a -> MultiKey a
+delete x (MultiKey indexes) = MultiKey $ map (deleteFromKey x) indexes
+
+updateKey :: (Typeable a, Typeable k) => k -> a -> MultiKey a -> MultiKey a
+updateKey k v mk = insert v $ maybe mk (flip delete mk) $ lookup k mk
+
+deleteKey :: (Typeable a, Typeable k) => k -> MultiKey a -> MultiKey a
+deleteKey k mim = maybe mim (flip delete mim) $ lookup k mim
+
+null :: MultiKey a -> Bool
+null (MultiKey (Key m _:_)) = M.null m
+null (MultiKey []) = True
+
+fromList :: MultiKeyable a => [a] -> MultiKey a
+fromList = flip insertList empty 
+
+toList :: MultiKey a -> [a]
+toList (MultiKey []) = []
+toList (MultiKey (Key m _:_)) = M.elems m
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2015 Jason Hickner
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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/data-map-multikey.cabal b/data-map-multikey.cabal
new file mode 100644
--- /dev/null
+++ b/data-map-multikey.cabal
@@ -0,0 +1,26 @@
+-- Initial data-map-multikey.cabal generated by cabal init.  For further 
+-- documentation, see http://haskell.org/cabal/users-guide/
+
+name:                data-map-multikey
+version:             0.0.1
+synopsis:            Data.Map with multiple, unique keys
+-- description:         
+homepage:            http://github.com/jhickner/data-map-multikey
+license:             MIT
+license-file:        LICENSE
+author:              Jason Hickner
+maintainer:          jhickner@gmail.com
+-- copyright:           
+category:            Data
+build-type:          Simple
+-- extra-source-files:  
+cabal-version:       >=1.10
+
+library
+  exposed-modules:     Data.Map.MultiKey
+  -- other-modules:       
+  other-extensions:    OverloadedStrings, ExistentialQuantification, DeriveDataTypeable
+  build-depends:       base >=4.7 && <4.8, 
+                       containers >=0.5 && <0.6
+  -- hs-source-dirs:      
+  default-language:    Haskell2010
