Haskell Länge + Kartenerklärung?

7

Ich spiele mit Haskell herum, seit ich die Sprache lerne, und ich habe gerade etwas gefunden, das ich nicht verstehe und ich kann keine Erklärung finden. Wenn ich versuche, diesen Code auszuführen:

%Vor%

Ich bekomme eine Division durch 0 Ausnahme, die erwartet wird. Aber wenn ich diesen Code ausführen:

%Vor%

Ich bekomme 4!

Ich würde gerne wissen, warum ich die Division nicht durch 0 Ausnahme bekomme, wenn ich das Mapping innerhalb der Längenfunktion mache!

    
DemianArdus 06.05.2014, 00:52
quelle

3 Antworten

15

Die Funktionen map und length können folgendermaßen definiert werden:

%Vor%

Lassen Sie uns nun von Hand herausfinden, warum Ihr zweites Beispiel so funktioniert. Es geht so:

%Vor%

Was ist der Trick hier? In Haskell wird der Prozess zum Auswerten eines Ausdrucks als forcieren bezeichnet. Das Erzwingen eines Ausdrucks führt die minimale Arbeit aus, die notwendig ist, um den äußersten Datenkonstruktor des Ergebnisses herauszufinden. In diesem Zusammenhang werden Teilausdrücke nur so weit erzwungen, wie es zum Erreichen des Ziels erforderlich ist.

In diesem Beispiel ist der äußerste Ausdruck, den wir erzwingen, eine Anwendung der Funktion length . Die Definition von length hat zwei Fälle, einen, der den [] list -Konstruktor verwendet und den anderen, der den (:) -Konstruktor benutzt. Um also length anzuwenden, müssen wir herausfinden, welcher dieser beiden Fälle auf den angewendet werden soll Streit. Da das Argument keinen Konstruktor in seiner äußersten Position hat, müssen wir es zwingen, es herauszufinden. Dies geschieht im Schritt zwischen der ersten und der zweiten Zeile der obigen Ableitung; Wir erzwingen den Unterausdruck map , indem wir auf seine Argumente schauen und die zweite map -Gleichung auswählen.

Aber nach diesem Punkt haben wir alle Informationen, die wir brauchen, um zu bestimmen, welche der beiden Gleichungen für length gilt, also gehen wir nach der "äußersten zuerst" -Regel und wenden die entsprechende length -Gleichung an. In diesem Fall verwirft dies den Unterausdruck, der die Division durch Null enthält, was bedeutet, dass Unterausdruck niemals erzwungen wird und der Fehler niemals ausgelöst wird.

In Ihrem ersten Beispiel bitten Sie den Interpreter implizit, das Ergebnis zu drucken, wenn Sie den Ausdruck in GHCI eingeben. Dies erfordert, dass das Rückgrat der Liste auf seine Elemente zugreift und die Elemente selbst dazu zwingt, sie zu drucken. Die Division durch Null Fehler passiert also, wenn Sie das erste Element der Liste erzwingen.

BEARBEITEN: Lassen Sie mich auf eine Nuance hinweisen, die Sie vielleicht nicht bemerkt haben. Wenn wir Ihr erstes Beispiel in GHCI ausprobieren, ist dies das Ergebnis der Sitzung:

%Vor%

Sehen Sie diese einsame öffnende eckige Klammer am Anfang der zweiten Zeile? Das ist die öffnende Klammer für die Liste, die gedruckt wurde, bevor der Fehler durch Division durch Null passiert ist. Beachten Sie auch, was in diesem Beispiel passiert:

%Vor%

Die ersten beiden Elemente der Ergebnisliste und sogar das Komma, das das zweite Element vom dritten trennt, werden erfolgreich gedruckt, weil Haskell nicht versucht, das dritte Listenelement zu berechnen, bis es gedruckt werden muss.

    
Luis Casillas 06.05.2014, 01:21
quelle
5

Wenn Sie den Ausdruck map in den Interpreter eingeben, wird er ausgewertet und die resultierende Liste gedruckt. Um dies zu tun, müssen alle Elemente der resultierenden Liste ausgewertet werden, da sie Teil der angezeigten Zeichenfolge sind.

Wenn der Interpreter jedoch den Ausdruck length auswertet, muss er sich nur die Struktur der resultierenden Liste ansehen. Es muss nicht die tatsächlichen Elemente in der Liste betrachten. Da Haskell eine faule Sprache ist, wird nur bewertet, was es bedeutet, das bedeutet, dass die Elemente nicht ausgewertet werden und somit keine Ausnahme ausgelöst wird.

    
sepp2k 06.05.2014 00:56
quelle
5

Dies ist eine gute alte Haskell-Lazy-Bewertung! Wenn Haskell nichts berechnen muss, wird es nicht funktionieren. In diesem Fall rufen Sie map in einer Liste der Länge 4 auf. Für Haskell gibt map auf eine beliebige Liste zurück, unabhängig davon, welche Operation Sie anwenden. Deshalb sagt Haskell einfach, dass die Länge 4 ist, ohne dass irgendetwas durch 0 geteilt wird.

    
donutmonger 06.05.2014 00:58
quelle

Tags und Links