Writing a time function in Haskell

寵の児 提交于 2019-12-04 09:08:29

问题


I’m new to Haskell and I’d like to be able to time the runtime of a given function call or snippet of code.

In Clojure I can use ‘time’:

user=> (time (apply * (range 2 10000)))
"Elapsed time: 289.795 msecs"
2846259680917054518906413212119868890148051...

In Scala, I can define the function myself:

scala> def time[T](code : => T) =  {
     |   val t0 = System.nanoTime : Double
     |   val res = code
     |   val t1 = System.nanoTime : Double
     |   println("Elapsed time " + (t1 - t0) / 1000000.0 + " msecs")
     |   res
     | }
time: [T](=> T)T

scala> time((1 to 10000).foldLeft(1:BigInt)(_*_))
Elapsed time 274.292224 msecs
res0: BigInt = 284625968091705451...

How can I write the equivalent of my Scala function or Clojure's ‘time’ in Haskell? The System.TimeIt module I've found on Hackage is not general enough because it works only if an IO computation is being measured. So timeIt(4 + 4) wouldn't work, only timeIt(print $ 4 + 4), which gets annoying fast. Beside, I really want to see how Haskell handles the general case.

Thank you!


回答1:


Please look at using the standard libraries for this:

  • Timing computations in Haskell
  • Criterion, possibly the best open source benchmarking/timing library in existence
  • About Criterion

Just use criterion.


A note on evaluation depth: laziness means you need to decide how much evaluation you want to have during your timing run. Typically you'll want to reduce your code to normal form. The NFData typeclass lets you do this via the rnf method. If evaluating to the outermost constructor is ok, use seq on your pure code to force its evaluation.




回答2:


Haskell is lazily evaluated. If your expression doesn't have some side effect (as encoded in the IO monad or the like), then the program doesn't need to actually resolve the expression to a value, and so won't.

To get meaningful numbers out of this, you might try timing print 4 and print expr and take the difference, in order to remove the overhead of string formatting and IO.




回答3:


Lazy means Lazy. Time is only relevant when inside a monad like IO.

Time has NO meaning in the expression "4 + 4" - or in any other mathematical equation. The answer simply IS. The "answer" to any other pure computation is already predetermined the instant that the computation is specified.

Unfortunately, this is the "answer" to your question. An answer that, in fact, existed before you even posed your question. It existed in 1998 when the language was finally defined. The fact that it took me a year to write this doesn't matter ;-)

OK, enough of that nonsense!!!! (But if the above is too annoying, then just forget about Haskell.)

If the Criterion package is too much pain, just write a test case and use +RTS to test it.

If you want to be really cool, create your own monad - one that times the execution of your algorithm and hands the result back tupled with the algorithm's return value. Good luck. We're all counting on you!



来源:https://stackoverflow.com/questions/1516808/writing-a-time-function-in-haskell

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!