{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE ExplicitForAll #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE NoStarIsType #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Time.Units
(
Time (..)
, Second
, Millisecond
, Microsecond
, Nanosecond
, Picosecond
, Minute
, Hour
, Day
, Week
, Fortnight
, UnitName
, KnownUnitName
, KnownRatName
, unitNameVal
, time
, floorUnit
, floorRat
, ceilingUnit
, ceilingRat
, toFractional
, sec
, ms
, mcs
, ns
, ps
, minute
, hour
, day
, week
, fortnight
, toUnit
, threadDelay
, getCPUTime
, timeout
) where
import Control.Monad (unless)
import Control.Monad.IO.Class (MonadIO, liftIO)
import Data.Char (isDigit, isLetter)
import Data.Coerce (coerce)
import Data.Data (Data)
#if !(MIN_VERSION_base(4,20,0))
import Data.Foldable (foldl')
#endif
import Data.Proxy (Proxy (..))
import Data.Semigroup (Semigroup (..))
import GHC.Generics (Generic)
import GHC.Natural (Natural)
import GHC.Read (Read (readPrec))
import GHC.Real (denominator, numerator, (%))
import GHC.TypeLits (KnownSymbol, Symbol, symbolVal)
import Text.ParserCombinators.ReadP (ReadP, char, munch1, option, pfail, (+++))
import Text.ParserCombinators.ReadPrec (ReadPrec, lift)
#ifdef HAS_aeson
import Data.Aeson (FromJSON (..), ToJSON (..), withText)
import qualified Data.Text as Text
import Text.Read (readMaybe)
#endif
import Time.Rational (KnownDivRat, KnownRat, Rat, RatioNat, ratVal, type (*), type (/), type (:%))
import qualified Control.Concurrent as Concurrent
import qualified System.CPUTime as CPUTime
import qualified System.Timeout as Timeout
type Second = 1 / 1
type Millisecond = Second / 1000
type Microsecond = Millisecond / 1000
type Nanosecond = Microsecond / 1000
type Picosecond = Nanosecond / 1000
type Minute = 60 * Second
type Hour = 60 * Minute
type Day = 24 * Hour
type Week = 7 * Day
type Fortnight = 2 * Week
newtype Time (rat :: Rat) = Time { forall (rat :: Rat). Time rat -> RatioNat
unTime :: RatioNat }
deriving (Time rat -> Time rat -> Bool
(Time rat -> Time rat -> Bool)
-> (Time rat -> Time rat -> Bool) -> Eq (Time rat)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall (rat :: Rat). Time rat -> Time rat -> Bool
$c== :: forall (rat :: Rat). Time rat -> Time rat -> Bool
== :: Time rat -> Time rat -> Bool
$c/= :: forall (rat :: Rat). Time rat -> Time rat -> Bool
/= :: Time rat -> Time rat -> Bool
Eq, Eq (Time rat)
Eq (Time rat) =>
(Time rat -> Time rat -> Ordering)
-> (Time rat -> Time rat -> Bool)
-> (Time rat -> Time rat -> Bool)
-> (Time rat -> Time rat -> Bool)
-> (Time rat -> Time rat -> Bool)
-> (Time rat -> Time rat -> Time rat)
-> (Time rat -> Time rat -> Time rat)
-> Ord (Time rat)
Time rat -> Time rat -> Bool
Time rat -> Time rat -> Ordering
Time rat -> Time rat -> Time rat
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
forall (rat :: Rat). Eq (Time rat)
forall (rat :: Rat). Time rat -> Time rat -> Bool
forall (rat :: Rat). Time rat -> Time rat -> Ordering
forall (rat :: Rat). Time rat -> Time rat -> Time rat
$ccompare :: forall (rat :: Rat). Time rat -> Time rat -> Ordering
compare :: Time rat -> Time rat -> Ordering
$c< :: forall (rat :: Rat). Time rat -> Time rat -> Bool
< :: Time rat -> Time rat -> Bool
$c<= :: forall (rat :: Rat). Time rat -> Time rat -> Bool
<= :: Time rat -> Time rat -> Bool
$c> :: forall (rat :: Rat). Time rat -> Time rat -> Bool
> :: Time rat -> Time rat -> Bool
$c>= :: forall (rat :: Rat). Time rat -> Time rat -> Bool
>= :: Time rat -> Time rat -> Bool
$cmax :: forall (rat :: Rat). Time rat -> Time rat -> Time rat
max :: Time rat -> Time rat -> Time rat
$cmin :: forall (rat :: Rat). Time rat -> Time rat -> Time rat
min :: Time rat -> Time rat -> Time rat
Ord, Int -> Time rat
Time rat -> Int
Time rat -> [Time rat]
Time rat -> Time rat
Time rat -> Time rat -> [Time rat]
Time rat -> Time rat -> Time rat -> [Time rat]
(Time rat -> Time rat)
-> (Time rat -> Time rat)
-> (Int -> Time rat)
-> (Time rat -> Int)
-> (Time rat -> [Time rat])
-> (Time rat -> Time rat -> [Time rat])
-> (Time rat -> Time rat -> [Time rat])
-> (Time rat -> Time rat -> Time rat -> [Time rat])
-> Enum (Time rat)
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
forall (rat :: Rat). Int -> Time rat
forall (rat :: Rat). Time rat -> Int
forall (rat :: Rat). Time rat -> [Time rat]
forall (rat :: Rat). Time rat -> Time rat
forall (rat :: Rat). Time rat -> Time rat -> [Time rat]
forall (rat :: Rat). Time rat -> Time rat -> Time rat -> [Time rat]
$csucc :: forall (rat :: Rat). Time rat -> Time rat
succ :: Time rat -> Time rat
$cpred :: forall (rat :: Rat). Time rat -> Time rat
pred :: Time rat -> Time rat
$ctoEnum :: forall (rat :: Rat). Int -> Time rat
toEnum :: Int -> Time rat
$cfromEnum :: forall (rat :: Rat). Time rat -> Int
fromEnum :: Time rat -> Int
$cenumFrom :: forall (rat :: Rat). Time rat -> [Time rat]
enumFrom :: Time rat -> [Time rat]
$cenumFromThen :: forall (rat :: Rat). Time rat -> Time rat -> [Time rat]
enumFromThen :: Time rat -> Time rat -> [Time rat]
$cenumFromTo :: forall (rat :: Rat). Time rat -> Time rat -> [Time rat]
enumFromTo :: Time rat -> Time rat -> [Time rat]
$cenumFromThenTo :: forall (rat :: Rat). Time rat -> Time rat -> Time rat -> [Time rat]
enumFromThenTo :: Time rat -> Time rat -> Time rat -> [Time rat]
Enum, (forall x. Time rat -> Rep (Time rat) x)
-> (forall x. Rep (Time rat) x -> Time rat) -> Generic (Time rat)
forall x. Rep (Time rat) x -> Time rat
forall x. Time rat -> Rep (Time rat) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (rat :: Rat) x. Rep (Time rat) x -> Time rat
forall (rat :: Rat) x. Time rat -> Rep (Time rat) x
$cfrom :: forall (rat :: Rat) x. Time rat -> Rep (Time rat) x
from :: forall x. Time rat -> Rep (Time rat) x
$cto :: forall (rat :: Rat) x. Rep (Time rat) x -> Time rat
to :: forall x. Rep (Time rat) x -> Time rat
Generic, Typeable (Time rat)
Typeable (Time rat) =>
(forall (c :: Type -> Type).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Time rat -> c (Time rat))
-> (forall (c :: Type -> Type).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Time rat))
-> (Time rat -> Constr)
-> (Time rat -> DataType)
-> (forall (t :: Type -> Type) (c :: Type -> Type).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c (Time rat)))
-> (forall (t :: Type -> Type -> Type) (c :: Type -> Type).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c (Time rat)))
-> ((forall b. Data b => b -> b) -> Time rat -> Time rat)
-> (forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Time rat -> r)
-> (forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Time rat -> r)
-> (forall u. (forall d. Data d => d -> u) -> Time rat -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> Time rat -> u)
-> (forall (m :: Type -> Type).
Monad m =>
(forall d. Data d => d -> m d) -> Time rat -> m (Time rat))
-> (forall (m :: Type -> Type).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Time rat -> m (Time rat))
-> (forall (m :: Type -> Type).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Time rat -> m (Time rat))
-> Data (Time rat)
Time rat -> Constr
Time rat -> DataType
(forall b. Data b => b -> b) -> Time rat -> Time rat
forall a.
Typeable a =>
(forall (c :: Type -> Type).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: Type -> Type).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: Type -> Type) (c :: Type -> Type).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: Type -> Type -> Type) (c :: Type -> Type).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: Type -> Type).
Monad m =>
(forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: Type -> Type).
MonadPlus m =>
(forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: Type -> Type).
MonadPlus m =>
(forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> Time rat -> u
forall u. (forall d. Data d => d -> u) -> Time rat -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Time rat -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Time rat -> r
forall (rat :: Rat). Typeable rat => Typeable (Time rat)
forall (rat :: Rat). Typeable rat => Time rat -> Constr
forall (rat :: Rat). Typeable rat => Time rat -> DataType
forall (rat :: Rat).
Typeable rat =>
(forall b. Data b => b -> b) -> Time rat -> Time rat
forall (rat :: Rat) u.
Typeable rat =>
Int -> (forall d. Data d => d -> u) -> Time rat -> u
forall (rat :: Rat) u.
Typeable rat =>
(forall d. Data d => d -> u) -> Time rat -> [u]
forall (rat :: Rat) r r'.
Typeable rat =>
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Time rat -> r
forall (rat :: Rat) r r'.
Typeable rat =>
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Time rat -> r
forall (rat :: Rat) (m :: Type -> Type).
(Typeable rat, Monad m) =>
(forall d. Data d => d -> m d) -> Time rat -> m (Time rat)
forall (rat :: Rat) (m :: Type -> Type).
(Typeable rat, MonadPlus m) =>
(forall d. Data d => d -> m d) -> Time rat -> m (Time rat)
forall (rat :: Rat) (c :: Type -> Type).
Typeable rat =>
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Time rat)
forall (rat :: Rat) (c :: Type -> Type).
Typeable rat =>
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Time rat -> c (Time rat)
forall (rat :: Rat) (t :: Type -> Type) (c :: Type -> Type).
(Typeable rat, Typeable t) =>
(forall d. Data d => c (t d)) -> Maybe (c (Time rat))
forall (rat :: Rat) (t :: Type -> Type -> Type)
(c :: Type -> Type).
(Typeable rat, Typeable t) =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Time rat))
forall (m :: Type -> Type).
Monad m =>
(forall d. Data d => d -> m d) -> Time rat -> m (Time rat)
forall (m :: Type -> Type).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Time rat -> m (Time rat)
forall (c :: Type -> Type).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Time rat)
forall (c :: Type -> Type).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Time rat -> c (Time rat)
forall (t :: Type -> Type) (c :: Type -> Type).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c (Time rat))
forall (t :: Type -> Type -> Type) (c :: Type -> Type).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Time rat))
$cgfoldl :: forall (rat :: Rat) (c :: Type -> Type).
Typeable rat =>
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Time rat -> c (Time rat)
gfoldl :: forall (c :: Type -> Type).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Time rat -> c (Time rat)
$cgunfold :: forall (rat :: Rat) (c :: Type -> Type).
Typeable rat =>
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Time rat)
gunfold :: forall (c :: Type -> Type).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Time rat)
$ctoConstr :: forall (rat :: Rat). Typeable rat => Time rat -> Constr
toConstr :: Time rat -> Constr
$cdataTypeOf :: forall (rat :: Rat). Typeable rat => Time rat -> DataType
dataTypeOf :: Time rat -> DataType
$cdataCast1 :: forall (rat :: Rat) (t :: Type -> Type) (c :: Type -> Type).
(Typeable rat, Typeable t) =>
(forall d. Data d => c (t d)) -> Maybe (c (Time rat))
dataCast1 :: forall (t :: Type -> Type) (c :: Type -> Type).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c (Time rat))
$cdataCast2 :: forall (rat :: Rat) (t :: Type -> Type -> Type)
(c :: Type -> Type).
(Typeable rat, Typeable t) =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Time rat))
dataCast2 :: forall (t :: Type -> Type -> Type) (c :: Type -> Type).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Time rat))
$cgmapT :: forall (rat :: Rat).
Typeable rat =>
(forall b. Data b => b -> b) -> Time rat -> Time rat
gmapT :: (forall b. Data b => b -> b) -> Time rat -> Time rat
$cgmapQl :: forall (rat :: Rat) r r'.
Typeable rat =>
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Time rat -> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Time rat -> r
$cgmapQr :: forall (rat :: Rat) r r'.
Typeable rat =>
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Time rat -> r
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Time rat -> r
$cgmapQ :: forall (rat :: Rat) u.
Typeable rat =>
(forall d. Data d => d -> u) -> Time rat -> [u]
gmapQ :: forall u. (forall d. Data d => d -> u) -> Time rat -> [u]
$cgmapQi :: forall (rat :: Rat) u.
Typeable rat =>
Int -> (forall d. Data d => d -> u) -> Time rat -> u
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Time rat -> u
$cgmapM :: forall (rat :: Rat) (m :: Type -> Type).
(Typeable rat, Monad m) =>
(forall d. Data d => d -> m d) -> Time rat -> m (Time rat)
gmapM :: forall (m :: Type -> Type).
Monad m =>
(forall d. Data d => d -> m d) -> Time rat -> m (Time rat)
$cgmapMp :: forall (rat :: Rat) (m :: Type -> Type).
(Typeable rat, MonadPlus m) =>
(forall d. Data d => d -> m d) -> Time rat -> m (Time rat)
gmapMp :: forall (m :: Type -> Type).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Time rat -> m (Time rat)
$cgmapMo :: forall (rat :: Rat) (m :: Type -> Type).
(Typeable rat, MonadPlus m) =>
(forall d. Data d => d -> m d) -> Time rat -> m (Time rat)
gmapMo :: forall (m :: Type -> Type).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Time rat -> m (Time rat)
Data)
instance Semigroup (Time (rat :: Rat)) where
<> :: Time rat -> Time rat -> Time rat
(<>) = (RatioNat -> RatioNat -> RatioNat)
-> Time rat -> Time rat -> Time rat
forall a b. Coercible a b => a -> b
coerce (RatioNat -> RatioNat -> RatioNat
forall a. Num a => a -> a -> a
(+) :: RatioNat -> RatioNat -> RatioNat)
{-# INLINE (<>) #-}
sconcat :: NonEmpty (Time rat) -> Time rat
sconcat = (Time rat -> Time rat -> Time rat)
-> Time rat -> NonEmpty (Time rat) -> Time rat
forall b a. (b -> a -> b) -> b -> NonEmpty a -> b
forall (t :: Type -> Type) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Time rat -> Time rat -> Time rat
forall a. Semigroup a => a -> a -> a
(<>) Time rat
forall a. Monoid a => a
mempty
{-# INLINE sconcat #-}
stimes :: forall b. Integral b => b -> Time rat -> Time rat
stimes b
n (Time RatioNat
t) = RatioNat -> Time rat
forall (rat :: Rat). RatioNat -> Time rat
Time (b -> RatioNat
forall a b. (Integral a, Num b) => a -> b
fromIntegral b
n RatioNat -> RatioNat -> RatioNat
forall a. Num a => a -> a -> a
* RatioNat
t)
{-# INLINE stimes #-}
instance Monoid (Time (rat :: Rat)) where
mempty :: Time rat
mempty = RatioNat -> Time rat
forall (rat :: Rat). RatioNat -> Time rat
Time RatioNat
0
{-# INLINE mempty #-}
mappend :: Time rat -> Time rat -> Time rat
mappend = Time rat -> Time rat -> Time rat
forall a. Semigroup a => a -> a -> a
(<>)
{-# INLINE mappend #-}
mconcat :: [Time rat] -> Time rat
mconcat = (Time rat -> Time rat -> Time rat)
-> Time rat -> [Time rat] -> Time rat
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: Type -> Type) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Time rat -> Time rat -> Time rat
forall a. Semigroup a => a -> a -> a
(<>) Time rat
forall a. Monoid a => a
mempty
{-# INLINE mconcat #-}
#ifdef HAS_aeson
instance (KnownUnitName unit) => ToJSON (Time (unit :: Rat)) where
toJSON = toJSON . show
instance (KnownUnitName unit) => FromJSON (Time (unit :: Rat)) where
parseJSON = withText "time" $ maybe parseFail pure . maybeTime
where
parseFail = fail $ "Can not parse Time. Expected unit: " ++ unitNameVal @unit
maybeTime = readMaybe @(Time unit) . Text.unpack
#endif
type family UnitName (unit :: Rat) :: Symbol
type instance UnitName (1 :% 1) = "s"
type instance UnitName (1 :% 1000) = "ms"
type instance UnitName (1 :% 1000000) = "mcs"
type instance UnitName (1 :% 1000000000) = "ns"
type instance UnitName (1 :% 1000000000000) = "ps"
type instance UnitName (60 :% 1) = "m"
type instance UnitName (3600 :% 1) = "h"
type instance UnitName (86400 :% 1) = "d"
type instance UnitName (604800 :% 1) = "w"
type instance UnitName (1209600 :% 1) = "fn"
type KnownUnitName unit = KnownSymbol (UnitName unit)
type KnownRatName unit = (KnownUnitName unit, KnownRat unit)
unitNameVal :: forall (unit :: Rat) . (KnownUnitName unit) => String
unitNameVal :: forall (unit :: Rat). KnownUnitName unit => String
unitNameVal = Proxy (UnitName unit) -> String
forall (n :: Symbol) (proxy :: Symbol -> Type).
KnownSymbol n =>
proxy n -> String
symbolVal (forall {k} (t :: k). Proxy t
forall (t :: Symbol). Proxy t
Proxy @(UnitName unit))
instance KnownUnitName unit => Show (Time unit) where
showsPrec :: Int -> Time unit -> ShowS
showsPrec Int
p (Time RatioNat
t) = Bool -> ShowS -> ShowS
showParen (Int
p Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
6)
(ShowS -> ShowS) -> ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$ RatioNat -> ShowS
forall {a}. (Integral a, Show a) => Ratio a -> ShowS
showsMixed RatioNat
t
ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString (forall (unit :: Rat). KnownUnitName unit => String
unitNameVal @unit)
where
showsMixed :: Ratio a -> ShowS
showsMixed Ratio a
0 = String -> ShowS
showString String
"0"
showsMixed Ratio a
rat =
let (a
n,a
d) = (Ratio a -> a
forall a. Ratio a -> a
numerator Ratio a
rat, Ratio a -> a
forall a. Ratio a -> a
denominator Ratio a
rat)
(a
q,a
r) = a
n a -> a -> (a, a)
forall a. Integral a => a -> a -> (a, a)
`quotRem` a
d
op :: String
op = if a
q a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 Bool -> Bool -> Bool
|| a
r a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 then String
"" else String
"+"
quotStr :: ShowS
quotStr = if a
q a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0
then ShowS
forall a. a -> a
id
else a -> ShowS
forall a. Show a => a -> ShowS
shows a
q
remStr :: ShowS
remStr = if a
r a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0
then ShowS
forall a. a -> a
id
else a -> ShowS
forall a. Show a => a -> ShowS
shows a
r
ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"/"
ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> ShowS
forall a. Show a => a -> ShowS
shows a
d
in
ShowS
quotStr ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
op ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS
remStr
instance KnownUnitName unit => Read (Time unit) where
readPrec :: ReadPrec (Time unit)
readPrec :: ReadPrec (Time unit)
readPrec = ReadP (Time unit) -> ReadPrec (Time unit)
forall a. ReadP a -> ReadPrec a
lift ReadP (Time unit)
readP
where
readP :: ReadP (Time unit)
readP :: ReadP (Time unit)
readP = do
let naturalP :: ReadP Natural
naturalP = String -> Natural
forall a. Read a => String -> a
read (String -> Natural) -> ReadP String -> ReadP Natural
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> (Char -> Bool) -> ReadP String
munch1 Char -> Bool
isDigit
let fullMixedExpr :: ReadP (Natural, Natural, Natural)
fullMixedExpr = (,,) (Natural -> Natural -> Natural -> (Natural, Natural, Natural))
-> ReadP Natural
-> ReadP (Natural -> Natural -> (Natural, Natural, Natural))
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> (ReadP Natural
naturalP ReadP Natural -> ReadP Char -> ReadP Natural
forall a b. ReadP a -> ReadP b -> ReadP a
forall (f :: Type -> Type) a b. Applicative f => f a -> f b -> f a
<* Char -> ReadP Char
char Char
'+')
ReadP (Natural -> Natural -> (Natural, Natural, Natural))
-> ReadP Natural -> ReadP (Natural -> (Natural, Natural, Natural))
forall a b. ReadP (a -> b) -> ReadP a -> ReadP b
forall (f :: Type -> Type) a b.
Applicative f =>
f (a -> b) -> f a -> f b
<*> (ReadP Natural
naturalP ReadP Natural -> ReadP Char -> ReadP Natural
forall a b. ReadP a -> ReadP b -> ReadP a
forall (f :: Type -> Type) a b. Applicative f => f a -> f b -> f a
<* Char -> ReadP Char
char Char
'/')
ReadP (Natural -> (Natural, Natural, Natural))
-> ReadP Natural -> ReadP (Natural, Natural, Natural)
forall a b. ReadP (a -> b) -> ReadP a -> ReadP b
forall (f :: Type -> Type) a b.
Applicative f =>
f (a -> b) -> f a -> f b
<*> ReadP Natural
naturalP
let improperExpr :: ReadP (Natural, Natural, Natural)
improperExpr = (,,) Natural
0 (Natural -> Natural -> (Natural, Natural, Natural))
-> ReadP Natural -> ReadP (Natural -> (Natural, Natural, Natural))
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadP Natural
naturalP
ReadP (Natural -> (Natural, Natural, Natural))
-> ReadP Natural -> ReadP (Natural, Natural, Natural)
forall a b. ReadP (a -> b) -> ReadP a -> ReadP b
forall (f :: Type -> Type) a b.
Applicative f =>
f (a -> b) -> f a -> f b
<*> Natural -> ReadP Natural -> ReadP Natural
forall a. a -> ReadP a -> ReadP a
option Natural
1 (Char -> ReadP Char
char Char
'/' ReadP Char -> ReadP Natural -> ReadP Natural
forall a b. ReadP a -> ReadP b -> ReadP b
forall (f :: Type -> Type) a b. Applicative f => f a -> f b -> f b
*> ReadP Natural
naturalP)
(Natural
q,Natural
r,Natural
d) <- ReadP (Natural, Natural, Natural)
fullMixedExpr ReadP (Natural, Natural, Natural)
-> ReadP (Natural, Natural, Natural)
-> ReadP (Natural, Natural, Natural)
forall a. ReadP a -> ReadP a -> ReadP a
+++ ReadP (Natural, Natural, Natural)
improperExpr
let n :: Natural
n = (Natural
q Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
* Natural
d Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
+ Natural
r)
String
timeUnitStr <- (Char -> Bool) -> ReadP String
munch1 Char -> Bool
isLetter
Bool -> ReadP () -> ReadP ()
forall (f :: Type -> Type). Applicative f => Bool -> f () -> f ()
unless (String
timeUnitStr String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== forall (unit :: Rat). KnownUnitName unit => String
unitNameVal @unit) ReadP ()
forall a. ReadP a
pfail
Time unit -> ReadP (Time unit)
forall a. a -> ReadP a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (Time unit -> ReadP (Time unit)) -> Time unit -> ReadP (Time unit)
forall a b. (a -> b) -> a -> b
$ RatioNat -> Time unit
forall (rat :: Rat). RatioNat -> Time rat
Time (Natural
n Natural -> Natural -> RatioNat
forall a. Integral a => a -> a -> Ratio a
% Natural
d)
time :: RatioNat -> Time unit
time :: forall (rat :: Rat). RatioNat -> Time rat
time RatioNat
n = RatioNat -> Time unit
forall (rat :: Rat). RatioNat -> Time rat
Time RatioNat
n
{-# INLINE time #-}
sec :: RatioNat -> Time Second
sec :: RatioNat -> Time Second
sec = RatioNat -> Time Second
RatioNat -> Time (1 :% 1)
forall (rat :: Rat). RatioNat -> Time rat
time
{-# INLINE sec #-}
ms :: RatioNat -> Time Millisecond
ms :: RatioNat -> Time Millisecond
ms = RatioNat -> Time Millisecond
RatioNat -> Time (1 :% 1000)
forall (rat :: Rat). RatioNat -> Time rat
time
{-# INLINE ms #-}
mcs :: RatioNat -> Time Microsecond
mcs :: RatioNat -> Time Microsecond
mcs = RatioNat -> Time Microsecond
RatioNat -> Time (1 :% 1000000)
forall (rat :: Rat). RatioNat -> Time rat
time
{-# INLINE mcs #-}
ns :: RatioNat -> Time Nanosecond
ns :: RatioNat -> Time Nanosecond
ns = RatioNat -> Time Nanosecond
RatioNat -> Time (1 :% 1000000000)
forall (rat :: Rat). RatioNat -> Time rat
time
{-# INLINE ns #-}
ps :: RatioNat -> Time Picosecond
ps :: RatioNat -> Time Picosecond
ps = RatioNat -> Time Picosecond
RatioNat -> Time (1 :% 1000000000000)
forall (rat :: Rat). RatioNat -> Time rat
time
{-# INLINE ps #-}
minute :: RatioNat -> Time Minute
minute :: RatioNat -> Time Minute
minute = RatioNat -> Time Minute
RatioNat -> Time (60 :% 1)
forall (rat :: Rat). RatioNat -> Time rat
time
{-# INLINE minute #-}
hour :: RatioNat -> Time Hour
hour :: RatioNat -> Time Hour
hour = RatioNat -> Time Hour
RatioNat -> Time (3600 :% 1)
forall (rat :: Rat). RatioNat -> Time rat
time
{-# INLINE hour #-}
day :: RatioNat -> Time Day
day :: RatioNat -> Time Day
day = RatioNat -> Time Day
RatioNat -> Time (86400 :% 1)
forall (rat :: Rat). RatioNat -> Time rat
time
{-# INLINE day #-}
week :: RatioNat -> Time Week
week :: RatioNat -> Time Week
week = RatioNat -> Time Week
RatioNat -> Time (604800 :% 1)
forall (rat :: Rat). RatioNat -> Time rat
time
{-# INLINE week #-}
fortnight :: RatioNat -> Time Fortnight
fortnight :: RatioNat -> Time Fortnight
fortnight = RatioNat -> Time Fortnight
RatioNat -> Time (1209600 :% 1)
forall (rat :: Rat). RatioNat -> Time rat
time
{-# INLINE fortnight #-}
floorRat :: forall b (unit :: Rat) . Integral b => Time unit -> b
floorRat :: forall b (unit :: Rat). Integral b => Time unit -> b
floorRat = RatioNat -> b
forall b. Integral b => RatioNat -> b
forall a b. (RealFrac a, Integral b) => a -> b
floor (RatioNat -> b) -> (Time unit -> RatioNat) -> Time unit -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Time unit -> RatioNat
forall (rat :: Rat). Time rat -> RatioNat
unTime
floorUnit :: forall (unit :: Rat) . Time unit -> Time unit
floorUnit :: forall (rat :: Rat). Time rat -> Time rat
floorUnit = RatioNat -> Time unit
forall (rat :: Rat). RatioNat -> Time rat
time (RatioNat -> Time unit)
-> (Time unit -> RatioNat) -> Time unit -> Time unit
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral @Natural (Natural -> RatioNat)
-> (Time unit -> Natural) -> Time unit -> RatioNat
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Time unit -> Natural
forall b (unit :: Rat). Integral b => Time unit -> b
floorRat
ceilingRat :: forall b (unit :: Rat) . (Integral b) => Time unit -> b
ceilingRat :: forall b (unit :: Rat). Integral b => Time unit -> b
ceilingRat = RatioNat -> b
forall b. Integral b => RatioNat -> b
forall a b. (RealFrac a, Integral b) => a -> b
ceiling (RatioNat -> b) -> (Time unit -> RatioNat) -> Time unit -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Time unit -> RatioNat
forall (rat :: Rat). Time rat -> RatioNat
unTime
ceilingUnit :: forall (unit :: Rat) . Time unit -> Time unit
ceilingUnit :: forall (rat :: Rat). Time rat -> Time rat
ceilingUnit = RatioNat -> Time unit
forall (rat :: Rat). RatioNat -> Time rat
time (RatioNat -> Time unit)
-> (Time unit -> RatioNat) -> Time unit -> Time unit
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral @Natural (Natural -> RatioNat)
-> (Time unit -> Natural) -> Time unit -> RatioNat
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Time unit -> Natural
forall b (unit :: Rat). Integral b => Time unit -> b
ceilingRat
toFractional :: forall r (unit :: Rat) . Fractional r => Time unit -> r
toFractional :: forall r (unit :: Rat). Fractional r => Time unit -> r
toFractional = Rational -> r
forall a. Fractional a => Rational -> a
fromRational (Rational -> r) -> (Time unit -> Rational) -> Time unit -> r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RatioNat -> Rational
forall a. Real a => a -> Rational
toRational (RatioNat -> Rational)
-> (Time unit -> RatioNat) -> Time unit -> Rational
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Time unit -> RatioNat
forall (rat :: Rat). Time rat -> RatioNat
unTime
toUnit :: forall (unitTo :: Rat) (unitFrom :: Rat) . KnownDivRat unitFrom unitTo
=> Time unitFrom
-> Time unitTo
toUnit :: forall (unitTo :: Rat) (unitFrom :: Rat).
KnownDivRat unitFrom unitTo =>
Time unitFrom -> Time unitTo
toUnit Time{RatioNat
unTime :: forall (rat :: Rat). Time rat -> RatioNat
unTime :: RatioNat
..} = RatioNat -> Time unitTo
forall (rat :: Rat). RatioNat -> Time rat
Time (RatioNat -> Time unitTo) -> RatioNat -> Time unitTo
forall a b. (a -> b) -> a -> b
$ RatioNat
unTime RatioNat -> RatioNat -> RatioNat
forall a. Num a => a -> a -> a
* forall (r :: Rat). KnownRat r => RatioNat
ratVal @(unitFrom / unitTo)
{-# INLINE toUnit #-}
threadDelay :: forall (unit :: Rat) m . (KnownDivRat unit Microsecond, MonadIO m)
=> Time unit
-> m ()
threadDelay :: forall (unit :: Rat) (m :: Type -> Type).
(KnownDivRat unit Microsecond, MonadIO m) =>
Time unit -> m ()
threadDelay = IO () -> m ()
forall a. IO a -> m a
forall (m :: Type -> Type) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> (Time unit -> IO ()) -> Time unit -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> IO ()
Concurrent.threadDelay (Int -> IO ()) -> (Time unit -> Int) -> Time unit -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Time (1 :% 1000000) -> Int
forall b (unit :: Rat). Integral b => Time unit -> b
floorRat (Time (1 :% 1000000) -> Int)
-> (Time unit -> Time (1 :% 1000000)) -> Time unit -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (unitTo :: Rat) (unitFrom :: Rat).
KnownDivRat unitFrom unitTo =>
Time unitFrom -> Time unitTo
toUnit @Microsecond
{-# INLINE threadDelay #-}
getCPUTime :: forall (unit :: Rat) m . (KnownDivRat Picosecond unit, MonadIO m)
=> m (Time unit)
getCPUTime :: forall (unit :: Rat) (m :: Type -> Type).
(KnownDivRat Picosecond unit, MonadIO m) =>
m (Time unit)
getCPUTime = Time (1 :% 1000000000000) -> Time unit
forall (unitTo :: Rat) (unitFrom :: Rat).
KnownDivRat unitFrom unitTo =>
Time unitFrom -> Time unitTo
toUnit (Time (1 :% 1000000000000) -> Time unit)
-> (Integer -> Time (1 :% 1000000000000)) -> Integer -> Time unit
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RatioNat -> Time Picosecond
RatioNat -> Time (1 :% 1000000000000)
ps (RatioNat -> Time (1 :% 1000000000000))
-> (Integer -> RatioNat) -> Integer -> Time (1 :% 1000000000000)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> RatioNat
forall a. Num a => Integer -> a
fromInteger (Integer -> Time unit) -> m Integer -> m (Time unit)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> IO Integer -> m Integer
forall a. IO a -> m a
forall (m :: Type -> Type) a. MonadIO m => IO a -> m a
liftIO IO Integer
CPUTime.getCPUTime
{-# INLINE getCPUTime #-}
timeout :: forall (unit :: Rat) m a . (MonadIO m, KnownDivRat unit Microsecond)
=> Time unit
-> IO a
-> m (Maybe a)
timeout :: forall (unit :: Rat) (m :: Type -> Type) a.
(MonadIO m, KnownDivRat unit Microsecond) =>
Time unit -> IO a -> m (Maybe a)
timeout Time unit
t = IO (Maybe a) -> m (Maybe a)
forall a. IO a -> m a
forall (m :: Type -> Type) a. MonadIO m => IO a -> m a
liftIO (IO (Maybe a) -> m (Maybe a))
-> (IO a -> IO (Maybe a)) -> IO a -> m (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> IO a -> IO (Maybe a)
forall a. Int -> IO a -> IO (Maybe a)
Timeout.timeout (Time Microsecond -> Int
forall b (unit :: Rat). Integral b => Time unit -> b
floorRat (Time Microsecond -> Int) -> Time Microsecond -> Int
forall a b. (a -> b) -> a -> b
$ forall (unitTo :: Rat) (unitFrom :: Rat).
KnownDivRat unitFrom unitTo =>
Time unitFrom -> Time unitTo
toUnit @Microsecond Time unit
t)
{-# INLINE timeout #-}