    {-# OPTIONS_GHC -fno-warn-type-defaults #-}
    module System.Clock.Seconds
      ( Clock(..)
      , Seconds(..)
      , getTime
      , getRes
      , fromNanoSecs
      , toNanoSecs
      , diffTimeSpec
      ) where

    import Data.Coerce
    import Data.Ratio
    import Data.Typeable (Typeable)
    import Foreign.Storable
    import GHC.Generics (Generic)

    import System.Clock(TimeSpec(..), Clock, s2ns, normalize)
    import qualified System.Clock as C

    newtype Seconds = Seconds { Seconds -> TimeSpec
    toTimeSpec :: TimeSpec }
     deriving ((forall x. Seconds -> Rep Seconds x)
    -> (forall x. Rep Seconds x -> Seconds) -> Generic Seconds
    forall x. Rep Seconds x -> Seconds
    forall x. Seconds -> Rep Seconds x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. Seconds -> Rep Seconds x
    from :: forall x. Seconds -> Rep Seconds x
    $cto :: forall x. Rep Seconds x -> Seconds
    to :: forall x. Rep Seconds x -> Seconds
    Generic, ReadPrec [Seconds]
    ReadPrec Seconds
    Int -> ReadS Seconds
    ReadS [Seconds]
    (Int -> ReadS Seconds)
    -> ReadS [Seconds]
    -> ReadPrec Seconds
    -> ReadPrec [Seconds]
    -> Read Seconds
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    $creadsPrec :: Int -> ReadS Seconds
    readsPrec :: Int -> ReadS Seconds
    $creadList :: ReadS [Seconds]
    readList :: ReadS [Seconds]
    $creadPrec :: ReadPrec Seconds
    readPrec :: ReadPrec Seconds
    $creadListPrec :: ReadPrec [Seconds]
    readListPrec :: ReadPrec [Seconds]
    Read, Int -> Seconds -> ShowS
    [Seconds] -> ShowS
    Seconds -> String
    (Int -> Seconds -> ShowS)
    -> (Seconds -> String) -> ([Seconds] -> ShowS) -> Show Seconds
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Seconds -> ShowS
    showsPrec :: Int -> Seconds -> ShowS
    $cshow :: Seconds -> String
    show :: Seconds -> String
    $cshowList :: [Seconds] -> ShowS
    showList :: [Seconds] -> ShowS
    Show, Typeable, Seconds -> Seconds -> Bool
    (Seconds -> Seconds -> Bool)
    -> (Seconds -> Seconds -> Bool) -> Eq Seconds
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Seconds -> Seconds -> Bool
    == :: Seconds -> Seconds -> Bool
    $c/= :: Seconds -> Seconds -> Bool
    /= :: Seconds -> Seconds -> Bool
    Eq, Eq Seconds
    Eq Seconds =>
    (Seconds -> Seconds -> Ordering)
    -> (Seconds -> Seconds -> Bool)
    -> (Seconds -> Seconds -> Bool)
    -> (Seconds -> Seconds -> Bool)
    -> (Seconds -> Seconds -> Bool)
    -> (Seconds -> Seconds -> Seconds)
    -> (Seconds -> Seconds -> Seconds)
    -> Ord Seconds
    Seconds -> Seconds -> Bool
    Seconds -> Seconds -> Ordering
    Seconds -> Seconds -> Seconds
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: Seconds -> Seconds -> Ordering
    compare :: Seconds -> Seconds -> Ordering
    $c< :: Seconds -> Seconds -> Bool
    < :: Seconds -> Seconds -> Bool
    $c<= :: Seconds -> Seconds -> Bool
    <= :: Seconds -> Seconds -> Bool
    $c> :: Seconds -> Seconds -> Bool
    > :: Seconds -> Seconds -> Bool
    $c>= :: Seconds -> Seconds -> Bool
    >= :: Seconds -> Seconds -> Bool
    $cmax :: Seconds -> Seconds -> Seconds
    max :: Seconds -> Seconds -> Seconds
    $cmin :: Seconds -> Seconds -> Seconds
    min :: Seconds -> Seconds -> Seconds
    Ord, Ptr Seconds -> IO Seconds
    Ptr Seconds -> Int -> IO Seconds
    Ptr Seconds -> Int -> Seconds -> IO ()
    Ptr Seconds -> Seconds -> IO ()
    Seconds -> Int
    (Seconds -> Int)
    -> (Seconds -> Int)
    -> (Ptr Seconds -> Int -> IO Seconds)
    -> (Ptr Seconds -> Int -> Seconds -> IO ())
    -> (forall b. Ptr b -> Int -> IO Seconds)
    -> (forall b. Ptr b -> Int -> Seconds -> IO ())
    -> (Ptr Seconds -> IO Seconds)
    -> (Ptr Seconds -> Seconds -> IO ())
    -> Storable Seconds
    forall b. Ptr b -> Int -> IO Seconds
    forall b. Ptr b -> Int -> Seconds -> IO ()
    forall a.
    (a -> Int)
    -> (a -> Int)
    -> (Ptr a -> Int -> IO a)
    -> (Ptr a -> Int -> a -> IO ())
    -> (forall b. Ptr b -> Int -> IO a)
    -> (forall b. Ptr b -> Int -> a -> IO ())
    -> (Ptr a -> IO a)
    -> (Ptr a -> a -> IO ())
    -> Storable a
    $csizeOf :: Seconds -> Int
    sizeOf :: Seconds -> Int
    $calignment :: Seconds -> Int
    alignment :: Seconds -> Int
    $cpeekElemOff :: Ptr Seconds -> Int -> IO Seconds
    peekElemOff :: Ptr Seconds -> Int -> IO Seconds
    $cpokeElemOff :: Ptr Seconds -> Int -> Seconds -> IO ()
    pokeElemOff :: Ptr Seconds -> Int -> Seconds -> IO ()
    $cpeekByteOff :: forall b. Ptr b -> Int -> IO Seconds
    peekByteOff :: forall b. Ptr b -> Int -> IO Seconds
    $cpokeByteOff :: forall b. Ptr b -> Int -> Seconds -> IO ()
    pokeByteOff :: forall b. Ptr b -> Int -> Seconds -> IO ()
    $cpeek :: Ptr Seconds -> IO Seconds
    peek :: Ptr Seconds -> IO Seconds
    $cpoke :: Ptr Seconds -> Seconds -> IO ()
    poke :: Ptr Seconds -> Seconds -> IO ()
    Storable, Seconds
    Seconds -> Seconds -> Bounded Seconds
    forall a. a -> a -> Bounded a
    $cminBound :: Seconds
    minBound :: Seconds
    $cmaxBound :: Seconds
    maxBound :: Seconds
    Bounded)

    instance Num Seconds where
      fromInteger :: Integer -> Seconds
    fromInteger Integer
    n = TimeSpec -> Seconds
    Seconds (TimeSpec -> Seconds) -> TimeSpec -> Seconds
    forall a b. (a -> b) -> a -> b
    $ Int64 -> Int64 -> TimeSpec
    TimeSpec (Integer -> Int64
    forall a. Num a => Integer -> a
    fromInteger Integer
    n) Int64
    0
      Seconds (TimeSpec Int64
    xs Int64
    xn) * :: Seconds -> Seconds -> Seconds
    * Seconds (TimeSpec Int64
    ys Int64
    yn) =
        TimeSpec -> Seconds
    Seconds (TimeSpec -> Seconds) -> TimeSpec -> Seconds
    forall a b. (a -> b) -> a -> b
    $ TimeSpec -> TimeSpec
    normalize (TimeSpec -> TimeSpec) -> TimeSpec -> TimeSpec
    forall a b. (a -> b) -> a -> b
    $! Int64 -> Int64 -> TimeSpec
    TimeSpec (Int64
    xsInt64 -> Int64 -> Int64
    forall a. Num a => a -> a -> a
    *Int64
    ys) (Int64
    xsInt64 -> Int64 -> Int64
    forall a. Num a => a -> a -> a
    *Int64
    ynInt64 -> Int64 -> Int64
    forall a. Num a => a -> a -> a
    +Int64
    xnInt64 -> Int64 -> Int64
    forall a. Num a => a -> a -> a
    *Int64
    ysInt64 -> Int64 -> Int64
    forall a. Num a => a -> a -> a
    +((Int64
    xnInt64 -> Int64 -> Int64
    forall a. Num a => a -> a -> a
    *Int64
    yn) Int64 -> Int64 -> Int64
    forall a. Integral a => a -> a -> a
    `div` Int64
    forall a. Num a => a
    s2ns))
      + :: Seconds -> Seconds -> Seconds
    (+) = (TimeSpec -> TimeSpec -> TimeSpec) -> Seconds -> Seconds -> Seconds
    forall a b. Coercible a b => a -> b
    coerce (TimeSpec -> TimeSpec -> TimeSpec
    forall a. Num a => a -> a -> a
    (+) :: TimeSpec -> TimeSpec -> TimeSpec)
      (-) = (TimeSpec -> TimeSpec -> TimeSpec) -> Seconds -> Seconds -> Seconds
    forall a b. Coercible a b => a -> b
    coerce ((-) :: TimeSpec -> TimeSpec -> TimeSpec)
      negate :: Seconds -> Seconds
    negate = (TimeSpec -> TimeSpec) -> Seconds -> Seconds
    forall a b. Coercible a b => a -> b
    coerce (TimeSpec -> TimeSpec
    forall a. Num a => a -> a
    negate :: TimeSpec -> TimeSpec)
      abs :: Seconds -> Seconds
    abs = (TimeSpec -> TimeSpec) -> Seconds -> Seconds
    forall a b. Coercible a b => a -> b
    coerce (TimeSpec -> TimeSpec
    forall a. Num a => a -> a
    abs :: TimeSpec -> TimeSpec)
      signum :: Seconds -> Seconds
    signum (Seconds TimeSpec
    a) = case TimeSpec -> TimeSpec
    forall a. Num a => a -> a
    signum TimeSpec
    a of
        TimeSpec
    1 -> Seconds
    1
        (-1) -> (-Seconds
    1)
        TimeSpec
    _ -> Seconds
    0

    instance Enum Seconds where
      succ :: Seconds -> Seconds
    succ Seconds
    x = Seconds
    x Seconds -> Seconds -> Seconds
    forall a. Num a => a -> a -> a
    + Seconds
    1
      pred :: Seconds -> Seconds
    pred Seconds
    x = Seconds
    x Seconds -> Seconds -> Seconds
    forall a. Num a => a -> a -> a
    - Seconds
    1
      toEnum :: Int -> Seconds
    toEnum Int
    x = TimeSpec -> Seconds
    Seconds (TimeSpec -> Seconds) -> TimeSpec -> Seconds
    forall a b. (a -> b) -> a -> b
    $ Int64 -> Int64 -> TimeSpec
    TimeSpec (Int -> Int64
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    x) Int64
    0
      fromEnum :: Seconds -> Int
    fromEnum (Seconds (TimeSpec Int64
    s Int64
    _)) = Int64 -> Int
    forall a. Enum a => a -> Int
    fromEnum Int64
    s

    instance Real Seconds where
      toRational :: Seconds -> Rational
    toRational (Seconds TimeSpec
    x) = TimeSpec -> Integer
    forall a. Integral a => a -> Integer
    toInteger TimeSpec
    x Integer -> Integer -> Rational
    forall a. Integral a => a -> a -> Ratio a
    % Integer
    forall a. Num a => a
    s2ns

    instance Fractional Seconds where
      fromRational :: Rational -> Seconds
    fromRational Rational
    x = TimeSpec -> Seconds
    Seconds (TimeSpec -> Seconds)
    -> (Integer -> TimeSpec) -> Integer -> Seconds
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Integer -> TimeSpec
    forall a. Num a => Integer -> a
    fromInteger (Integer -> Seconds) -> Integer -> Seconds
    forall a b. (a -> b) -> a -> b
    $ Rational -> Integer
    forall b. Integral b => Rational -> b
    forall a b. (RealFrac a, Integral b) => a -> b
    floor (Rational
    x Rational -> Rational -> Rational
    forall a. Num a => a -> a -> a
    * Rational
    forall a. Num a => a
    s2ns)
      Seconds TimeSpec
    a / :: Seconds -> Seconds -> Seconds
    / Seconds TimeSpec
    b = TimeSpec -> Seconds
    Seconds (TimeSpec -> Seconds) -> TimeSpec -> Seconds
    forall a b. (a -> b) -> a -> b
    $ TimeSpec
    a TimeSpec -> TimeSpec -> TimeSpec
    forall a. Num a => a -> a -> a
    * TimeSpec
    forall a. Num a => a
    s2ns TimeSpec -> TimeSpec -> TimeSpec
    forall a. Integral a => a -> a -> a
    `div` TimeSpec
    b
      recip :: Seconds -> Seconds
    recip (Seconds TimeSpec
    a) = TimeSpec -> Seconds
    Seconds (TimeSpec -> Seconds) -> TimeSpec -> Seconds
    forall a b. (a -> b) -> a -> b
    $ TimeSpec
    forall a. Num a => a
    s2ns TimeSpec -> TimeSpec -> TimeSpec
    forall a. Num a => a -> a -> a
    * TimeSpec
    forall a. Num a => a
    s2ns TimeSpec -> TimeSpec -> TimeSpec
    forall a. Integral a => a -> a -> a
    `div` TimeSpec
    a

    instance RealFrac Seconds where
      properFraction :: forall b. Integral b => Seconds -> (b, Seconds)
    properFraction (Seconds (TimeSpec Int64
    s Int64
    ns))
        | Int64
    s Int64 -> Int64 -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int64
    0 = (Int64 -> b
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int64
    s, TimeSpec -> Seconds
    Seconds (TimeSpec -> Seconds) -> TimeSpec -> Seconds
    forall a b. (a -> b) -> a -> b
    $ Int64 -> Int64 -> TimeSpec
    TimeSpec Int64
    0 Int64
    ns)
        | Bool
    otherwise = (Int64 -> b
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Int64
    sInt64 -> Int64 -> Int64
    forall a. Num a => a -> a -> a
    +Int64
    1), TimeSpec -> Seconds
    Seconds (TimeSpec -> Seconds) -> TimeSpec -> Seconds
    forall a b. (a -> b) -> a -> b
    $ Int64 -> Int64 -> TimeSpec
    TimeSpec (-Int64
    1) Int64
    ns)

    -- | The 'getTime' function shall return the current value for the
    --   specified clock.
    getTime :: Clock -> IO Seconds
    getTime :: Clock -> IO Seconds
    getTime = (Clock -> IO TimeSpec) -> Clock -> IO Seconds
    forall a b. Coercible a b => a -> b
    coerce Clock -> IO TimeSpec
    C.getTime

    -- | The 'getRes' function shall return the resolution of any clock.
    --   Clock resolutions are implementation-defined and cannot be set
    --   by a process.
    getRes :: Clock -> IO Seconds
    getRes :: Clock -> IO Seconds
    getRes = (Clock -> IO TimeSpec) -> Clock -> IO Seconds
    forall a b. Coercible a b => a -> b
    coerce Clock -> IO TimeSpec
    C.getRes

    -- | Seconds from nano seconds.
    fromNanoSecs :: Integer -> Seconds
    fromNanoSecs :: Integer -> Seconds
    fromNanoSecs = (Integer -> TimeSpec) -> Integer -> Seconds
    forall a b. Coercible a b => a -> b
    coerce Integer -> TimeSpec
    C.fromNanoSecs

    -- | Seconds to nano seconds.
    toNanoSecs :: Seconds -> Integer
    toNanoSecs :: Seconds -> Integer
    toNanoSecs = (TimeSpec -> Integer) -> Seconds -> Integer
    forall a b. Coercible a b => a -> b
    coerce TimeSpec -> Integer
    C.toNanoSecs

    -- | Compute the absolute difference.
    diffTimeSpec :: Seconds -> Seconds -> Seconds
    diffTimeSpec :: Seconds -> Seconds -> Seconds
    diffTimeSpec = (TimeSpec -> TimeSpec -> TimeSpec) -> Seconds -> Seconds -> Seconds
    forall a b. Coercible a b => a -> b
    coerce TimeSpec -> TimeSpec -> TimeSpec
    C.diffTimeSpec