    module Network.Control.Rate (
        -- * Rate control
        Rate,
        newRate,
        getRate,
        addRate,
    ) where

    import Data.IORef
    import Data.UnixTime

    -- | Type for rating.
    newtype Rate = Rate (IORef Counter)

    data Counter = Counter Int UnixTime

    -- | Creating a new 'Rate'.
    newRate :: IO Rate
    newRate :: IO Rate
    newRate = do
        cntr <- Int -> UnixTime -> Counter
    Counter Int
    0 (UnixTime -> Counter) -> IO UnixTime -> IO Counter
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> IO UnixTime
    getUnixTime
        Rate <$> newIORef cntr

    -- | Getting the current rate.
    -- If one or more seconds have passed since the previous call, the
    -- counter is re-initialized with 1 and it is returned.  Otherwise,
    -- incremented counter number is returned.
    getRate :: Rate -> IO Int
    getRate :: Rate -> IO Int
    getRate Rate
    r = Rate -> Int -> IO Int
    addRate Rate
    r Int
    1

    -- | Getting the current rate.
    -- If one or more seconds have passed since the previous call, the
    -- counter is re-initialized with the second argument and it is
    -- returned.  Otherwise, increased counter number is returned.
    addRate :: Rate -> Int -> IO Int
    addRate :: Rate -> Int -> IO Int
    addRate (Rate IORef Counter
    ref) Int
    x = do
        Counter n beg <- IORef Counter -> IO Counter
    forall a. IORef a -> IO a
    readIORef IORef Counter
    ref
        cur <- getUnixTime
        if (cur `diffUnixTime` beg) > 1
            then do
                let n' = Int
    x
                writeIORef ref $ Counter n' cur
                return n'
            else do
                let n' = Int
    n Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    x
                writeIORef ref $ Counter n' beg
                return n'