    {-# LANGUAGE OverloadedStrings #-}
    -- |

    -- Module : Caching.ExpiringCacheMap.Internal

    -- Copyright: (c) 2014 Edward L. Blake

    -- License: BSD-style

    -- Maintainer: Edward L. Blake <edwardlblake@gmail.com>

    -- Stability: experimental

    -- Portability: portable

    --

    -- A module with internal functions used in common by HashECM and OrdECM.

    -- Assume these functions to change from version to version.

    --

    module Caching.ExpiringCacheMap.Internal.Internal (
        updateUses,
        detECM,
        getStatsString,
        detNotExpired
    ) where

    import qualified Data.List as L

    import Caching.ExpiringCacheMap.Types
    import Caching.ExpiringCacheMap.Internal.Types

    updateUses :: (Eq k) => ([(k, ECMIncr)], ECMULength) -> k
      -> ECMIncr -> ECMULength -> ([(k, ECMIncr)] -> [(k, ECMIncr)])
        -> ([(k, ECMIncr)], ECMULength)
    {-# INLINE updateUses #-}
    updateUses :: forall k.
    Eq k =>
    ([(k, ECMIncr)], ECMULength)
    -> k
    -> ECMIncr
    -> ECMULength
    -> ([(k, ECMIncr)] -> [(k, ECMIncr)])
    -> ([(k, ECMIncr)], ECMULength)
    updateUses ([(k, ECMIncr)]
    usesl, ECMULength
    lcount) k
    id ECMIncr
    incr' ECMULength
    compactlistsize [(k, ECMIncr)] -> [(k, ECMIncr)]
    compactUses
     | ECMULength
    lcount ECMULength -> ECMULength -> Bool
    forall a. Ord a => a -> a -> Bool
    >= ECMULength
    5 =
        case [(k, ECMIncr)]
    usesl of
            (k
    id', ECMIncr
    _) : [(k, ECMIncr)]
    rest | k
    id' k -> k -> Bool
    forall a. Eq a => a -> a -> Bool
    == k
    id ->
              ((k
    id', ECMIncr
    incr') (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : [(k, ECMIncr)]
    rest, ECMULength
    lcount)

            (k, ECMIncr)
    latest : (k
    id1, ECMIncr
    oincr1) : (k
    id2, ECMIncr
    oincr2) : (k
    id3, ECMIncr
    oincr3) : (k
    id4, ECMIncr
    oincr4) : [(k, ECMIncr)]
    rest ->
              case Bool
    True of
                Bool
    _ | k
    id1 k -> k -> Bool
    forall a. Eq a => a -> a -> Bool
    == k
    id -> ((k
    id1, ECMIncr
    incr') (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k, ECMIncr)
    latest (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k
    id2, ECMIncr
    oincr2) (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k
    id3, ECMIncr
    oincr3) (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k
    id4, ECMIncr
    oincr4) (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : [(k, ECMIncr)]
    rest, ECMULength
    lcount)
                Bool
    _ | k
    id2 k -> k -> Bool
    forall a. Eq a => a -> a -> Bool
    == k
    id -> ((k
    id2, ECMIncr
    incr') (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k, ECMIncr)
    latest (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k
    id1, ECMIncr
    oincr1) (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k
    id3, ECMIncr
    oincr3) (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k
    id4, ECMIncr
    oincr4) (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : [(k, ECMIncr)]
    rest, ECMULength
    lcount)
                Bool
    _ | k
    id3 k -> k -> Bool
    forall a. Eq a => a -> a -> Bool
    == k
    id -> ((k
    id3, ECMIncr
    incr') (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k, ECMIncr)
    latest (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k
    id1, ECMIncr
    oincr1) (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k
    id2, ECMIncr
    oincr2) (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k
    id4, ECMIncr
    oincr4) (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : [(k, ECMIncr)]
    rest, ECMULength
    lcount)
                Bool
    _ | k
    id4 k -> k -> Bool
    forall a. Eq a => a -> a -> Bool
    == k
    id -> ((k
    id4, ECMIncr
    incr') (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k, ECMIncr)
    latest (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k
    id1, ECMIncr
    oincr1) (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k
    id2, ECMIncr
    oincr2) (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k
    id3, ECMIncr
    oincr3) (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : [(k, ECMIncr)]
    rest, ECMULength
    lcount)
                Bool
    _ -> ([(k, ECMIncr)], ECMULength)
    justPrepend
              {-
              if id1 == id
                then ((id1, incr') : latest : (id2, oincr2) : (id3, oincr3) : (id4, oincr4) : rest, lcount)
                else if id2 == id
                       then ((id2, incr') : latest : (id1, oincr1) : (id3, oincr3) : (id4, oincr4) : rest, lcount)
                       else if id3 == id
                              then ((id3, incr') : latest : (id1, oincr1) : (id2, oincr2) : (id4, oincr4) : rest, lcount)
                              else if id4 == id
                                     then ((id4, incr') : latest : (id1, oincr1) : (id2, oincr2) : (id3, oincr3) : rest, lcount)
                                     else justPrepend
              -}

            [(k, ECMIncr)]
    _ -> ([(k, ECMIncr)], ECMULength)
    justPrepend
     | Bool
    otherwise =
        case [(k, ECMIncr)]
    usesl of
            (k
    id', ECMIncr
    _) : [(k, ECMIncr)]
    rest | k
    id' k -> k -> Bool
    forall a. Eq a => a -> a -> Bool
    == k
    id ->
              ((k
    id', ECMIncr
    incr') (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : [(k, ECMIncr)]
    rest, ECMULength
    lcount)

            (k, ECMIncr)
    latest : (k
    id1, ECMIncr
    oincr1) : (k
    id2, ECMIncr
    oincr2) : (k
    id3, ECMIncr
    oincr3) : [(k, ECMIncr)]
    rest ->
              case Bool
    True of
                Bool
    _ | k
    id1 k -> k -> Bool
    forall a. Eq a => a -> a -> Bool
    == k
    id -> ((k
    id1, ECMIncr
    incr') (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k, ECMIncr)
    latest (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k
    id2, ECMIncr
    oincr2) (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k
    id3, ECMIncr
    oincr3) (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : [(k, ECMIncr)]
    rest, ECMULength
    lcount)
                Bool
    _ | k
    id2 k -> k -> Bool
    forall a. Eq a => a -> a -> Bool
    == k
    id -> ((k
    id2, ECMIncr
    incr') (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k, ECMIncr)
    latest (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k
    id1, ECMIncr
    oincr1) (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k
    id3, ECMIncr
    oincr3) (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : [(k, ECMIncr)]
    rest, ECMULength
    lcount)
                Bool
    _ | k
    id3 k -> k -> Bool
    forall a. Eq a => a -> a -> Bool
    == k
    id -> ((k
    id3, ECMIncr
    incr') (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k, ECMIncr)
    latest (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k
    id1, ECMIncr
    oincr1) (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k
    id2, ECMIncr
    oincr2) (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : [(k, ECMIncr)]
    rest, ECMULength
    lcount)
                Bool
    _ -> ([(k, ECMIncr)], ECMULength)
    justPrepend
              {-
              if id1 == id
                then ((id1, incr') : latest : (id2, oincr2) : (id3, oincr3) : rest, lcount)
                else if id2 == id
                       then ((id2, incr') : latest : (id1, oincr1) : (id3, oincr3) : rest, lcount)
                       else if id3 == id
                              then ((id3, incr') : latest : (id1, oincr1) : (id2, oincr2) : rest, lcount)
                              else justPrepend
              -}

            (k, ECMIncr)
    latest : (k
    id1, ECMIncr
    oincr1) : (k
    id2, ECMIncr
    oincr2) : [(k, ECMIncr)]
    rest ->
              case Bool
    True of
                Bool
    _ | k
    id1 k -> k -> Bool
    forall a. Eq a => a -> a -> Bool
    == k
    id -> ((k
    id1, ECMIncr
    incr') (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k, ECMIncr)
    latest (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k
    id2, ECMIncr
    oincr2) (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : [(k, ECMIncr)]
    rest, ECMULength
    lcount)
                Bool
    _ | k
    id2 k -> k -> Bool
    forall a. Eq a => a -> a -> Bool
    == k
    id -> ((k
    id2, ECMIncr
    incr') (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k, ECMIncr)
    latest (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k
    id1, ECMIncr
    oincr1) (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : [(k, ECMIncr)]
    rest, ECMULength
    lcount)
                Bool
    _ -> ([(k, ECMIncr)], ECMULength)
    justPrepend
              {-
              if id1 == id
                then ((id1, incr') : latest : (id2, oincr2) : rest, lcount)
                else if id2 == id
                       then ((id2, incr') : latest : (id1, oincr1) : rest, lcount)
                       else justPrepend
              -}

            (k, ECMIncr)
    latest : (k
    id', ECMIncr
    _) : [(k, ECMIncr)]
    rest ->
              if k
    id' k -> k -> Bool
    forall a. Eq a => a -> a -> Bool
    == k
    id
                then ((k
    id', ECMIncr
    incr') (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : (k, ECMIncr)
    latest (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : [(k, ECMIncr)]
    rest, ECMULength
    lcount)
                else ([(k, ECMIncr)], ECMULength)
    justPrepend

            [(k, ECMIncr)]
    _ -> ([(k, ECMIncr)], ECMULength)
    justPrepend
      where
        justPrepend :: ([(k, ECMIncr)], ECMULength)
    justPrepend =
          if ECMULength
    lcount ECMULength -> ECMULength -> Bool
    forall a. Ord a => a -> a -> Bool
    > ECMULength
    compactlistsize
            then let newusesl :: [(k, ECMIncr)]
    newusesl = [(k, ECMIncr)] -> [(k, ECMIncr)]
    compactUses [(k, ECMIncr)]
    usesl
                  in ((k
    id, ECMIncr
    incr') (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : [(k, ECMIncr)]
    newusesl, (ECMULength -> ECMULength -> ECMULength
    forall a. Num a => a -> a -> a
    +ECMULength
    1) (ECMULength -> ECMULength) -> ECMULength -> ECMULength
    forall a b. (a -> b) -> a -> b
    $! ([(k, ECMIncr)] -> ECMULength
    forall a. [a] -> ECMULength
    forall (t :: * -> *) a. Foldable t => t a -> ECMULength
    L.length [(k, ECMIncr)]
    newusesl) )
            else ((k
    id, ECMIncr
    incr') (k, ECMIncr) -> [(k, ECMIncr)] -> [(k, ECMIncr)]
    forall a. a -> [a] -> [a]
    : [(k, ECMIncr)]
    usesl, ECMULength
    lcount ECMULength -> ECMULength -> ECMULength
    forall a. Num a => a -> a -> a
    + ECMULength
    1)

    detECM
      :: (Monad m, Eq k) =>
         Maybe (TimeUnits, TimeUnits, v)
         -> Maybe s
         -> m (TimeUnits, (Maybe s, v))
         -> ( ((TimeUnits, TimeUnits, v) -> mp k (TimeUnits, TimeUnits, v)),
              ((TimeUnits, TimeUnits, v) -> [(k, ECMIncr)] -> mp k (TimeUnits, TimeUnits, v)),
              ([(k, ECMIncr)] -> [(k, ECMIncr)]),
              ECMMapSize,
              ECMULength)
         -> m TimeUnits
         -> (((TimeUnits, TimeUnits, v) -> Bool)
             -> mp k (TimeUnits, TimeUnits, v) -> mp k (TimeUnits, TimeUnits, v))
         -> ECMMapSize
         -> (mp k (TimeUnits, TimeUnits, v) -> ECMMapSize)
         -> ([(k, ECMIncr)], ECMULength)
         -> ECMIncr
         -> ECMIncr
         -> mp k (TimeUnits, TimeUnits, v)
           -> m ((CacheState s mp k v, v), Bool)
    {-# INLINE detECM #-}
    detECM :: forall (m :: * -> *) k v s (mp :: * -> * -> *).
    (Monad m, Eq k) =>
    Maybe (ECMULength, ECMULength, v)
    -> Maybe s
    -> m (ECMULength, (Maybe s, v))
    -> ((ECMULength, ECMULength, v)
        -> mp k (ECMULength, ECMULength, v),
        (ECMULength, ECMULength, v)
        -> [(k, ECMIncr)] -> mp k (ECMULength, ECMULength, v),
        [(k, ECMIncr)] -> [(k, ECMIncr)], ECMULength, ECMULength)
    -> m ECMULength
    -> (((ECMULength, ECMULength, v) -> Bool)
        -> mp k (ECMULength, ECMULength, v)
        -> mp k (ECMULength, ECMULength, v))
    -> ECMULength
    -> (mp k (ECMULength, ECMULength, v) -> ECMULength)
    -> ([(k, ECMIncr)], ECMULength)
    -> ECMIncr
    -> ECMIncr
    -> mp k (ECMULength, ECMULength, v)
    -> m ((CacheState s mp k v, v), Bool)
    detECM Maybe (ECMULength, ECMULength, v)
    result Maybe s
    retr_state m (ECMULength, (Maybe s, v))
    retr_id ((ECMULength, ECMULength, v) -> mp k (ECMULength, ECMULength, v),
     (ECMULength, ECMULength, v)
     -> [(k, ECMIncr)] -> mp k (ECMULength, ECMULength, v),
     [(k, ECMIncr)] -> [(k, ECMIncr)], ECMULength, ECMULength)
    etc  m ECMULength
    gettime ((ECMULength, ECMULength, v) -> Bool)
    -> mp k (ECMULength, ECMULength, v)
    -> mp k (ECMULength, ECMULength, v)
    filt  ECMULength
    cmapsize mp k (ECMULength, ECMULength, v) -> ECMULength
    newsize ([(k, ECMIncr)], ECMULength)
    uses' ECMIncr
    incr' ECMIncr
    timecheckmodulo mp k (ECMULength, ECMULength, v)
    maps =
        case Maybe (ECMULength, ECMULength, v)
    result of
            Maybe (ECMULength, ECMULength, v)
    Nothing -> do
              (expirytime, (retr_state', r)) <- m (ECMULength, (Maybe s, v))
    retr_id
              time <- gettime
              let (newmaps,mapsize',newuses) = insertAndPerhapsRemoveSome etc cmapsize newsize filt time r expirytime uses'
              return $! ((CacheState (retr_state', newmaps, mapsize', newuses, incr'), r), False)
            Just (ECMULength
    _accesstime, ECMULength
    _expirytime, v
    m) -> do
              if ECMIncr
    incr' ECMIncr -> ECMIncr -> ECMIncr
    forall a. Integral a => a -> a -> a
    `mod` ECMIncr
    timecheckmodulo ECMIncr -> ECMIncr -> Bool
    forall a. Eq a => a -> a -> Bool
    == ECMIncr
    0
                then do
                  time <- m ECMULength
    gettime
                  return $! let maps' = ECMULength
    -> mp k (ECMULength, ECMULength, v)
    -> mp k (ECMULength, ECMULength, v)
    filterExpired ECMULength
    time mp k (ECMULength, ECMULength, v)
    maps
                             in ((CacheState (retr_state, maps', (+0) $! newsize maps', uses', incr'), m), True)
                else ((CacheState s mp k v, v), Bool)
    -> m ((CacheState s mp k v, v), Bool)
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (((Maybe s, mp k (ECMULength, ECMULength, v), ECMULength,
     ([(k, ECMIncr)], ECMULength), ECMIncr)
    -> CacheState s mp k v
    forall s (m :: * -> * -> *) k v.
    (Maybe s, m k (ECMULength, ECMULength, v), ECMULength,
     ([(k, ECMIncr)], ECMULength), ECMIncr)
    -> CacheState s m k v
    CacheState (Maybe s
    retr_state, mp k (ECMULength, ECMULength, v)
    maps, ECMULength
    cmapsize, ([(k, ECMIncr)], ECMULength)
    uses', ECMIncr
    incr'), v
    m), Bool
    False)
      where
        filterExpired :: ECMULength
    -> mp k (ECMULength, ECMULength, v)
    -> mp k (ECMULength, ECMULength, v)
    filterExpired = (((ECMULength, ECMULength, v) -> Bool)
     -> mp k (ECMULength, ECMULength, v)
     -> mp k (ECMULength, ECMULength, v))
    -> ECMULength
    -> mp k (ECMULength, ECMULength, v)
    -> mp k (ECMULength, ECMULength, v)
    forall {a} {c} {t}.
    (Ord a, Num a) =>
    (((a, a, c) -> Bool) -> t) -> a -> t
    filterExpired' ((ECMULength, ECMULength, v) -> Bool)
    -> mp k (ECMULength, ECMULength, v)
    -> mp k (ECMULength, ECMULength, v)
    filt

    {-# INLINE insertAndPerhapsRemoveSome #-}
    insertAndPerhapsRemoveSome :: ((a, b, c) -> t, (a, b, c) -> [(b, a)] -> t, [(b, a)] -> [(b, a)],
     ECMULength, b)
    -> b
    -> (t -> b)
    -> (((a, a, c) -> Bool) -> t -> t)
    -> a
    -> c
    -> b
    -> ([(b, a)], ECMULength)
    -> (t, b, ([(b, a)], ECMULength))
    insertAndPerhapsRemoveSome ((a, b, c) -> t
    insert_id1, (a, b, c) -> [(b, a)] -> t
    insert_id2, [(b, a)] -> [(b, a)]
    mnub, ECMULength
    minimumkeep, b
    removalsize) b
    cmapsize t -> b
    newsize ((a, a, c) -> Bool) -> t -> t
    filt a
    time c
    r b
    expirytime ([(b, a)], ECMULength)
    uses =
          if b
    cmapsize b -> b -> Bool
    forall a. Ord a => a -> a -> Bool
    >= b
    removalsize
            then
              let ([(b, a)]
    keepuses, [b]
    _removekeys) = [(b, a)] -> ([(b, a)], [b])
    getKeepAndRemove [(b, a)]
    usesl
                  newmaps :: t
    newmaps = (a, b, c) -> [(b, a)] -> t
    insert_id2 (a
    time, b
    expirytime, c
    r) [(b, a)]
    keepuses
                  newmaps' :: t
    newmaps' = a -> t -> t
    filterExpired a
    time t
    newmaps
               in (t
    newmaps', (b -> b -> b
    forall a. Num a => a -> a -> a
    +b
    0) (b -> b) -> b -> b
    forall a b. (a -> b) -> a -> b
    $! t -> b
    newsize t
    newmaps', ([(b, a)]
    keepuses, (ECMULength -> ECMULength -> ECMULength
    forall a. Num a => a -> a -> a
    +ECMULength
    0) (ECMULength -> ECMULength) -> ECMULength -> ECMULength
    forall a b. (a -> b) -> a -> b
    $! ([(b, a)] -> ECMULength
    forall a. [a] -> ECMULength
    forall (t :: * -> *) a. Foldable t => t a -> ECMULength
    L.length [(b, a)]
    keepuses)))
            else
              let newmaps :: t
    newmaps = (a, b, c) -> t
    insert_id1 (a
    time, b
    expirytime, c
    r)
               in (t
    newmaps, b
    cmapsize b -> b -> b
    forall a. Num a => a -> a -> a
    + b
    1, ([(b, a)], ECMULength)
    uses) -- filterExpired time

          where
            ([(b, a)]
    usesl, ECMULength
    _lcount) = ([(b, a)], ECMULength)
    uses
            getKeepAndRemove :: [(b, a)] -> ([(b, a)], [b])
    getKeepAndRemove =
              ([(a, b)], [(a, b)]) -> ([(b, a)], [b])
    forall {b} {a} {a} {b}. ([(b, a)], [(a, b)]) -> ([(a, b)], [b])
    finalTup (([(a, b)], [(a, b)]) -> ([(b, a)], [b]))
    -> ([(b, a)] -> ([(a, b)], [(a, b)]))
    -> [(b, a)]
    -> ([(b, a)], [b])
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ECMULength -> [(a, b)] -> ([(a, b)], [(a, b)])
    forall a. ECMULength -> [a] -> ([a], [a])
    splitAt ECMULength
    minimumkeep ([(a, b)] -> ([(a, b)], [(a, b)]))
    -> ([(b, a)] -> [(a, b)]) -> [(b, a)] -> ([(a, b)], [(a, b)])
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [(a, b)] -> [(a, b)]
    forall a. [a] -> [a]
    reverse ([(a, b)] -> [(a, b)])
    -> ([(b, a)] -> [(a, b)]) -> [(b, a)] -> [(a, b)]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .
                  [(a, b)] -> [(a, b)]
    forall {b}. [(a, b)] -> [(a, b)]
    sortI ([(a, b)] -> [(a, b)])
    -> ([(b, a)] -> [(a, b)]) -> [(b, a)] -> [(a, b)]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ((b, a) -> (a, b)) -> [(b, a)] -> [(a, b)]
    forall a b. (a -> b) -> [a] -> [b]
    map (b, a) -> (a, b)
    forall {b} {a}. (b, a) -> (a, b)
    swap2 ([(b, a)] -> [(a, b)])
    -> ([(b, a)] -> [(b, a)]) -> [(b, a)] -> [(a, b)]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [(b, a)] -> [(b, a)]
    mnub
                where swap2 :: (b, a) -> (a, b)
    swap2 (b
    a,a
    b) = (a
    b,b
    a)
                      finalTup :: ([(b, a)], [(a, b)]) -> ([(a, b)], [b])
    finalTup ([(b, a)]
    l1,[(a, b)]
    l2) =
                        (((b, a) -> (a, b)) -> [(b, a)] -> [(a, b)]
    forall a b. (a -> b) -> [a] -> [b]
    map (\(b
    c,a
    k) -> (a
    k,b
    c)) [(b, a)]
    l1, ((a, b) -> b) -> [(a, b)] -> [b]
    forall a b. (a -> b) -> [a] -> [b]
    map (\(a
    c,b
    k) -> b
    k) [(a, b)]
    l2)
                      sortI :: [(a, b)] -> [(a, b)]
    sortI = ((a, b) -> (a, b) -> Ordering) -> [(a, b)] -> [(a, b)]
    forall a. (a -> a -> Ordering) -> [a] -> [a]
    L.sortBy (\(a
    l,b
    _) (a
    r,b
    _) -> a -> a -> Ordering
    forall a. Ord a => a -> a -> Ordering
    compare a
    l a
    r)

            filterExpired :: a -> t -> t
    filterExpired = (((a, a, c) -> Bool) -> t -> t) -> a -> t -> t
    forall {a} {c} {t}.
    (Ord a, Num a) =>
    (((a, a, c) -> Bool) -> t) -> a -> t
    filterExpired' ((a, a, c) -> Bool) -> t -> t
    filt

    {-# INLINE filterExpired' #-}
    filterExpired' :: (((a, a, c) -> Bool) -> t) -> a -> t
    filterExpired' ((a, a, c) -> Bool) -> t
    filt a
    time =
          ((a, a, c) -> Bool) -> t
    filt (\(a
    accesstime, a
    expirytime, c
    _value) ->
                     (a
    accesstime a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    <= a
    time) Bool -> Bool -> Bool
    &&
                       (a
    accesstime a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    > (a
    time a -> a -> a
    forall a. Num a => a -> a -> a
    - a
    expirytime)))

    detNotExpired
     :: TimeUnits -> [(k, (TimeUnits, TimeUnits, v))] -> [k]
    {-# INLINE detNotExpired #-}
    detNotExpired :: forall k v. ECMULength -> [(k, (ECMULength, ECMULength, v))] -> [k]
    detNotExpired ECMULength
    _time [(k, (ECMULength, ECMULength, v))]
    l = ECMULength -> [(k, (ECMULength, ECMULength, v))] -> [k] -> [k]
    forall {t} {a} {c}.
    (Ord t, Num t) =>
    t -> [(a, (t, t, c))] -> [a] -> [a]
    detNotExpired' ECMULength
    _time [(k, (ECMULength, ECMULength, v))]
    l []

    {-# INLINE detNotExpired' #-}
    detNotExpired' :: t -> [(a, (t, t, c))] -> [a] -> [a]
    detNotExpired' t
    _time [] [a]
    l = [a] -> [a]
    forall a. [a] -> [a]
    reverse [a]
    l
    detNotExpired'  t
    time ((a
    key, (t
    accesstime, t
    expirytime, c
    _value)) : [(a, (t, t, c))]
    r) [a]
    l
      | (t
    accesstime t -> t -> Bool
    forall a. Ord a => a -> a -> Bool
    <= t
    time) Bool -> Bool -> Bool
    && (t
    accesstime t -> t -> Bool
    forall a. Ord a => a -> a -> Bool
    > (t
    time t -> t -> t
    forall a. Num a => a -> a -> a
    - t
    expirytime)) =
            t -> [(a, (t, t, c))] -> [a] -> [a]
    detNotExpired' t
    time [(a, (t, t, c))]
    r (a
    keya -> [a] -> [a]
    forall a. a -> [a] -> [a]
    :[a]
    l)
      | Bool
    otherwise =
            t -> [(a, (t, t, c))] -> [a] -> [a]
    detNotExpired' t
    time [(a, (t, t, c))]
    r [a]
    l

    -- | Debugging function

    --

    getStatsString :: ECM m b s m k v -> m String
    getStatsString ECM m b s m k v
    ecm = do
      CacheState (_retr_state, _maps, _mapsize, uses, _incr) <- ECMReadState m b s m k v
    ro b (CacheState s m k v)
    m'uses
      return $ show uses
      where
        ECM ( b (CacheState s m k v)
    m'uses, Maybe s -> k -> m (ECMULength, (Maybe s, v))
    _retr, m ECMULength
    _gettime, ECMULength
    _minimumkeep, ECMIncr
    _timecheckmodulo, ECMULength
    _removalsize,
              ECMULength
    _compactlistsize, ECMEnterState m b s m k v
    _enter, ECMReadState m b s m k v
    ro ) = ECM m b s m k v
    ecm