vault-0.3.1.2/0000755000000000000000000000000013331301167011172 5ustar0000000000000000vault-0.3.1.2/CHANGELOG.md0000644000000000000000000000201213331301167012776 0ustar0000000000000000## Changelog for the `vault` package **0.3.1.2** * Bump dependencies to allow `containers-0.6`. * Compatibility with GHC-8.6 * Bump dependencies to allow `base >= 4.5 && < 4.13`. **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`. **0.3.0.6** * Bump dependencies to allow `base >= 4.5 && < 4.10`. **0.3.0.5** * Add support for GHC type roles extension, using the `RoleAnnotations` language pragma. **0.3.0.4** * Bump upper version bound for the `base` dependency. **0.3.0.3** * Bump upper version bound for the `base` dependency. **0.3.0.2** * Fix tarball. **0.3.0.1** * Use CPP to reduce code duplication. **0.3.0.0** * Split modules into Lazy and Strict variants, no default choice. * Add Hashable instance to `Data.Unique.Really` for all implementations. vault-0.3.1.2/LICENSE0000644000000000000000000000277313331301167012210 0ustar0000000000000000Copyright (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. vault-0.3.1.2/README.md0000644000000000000000000000302713331301167012453 0ustar0000000000000000[![Build Status](https://travis-ci.org/HeinrichApfelmus/vault.png)](https://travis-ci.org/HeinrichApfelmus/vault) *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 vault-0.3.1.2/Setup.hs0000644000000000000000000000005613331301167012627 0ustar0000000000000000import Distribution.Simple main = defaultMain vault-0.3.1.2/vault.cabal0000644000000000000000000000357013331301167013316 0ustar0000000000000000Name: vault Version: 0.3.1.2 Synopsis: a persistent store for values of arbitrary types Description: A /vault/ is a 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. . Also provided is a /locker/ type, representing a store for a single element. Category: Data License: BSD3 License-file: LICENSE Author: Heinrich Apfelmus, Elliott Hird Maintainer: Heinrich Apfelmus Homepage: https://github.com/HeinrichApfelmus/vault Copyright: (c) Heinrich Apfelmus 2011-2013 build-type: Simple cabal-version: >= 1.6 extra-source-files: CHANGELOG.md README.md src/Data/Vault/IO.h src/Data/Vault/ST/ST.h src/Data/Vault/ST/backends/GHC.h source-repository head type: git location: git://github.com/HeinrichApfelmus/vault.git flag UseGHC description: Use GHC-specific packages and extensions. default: True Library hs-source-dirs: src build-depends: base >= 4.5 && < 4.13, containers >= 0.4 && < 0.7, semigroups >= 0.1 && < 1.0, unordered-containers >= 0.2.3.0 && < 0.3, hashable >= 1.1.2.5 && < 1.3 extensions: CPP ghc-options: -Wall -fno-warn-missing-signatures exposed-modules: Data.Vault.Lazy, Data.Vault.Strict, Data.Vault.ST.Lazy, Data.Vault.ST.Strict, Data.Unique.Really if impl(ghc) && flag(UseGHC) CPP-options: -DUseGHC vault-0.3.1.2/src/0000755000000000000000000000000013331301167011761 5ustar0000000000000000vault-0.3.1.2/src/Data/0000755000000000000000000000000013331301167012632 5ustar0000000000000000vault-0.3.1.2/src/Data/Unique/0000755000000000000000000000000013331301167014100 5ustar0000000000000000vault-0.3.1.2/src/Data/Unique/Really.hs0000644000000000000000000000354713331301167015675 0ustar0000000000000000-- | An abstract interface to a unique symbol generator. module Data.Unique.Really ( Unique, newUnique, hashUnique, ) where import Control.Applicative ((<$>)) import Data.Hashable #if UseGHC import Control.Exception (evaluate) import qualified Data.Unique import System.Mem.StableName -- | An abstract unique value. -- Values of type 'Unique' may be compared for equality -- and hashed into Int. -- -- Note: Unlike the symbols from "Data.Unique", the symbols from this -- module do not become equal after reloads in the GHC interpreter! newtype Unique = Unique (StableName Data.Unique.Unique) deriving (Eq) newUnique = do x <- Data.Unique.newUnique _ <- evaluate x Unique <$> makeStableName x hashUnique (Unique s) = hashStableName s #else import Data.IORef import System.IO.Unsafe (unsafePerformIO) {-# NOINLINE refNumber #-} refNumber :: IORef Integer refNumber = unsafePerformIO $ newIORef 0 newNumber = atomicModifyIORef' refNumber $ \x -> let x' = x+1 in (x', x') -- | An abstract unique value. -- Values of type 'Unique' may be compared for equality -- and hashed into Int. -- -- NOTE: You haven't compiled this module with GHC. -- The functionality will be identitcal to "Data.Unique". newtype Unique = Unique Integer deriving (Eq,Ord) newUnique = Unique <$> newNumber hashUnique (Unique s) = fromIntegral s #endif -- | Creates a new object of type 'Unique'. -- The value returned will not compare equal to any other -- value of type 'Unique' returned by previous calls to 'newUnique'. -- There is no limit on the number of times you may call this function. newUnique :: IO Unique -- | Hashes a 'Unique' into an 'Int'. -- Two Uniques may hash to the same value, although in practice this is unlikely. -- The 'Int' returned makes a good hash key. hashUnique :: Unique -> Int instance Hashable Unique where hashWithSalt s = hashWithSalt s . hashUnique vault-0.3.1.2/src/Data/Vault/0000755000000000000000000000000013331301167013725 5ustar0000000000000000vault-0.3.1.2/src/Data/Vault/IO.h0000644000000000000000000000351513331301167014411 0ustar0000000000000000module 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 vault-0.3.1.2/src/Data/Vault/Lazy.hs0000644000000000000000000000026213331301167015200 0ustar0000000000000000#define LAZINESS Lazy -- | 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.h" vault-0.3.1.2/src/Data/Vault/Strict.hs0000644000000000000000000000025113331301167015527 0ustar0000000000000000#define LAZINESS Strict -- | A persistent store for values of arbitrary types. -- -- The 'Vault' type in this module is strict in both keys and values. #include "IO.h" vault-0.3.1.2/src/Data/Vault/ST/0000755000000000000000000000000013331301167014253 5ustar0000000000000000vault-0.3.1.2/src/Data/Vault/ST/Lazy.hs0000644000000000000000000000032113331301167015522 0ustar0000000000000000#define LAZINESS Lazy -- | A persistent store for values of arbitrary types. -- Variant for the 'ST' monad. -- -- The 'Vault' type in this module is strict in the keys but lazy in the values. #include "ST.h" vault-0.3.1.2/src/Data/Vault/ST/ST.h0000644000000000000000000000405313331301167014754 0ustar0000000000000000#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 vault-0.3.1.2/src/Data/Vault/ST/Strict.hs0000644000000000000000000000033313331301167016056 0ustar0000000000000000#define LAZINESS Strict #define IsStrict 1 -- | A persistent store for values of arbitrary types. -- Variant for the 'ST' monad. -- -- The 'Vault' type in this module is strict in both keys and values. #include "ST.h" vault-0.3.1.2/src/Data/Vault/ST/backends/0000755000000000000000000000000013331301167016025 5ustar0000000000000000vault-0.3.1.2/src/Data/Vault/ST/backends/GHC.h0000644000000000000000000000237613331301167016607 0ustar0000000000000000-- 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