build-0.0.1: src/Build/Store.hs
-- | An abstract key/value store.
module Build.Store (
-- * Hashing
Hash, Hashable (..),
-- * Store
Store, getValue, putValue, getHash, getInfo, putInfo, mapInfo,
initialise
) where
-- | A 'Hash' is used for efficient tracking and sharing of build results. We
-- use @newtype Hash a = Hash a@ for prototyping.
newtype Hash a = Hash a deriving (Eq, Ord,Show)
instance Functor Hash where
fmap f (Hash a) = Hash (f a)
instance Applicative Hash where
pure = Hash
Hash f <*> Hash a = Hash (f a)
class Ord a => Hashable a where
-- | Compute the hash of a given value. We typically assume cryptographic
-- hashing, e.g. SHA256.
hash :: a -> Hash a
instance Hashable Int where
hash = Hash
instance Hashable Integer where
hash = Hash
instance Hashable a => Hashable [a] where
hash = Hash
instance Hashable a => Hashable (Hash a) where
hash = Hash
instance (Hashable a, Hashable b) => Hashable (a, b) where
hash = Hash
-- | An abstract datatype for a key/value store with build information of type @i@.
data Store i k v = Store { info :: i, values :: k -> v }
-- | Read the build information.
getInfo :: Store i k v -> i
getInfo = info
-- | Read the value of a key.
getValue :: k -> Store i k v -> v
getValue = flip values
-- | Read the hash of a key's value. In some cases may be implemented more
-- efficiently than @hash . getValue k@.
getHash :: Hashable v => k -> Store i k v -> Hash v
getHash k = hash . getValue k
-- | Write the build information.
putInfo :: i -> Store i k v -> Store i k v
putInfo i s = s { info = i }
-- | Modify the build information.
mapInfo :: (i -> j) -> Store i k v -> Store j k v
mapInfo f (Store i kv) = Store (f i) kv
-- | Update the value of a key.
putValue :: Eq k => k -> v -> Store i k v -> Store i k v
putValue k v s = s { values = \key -> if key == k then v else values s key }
-- | Initialise the store.
initialise :: i -> (k -> v) -> Store i k v
initialise = Store