scientist-0.0.0.0: library/Scientist/Duration.hs
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Scientist.Duration
( Duration
, measureDuration
, durationToSeconds
) where
import Prelude
import Control.Monad.IO.Class (MonadIO(..))
import Data.Fixed (Fixed(..), Nano, showFixed)
import qualified System.Clock as Clock
-- | Time elapsed in seconds up to nanosecond precision
--
-- >> 1.005
-- 1.005s
newtype Duration = Duration
{ _unDuration :: Nano
}
deriving stock (Eq)
deriving newtype (Enum, Ord, Num, Real, Fractional, RealFrac)
instance Show Duration where
show (Duration x) = showFixed True x <> "s"
measureDuration :: MonadIO m => m a -> m (a, Duration)
measureDuration f = do
begin <- liftIO getTime
(,) <$> f <*> liftIO
(fromNanoSecs . Clock.toNanoSecs . subtract begin <$> getTime)
where getTime = Clock.getTime Clock.Monotonic
-- | Convert from duration to seconds
--
-- >> toSecs 0.000001
-- 0.000001
durationToSeconds :: Duration -> Double
durationToSeconds = realToFrac
-- | Convert to duration from nanoseconds
--
-- >> fromNanoSecs 1000
-- 0.000001s
fromNanoSecs :: Integer -> Duration
fromNanoSecs = Duration . MkFixed