bloomfilter-redis 0.1.0.0 → 0.1.0.1
raw patch · 6 files changed
+38/−21 lines, 6 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
+ Data.RedisBloom: querySafeBF :: (Applicative f, MonadRedis m, RedisCtx m f) => Bloom a -> a -> m (f Bool)
- Data.RedisBloom.Hash.FNV: fnvPrime :: (Num a, FiniteBits a) => a
+ Data.RedisBloom.Hash.FNV: fnvPrime :: forall a. (Num a, FiniteBits a) => a
- Data.RedisBloom.Suggestions: suggestCapacity :: (Integral a, RealFrac b, Floating b) => a -> b -> Capacity
+ Data.RedisBloom.Suggestions: suggestCapacity :: forall a b. (Integral a, RealFrac b, Floating b) => a -> b -> Capacity
- Data.RedisBloom.Suggestions: suggestHashCount :: (Integral a) => a -> Capacity -> HashCount
+ Data.RedisBloom.Suggestions: suggestHashCount :: forall a. (Integral a) => a -> Capacity -> HashCount
Files
- CHANGELOG.md +6/−0
- README.md +7/−5
- bloomfilter-redis.cabal +1/−1
- src/Data/RedisBloom.hs +13/−10
- test/Common.hs +2/−1
- test/TestBloom.hs +9/−4
CHANGELOG.md view
@@ -1,3 +1,9 @@+0.1.0.1+------+* README improvements+* Compatibility with GHC 7.8/base-4.7+* Test suite improvements+ 0.1.0.0 ------ Initial release
README.md view
@@ -1,9 +1,11 @@+# bloomfilter-redis [](https://travis-ci.org/hesiod/bloomfilter-redis)+ Distributed bloom filters on Redis (using the Hedis client). The hash family algorithm is partly inspired by [Brian O'Sullivan's bloomfilter package](https://hackage.haskell.org/package/bloomfilter). -# Features+## Features * Implementation of the FNV-1/FNV-1a hash function is included * Automatic derivation of a hash family from a single hash function@@ -13,7 +15,7 @@ * Every `Hashable` type can be added to the bloom filter * Every `Binary` type can be hashed -# Benchmark and Testing suite+## Benchmark and Testing suite A benchmark for the FNV hash function is included and can be invoked using `cabal bench` or `stack bench`.@@ -21,15 +23,15 @@ A testing suite using `tasty` is included. -# Further Information-## Todo+## Further Information+### Todo * Separate the FNV hash function into a separate package * The actual operations (`addBF`, `queryBF`, etc) should ideally live in a `MonadReader (Bloom a)`, but this requires some work on the Hedis side because of `RedisCtx` -## Caveats+### Caveats * The only supported FNV hash sizes are 32 and 64 bits. Support for larger widths is a matter of having a
bloomfilter-redis.cabal view
@@ -1,5 +1,5 @@ name: bloomfilter-redis-version: 0.1.0.0+version: 0.1.0.1 synopsis: Distributed bloom filters on Redis (using the Hedis client). description: Distributed bloom filters on Redis (using the Hedis client).
src/Data/RedisBloom.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE CPP #-} {-# LANGUAGE Trustworthy #-} @@ -11,7 +12,7 @@ -- ** Static bloom filter configuration Bloom(..), -- * Bloom filter operations- createBF, createIfNewBF, addBF, queryBF+ createBF, createIfNewBF, addBF, queryBF, querySafeBF ) where #if !MIN_VERSION_base(4,8,0)@@ -57,26 +58,28 @@ (Capacity cap) = capacity bf one = pack "1" -getBit :: (MonadRedis m, RedisCtx m (Either Reply)) => Bloom a -> Integer -> m Bool+getBit :: forall m f a. (Functor f, MonadRedis m, RedisCtx m f) => Bloom a -> Integer -> m (f Bool) getBit bf i = do r <- getbit (key bf) i- let l = case r of- Left _ -> False- Right j -> j >= 1- return l+ return . fmap (>= 1) $ (r :: f Integer) -- | Query whether an element exists in the bloom filter.+querySafeBF :: (Applicative f, MonadRedis m, RedisCtx m f) => Bloom a -> a -> m (f Bool)+querySafeBF bf = query (capacity bf) (getBit bf) (hf bf)++-- | Query whether an element exists in the bloom filter. -- -- Gracefully fails upon failure by returning 'False'. queryBF :: (MonadRedis m, RedisCtx m (Either Reply)) => Bloom a -> a -> m Bool-queryBF bf = query (capacity bf) (getBit bf) (hf bf)+queryBF bf = fmap (either (const False) id) . query (capacity bf) (getBit bf) (hf bf) -query :: Monad m => Capacity -> (Integer -> m Bool) -> HashFamily a -> a -> m Bool+query :: (Applicative f, Monad m) => Capacity -> (Integer -> m (f Bool)) -> HashFamily a -> a -> m (f Bool) query (Capacity c) q hashf x = do let hashes = fmap (toInteger . (`mod` c) . fromIntegral) . hashf $ x lookupMany q hashes -lookupMany :: (Traversable t, Monad m) => (a -> m Bool) -> t a -> m Bool+lookupMany :: (Applicative f, Traversable t, Monad m) => (a -> m (f Bool)) -> t a -> m (f Bool) lookupMany lookupBit hashes = do bools <- mapM lookupBit hashes- return . getAll . foldMap All $ bools+ let b' = fmap (getAll . foldMap All) . sequenceA $ bools+ return b'
test/Common.hs view
@@ -5,6 +5,7 @@ #if !MIN_VERSION_base(4,8,0) import Prelude hiding (mapM, mapM_)+import Data.Foldable (Foldable(..), mapM_) import Data.Traversable (Traversable(..)) #endif import Data.Hashable@@ -27,7 +28,7 @@ createAddQuery :: Hashable a => Bloom a -> a -> Redis Bool createAddQuery b x = createBF b >> addBF b x >> queryBF b x-createAddL :: (Hashable a, Traversable t) => Bloom a -> t a -> Redis ()+createAddL :: (Hashable a, Foldable t) => Bloom a -> t a -> Redis () createAddL b l = createBF b >> mapM_ (addBF b) l queryL :: (Hashable a, Traversable t) => Bloom a -> t a -> Redis (t Bool) queryL b = mapM (queryBF b)
test/TestBloom.hs view
@@ -1,3 +1,12 @@+{-# LANGUAGE CPP #-}++#if !MIN_VERSION_base(4,8,0)+import Data.Foldable (foldMap)+#endif+import Data.List (nub)+import Data.Monoid (All(..))+import Data.Word (Word32, Word64)+ import Test.Tasty import Test.Tasty.Runners import Test.Tasty.Ingredients.Rerun@@ -5,11 +14,7 @@ import Test.Tasty.HUnit as HU hiding (assert) import Test.QuickCheck.Monadic -import Data.List (nub)-import Data.Monoid (All(..))-import Data.Word (Word32, Word64) import Database.Redis- import Data.RedisBloom import Data.RedisBloom.Hash.FNV import Data.RedisBloom.Suggestions