I am relatively new to Haskell and I am trying to learn how different actions can be executed in sequence using the do notation. In particular, I am writing a program to benchmark an algorithm (a function)

foo :: [String] -> [String]

To this purpose I would like to write a function like

import System.CPUTime

benchmark :: [String] -> IO Integer
benchmark inputList = do
                         start <- getCPUTime
                         let r = foo inputList
                         end <- getCPUTime
                         return (end - start) -- Possible conversion needed.

The last line might need a conversion (e.g. to milliseconds) but this is not the topic of this question.

Is this the correct way to measure the time needed to compute function foo on some argument inputList?

In other words, will the expression foo inputList be completely reduced before the action end <- getCPUTime is executed? Or will r only be bound to the thunk foo inputList?

More in general, how can I ensure that an expression is completely evaluated before some action is executed?

closed as off topic by Walter, user7007, Thomas Owens Jan 4 '13 at 15:20

Questions on Software Engineering Stack Exchange are expected to relate to software engineering within the scope defined by the community. Consider editing the question or leaving comments for improvement if you believe the question can be reworded to fit within the scope. Read more about reopening questions here. If this question can be reworded to fit the rules in the help center, please edit the question.

  • Can someone explain why this question is off-topic? I may be wrong but it seems perfectly OK to me. – Giorgio Jan 27 '14 at 11:16
  • Maybe this should be asked on stackoverflow. – Ray Aug 12 '14 at 21:22

Indeed you version will not benchmark your algorithm. As r is not used it will not be evaluated at all.

You should be able to do it with DeepSeq[1]:

benchmark :: [String] -> IO Integer
benchmark inputList = do
                     start <- getCPUTime
                     let r = foo inputList
                     end <- r `deepseq` getCPUTime
                     return (end - start)

(a deepseq b) is some "magic" expression which forces the complete/recursive evaluation of 'a' before retuning 'b'.

[1] http://www.haskell.org/ghc/docs/7.4.1/html/libraries/deepseq-

  • 1
    +1: Thanks for the answer, I will try it out today. In your code, I think you need to keep the expression let r = foo inputList between the two getCPUTime, otherwise r will be undefined. – Giorgio Aug 13 '12 at 7:17
  • @ysdx This question is off-topic for us here on Programmers. It has been reposted on Stack Overflow where it's on-topic. If you want to repost an answer there, feel free to do so and then flag the repost of your answer for deletion to set things right. Ping me in chat for any questions. – Thomas Owens Jan 4 '13 at 18:58

Not the answer you're looking for? Browse other questions tagged or ask your own question.