Angenommen, Sie haben eine nullary-Funktion in haskell, die mehrmals im Code verwendet wird. Wird es immer nur einmal ausgewertet? Ich habe den folgenden Code bereits getestet:
%Vor%Wenn ich Test 10 anrufe, schreibt er einmal "Hallo", so dass das Ergebnis der Funktion nach der ersten Auswertung gespeichert wird. Meine Frage ist, ist es garantiert? Bekomme ich das gleiche Ergebnis über verschiedene Compiler hinweg?
Bearbeiten Der Grund für die Verwendung von unsafePerformIO besteht darin, zu überprüfen, ob sayHello mehr als einmal ausgewertet wird. Ich benutze das nicht in meinem Programm. Normalerweise erwarte ich, dass sayHello bei jeder Auswertung genau das gleiche Ergebnis hat. Aber es ist eine zeitaufwendige Operation, also wollte ich wissen, ob auf diese Weise zugegriffen werden kann, oder ob es als Argument übergeben werden soll, wo immer es benötigt wird, um sicherzustellen, dass es nicht mehrfach ausgewertet wird, zB:
%Vor%Laut den Antworten sollte dies verwendet werden.
Es gibt keine so genannte Nullfunktion. Eine Funktion in Haskell hat genau ein Argument und hat immer den Typ ... -> ...
. sayHello
ist ein Wert - ein Int
- aber keine Funktion. Weitere Informationen finden Sie in diesem Artikel .
On Garantien: Nein, Sie bekommen wirklich keine Garantien. Der Haskell-Bericht gibt an, dass Haskell nicht strikt ist - Sie wissen also, auf welchen Wert sich die Dinge letztendlich reduzieren werden - aber keine bestimmte Bewertungsstrategie. Die Evaluierungsstrategie, die GHC im Allgemeinen verwendet, ist Lazy Evaluation , dh nicht-strikte Bewertung mit Teilen, aber es gibt keine starken Garantien darüber hinaus - der Optimierer könnte Ihren Code herum mischen, so dass Dinge mehr als einmal ausgewertet werden.
Es gibt auch verschiedene Ausnahmen - zum Beispiel ist foo :: Num a => a
polymorph, also wird es wahrscheinlich nicht geteilt (es wird zu einer tatsächlichen Funktion kompiliert). Manchmal wird ein reiner Wert von mehr als einem Thread gleichzeitig ausgewertet (was in diesem Fall nicht der Fall ist, weil unsafePerformIO
explizit noDuplicate
verwendet, um dies zu vermeiden). Also, wenn Sie programmieren, können Sie im Allgemeinen Faulheit erwarten, aber wenn Sie irgendeine Art von Garantien wollen, müssen Sie sehr vorsichtig sein. Der Bericht selbst gibt Ihnen nicht wirklich Auskunft über wie Ihr Programm bewertet wird.
unsafePerformIO
gibt Ihnen selbstverständlich noch weniger Garantien. Es gibt einen Grund, warum es "unsicher" heißt.
Top-Level-Funktionen ohne Argumente wie sayHello
heißen Constant Applicative Forms und sind immer Memoisiert (zumindest in GHC - siehe Ссылка ). Sie müssten auf Tricks wie das Übergeben von Dummy-Argumenten und das Deaktivieren von Optimierungen auf nicht zugreifen, um eine CAF global zu teilen.
Bearbeiten : Zitat aus dem obigen Link -
Haskell ist eine faule Sprache, und bestimmte Ausdrücke sind immer nur einmal bewertet. Zum Beispiel, wenn wir schreiben:
x = nfib 25
thenx
wird nur einmal ausgewertet (wenn überhaupt), und Nachfolgende Anforderungen fürx
sehen sofort das zwischengespeicherte Ergebnis. Die Definitionx
wird CAF (Constant Applicative Form) genannt, weil Es hat keine Argumente.
Wenn Sie möchten, dass "Hallo" n mal gedruckt wird, müssen Sie unsafePermformIO
entfernen, damit die Laufzeitumgebung weiß, dass wiederholte Aufrufe von putStr
nicht optimiert werden können. Ich bin nicht klar, ob Sie die Liste von int zurückgeben wollen, also habe ich zwei Testversionen geschrieben, von denen eine zurückgibt (), eine [Int].
Tags und Links haskell functional-programming lazy-evaluation