Search code examples
haskellmonadstiming

Repeated timing of function


I have a very simple function f :: Int -> Int and I want to write a program that calls f for each n = 1,2,...,max. After each call of f the (cumulative) time that was used up to that point should be displayed (along with n and f n). How can this be implemented?

I'm still really new to input/output in Haskell, so this is what I've tried so far (using some toy example function f)

f :: Int -> Int
f n = sum [1..n]

evalAndTimeFirstN :: Int -> Int -> Int -> IO()
evalAndTimeFirstN n max time = 
  if n == max 
   then return () -- in the following we have to calculate the time difference from start to now
   else let str =  ("(" ++ (show n) ++  ", " ++ (show $ f n) ++ ", "++ (show time)++ ")\n") 
         in putStrLn str >> evalAndTimeFirstN (n+1) max time -- here we have to calculate the time difference

main :: IO()
main = evalAndTimeFirstN 1 5 0

I don't quite see how I have to introduce the timing here. (The Int for time probably has to be replaced with something else.)


Solution

  • I finally managed to find a solution. In this case we're measuring the "real" time in ms.

    import Data.Time
    import Data.Time.Clock.POSIX
    
    f n = sum[0..n]
    
    getTime = getCurrentTime >>= pure . (1000*) . utcTimeToPOSIXSeconds >>= pure . round
    
    main = do 
        maxns <- getLine 
        let maxn = (read maxns)::Int
        t0 <- getTime 
        loop 1 maxn t0
         where loop n maxn t0|n==maxn = return ()
               loop n maxn t0
                 = do 
                     putStrLn $ "fun eval: " ++ (show n) ++ ", " ++ (show $ (f n)) 
                     t <- getTime
                     putStrLn $ "time: " ++ show (t-t0); 
                     loop (n+1) maxn t0