2009-10-04 8 views
27

Je ne connais pas encore Haskell et j'aimerais connaître le temps d'exécution d'un appel de fonction donné ou d'un extrait de code.Ecriture d'une fonction de temps dans Haskell

En Clojure je peux utiliser 'time ':

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

En Scala, je peux définir moi-même la fonction:

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

Comment puis-je écrire l'équivalent de ma fonction Scala ou Clojure de' Heure à Haskell Le System.TimeIt module que j'ai trouvé sur Hackage n'est pas assez général car il ne fonctionne que si un calcul d'E/S est mesuré. Donc, timeIt(4 + 4) ne fonctionnerait pas, seulement timeIt(print $ 4 + 4), ce qui devient vite ennuyeux. A côté, je veux vraiment voir comment Haskell gère le cas général.

Merci!

Répondre

22

S'il vous plaît regarder en utilisant les bibliothèques standard pour cela:

Il suffit d'utiliser le critère .


Une note sur la profondeur d'évaluation: la paresse signifie que vous devez décider combien d'évaluation vous voulez avoir pendant votre course de synchronisation. Généralement, vous voudrez réduire votre code à la forme normale. La typeclass NFData vous permet de le faire via la méthode rnf. Si l'évaluation du constructeur le plus externe est correcte, utilisez seq sur votre code pur pour forcer son évaluation.

+0

L'entrée wiki était exactement ce dont j'avais besoin, merci! – dimo414

+0

Un +1 va vers vous :) Un autre +1 va sur le blog de Bryan O'Sullivan :) – CoR

6

Haskell est évalué paresseusement. Si votre expression n'a pas d'effet secondaire (tel que codé dans la monade d'E/S ou similaire), alors le programme n'a pas besoin de résoudre réellement l'expression en une valeur, ce qui n'est pas le cas.

Pour obtenir des nombres significatifs à partir de cela, vous pouvez essayer de chronométrer print 4 et print expr et prendre la différence, afin de supprimer la surcharge de formatage de chaîne et d'E/S.

5

Lazy signifie Lazy. Le temps n'est pertinent que dans une monade comme IO.

Le temps n'a AUCUN sens dans l'expression "4 + 4" - ou dans toute autre équation mathématique. La réponse est simplement IS. La "réponse" à tout autre calcul pur est déjà prédéterminée à l'instant où le calcul est spécifié.

Malheureusement, ceci est la "réponse" à votre question. Une réponse qui, en fait, existait avant même que vous ayez posé votre question. Il existait en 1998 lorsque la langue a été définitivement définie. Le fait qu'il m'a fallu un an pour écrire cela n'a pas d'importance ;-)

OK, assez de ce non-sens !!!! (Mais si ce qui précède est trop ennuyeux, alors oubliez simplement Haskell.)

Si le paquet Criterion est trop difficile, écrivez simplement un cas de test et utilisez + RTS pour le tester.

Si vous voulez être vraiment cool, créez votre propre monade - celle qui multiplie l'exécution de votre algorithme et restitue le résultat avec la valeur de retour de l'algorithme. Bonne chance. Nous comptons tous sur vous!

+1

Cependant, '4 + 4' n'est pas réellement une fonction car elle ne prend aucune entrée. Maintenant \ x -> x + 4 est une fonction. La valeur de 'x' pourrait être n'importe quoi. La question est, combien de temps cela prend-il à partir du moment où x est connu jusqu'à ce que le résultat de la fonction soit connu. –

+0

Haskell n'a pas été «définitivement défini» en 1998. Haskell a toujours été en développement constant et il est donc arrivé que les créateurs aient décidé d'ajouter la balise «Haskell Standard» à l'une des versions du rapport Haskell. Source: "Une histoire de Haskell: être paresseux avec la classe" –