    -- | This module defines a type for mutable, integer-valued counters.
    -- Counters are non-negative, monotonically increasing values and can
    -- be used to track e.g. the number of requests served since program
    -- start.  All operations on counters are thread-safe.
    module System.Metrics.Counter
        (
          Counter
        , new
        , read
        , inc
        , add
        ) where

    import qualified Data.Atomic as Atomic
    import Data.Int (Int64)
    import Prelude hiding (read)

    -- | A mutable, integer-valued counter.
    newtype Counter = C { Counter -> Atomic
    unC :: Atomic.Atomic }

    -- | Create a new, zero initialized, counter.
    new :: IO Counter
    new :: IO Counter
    new = Atomic -> Counter
    C (Atomic -> Counter) -> IO Atomic -> IO Counter
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    `fmap` Int64 -> IO Atomic
    Atomic.new 0

    -- | Get the current value of the counter.
    read :: Counter -> IO Int64
    read :: Counter -> IO Int64
    read = Atomic -> IO Int64
    Atomic.read (Atomic -> IO Int64) -> (Counter -> Atomic) -> Counter -> IO Int64
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Counter -> Atomic
    unC

    -- | Increase the counter by one.
    inc :: Counter -> IO ()
    inc :: Counter -> IO ()
    inc counter :: Counter
    counter = Counter -> Int64 -> IO ()
    add Counter
    counter 1

    -- | Add the argument to the counter.
    add :: Counter -> Int64 -> IO ()
    add :: Counter -> Int64 -> IO ()
    add counter :: Counter
    counter = Atomic -> Int64 -> IO ()
    Atomic.add (Counter -> Atomic
    unC Counter
    counter)