Frage

Ich kam in der folgenden Definition als ich versuche, Haskell mit einem realen Projekt zu lernen, es zu fahren. Ich verstehe nicht, was das Ausrufezeichen vor jedem Argument bedeutet, und meine Bücher schien es nicht zu erwähnen.

data MidiMessage = MidiMessage !Int !MidiMessage
War es hilfreich?

Lösung

Es ist eine Strikt Erklärung. Im Grunde bedeutet es, dass es zu bewerten muß, was „schwach normale Kopfform“ genannt wird, wenn die Datenstruktur Wert erzeugt wird. Lassen Sie uns ein Beispiel an, so dass wir nur sehen, was das bedeutet:

data Foo = Foo Int Int !Int !(Maybe Int)

f = Foo (2+2) (3+3) (4+4) (Just (5+5))

Die Funktion f oben, wenn beurteilt wird ein „Thunk“ zurück: das heißt, um den Code auszuführen seinen Wert herauszufinden. An diesem Punkt ist ein Foo noch nicht einmal existieren, nur den Code.

Aber irgendwann jemand kann versuchen, im Innern zu suchen, wahrscheinlich durch einen Mustervergleich:

case f of
     Foo 0 _ _ _ -> "first arg is zero"
     _           -> "first arge is something else"

Das wird genug Code ausführen zu tun, was er braucht, und nicht mehr. So wird es eine Foo mit vier Parametern erstellen (weil Sie nicht hinein schauen kann, ohne sie vorhanden). Die erste, da wir es sind zu testen, müssen wir den ganzen Weg bewerten 4, wo wir es nicht erkennen, entsprechen.

Der zweite muss nicht ausgewertet werden, weil wir testen es nicht. Anstatt also 6 in dieser Speicherstelle gespeichert werden, werden wir speichern nur den Code für eine mögliche spätere Auswertung, (3+3). Das wird sich in einem 6 nur, wenn jemand es aussieht.

Der dritte Parameter hat jedoch eine ! vor ihm ist so streng beurteilt:. (4+4) ausgeführt wird, und 8 wird in diesem Speicherplatz gespeichert

Der vierte Parameter wird auch streng bewertet. Aber hier ist, wo es ein bisschen knifflig: wir nicht vollständig sind Auswertung, sondern nur schwach normale Kopfform. Das bedeutet, dass wir herausfinden, ob es Nothing oder Just etwas, und zu speichern, aber wir gehen nicht weiter. Das bedeutet, dass wir nicht Just 10 speichern, sondern tatsächlich Just (5+5), die Thunk innen unevaluierten verlassen. Dies ist wichtig zu wissen, obwohl ich glaube, dass alle Auswirkungen dieser eher gehen über den Rahmen dieser Frage.

Sie können Funktionsargumente in der gleichen Art und Weise mit Anmerkungen versehen, wenn Sie die BangPatterns Spracherweiterung aktivieren:

f x !y = x*y

f (1+1) (2+2) die Thunk (1+1)*4 zurück.

Andere Tipps

Eine einfache Möglichkeit, den Unterschied zwischen streng und nicht-strengem Konstruktorargumente zu sehen ist, wie sie sich verhalten, wenn sie nicht definiert sind. Gegeben

data Foo = Foo Int !Int

first (Foo x _) = x
second (Foo _ y) = y

Da das nicht-strenge Argument von second nicht ausgewertet wird, in undefined vorbei verursacht kein Problem:

> second (Foo undefined 1)
1

Aber das strenge Argument kann nicht undefined werden, auch wenn wir den Wert nicht verwenden:

> first (Foo 1 undefined)
*** Exception: Prelude.undefined

Ich glaube, es ist eine Strikt Anmerkung.

Haskell ist eine reine und faul funktionale Sprache, aber manchmal der Aufwand für lazyness kann zu viel oder verschwenderisch sein. Also damit zu umgehen, können Sie bitten, Compiler vollständig die Argumente zu einer Funktion auszuwerten, anstatt Thunks um zu parsen.

Es gibt mehr Informationen auf dieser Seite. Leistung / Strikt

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top