diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,15 @@
 ## Changelog for the `vault` package
 
+**0.3.1.1**
+
+* Rename source files to allow building the package with [Bazel](https://bazel.build).
+
+**0.3.1.0**
+
+* Compatibility with GHC-8.4:
+     * Bump dependencies to allow `base >= 4.5 && < 4.12`.
+     * Add `Semigroup` instances.
+
 **0.3.0.7**
 
 * Bump dependencies to allow `base >= 4.5 && < 4.11`.
diff --git a/src/Data/Vault/IO.h b/src/Data/Vault/IO.h
new file mode 100644
--- /dev/null
+++ b/src/Data/Vault/IO.h
@@ -0,0 +1,70 @@
+module Data.Vault.LAZINESS (
+    -- * Vault
+    Vault, Key,
+    empty, newKey, lookup, insert, adjust, delete, union,
+
+    -- * Locker
+    Locker,
+    lock, unlock,
+    ) where
+
+import Prelude hiding (lookup)
+import Control.Monad.ST
+import qualified Data.Vault.ST.LAZINESS as ST
+
+
+{-----------------------------------------------------------------------------
+    Vault
+------------------------------------------------------------------------------}
+
+-- | A 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.
+type Vault = ST.Vault RealWorld
+
+-- | Keys for the vault.
+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
+
+{-----------------------------------------------------------------------------
+    Locker
+------------------------------------------------------------------------------}
+
+-- | A persistent store for a single value.
+type Locker = ST.Locker RealWorld
+
+-- | Put a single value into a 'Locker'.
+lock :: Key a -> a -> Locker
+lock = ST.lock
+
+-- | Retrieve the value from the 'Locker'.
+unlock :: Key a -> Locker -> Maybe a
+unlock = ST.unlock
diff --git a/src/Data/Vault/IO.hs b/src/Data/Vault/IO.hs
deleted file mode 100644
--- a/src/Data/Vault/IO.hs
+++ /dev/null
@@ -1,70 +0,0 @@
-module Data.Vault.LAZINESS (
-    -- * Vault
-    Vault, Key,
-    empty, newKey, lookup, insert, adjust, delete, union,
-
-    -- * Locker
-    Locker,
-    lock, unlock,
-    ) where
-
-import Prelude hiding (lookup)
-import Control.Monad.ST
-import qualified Data.Vault.ST.LAZINESS as ST
-
-
-{-----------------------------------------------------------------------------
-    Vault
-------------------------------------------------------------------------------}
-
--- | A 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.
-type Vault = ST.Vault RealWorld
-
--- | Keys for the vault.
-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
-
-{-----------------------------------------------------------------------------
-    Locker
-------------------------------------------------------------------------------}
-
--- | A persistent store for a single value.
-type Locker = ST.Locker RealWorld
-
--- | Put a single value into a 'Locker'.
-lock :: Key a -> a -> Locker
-lock = ST.lock
-
--- | Retrieve the value from the 'Locker'.
-unlock :: Key a -> Locker -> Maybe a
-unlock = ST.unlock
diff --git a/src/Data/Vault/Lazy.hs b/src/Data/Vault/Lazy.hs
--- a/src/Data/Vault/Lazy.hs
+++ b/src/Data/Vault/Lazy.hs
@@ -3,4 +3,4 @@
 -- | A persistent store for values of arbitrary types.
 --
 -- The 'Vault' type in this module is strict in the keys but lazy in the values.
-#include "IO.hs"
+#include "IO.h"
diff --git a/src/Data/Vault/ST/Lazy.hs b/src/Data/Vault/ST/Lazy.hs
--- a/src/Data/Vault/ST/Lazy.hs
+++ b/src/Data/Vault/ST/Lazy.hs
@@ -4,4 +4,4 @@
 -- Variant for the 'ST' monad.
 --
 -- The 'Vault' type in this module is strict in the keys but lazy in the values.
-#include "ST.hs"
+#include "ST.h"
diff --git a/src/Data/Vault/ST/ST.h b/src/Data/Vault/ST/ST.h
new file mode 100644
--- /dev/null
+++ b/src/Data/Vault/ST/ST.h
@@ -0,0 +1,80 @@
+#if __GLASGOW_HASKELL__ >= 708
+{-# LANGUAGE RoleAnnotations #-}
+#endif
+
+module Data.Vault.ST.LAZINESS (
+    -- * Vault
+    Vault, Key,
+    empty, newKey, lookup, insert, adjust, delete, union,
+
+    -- * Locker
+    Locker,
+    lock, unlock,
+    ) where
+
+import Data.Monoid (Monoid(..))
+import Data.Semigroup (Semigroup((<>)))
+import Prelude hiding (lookup)
+import Control.Applicative ((<$>))
+import Control.Monad.ST
+import Control.Monad.ST.Unsafe as STUnsafe
+
+import Data.Unique.Really
+
+{-
+    The GHC-specific implementation uses  unsafeCoerce
+    for reasons of efficiency.
+
+    See  http://apfelmus.nfshost.com/blog/2011/09/04-vault.html
+    for the second implementation that doesn't need to
+    bypass the type checker.
+-}
+#if UseGHC
+#include "backends/GHC.h"
+#else
+#include "backends/IORef.hs"
+#endif
+
+{-----------------------------------------------------------------------------
+    Vault
+------------------------------------------------------------------------------}
+
+instance Semigroup (Vault s) where
+    (<>) = union
+
+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)
+
+-- | Lookup the value of a key in the vault.
+lookup :: Key s a -> Vault s -> Maybe a
+
+-- | Insert a value for a given key. Overwrites any previous value.
+insert :: Key s a -> a -> Vault s -> Vault s
+
+-- | Adjust the value for a given key if it's present in the vault.
+adjust :: (a -> a) -> Key s a -> Vault s -> Vault s
+
+-- | Delete a key from the vault.
+delete :: Key s a -> Vault s -> Vault s
+
+-- | Merge two vaults (left-biased).
+union :: Vault s -> Vault s -> Vault s
+union (Vault m) (Vault m') = Vault $ Map.union m m'
+
+{-----------------------------------------------------------------------------
+    Locker
+------------------------------------------------------------------------------}
+
+-- | Put a single value into a 'Locker'.
+lock :: Key s a -> a -> Locker s
+
+-- | Retrieve the value from the 'Locker'.
+unlock :: Key s a -> Locker s -> Maybe a
diff --git a/src/Data/Vault/ST/ST.hs b/src/Data/Vault/ST/ST.hs
deleted file mode 100644
--- a/src/Data/Vault/ST/ST.hs
+++ /dev/null
@@ -1,80 +0,0 @@
-#if __GLASGOW_HASKELL__ >= 708
-{-# LANGUAGE RoleAnnotations #-}
-#endif
-
-module Data.Vault.ST.LAZINESS (
-    -- * Vault
-    Vault, Key,
-    empty, newKey, lookup, insert, adjust, delete, union,
-
-    -- * Locker
-    Locker,
-    lock, unlock,
-    ) where
-
-import Data.Monoid (Monoid(..))
-import Data.Semigroup (Semigroup((<>)))
-import Prelude hiding (lookup)
-import Control.Applicative ((<$>))
-import Control.Monad.ST
-import Control.Monad.ST.Unsafe as STUnsafe
-
-import Data.Unique.Really
-
-{-
-    The GHC-specific implementation uses  unsafeCoerce
-    for reasons of efficiency.
-
-    See  http://apfelmus.nfshost.com/blog/2011/09/04-vault.html
-    for the second implementation that doesn't need to
-    bypass the type checker.
--}
-#if UseGHC
-#include "backends/GHC.hs"
-#else
-#include "backends/IORef.hs"
-#endif
-
-{-----------------------------------------------------------------------------
-    Vault
-------------------------------------------------------------------------------}
-
-instance Semigroup (Vault s) where
-    (<>) = union
-
-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)
-
--- | Lookup the value of a key in the vault.
-lookup :: Key s a -> Vault s -> Maybe a
-
--- | Insert a value for a given key. Overwrites any previous value.
-insert :: Key s a -> a -> Vault s -> Vault s
-
--- | Adjust the value for a given key if it's present in the vault.
-adjust :: (a -> a) -> Key s a -> Vault s -> Vault s
-
--- | Delete a key from the vault.
-delete :: Key s a -> Vault s -> Vault s
-
--- | Merge two vaults (left-biased).
-union :: Vault s -> Vault s -> Vault s
-union (Vault m) (Vault m') = Vault $ Map.union m m'
-
-{-----------------------------------------------------------------------------
-    Locker
-------------------------------------------------------------------------------}
-
--- | Put a single value into a 'Locker'.
-lock :: Key s a -> a -> Locker s
-
--- | Retrieve the value from the 'Locker'.
-unlock :: Key s a -> Locker s -> Maybe a
diff --git a/src/Data/Vault/ST/Strict.hs b/src/Data/Vault/ST/Strict.hs
--- a/src/Data/Vault/ST/Strict.hs
+++ b/src/Data/Vault/ST/Strict.hs
@@ -5,4 +5,4 @@
 -- Variant for the 'ST' monad.
 --
 -- The 'Vault' type in this module is strict in both keys and values.
-#include "ST.hs"
+#include "ST.h"
diff --git a/src/Data/Vault/ST/backends/GHC.h b/src/Data/Vault/ST/backends/GHC.h
new file mode 100644
--- /dev/null
+++ b/src/Data/Vault/ST/backends/GHC.h
@@ -0,0 +1,46 @@
+-- This implementation is specific to GHC
+-- und uses  unsafeCoerce  for reasons of efficiency.
+import GHC.Exts (Any)
+import Unsafe.Coerce (unsafeCoerce)
+
+import qualified Data.HashMap.LAZINESS as Map
+type Map = Map.HashMap
+
+toAny :: a -> Any
+toAny = unsafeCoerce
+
+fromAny :: Any -> a
+fromAny = unsafeCoerce
+
+{-----------------------------------------------------------------------------
+    Vault
+------------------------------------------------------------------------------}
+newtype Vault s = Vault (Map Unique Any)
+newtype Key s a = Key Unique
+
+#if __GLASGOW_HASKELL__ >= 708
+type role Vault nominal
+type role Key nominal nominal
+#endif
+
+newKey = STUnsafe.unsafeIOToST $ Key <$> newUnique
+
+lookup (Key k) (Vault m) = fromAny <$> Map.lookup k m
+
+insert (Key k) x (Vault m) = Vault $ Map.insert k (toAny x) m
+
+adjust f (Key k) (Vault m) = Vault $ Map.adjust f' k m
+    where f' = toAny . f . fromAny
+
+delete (Key k) (Vault m) = Vault $ Map.delete k m
+
+{-----------------------------------------------------------------------------
+    Locker
+------------------------------------------------------------------------------}
+data Locker s = Locker !Unique !Any
+
+lock (Key k) = Locker k . toAny
+
+unlock (Key k) (Locker k' a)
+  | k == k' = Just $ fromAny a
+  | otherwise = Nothing
diff --git a/src/Data/Vault/ST/backends/GHC.hs b/src/Data/Vault/ST/backends/GHC.hs
deleted file mode 100644
--- a/src/Data/Vault/ST/backends/GHC.hs
+++ /dev/null
@@ -1,46 +0,0 @@
--- This implementation is specific to GHC
--- und uses  unsafeCoerce  for reasons of efficiency.
-import GHC.Exts (Any)
-import Unsafe.Coerce (unsafeCoerce)
-
-import qualified Data.HashMap.LAZINESS as Map
-type Map = Map.HashMap
-
-toAny :: a -> Any
-toAny = unsafeCoerce
-
-fromAny :: Any -> a
-fromAny = unsafeCoerce
-
-{-----------------------------------------------------------------------------
-    Vault
-------------------------------------------------------------------------------}
-newtype Vault s = Vault (Map Unique Any)
-newtype Key s a = Key Unique
-
-#if __GLASGOW_HASKELL__ >= 708
-type role Vault nominal
-type role Key nominal nominal
-#endif
-
-newKey = STUnsafe.unsafeIOToST $ Key <$> newUnique
-
-lookup (Key k) (Vault m) = fromAny <$> Map.lookup k m
-
-insert (Key k) x (Vault m) = Vault $ Map.insert k (toAny x) m
-
-adjust f (Key k) (Vault m) = Vault $ Map.adjust f' k m
-    where f' = toAny . f . fromAny
-
-delete (Key k) (Vault m) = Vault $ Map.delete k m
-
-{-----------------------------------------------------------------------------
-    Locker
-------------------------------------------------------------------------------}
-data Locker s = Locker !Unique !Any
-
-lock (Key k) = Locker k . toAny
-
-unlock (Key k) (Locker k' a)
-  | k == k' = Just $ fromAny a
-  | otherwise = Nothing
diff --git a/src/Data/Vault/Strict.hs b/src/Data/Vault/Strict.hs
--- a/src/Data/Vault/Strict.hs
+++ b/src/Data/Vault/Strict.hs
@@ -3,4 +3,4 @@
 -- | A persistent store for values of arbitrary types.
 --
 -- The 'Vault' type in this module is strict in both keys and values.
-#include "IO.hs"
+#include "IO.h"
diff --git a/vault.cabal b/vault.cabal
--- a/vault.cabal
+++ b/vault.cabal
@@ -1,5 +1,5 @@
 Name:               vault
-Version:            0.3.1.0
+Version:            0.3.1.1
 Synopsis:           a persistent store for values of arbitrary types
 Description:
   A /vault/ is a persistent store for values of arbitrary types.
@@ -25,9 +25,9 @@
 extra-source-files:
     CHANGELOG.md
     README.md
-    src/Data/Vault/IO.hs
-    src/Data/Vault/ST/ST.hs
-    src/Data/Vault/ST/backends/GHC.hs
+    src/Data/Vault/IO.h
+    src/Data/Vault/ST/ST.h
+    src/Data/Vault/ST/backends/GHC.h
 
 source-repository head
     type:           git
