diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2014, Yu Fukuzawa
+
+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 Yu Fukuzawa 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/OpenUnion.hs b/src/Data/OpenUnion.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/OpenUnion.hs
@@ -0,0 +1,29 @@
+{-# LANGUAGE ConstraintKinds       #-}
+{-# LANGUAGE DataKinds             #-}
+{-# LANGUAGE FlexibleContexts      #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE GADTs                 #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverlappingInstances  #-}
+{-# LANGUAGE ScopedTypeVariables   #-}
+{-# LANGUAGE TypeFamilies          #-}
+{-# LANGUAGE TypeOperators         #-}
+
+module Data.OpenUnion (
+  -- * UnionType
+    Union
+  -- * Utility Functions
+  , exhaust
+  , (||>)
+  , picked
+  , liftU
+  , retractU
+  , hoistU
+  -- * Constraints
+  , Member
+  , Include(..)
+  , type (∈)
+  , type (⊆)
+  , type (＝)
+  ) where
+import Data.OpenUnion.Internal
diff --git a/src/Data/OpenUnion/Internal.hs b/src/Data/OpenUnion/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/OpenUnion/Internal.hs
@@ -0,0 +1,112 @@
+{-# LANGUAGE ConstraintKinds        #-}
+{-# LANGUAGE DataKinds              #-}
+{-# LANGUAGE FlexibleContexts       #-}
+{-# LANGUAGE FlexibleInstances      #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE GADTs                  #-}
+{-# LANGUAGE MultiParamTypeClasses  #-}
+{-# LANGUAGE OverlappingInstances   #-}
+{-# LANGUAGE ScopedTypeVariables    #-}
+{-# LANGUAGE TypeFamilies           #-}
+{-# LANGUAGE TypeOperators          #-}
+{-# LANGUAGE UndecidableInstances   #-}
+
+module Data.OpenUnion.Internal where
+import           Control.Applicative
+import           Data.Monoid         hiding (All)
+import           GHC.Exts            (Constraint)
+
+data Union (as :: [*]) where
+  Single    :: a -> Union (a ': as)
+  Union     :: Union as -> Union (a ': as)
+  Exhausted :: Union '[] -> Union '[]
+
+exhaust :: Union '[] -> a
+exhaust (Exhausted x) = exhaust x
+{-# INLINE exhaust #-}
+
+type family All (ca :: * -> Constraint) (as :: [*]) :: Constraint
+type instance All ca '[] = ()
+type instance All ca (a ': as) = (ca a, All ca as)
+
+instance (All Show r) => Show (Union r) where
+  show (Single x) = show x
+  show (Union u)  = show u
+  show _ = undefined
+
+(||>) :: (a -> r) -> (Union as -> r) -> (Union (a ': as) -> r)
+(||>) f _ (Single x) = f x
+(||>) _ g (Union u) = g u
+infixr 2 ||>
+{-# INLINE (||>) #-}
+
+data Position (a :: *) (as :: [*]) where
+  Zero :: Position a (a ': as)
+  Succ :: Position a as -> Position a (b ': as)
+
+class Member a as | as -> a where
+  position :: Position a as
+
+instance Member a (a ': as) where
+  position = Zero
+
+instance Member a as => Member a (b ': as) where
+  position = Succ position
+
+-- | Lift a value into a Union.
+liftU :: forall a as. Member a as => a -> Union as
+liftU x = go (position :: Position a as)
+  where
+    go :: Position a bs -> Union bs
+    go Zero     = Single x
+    go (Succ n) = Union $ go n
+{-# INLINE liftU #-}
+
+-- | Traversal for a specific element.
+picked :: forall a as f. (Applicative f, Member a as) => (a -> f a) -> Union as -> f (Union as)
+picked k = go (position :: Position a as)
+  where
+    go :: Position a bs -> Union bs -> f (Union bs)
+    go Zero (Single x)       = Single <$> k x
+    go Zero u@(Union _)      = pure u
+    go (Succ _) u@(Single _) = pure u
+    go (Succ n) (Union u)    = Union <$> go n u
+{-# INLINE picked #-}
+
+-- | Retrieve the value from a Union.
+retractU :: Member a as => Union as -> Maybe a
+retractU = getFirst . getConst . picked (Const . First . Just)
+{-# INLINE retractU #-}
+
+-- | Lift a function into @Union@.
+hoistU :: Member a as => (a -> a) -> Union as -> Union as
+hoistU f = getId . picked (Id . f)
+{-# INLINE hoistU #-}
+
+-- | Instead of Identity.
+newtype Id a = Id { getId :: a }
+
+instance Functor Id where
+  fmap f (Id a) = Id (f a)
+
+instance Applicative Id where
+  pure = Id
+  Id f <*> Id a = Id (f a)
+
+class Include as bs where
+  reunion :: Union as -> Union bs
+
+instance (Member a bs, Include as bs) => Include (a ': as) bs where
+  reunion (Single x) = liftU x
+  reunion (Union u)  = reunion u
+
+instance (Include '[] bs) where
+  reunion = exhaust
+
+type a ∈ as  = Member a as
+type as ⊆ bs = Include as bs
+type as ＝ bs = (Include as bs, Include bs as)
+
+infix 4 ∈
+infix 4 ⊆
+infix 4 ＝
diff --git a/src/Data/UnionIntMap.hs b/src/Data/UnionIntMap.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/UnionIntMap.hs
@@ -0,0 +1,65 @@
+-- |
+-- An implementation of heterogeneous tree-map by open unions.
+-- This module uses the @Data.IntMap@ inside,
+-- see also <https://hackage.haskell.org/package/containers>.
+--
+module Data.UnionIntMap (
+  -- * Map type
+    UnionIntMap
+
+  -- * Operators
+  , (\\), (!)
+
+  -- * Construction
+  , empty
+  , singleton
+
+  -- * Query
+  , null
+  , size
+  , member
+  , notMember
+  , lookup
+  , lookupU
+  , find
+  , findU
+  , findWithDefault
+
+  -- ** Insertion
+  , insert
+  , insertWith
+  , insertWithKey
+  -- ** Delete\/Update
+  , delete
+  , adjust
+  , adjustWithKey
+  , update
+  , updateWithKey
+
+  -- * Set Operation
+  , union
+  , unions
+  , difference
+  , intersection
+  -- * Conversion
+  , keys
+  , rebuild
+  -- * Map
+  , mapU
+  , mapWithKeyU
+  , mapU'
+  , mapWithKeyU'
+  -- * Filter
+  , filterU
+  , filterWithKeyU
+  -- * Folds
+  , foldrU
+  , foldrWithKeyU
+  , foldlU'
+  , foldlWithKeyU'
+  -- * Debugging
+  , showTree
+  ) where
+
+import           Data.UnionIntMap.Internal
+import           Prelude                   ()
diff --git a/src/Data/UnionIntMap/Internal.hs b/src/Data/UnionIntMap/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/UnionIntMap/Internal.hs
@@ -0,0 +1,194 @@
+{-# LANGUAGE FlexibleContexts           #-}
+{-# LANGUAGE GADTs                      #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE MultiParamTypeClasses      #-}
+module Data.UnionIntMap.Internal where
+
+import           Control.Applicative hiding (empty)
+import           Control.Monad
+import           Data.IntMap         (IntMap)
+import qualified Data.IntMap         as IM
+import qualified Data.List           as L
+import           Data.Maybe
+import           Data.Monoid
+import           Data.OpenUnion
+import           Prelude             hiding (lookup)
+
+newtype UnionIntMap r = UnionIntMap (IntMap (Union r))
+  deriving (Monoid, Show)
+
+type Key = Int
+
+null :: UnionIntMap r -> Bool
+null (UnionIntMap m) = IM.null m
+{-# INLINE null #-}
+
+empty :: UnionIntMap r
+empty = UnionIntMap IM.empty
+{-# INLINE empty #-}
+
+size :: UnionIntMap r -> Int
+size (UnionIntMap m) = IM.size m
+{-# INLINE size #-}
+
+member :: Key -> UnionIntMap r -> Bool
+member k (UnionIntMap m) = IM.member k m
+{-# INLINE member #-}
+
+notMember :: Key -> UnionIntMap r -> Bool
+notMember k = not . member k
+{-# INLINE notMember #-}
+
+singleton :: Member a as => Key -> a -> UnionIntMap as
+singleton k x = insert k x empty
+{-# INLINE singleton #-}
+
+liftUM :: (IntMap (Union r) -> IntMap (Union s)) -> UnionIntMap r -> UnionIntMap s
+liftUM f (UnionIntMap m) = UnionIntMap $ f m
+{-# INLINE liftUM #-}
+
+liftUM2 :: (IntMap (Union r) -> IntMap (Union s) -> IntMap (Union t)) -> UnionIntMap r -> UnionIntMap s -> UnionIntMap t
+liftUM2 f (UnionIntMap m1) (UnionIntMap m2) = UnionIntMap $ f m1 m2
+{-# INLINE liftUM2 #-}
+
+lookup :: Member a as => Key -> UnionIntMap as -> Maybe a
+lookup k (UnionIntMap m) = IM.lookup k m >>= retractU
+{-# INLINE lookup #-}
+
+lookupU :: Key -> UnionIntMap r -> Maybe (Union r)
+lookupU k (UnionIntMap m) = IM.lookup k m
+{-# INLINE lookupU #-}
+
+find :: Member a as => Key -> UnionIntMap as -> a
+find k um = flip fromMaybe (lookup k um)
+  $ error "UnionIntMap.find: given key is not an element in the map, or is not associated a value of the type expected."
+{-# INLINE find #-}
+
+findU :: Key -> UnionIntMap r -> Union r
+findU k um = flip fromMaybe (lookupU k um)
+  $ error "UnionIntMap.findU: given key is not an element in the map, or is not associated a value of the type expected."
+{-# INLINE findU #-}
+
+findWithDefault :: Member a as => a -> Key -> UnionIntMap as -> a
+findWithDefault def k um = fromMaybe def $ lookup k um
+{-# INLINE findWithDefault #-}
+
+(!) :: Member a as => UnionIntMap as -> Key -> a
+um ! k = flip fromMaybe (lookup k um)
+  $ error "UnionIntMap.!: given key is not an element in the map, or is not associated a value of the type expected."
+{-# INLINE (!) #-}
+
+insert :: Member a as => Key -> a -> UnionIntMap as -> UnionIntMap as
+insert k x = liftUM (IM.insert k (liftU x))
+{-# INLINE insert #-}
+
+insertWith :: Member a as => (a -> a -> a) -> Key -> a -> UnionIntMap as -> UnionIntMap as
+insertWith f = insertWithKey (\_ y z -> f y z)
+{-# INLINE insertWith #-}
+
+insertWithKey :: Member a as => (Key -> a -> a -> a) -> Key -> a -> UnionIntMap as -> UnionIntMap as
+insertWithKey f k x = liftUM (IM.insertWithKey go k (liftU x))
+  where
+    go k' _ s = maybe (liftU x) liftU $ f <$> pure k' <*> return x <*> retractU s
+    {-# INLINE go #-}
+{-# INLINE insertWithKey #-}
+
+delete :: Key -> UnionIntMap as -> UnionIntMap as
+delete = liftUM . IM.delete
+{-# INLINE delete #-}
+
+adjust :: Member a as => (a -> a) -> Key -> UnionIntMap as -> UnionIntMap as
+adjust f = adjustWithKey (\_ x -> f x)
+{-# INLINE adjust #-}
+
+adjustWithKey :: Member a as => (Key -> a -> a) -> Key -> UnionIntMap as -> UnionIntMap as
+adjustWithKey f k = liftUM (IM.adjust (hoistU (f k)) k)
+{-# INLINE adjustWithKey #-}
+
+update :: Member a as => (a -> Maybe a) -> Key -> UnionIntMap as -> UnionIntMap as
+update f = updateWithKey (\_ x -> f x)
+{-# INLINE update #-}
+
+updateWithKey :: Member a as => (Key -> a -> Maybe a) -> Key -> UnionIntMap as -> UnionIntMap as
+updateWithKey f k = liftUM (IM.update (retractU >=> f k >=> return . liftU) k)
+{-# INLINE updateWithKey #-}
+
+union :: UnionIntMap r -> UnionIntMap r -> UnionIntMap r
+union = liftUM2 IM.union
+{-# INLINE union #-}
+
+unions :: [UnionIntMap r] -> UnionIntMap r
+unions = L.foldl' union empty
+{-# INLINE unions #-}
+
+difference :: UnionIntMap r -> UnionIntMap r -> UnionIntMap r
+difference = liftUM2 IM.difference
+{-# INLINE difference #-}
+
+(\\) :: UnionIntMap r -> UnionIntMap r -> UnionIntMap r
+(\\) = difference
+{-# INLINE (\\) #-}
+
+intersection :: UnionIntMap r -> UnionIntMap r -> UnionIntMap r
+intersection = liftUM2 IM.intersection
+{-# INLINE intersection #-}
+
+keys :: UnionIntMap r -> [Key]
+keys (UnionIntMap m)  = IM.keys m
+{-# INLINE keys #-}
+
+map :: Member a as => (a -> a) -> UnionIntMap as -> UnionIntMap as
+map f = mapWithKey (\_ x -> f x)
+{-# INLINE map #-}
+
+mapWithKey :: Member a as => (Key -> a -> a) -> UnionIntMap as -> UnionIntMap as
+mapWithKey f = liftUM (IM.mapWithKey (hoistU . f))
+{-# INLINE mapWithKey #-}
+
+mapU :: (Union r -> Union s) -> UnionIntMap r -> UnionIntMap s
+mapU f = mapWithKeyU (\_ u -> f u)
+{-# INLINE mapU #-}
+
+mapWithKeyU :: (Key -> Union r -> Union s) -> UnionIntMap r -> UnionIntMap s
+mapWithKeyU = liftUM . IM.mapWithKey
+{-# INLINE mapWithKeyU #-}
+
+mapU' :: (Union r -> a) -> UnionIntMap r -> IntMap a
+mapU' f = mapWithKeyU' (\_ u -> f u)
+{-# INLINE mapU' #-}
+
+mapWithKeyU' :: (Key -> Union r -> a) -> UnionIntMap r -> IntMap a
+mapWithKeyU' f (UnionIntMap m) = IM.mapWithKey f m
+{-# INLINE mapWithKeyU' #-}
+
+rebuild :: Include r s => UnionIntMap r -> UnionIntMap s
+rebuild = mapU reunion
+{-# INLINE rebuild #-}
+
+filterU :: (Union r -> Bool) -> UnionIntMap r -> UnionIntMap r
+filterU p = filterWithKeyU (\_ u -> p u)
+{-# INLINE filterU #-}
+
+filterWithKeyU :: (Key -> Union r -> Bool) -> UnionIntMap r -> UnionIntMap r
+filterWithKeyU = liftUM . IM.filterWithKey
+{-# INLINE filterWithKeyU #-}
+
+foldrU :: (Union r -> b -> b) -> b -> UnionIntMap r -> b
+foldrU f = foldrWithKeyU (\_ u z -> f u z)
+{-# INLINE foldrU #-}
+
+foldrWithKeyU :: (Key -> Union r -> b -> b) -> b -> UnionIntMap r -> b
+foldrWithKeyU f z (UnionIntMap m) = IM.foldrWithKey f z m
+{-# INLINE foldrWithKeyU #-}
+
+foldlU' :: (a -> Union r -> a) -> a -> UnionIntMap r -> a
+foldlU' f = foldlWithKeyU' (\z _ u -> f z u)
+{-# INLINE foldlU' #-}
+
+foldlWithKeyU' :: (a -> Key -> Union r -> a) -> a -> UnionIntMap r -> a
+foldlWithKeyU' f z (UnionIntMap m) = IM.foldlWithKey' f z m
+{-# INLINE foldlWithKeyU' #-}
+
+showTree :: Show (Union r) => UnionIntMap r -> String
+showTree (UnionIntMap m) = IM.showTree m
+{-# INLINE showTree #-}
diff --git a/src/Data/UnionMap.hs b/src/Data/UnionMap.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/UnionMap.hs
@@ -0,0 +1,66 @@
+-- |
+-- An implementation of heterogeneous tree-map by open unions.
+-- This module uses the @Data.Map@ module inside,
+-- see also <https://hackage.haskell.org/package/containers>.
+--
+module Data.UnionMap (
+  -- * Map type
+    UnionMap
+
+  -- * Operators
+  , (\\), (!)
+
+  -- * Construction
+  , empty
+  , singleton
+
+  -- * Query
+  , null
+  , size
+  , member
+  , notMember
+  , lookup
+  , lookupU
+  , find
+  , findU
+  , findWithDefault
+
+  -- ** Insertion
+  , insert
+  , insertWith
+  , insertWithKey
+  -- ** Delete\/Update
+  , delete
+  , adjust
+  , adjustWithKey
+  , update
+  , updateWithKey
+
+  -- * Set Operation
+  , union
+  , unions
+  , difference
+  , intersection
+  -- * Conversion
+  , keys
+  , rebuild
+
+  -- * Map
+  , mapU
+  , mapWithKeyU
+  , mapU'
+  , mapWithKeyU'
+  -- * Filter
+  , filterU
+  , filterWithKeyU
+  -- * Folds
+  , foldrU
+  , foldrWithKeyU
+  , foldlU'
+  , foldlWithKeyU'
+  -- * Debugging
+  , showTree
+  ) where
+
+import           Data.UnionMap.Internal
+import           Prelude                ()
diff --git a/src/Data/UnionMap/Internal.hs b/src/Data/UnionMap/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/UnionMap/Internal.hs
@@ -0,0 +1,192 @@
+{-# LANGUAGE FlexibleContexts           #-}
+{-# LANGUAGE GADTs                      #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE MultiParamTypeClasses      #-}
+module Data.UnionMap.Internal where
+
+import           Control.Applicative hiding (empty)
+import           Control.Monad
+import qualified Data.List           as L
+import           Data.Map            (Map)
+import qualified Data.Map            as M
+import           Data.Maybe
+import           Data.Monoid
+import           Data.OpenUnion
+import           Prelude             hiding (lookup)
+
+newtype UnionMap k r = UnionMap (Map k (Union r))
+  deriving (Monoid, Show)
+
+null :: UnionMap k r -> Bool
+null (UnionMap m) = M.null m
+{-# INLINE null #-}
+
+empty :: UnionMap k r
+empty = UnionMap M.empty
+{-# INLINE empty #-}
+
+size :: UnionMap k r -> Int
+size (UnionMap m) = M.size m
+{-# INLINE size #-}
+
+member :: Ord k => k -> UnionMap k r -> Bool
+member k (UnionMap m) = M.member k m
+{-# INLINE member #-}
+
+notMember :: Ord k => k -> UnionMap k r -> Bool
+notMember k = not . member k
+{-# INLINE notMember #-}
+
+singleton :: (Ord k, Member a as) => k -> a -> UnionMap k as
+singleton k x = insert k x empty
+{-# INLINE singleton #-}
+
+liftUM :: (Map k (Union r) -> Map k (Union s)) -> UnionMap k r -> UnionMap k s
+liftUM f (UnionMap m) = UnionMap $ f m
+{-# INLINE liftUM #-}
+
+liftUM2 :: (Map k (Union r) -> Map k (Union s) -> Map k (Union t)) -> UnionMap k r -> UnionMap k s -> UnionMap k t
+liftUM2 f (UnionMap m1) (UnionMap m2) = UnionMap $ f m1 m2
+{-# INLINE liftUM2 #-}
+
+lookup :: (Ord k, Member a as) => k -> UnionMap k as -> Maybe a
+lookup k (UnionMap m) = M.lookup k m >>= retractU
+{-# INLINE lookup #-}
+
+lookupU :: Ord k => k -> UnionMap k r -> Maybe (Union r)
+lookupU k (UnionMap m) = M.lookup k m
+{-# INLINE lookupU #-}
+
+find :: (Ord k, Member a as) => k -> UnionMap k as -> a
+find k um = flip fromMaybe (lookup k um)
+  $ error "UnionMap.find: given key is not an element in the map, or is not associated a value of the type expected."
+{-# INLINE find #-}
+
+findU :: Ord k => k -> UnionMap k r -> Union r
+findU k um = flip fromMaybe (lookupU k um)
+  $ error "UnionMap.findU: given key is not an element in the map, or is not associated a value of the type expected."
+{-# INLINE findU #-}
+
+findWithDefault :: (Ord k, Member a as) => a -> k -> UnionMap k as -> a
+findWithDefault def k um = fromMaybe def $ lookup k um
+{-# INLINE findWithDefault #-}
+
+(!) :: (Ord k, Member a as) => UnionMap k as -> k -> a
+um ! k = flip fromMaybe (lookup k um)
+  $ error "UnionMap.!: given key is not an element in the map, or is not associated a value of the type expected."
+{-# INLINE (!) #-}
+
+insert :: (Ord k, Member a as) => k -> a -> UnionMap k as -> UnionMap k as
+insert k x = liftUM (M.insert k (liftU x))
+{-# INLINE insert #-}
+
+insertWith :: (Ord k, Member a as) => (a -> a -> a) -> k -> a -> UnionMap k as -> UnionMap k as
+insertWith f = insertWithKey (\_ y z -> f y z)
+{-# INLINE insertWith #-}
+
+insertWithKey :: (Ord k, Member a as) => (k -> a -> a -> a) -> k -> a -> UnionMap k as -> UnionMap k as
+insertWithKey f k x = liftUM (M.insertWithKey go k (liftU x))
+  where
+    go k' _ s = maybe (liftU x) liftU $ f <$> pure k' <*> return x <*> retractU s
+    {-# INLINE go #-}
+{-# INLINE insertWithKey #-}
+
+delete :: Ord k => k -> UnionMap k as -> UnionMap k as
+delete = liftUM . M.delete
+{-# INLINE delete #-}
+
+adjust :: (Ord k, Member a as) => (a -> a) -> k -> UnionMap k as -> UnionMap k as
+adjust f = adjustWithKey (\_ x -> f x)
+{-# INLINE adjust #-}
+
+adjustWithKey :: (Ord k, Member a as) => (k -> a -> a) -> k -> UnionMap k as -> UnionMap k as
+adjustWithKey f k = liftUM (M.adjust (hoistU (f k)) k)
+{-# INLINE adjustWithKey #-}
+
+update :: (Ord k, Member a as) => (a -> Maybe a) -> k -> UnionMap k as -> UnionMap k as
+update f = updateWithKey (\_ x -> f x)
+{-# INLINE update #-}
+
+updateWithKey :: (Ord k, Member a as) => (k -> a -> Maybe a) -> k -> UnionMap k as -> UnionMap k as
+updateWithKey f k = liftUM (M.update (retractU >=> f k >=> return . liftU) k)
+{-# INLINE updateWithKey #-}
+
+union :: Ord k => UnionMap k r -> UnionMap k r -> UnionMap k r
+union = liftUM2 M.union
+{-# INLINE union #-}
+
+unions :: Ord k => [UnionMap k r] -> UnionMap k r
+unions = L.foldl' union empty
+{-# INLINE unions #-}
+
+difference :: Ord k => UnionMap k r -> UnionMap k r -> UnionMap k r
+difference = liftUM2 M.difference
+{-# INLINE difference #-}
+
+(\\) :: Ord k => UnionMap k r -> UnionMap k r -> UnionMap k r
+(\\) = difference
+{-# INLINE (\\) #-}
+
+intersection :: Ord k => UnionMap k r -> UnionMap k r -> UnionMap k r
+intersection = liftUM2 M.intersection
+{-# INLINE intersection #-}
+
+keys :: UnionMap k r -> [k]
+keys (UnionMap m)  = M.keys m
+{-# INLINE keys #-}
+
+map :: Member a as => (a -> a) -> UnionMap k as -> UnionMap k as
+map f = mapWithKey (\_ x -> f x)
+{-# INLINE map #-}
+
+mapWithKey :: Member a as => (k -> a -> a) -> UnionMap k as -> UnionMap k as
+mapWithKey f = liftUM (M.mapWithKey (hoistU . f))
+{-# INLINE mapWithKey #-}
+
+mapU :: (Union r -> Union s) -> UnionMap k r -> UnionMap k s
+mapU f = mapWithKeyU (\_ u -> f u)
+{-# INLINE mapU #-}
+
+mapWithKeyU :: (k -> Union r -> Union s) -> UnionMap k r -> UnionMap k s
+mapWithKeyU = liftUM . M.mapWithKey
+{-# INLINE mapWithKeyU #-}
+
+mapU' :: (Union r -> a) -> UnionMap k r -> Map k a
+mapU' f = mapWithKeyU' (\_ u -> f u)
+{-# INLINE mapU' #-}
+
+mapWithKeyU' :: (k -> Union r -> a) -> UnionMap k r -> Map k a
+mapWithKeyU' f (UnionMap m) = M.mapWithKey f m
+{-# INLINE mapWithKeyU' #-}
+
+rebuild :: Include r s => UnionMap k r -> UnionMap k s
+rebuild = mapU reunion
+{-# INLINE rebuild #-}
+
+filterU :: (Union r -> Bool) -> UnionMap k r -> UnionMap k r
+filterU p = filterWithKeyU (\_ u -> p u)
+{-# INLINE filterU #-}
+
+filterWithKeyU :: (k -> Union r -> Bool) -> UnionMap k r -> UnionMap k r
+filterWithKeyU = liftUM . M.filterWithKey
+{-# INLINE filterWithKeyU #-}
+
+foldrU :: (Union r -> b -> b) -> b -> UnionMap k r -> b
+foldrU f = foldrWithKeyU (\_ u z -> f u z)
+{-# INLINE foldrU #-}
+
+foldrWithKeyU :: (k -> Union r -> b -> b) -> b -> UnionMap k r -> b
+foldrWithKeyU f z (UnionMap m) = M.foldrWithKey f z m
+{-# INLINE foldrWithKeyU #-}
+
+foldlU' :: (a -> Union r -> a) -> a -> UnionMap k r -> a
+foldlU' f = foldlWithKeyU' (\z _ u -> f z u)
+{-# INLINE foldlU' #-}
+
+foldlWithKeyU' :: (a -> k -> Union r -> a) -> a -> UnionMap k r -> a
+foldlWithKeyU' f z (UnionMap m) = M.foldlWithKey' f z m
+{-# INLINE foldlWithKeyU' #-}
+
+showTree :: (Show k, Show (Union r)) => UnionMap k r -> String
+showTree (UnionMap m) = M.showTree m
+{-# INLINE showTree #-}
diff --git a/union-map.cabal b/union-map.cabal
new file mode 100644
--- /dev/null
+++ b/union-map.cabal
@@ -0,0 +1,22 @@
+name:                union-map
+version:             0.0
+synopsis:            Heterogeneous map by open unions.
+description:         Heterogeneous map implementation, not requires IO and Typeable likes
+license:             BSD3
+license-file:        LICENSE
+author:              Yu Fukuzawa
+maintainer:          minpou.primer@gmail.com
+category:            Data
+build-type:          Simple
+cabal-version:       >=1.10
+homepage:            http://github.com/minpou/union-map
+
+library
+  exposed-modules:     Data.UnionMap, Data.UnionIntMap
+                     , Data.OpenUnion , Data.OpenUnion.Internal
+  other-modules:       Data.UnionMap.Internal, Data.UnionIntMap.Internal
+  build-depends:       base >= 4.6 && < 5
+                     , containers >= 0.4.2
+  hs-source-dirs:      src
+  ghc-options:         -Wall
+  default-language:    Haskell2010
