lrucache 1.0 → 1.1
raw patch · 5 files changed
+34/−12 lines, 5 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Data.Cache.LRU.IO: modifyAtomicLRU :: (LRU key val -> LRU key val) -> AtomicLRU key val -> IO ()
+ Data.Cache.LRU.IO.Internal: modifyAtomicLRU :: (LRU key val -> LRU key val) -> AtomicLRU key val -> IO ()
+ Data.Cache.LRU.Internal: instance Functor (LRU key)
+ Data.Cache.LRU.Internal: instance Functor (LinkedVal key)
- Data.Cache.LRU: delete :: (Ord key) => key -> LRU key val -> (LRU key val, Maybe val)
+ Data.Cache.LRU: delete :: Ord key => key -> LRU key val -> (LRU key val, Maybe val)
- Data.Cache.LRU: fromList :: (Ord key) => Maybe Int -> [(key, val)] -> LRU key val
+ Data.Cache.LRU: fromList :: Ord key => Maybe Integer -> [(key, val)] -> LRU key val
- Data.Cache.LRU: insert :: (Ord key) => key -> val -> LRU key val -> LRU key val
+ Data.Cache.LRU: insert :: Ord key => key -> val -> LRU key val -> LRU key val
- Data.Cache.LRU: lookup :: (Ord key) => key -> LRU key val -> (LRU key val, Maybe val)
+ Data.Cache.LRU: lookup :: Ord key => key -> LRU key val -> (LRU key val, Maybe val)
- Data.Cache.LRU: maxSize :: LRU key val -> (Maybe Int)
+ Data.Cache.LRU: maxSize :: LRU key val -> (Maybe Integer)
- Data.Cache.LRU: newLRU :: (Ord key) => Maybe Int -> LRU key val
+ Data.Cache.LRU: newLRU :: Ord key => Maybe Integer -> LRU key val
- Data.Cache.LRU: pop :: (Ord key) => LRU key val -> (LRU key val, Maybe (key, val))
+ Data.Cache.LRU: pop :: Ord key => LRU key val -> (LRU key val, Maybe (key, val))
- Data.Cache.LRU: toList :: (Ord key) => LRU key val -> [(key, val)]
+ Data.Cache.LRU: toList :: Ord key => LRU key val -> [(key, val)]
- Data.Cache.LRU.IO: delete :: (Ord key) => key -> AtomicLRU key val -> IO (Maybe val)
+ Data.Cache.LRU.IO: delete :: Ord key => key -> AtomicLRU key val -> IO (Maybe val)
- Data.Cache.LRU.IO: fromList :: (Ord key) => Maybe Int -> [(key, val)] -> IO (AtomicLRU key val)
+ Data.Cache.LRU.IO: fromList :: Ord key => Maybe Integer -> [(key, val)] -> IO (AtomicLRU key val)
- Data.Cache.LRU.IO: insert :: (Ord key) => key -> val -> AtomicLRU key val -> IO ()
+ Data.Cache.LRU.IO: insert :: Ord key => key -> val -> AtomicLRU key val -> IO ()
- Data.Cache.LRU.IO: lookup :: (Ord key) => key -> AtomicLRU key val -> IO (Maybe val)
+ Data.Cache.LRU.IO: lookup :: Ord key => key -> AtomicLRU key val -> IO (Maybe val)
- Data.Cache.LRU.IO: maxSize :: AtomicLRU key val -> IO (Maybe Int)
+ Data.Cache.LRU.IO: maxSize :: AtomicLRU key val -> IO (Maybe Integer)
- Data.Cache.LRU.IO: newAtomicLRU :: (Ord key) => Maybe Int -> IO (AtomicLRU key val)
+ Data.Cache.LRU.IO: newAtomicLRU :: Ord key => Maybe Integer -> IO (AtomicLRU key val)
- Data.Cache.LRU.IO: pop :: (Ord key) => AtomicLRU key val -> IO (Maybe (key, val))
+ Data.Cache.LRU.IO: pop :: Ord key => AtomicLRU key val -> IO (Maybe (key, val))
- Data.Cache.LRU.IO: toList :: (Ord key) => AtomicLRU key val -> IO [(key, val)]
+ Data.Cache.LRU.IO: toList :: Ord key => AtomicLRU key val -> IO [(key, val)]
- Data.Cache.LRU.IO.Internal: delete :: (Ord key) => key -> AtomicLRU key val -> IO (Maybe val)
+ Data.Cache.LRU.IO.Internal: delete :: Ord key => key -> AtomicLRU key val -> IO (Maybe val)
- Data.Cache.LRU.IO.Internal: fromList :: (Ord key) => Maybe Int -> [(key, val)] -> IO (AtomicLRU key val)
+ Data.Cache.LRU.IO.Internal: fromList :: Ord key => Maybe Integer -> [(key, val)] -> IO (AtomicLRU key val)
- Data.Cache.LRU.IO.Internal: insert :: (Ord key) => key -> val -> AtomicLRU key val -> IO ()
+ Data.Cache.LRU.IO.Internal: insert :: Ord key => key -> val -> AtomicLRU key val -> IO ()
- Data.Cache.LRU.IO.Internal: lookup :: (Ord key) => key -> AtomicLRU key val -> IO (Maybe val)
+ Data.Cache.LRU.IO.Internal: lookup :: Ord key => key -> AtomicLRU key val -> IO (Maybe val)
- Data.Cache.LRU.IO.Internal: maxSize :: AtomicLRU key val -> IO (Maybe Int)
+ Data.Cache.LRU.IO.Internal: maxSize :: AtomicLRU key val -> IO (Maybe Integer)
- Data.Cache.LRU.IO.Internal: newAtomicLRU :: (Ord key) => Maybe Int -> IO (AtomicLRU key val)
+ Data.Cache.LRU.IO.Internal: newAtomicLRU :: Ord key => Maybe Integer -> IO (AtomicLRU key val)
- Data.Cache.LRU.IO.Internal: pop :: (Ord key) => AtomicLRU key val -> IO (Maybe (key, val))
+ Data.Cache.LRU.IO.Internal: pop :: Ord key => AtomicLRU key val -> IO (Maybe (key, val))
- Data.Cache.LRU.IO.Internal: toList :: (Ord key) => AtomicLRU key val -> IO [(key, val)]
+ Data.Cache.LRU.IO.Internal: toList :: Ord key => AtomicLRU key val -> IO [(key, val)]
- Data.Cache.LRU.Internal: LRU :: !Maybe key -> !Maybe key -> !Maybe Int -> !Map key (LinkedVal key val) -> LRU key val
+ Data.Cache.LRU.Internal: LRU :: !Maybe key -> !Maybe key -> !Maybe Integer -> !Map key (LinkedVal key val) -> LRU key val
- Data.Cache.LRU.Internal: adjust' :: (Ord k) => (a -> a) -> k -> Map k a -> Map k a
+ Data.Cache.LRU.Internal: adjust' :: Ord k => (a -> a) -> k -> Map k a -> Map k a
- Data.Cache.LRU.Internal: delete :: (Ord key) => key -> LRU key val -> (LRU key val, Maybe val)
+ Data.Cache.LRU.Internal: delete :: Ord key => key -> LRU key val -> (LRU key val, Maybe val)
- Data.Cache.LRU.Internal: delete' :: (Ord key) => key -> LRU key val -> Map key (LinkedVal key val) -> LinkedVal key val -> LRU key val
+ Data.Cache.LRU.Internal: delete' :: Ord key => key -> LRU key val -> Map key (LinkedVal key val) -> LinkedVal key val -> LRU key val
- Data.Cache.LRU.Internal: fromList :: (Ord key) => Maybe Int -> [(key, val)] -> LRU key val
+ Data.Cache.LRU.Internal: fromList :: Ord key => Maybe Integer -> [(key, val)] -> LRU key val
- Data.Cache.LRU.Internal: hit' :: (Ord key) => key -> LRU key val -> LRU key val
+ Data.Cache.LRU.Internal: hit' :: Ord key => key -> LRU key val -> LRU key val
- Data.Cache.LRU.Internal: insert :: (Ord key) => key -> val -> LRU key val -> LRU key val
+ Data.Cache.LRU.Internal: insert :: Ord key => key -> val -> LRU key val -> LRU key val
- Data.Cache.LRU.Internal: lookup :: (Ord key) => key -> LRU key val -> (LRU key val, Maybe val)
+ Data.Cache.LRU.Internal: lookup :: Ord key => key -> LRU key val -> (LRU key val, Maybe val)
- Data.Cache.LRU.Internal: maxSize :: LRU key val -> !Maybe Int
+ Data.Cache.LRU.Internal: maxSize :: LRU key val -> !Maybe Integer
- Data.Cache.LRU.Internal: newLRU :: (Ord key) => Maybe Int -> LRU key val
+ Data.Cache.LRU.Internal: newLRU :: Ord key => Maybe Integer -> LRU key val
- Data.Cache.LRU.Internal: pop :: (Ord key) => LRU key val -> (LRU key val, Maybe (key, val))
+ Data.Cache.LRU.Internal: pop :: Ord key => LRU key val -> (LRU key val, Maybe (key, val))
- Data.Cache.LRU.Internal: toList :: (Ord key) => LRU key val -> [(key, val)]
+ Data.Cache.LRU.Internal: toList :: Ord key => LRU key val -> [(key, val)]
- Data.Cache.LRU.Internal: valid :: (Ord key) => LRU key val -> Bool
+ Data.Cache.LRU.Internal: valid :: Ord key => LRU key val -> Bool
Files
- Data/Cache/LRU/IO.hs +1/−0
- Data/Cache/LRU/IO/Internal.hs +10/−3
- Data/Cache/LRU/Internal.hs +12/−6
- OpTest.hs +6/−2
- lrucache.cabal +5/−1
Data/Cache/LRU/IO.hs view
@@ -21,6 +21,7 @@ , delete , pop , size+ , modifyAtomicLRU ) where
Data/Cache/LRU/IO/Internal.hs view
@@ -27,13 +27,13 @@ -- | Make a new AtomicLRU that will not grow beyond the optional -- maximum size, if specified.-newAtomicLRU :: Ord key => Maybe Int -- ^ the optional maximum size+newAtomicLRU :: Ord key => Maybe Integer -- ^ the optional maximum size -> IO (AtomicLRU key val) newAtomicLRU = fmap C . MV.newMVar . LRU.newLRU -- | Build a new LRU from the optional maximum size and list of -- contents. See 'LRU.fromList' for the semantics.-fromList :: Ord key => Maybe Int -- ^ the optional maximum size+fromList :: Ord key => Maybe Integer -- ^ the optional maximum size -> [(key, val)] -> IO (AtomicLRU key val) fromList s l = fmap C . MV.newMVar $ LRU.fromList s l @@ -42,7 +42,7 @@ toList :: Ord key => AtomicLRU key val -> IO [(key, val)] toList (C mvar) = LRU.toList <$> MV.readMVar mvar -maxSize :: AtomicLRU key val -> IO (Maybe Int)+maxSize :: AtomicLRU key val -> IO (Maybe Integer) maxSize (C mvar) = LRU.maxSize <$> MV.readMVar mvar -- | Insert a key/value pair into an AtomicLRU. See 'LRU.insert' for@@ -68,6 +68,13 @@ -- | Returns the number of elements the AtomicLRU currently contains. size :: AtomicLRU key val -> IO Int size (C mvar) = LRU.size <$> MV.readMVar mvar++-- | Given a function that takes an 'LRU.LRU' and returns one of the+-- same type, use it to modify the contents of this AtomicLRU.+modifyAtomicLRU :: (LRU.LRU key val -> LRU.LRU key val)+ -> AtomicLRU key val+ -> IO ()+modifyAtomicLRU f (C mvar) = modifyMVar_' mvar (return . f) -- | A version of 'MV.modifyMVar_' that forces the result of the -- function application to WHNF.
Data/Cache/LRU/Internal.hs view
@@ -19,7 +19,7 @@ data LRU key val = LRU { first :: !(Maybe key) -- ^ the key of the most recently accessed entry , last :: !(Maybe key) -- ^ the key of the least recently accessed entry- , maxSize :: !(Maybe Int) -- ^ the maximum size of the LRU cache+ , maxSize :: !(Maybe Integer) -- ^ the maximum size of the LRU cache , content :: !(Map key (LinkedVal key val)) -- ^ the backing 'Map' } deriving Eq @@ -27,6 +27,9 @@ instance (Ord key, Show key, Show val) => Show (LRU key val) where show lru = "fromList " ++ show (toList lru) +instance Functor (LRU key) where+ fmap f lru = lru { content = fmap (fmap f) . content $ lru }+ -- | The values stored in the Map of the LRU cache. They embed a -- doubly-linked list through the values of the 'Map'. data LinkedVal key val = Link {@@ -35,16 +38,19 @@ , next :: !(Maybe key) -- ^ the key of the value after this one } deriving Eq +instance Functor (LinkedVal key) where+ fmap f lv = lv { value = f . value $ lv }+ -- | Make an LRU. If a size limit is specified, the LRU is guaranteed -- to not grow above the specified number of entries.-newLRU :: (Ord key) => Maybe Int -- ^ the optional maximum size of the LRU+newLRU :: (Ord key) => Maybe Integer -- ^ the optional maximum size of the LRU -> LRU key val newLRU (Just s) | s <= 0 = error "non-positive size LRU" newLRU s = LRU Nothing Nothing s Map.empty -- | Build a new LRU from the given maximum size and list of contents, -- in order from most recently accessed to least recently accessed.-fromList :: Ord key => Maybe Int -- ^ the optional maximum size of the LRU+fromList :: Ord key => Maybe Integer -- ^ the optional maximum size of the LRU -> [(key, val)] -> LRU key val fromList s l = appendAll $ newLRU s where appendAll = foldr ins id l@@ -73,7 +79,7 @@ insert key val lru = maybe emptyCase nonEmptyCase $ first lru where contents = content lru- full = maybe False (Map.size contents ==) $ maxSize lru+ full = maybe False (fromIntegral (Map.size contents) ==) $ maxSize lru present = key `Map.member` contents -- this is the case for adding to an empty LRU Cache@@ -252,10 +258,10 @@ -- -- 4. Every key in the linked list is in the 'Map'. valid :: Ord key => LRU key val -> Bool-valid lru = maybe True (size lru <=) (maxSize lru) &&+valid lru = maybe True (fromIntegral (size lru) <=) (maxSize lru) && reverse orderedKeys == reverseKeys && size lru == length orderedKeys &&- all (`Map.member` contents) orderedKeys + all (`Map.member` contents) orderedKeys where contents = content lru orderedKeys = traverse next . first $ lru traverse _ Nothing = []
OpTest.hs view
@@ -1,4 +1,6 @@ {-# LANGUAGE FlexibleInstances #-}+module OpTest where+ import qualified Prelude import Prelude hiding ( lookup, last ) @@ -36,7 +38,9 @@ shrink = shrinkNothing -newtype History key val = H (Maybe Int, [Action key val] -> [Action key val])+newtype History key val = H ( Maybe Integer+ , [Action key val] -> [Action key val]+ ) instance Arbitrary (History Int Int) where arbitrary = liftM2 (curry H) s h@@ -64,7 +68,7 @@ post = toList lru' naive = (key, val) : filter ((key /=) . fst) pre- sizeOk = maybe True (length naive <=) k+ sizeOk = maybe True (fromIntegral (length naive) <=) k projected = if sizeOk then naive else init naive when (projected /= post) $ throw "unexpected result"
lrucache.cabal view
@@ -1,5 +1,5 @@ Name: lrucache-Version: 1.0+Version: 1.1 Synopsis: a simple, pure LRU cache License: BSD3 License-file: LICENSE@@ -18,6 +18,10 @@ an LRU cache. . Version History:+ .+ 1.1 - Add a Functor instance for LRUCache.+ Add a generic modification modification function+ for AtomicLRUCache. . 1.0 - Breaking API changes: 1) The newLRU smart constructor now makes the maximum