diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c)2011, Heinrich Apfelmus
+
+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 Heinrich Apfelmus 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/Readme.md b/Readme.md
new file mode 100644
--- /dev/null
+++ b/Readme.md
@@ -0,0 +1,44 @@
+*Vault* is a tiny library that provides a single data structure called *vault*.
+
+A *vault* is a type-safe, persistent storage for values of arbitrary types. Like `IORef`, I want to be able to store values of any type in it, but unlike `IORef`, I want the storage space to behave like a persistent, first-class data structure, as appropriate for a purely functional language.
+
+It is analogous to a bank vault, where you can access different bank boxes with different keys; hence the name.
+
+In other words, a vault is an abstract data type with the following basic signature
+
+    data Key a
+    data Vault
+
+    newKey :: IO (Key a)
+    empty  :: Vault
+    lookup :: Key a -> Vault -> Maybe a
+    insert :: Key a -> a -> Vault -> Vault
+    delete :: Key a -> Vault -> Vault
+
+A few common functions for finite maps, like `adjust` and `union`, are provided as well.
+
+
+This library was created thanks to the feedback on my blog post [Vault - a persistent store for values of arbitrary types][1].
+
+  [1]: http://apfelmus.nfshost.com/blog/2011/09/04-vault.html
+
+
+Installation
+============
+The whole thing is [available on hackage][hackage], so you just have to type
+
+    cabal update
+    cabal install vault
+
+  [hackage]: http://hackage.haskell.org/package/vault
+
+Feedback
+========
+Use the [issue tracker][2] or send an [email to the maintainer][3].
+
+  [2]: https://github.com/HeinrichApfelmus/vault/issues
+  [3]: mailto:apfelmus@quantentunnel.de
+
+
+
+
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/Vault.hs b/src/Data/Vault.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Vault.hs
@@ -0,0 +1,57 @@
+{-----------------------------------------------------------------------------
+    Vault
+    
+    A typed, persistent store for values of arbitrary types
+    
+    This implementation uses  unsafeCoerce  for reasons of efficiency.
+    See  http://apfelmus.nfshost.com/blog/2011/09/04-vault.html
+    for an implementation that doesn't need to bypass the type checker.
+------------------------------------------------------------------------------}
+module Data.Vault (
+    Vault, Key,
+    empty, newKey, lookup, insert, adjust, delete, union,
+    ) where
+
+import Prelude hiding (lookup)
+import Control.Monad.ST
+import qualified Data.Vault.ST as ST
+
+-- | A typed, persistent store for values of arbitrary types.
+-- 
+-- This variant is the simplest and creates keys in the 'IO' monad.
+-- See the module "Data.Vault.ST" if you want to use it with the 'ST' monad instead.
+--
+-- > instance Monoid Vault
+type Vault = ST.Vault RealWorld
+-- | Keys for the vault.
+--
+-- > Key :: * -> *
+type Key = ST.Key RealWorld
+
+-- | The empty vault.
+empty :: Vault
+empty = ST.empty
+
+-- | Create a new key for use with a vault.
+newKey :: IO (Key a)
+newKey = stToIO ST.newKey
+
+-- | Lookup the value of a key in the vault.
+lookup :: Key a -> Vault -> Maybe a
+lookup = ST.lookup
+
+-- | Insert a value for a given key. Overwrites any previous value.
+insert :: Key a -> a -> Vault -> Vault
+insert = ST.insert
+
+-- | Adjust the value for a given key if it's present in the vault.
+adjust :: (a -> a) -> Key a -> Vault -> Vault
+adjust = ST.adjust
+
+-- | Delete a key from the vault.
+delete :: Key a -> Vault -> Vault
+delete = ST.delete
+
+-- | Merge two vaults (left-biased).
+union :: Vault -> Vault -> Vault
+union = ST.union
diff --git a/src/Data/Vault/ST.hs b/src/Data/Vault/ST.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Vault/ST.hs
@@ -0,0 +1,66 @@
+{-----------------------------------------------------------------------------
+    Vault
+    
+    A typed, persistent store for values of arbitrary types
+    
+    This implementation uses  unsafeCoerce  for reasons of efficiency.
+    See  http://apfelmus.nfshost.com/blog/2011/09/04-vault.html
+    for an implementation that doesn't need to bypass the type checker.
+------------------------------------------------------------------------------}
+module Data.Vault.ST (
+    Vault, Key,
+    empty, newKey, lookup, insert, adjust, delete, union,
+    ) where
+
+import Prelude hiding (lookup)
+import Data.Monoid hiding (Any)
+import Data.Functor
+import Data.Map (Map)
+import qualified Data.Map as Map
+import Data.Unique
+import Control.Monad.ST
+
+import GHC.Exts (Any)   -- ghc specific tricks
+import Unsafe.Coerce (unsafeCoerce)
+
+-- | A typed, persistent store for values of arbitrary types.
+-- 
+-- This variant has more complex types so that you can create keys in the 'ST' monad.
+-- See the module "Data.Vault" if you'd like to use a simpler version with the 'IO' monad.
+-- You can also use both variants simultaneously; they share a single representation.
+newtype Vault s = Vault (Map Unique Any)
+-- | Keys for the vault.
+newtype Key s a = Key Unique
+
+instance Monoid (Vault s) where
+    mempty = empty
+    mappend = union
+
+-- | The empty vault.
+empty :: Vault s
+empty = Vault Map.empty
+
+-- | Create a new key for use with a vault.
+newKey :: ST s (Key s a)
+newKey = Key <$> unsafeIOToST newUnique
+
+-- | Lookup the value of a key in the vault.
+lookup :: Key s a -> Vault s -> Maybe a
+lookup (Key k) (Vault m) = unsafeCoerce <$> Map.lookup k m 
+
+-- | Insert a value for a given key. Overwrites any previous value.
+insert :: Key s a -> a -> Vault s -> Vault s
+insert (Key k) x (Vault m) = Vault $ Map.insert k (unsafeCoerce x) m
+
+-- | Adjust the value for a given key if it's present in the vault.
+adjust :: (a -> a) -> Key s a -> Vault s -> Vault s
+adjust f (Key k) (Vault m) = Vault $ Map.alter f' k m
+    where f' = unsafeCoerce . f . unsafeCoerce
+
+-- | Delete a key from the vault.
+delete :: Key s a -> Vault s -> Vault s
+delete (Key k) (Vault m) = Vault $ Map.delete k m
+
+-- | Merge two vaults (left-biased).
+union :: Vault s -> Vault s -> Vault s
+union (Vault m) (Vault m') = Vault $ Map.union m m'
diff --git a/vault.cabal b/vault.cabal
new file mode 100644
--- /dev/null
+++ b/vault.cabal
@@ -0,0 +1,34 @@
+Name:               vault
+Version:            0.1.0.0
+Synopsis:           a typed, persistent store for values of arbitrary types
+Description:
+  A /vault/ is a typed, persistent store for values of arbitrary types.
+  It's like having first-class access to the storage space behind IORefs.
+  .
+  The data structure is analogous to a bank vault,
+  where you can access different bank boxes with different keys;
+  hence the name.
+  
+Category:           Data
+License:            BSD3
+License-file:       LICENSE
+Author:             Heinrich Apfelmus, Elliott Hird
+Maintainer:         Heinrich Apfelmus <apfelmus at quantentunnel de>
+Homepage:           https://github.com/HeinrichApfelmus/vault
+Copyright:          (c) Heinrich Apfelmus 2011
+
+build-type:         Simple
+cabal-version:      >= 1.6
+
+extra-source-files: Readme.md
+
+source-repository head
+    type:           git
+    location:       git://github.com/HeinrichApfelmus/vault.git
+
+Library
+    hs-source-dirs:     src
+    build-depends:      base == 4.*, containers == 0.4.*
+    ghc-options:        -Wall
+    exposed-modules:    Data.Vault, Data.Vault.ST
+
