Написание функции времени на Хаскеле - PullRequest
27 голосов
/ 04 октября 2009

Я новичок в Haskell и хотел бы иметь возможность рассчитать время выполнения данного вызова функции или фрагмента кода.

В Clojure я могу использовать ‘ time ’:

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

В Scala я могу определить функцию самостоятельно:

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...

Как я могу написать эквивалент моей функции Scala или «времени» Clojure в Haskell? Модуль System.TimeIt , обнаруженный мной в Hackage, не является достаточно общим, поскольку он работает только при измерении вычислений ввода-вывода. Так что timeIt(4 + 4) не сработает, только timeIt(print $ 4 + 4), что быстро раздражает. Кроме того, я действительно хочу посмотреть, как Хаскелл справляется с общим делом.

Спасибо!

Ответы [ 3 ]

22 голосов
/ 04 октября 2009

Пожалуйста, посмотрите на использование стандартных библиотек для этого:

Просто используйте критерий.


Примечание о глубине оценки : лень означает, что вам нужно решить, какую оценку вы хотите получить во время пробежки по времени. Как правило, вы хотите привести свой код к нормальной форме. Класс типов NFData позволяет вам делать это с помощью метода rnf. Если оценка для самого внешнего конструктора в порядке, используйте seq в вашем чистом коде, чтобы форсировать его оценку.

6 голосов
/ 04 октября 2009

Haskell лениво оценивается. Если ваше выражение не имеет какого-либо побочного эффекта (как закодировано в монаде IO и т. П.), То программе не нужно фактически преобразовывать выражение в значение, и поэтому не будет.

Чтобы извлечь из этого значимые числа, вы можете попробовать синхронизировать print 4 и print expr и взять разницу, чтобы устранить накладные расходы на форматирование строк и ввод-вывод.

5 голосов
/ 25 июня 2010

Ленивый означает Ленивый. Время имеет значение только в монаде, подобной IO.

Время не имеет значения в выражении «4 + 4» - или в любом другом математическом уравнении. Ответ просто ЕСТЬ. «Ответ» на любое другое чистое вычисление уже предопределено в тот момент, когда вычисление указано.

К сожалению, это «ответ» на ваш вопрос. Ответ, который, на самом деле, существовал еще до того, как вы задали свой вопрос. Он существовал в 1998 году, когда язык был окончательно определен. Тот факт, что мне потребовался год, чтобы написать это, не имеет значения; -)

Хорошо, хватит этой ерунды !!!! (Но если вышесказанное слишком раздражает, просто забудьте про Haskell.)

Если пакет Criterion доставляет слишком много боли, просто напишите контрольный пример и используйте + RTS для его проверки.

Если вы хотите быть по-настоящему крутым, создайте свою собственную монаду - такую, которая умножит время выполнения вашего алгоритма и вернет результат обратно в соответствие с возвращаемым значением алгоритма. Удачи. Мы все рассчитываем на тебя!

...