module System.TimeIt(timeIt, timeItShow, timeItNamed, timeItT) where
import System.CPUTime
import Text.Printf

-- | Wrap an IO computation so that it prints out the execution time.
--
-- Note: Use IO instead of MonadIO to avoid redundant import issues on some
-- GHC installations/architectures.
timeIt :: IO a -> IO a
timeIt :: forall a. IO a -> IO a
timeIt = String -> IO a -> IO a
forall a. String -> IO a -> IO a
timeItNamed String
"CPU time"

-- | Like 'timeIt', but uses the 'show' rendering of @a@ as label for the
-- timing.
--
-- @since 2.0
timeItShow :: Show a => IO a -> IO a
timeItShow :: forall a. Show a => IO a -> IO a
timeItShow IO a
ioa = do
    (t, a) <- IO a -> IO (Double, a)
forall a. IO a -> IO (Double, a)
timeItT IO a
ioa
    printf (show a ++ ": %6.2fs\n") t
    return a

-- | Like 'timeIt', but uses the 'String' as label for the timing.
--
-- @since 2.0
timeItNamed :: String -> IO a -> IO a
timeItNamed :: forall a. String -> IO a -> IO a
timeItNamed String
name IO a
ioa = do
    (t, a) <- IO a -> IO (Double, a)
forall a. IO a -> IO (Double, a)
timeItT IO a
ioa
    printf (name ++ ": %6.2fs\n") t
    return a

-- | Wrap an IO computation so that it returns execution time in seconds,
-- as well as the result value.
timeItT :: IO a -> IO (Double, a)
timeItT :: forall a. IO a -> IO (Double, a)
timeItT IO a
ioa = do
    t1 <- IO Integer
getCPUTime
    a <- ioa
    t2 <- getCPUTime
    let t :: Double
        t = Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer
t2Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
-Integer
t1) Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
1e-12
    return (t, a)