diff --git a/ChangeLog b/ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,6 @@
-1.0.3 : Safety prevention for inlining and let-floating. 
+1.0.5 : Added KeyM monad
+
+1.0.3 : Added NOINLINE pragma
 
 1.0.2 : Small improvements to documentation.
 
diff --git a/Data/HMap.hs b/Data/HMap.hs
--- a/Data/HMap.hs
+++ b/Data/HMap.hs
@@ -161,13 +161,18 @@
             , difference
 
             -- ** Intersection
-            , intersection
+            , intersection,
+            -- * Key Monad
+            KeyM,
+            getKey,
+            runKeyM
             )
 where
 import Prelude hiding (lookup,null)
 import Unsafe.Coerce
 import Data.Unique
 import System.IO.Unsafe
+import Control.Monad
 import Data.Hashable
 import Data.HashMap.Lazy(HashMap)
 
@@ -218,7 +223,7 @@
 -- @withKey f@ twice, that it will get a different key the second time.
 
 withKey :: (forall x. Key x a -> b) -> b
-withKey f = unsafePerformIO $ newUnique >>= \x -> return $ f $ Key x
+withKey f = unsafePerformIO $ liftM f createKey 
 {-# NOINLINE withKey #-} 
 
 -- | The scope of top-level keys.
@@ -473,5 +478,43 @@
 #if __GLASGOW_HASKELL__ >= 700
 {-# INLINABLE intersection #-}
 #endif
+
+
+{--------------------------------------------------------------------
+  Key Monad
+--------------------------------------------------------------------}
+
+-- | A monad that can be used to create keys
+--   Keys cannot escape the monad, analogous to the ST Monad.
+--   Can be used instead of the 'withKey' function if you
+--   need an statically unkown number of keys.
+
+data GD s a = Done a
+           | forall b. GetKey (Key s b -> GD s a)
+
+-- uses Codensity monad like definition for speed.
+
+
+
+newtype KeyM s a = KeyM { rk :: forall b. (a -> GD s b) -> GD s b }
+
+instance Monad (KeyM s) where
+  return a = KeyM (\k -> k a)
+  c >>= f  = KeyM (\k -> rk c (\a -> rk (f a) k))
+
+-- | Obtain a key in the key monad
+getKey :: KeyM s (Key s a)
+getKey = KeyM $ \c -> GetKey c
+#if __GLASGOW_HASKELL__ >= 700
+{-# INLINABLE getKey #-}
+#endif
+
+
+-- | Run a key monad. Existential type makes sure keys cannot escape.
+runKeyM :: (forall s. KeyM s a) -> a
+runKeyM m = loop (rk m Done) where
+  loop (Done a) = a
+  loop (GetKey c) = loop $ unsafePerformIO $ liftM c createKey 
+  {-# NOINLINE loop #-} 
 
 
diff --git a/HMap.cabal b/HMap.cabal
--- a/HMap.cabal
+++ b/HMap.cabal
@@ -1,5 +1,5 @@
 Name:                HMap
-Version:             1.0.3
+Version:             1.0.5
 Synopsis:	     Fast heterogeneous maps.
 Description:         Fast heterogeneous maps based on Hashmaps.
 License:             BSD3
