Warum ist es gut, sich nicht auf Zustandsänderungen zu verlassen?

16

Diese Frage ergibt sich aus der Frage /software/25569/is-haskell-worth-learning

Im Allgemeinen werden einige häufig wiederholte Aussagen darüber gemacht, wie Haskell Ihre Codierungsfähigkeiten in anderen Sprachen verbessert, und außerdem, weil Haskell zustandslos ist, und das ist eine gute Sache.

Warum?

Ich habe gesehen, dass jemand dies damit vergleicht, nur mit der linken Hand zu tippen oder vielleicht für einen Tag die Augen zu schließen und sich nur auf die Berührung zu verlassen. Da steckt doch mehr dahinter?

Bezieht es sich auf den Hardware-Speicherzugriff oder auf etwas anderes, das einen großen Leistungsgewinn darstellt?

ocodo
quelle
2
Haskell ist akademisch. Ich würde mir einige Vorträge von Rich Hickey über Clojure ansehen - dort macht er mörderische pragmatische Argumente (ähnlich den 3 Punkten von Javier, aber auch auf einfache Weise gemacht).
Job
2
Ja, siehe clojure.org/state
LennyProgrammers
6
Nur weil Haskell "akademisch" ist, heißt das nicht, dass es unpraktisch oder nicht pragmatisch ist.
Tikhon Jelvis

Antworten:

17

Es gibt mindestens drei große Vorteile auf den ersten Blick:

  1. Dadurch werden Programme mathematischen Ausdrücken näher gebracht. In der Mathematik xändert sich nichts, Sie wissen nur nicht, was es ist, bis Sie die Gleichung lösen.

  2. Am Ende kommt es zu einer Zustandsänderung (immerhin funktioniert der Computer so auf niedriger Ebene). aber es ist durch die Sprache auf bestimmte Orte beschränkt. Dadurch hat der Compiler große Möglichkeiten, Code zu verschieben, um ihn zu optimieren, da er weiß, dass er nichts ändert, von dem anderer Code abhängt.

  3. Der gleichzeitige Code muss nicht synchronisiert werden, um auf sich nicht ändernde Daten zuzugreifen. Daher wird die Parallelität sowohl in SMP-Shared-Memory-Systemen (alle Multicore-Systeme von heute) als auch in lose verbundenen Clustern verbessert.

Javier
quelle
3
Propoennts der funktionalen Programmierung belasten am meisten # 3, dh einfacheres gleichzeitiges Programmieren.
Mchl
4
@Mchl: Meiner Erfahrung nach legen sie größten Wert auf "Es ist einfacher zu verstehen und zu überlegen", was 1 entspricht. Allerdings kann sich das zwischen den Sprachgemeinschaften unterscheiden.
8.
+1, sehr vollständige Antwort. @ sepp2k: beides ist wohl wichtig. Über ein Programm nachzudenken ist das, was wir täglich tun, und es ist wahr, dass es viel einfacher ist, nur übergeordnete Methoden zu lesen und zu erfassen, was los ist, wenn Sie nicht überprüfen müssen, ob sich der Status in einer tief verborgenen Funktion geändert hat. In Bezug auf die Hardware: Da wir uns immer mehr auf Multi-Core- und Multi-Prozessor-Systeme konzentrieren (obwohl es wohl eine Weile dauern wird, bis Heimcomputer Multi-Prozessor-Systeme einsetzen), ist eine Sprache, die die gleichzeitige Programmierung erleichtert, eine Grundvoraussetzung.
Matthieu M.
Gute Antwort, Nr. 2 war vermutlich die Antwort, und obwohl ich oft über Multiprocessing-Vorteile gelesen habe, wird es selten als klarer, großartiger Job bezeichnet.
Ocodo
1
@Yttrill, funktionale Sprachen sind nicht eindeutig in ihrer Abhängigkeit von Garbage Collection und Garbage Collection ist viel einfacher, wenn Sie mit unveränderlichen Daten arbeiten. Wenn Sie eine befehlsbasierte Architektur berechnen, müssen Sie den Status ändern. Dies bedeutet jedoch nicht, dass die Parallelisierung funktionaler Sprachen schwieriger ist. Funktionale Sprachen rocken an Parallelität; Lookup-Daten parallel zu Haskell, es ist eine Funktion, die sich kaum zu einer imperativen Sprache hinzufügen lässt.
Dan_waterworth
4

Hier ist ein weiterer Vorteil: Reduzierte Kopplung. Wenn Sie Code haben wie:

 function doStuff(x) { return x + y;}

und woanders hast du:

 function doOtherStuff(x) { y++; return y + x;}

dann sind die beiden Funktionen implizit abhängig . Es gibt keine einfache Möglichkeit, festzustellen, dass Anrufe doStuffvon Anrufen betroffen sind doOtherStuff. Ohne veränderlichen Zustand müssten Sie die Verbindung explizit machen.

Natürlich ist dies kein Problem bei allen veränderlichen Zuständen , sondern bei allen durchdringenden veränderlichen Zuständen. Die wirkliche Lösung besteht darin, standardmäßig unveränderlich zu sein und den veränderlichen Zustand auf eine Art und Weise zu "markieren" und ihn auf den gewünschten Ort zu beschränken.

Tikhon Jelvis
quelle
+1. Viele erfahrene Programmierer wissen, dass sie keinen Code wie den oben genannten schreiben müssen, und es ist kein großer Schritt, vom "veränderlichen Zustand ist in dieser Situation schlecht" zum "ernsthaften Verringern des Zustands, den wir ändern und funktionaler schreiben" überzugehen, aber es ist ein Schritt das machen enttäuschend wenige.
Dan_waterworth
2

Eine vereinfachte Antwort lautet: Wenn Sie einen Namen in einer rein funktionalen Sprache sehen, wissen Sie, was der zugehörige Wert ist, indem Sie seine Definition einfach nachschlagen. Wenn Sie veränderbare Variablen haben, können Sie nur anhand der zuletzt ausgeführten Zuweisungen feststellen, welche der verschiedenen Zuweisungen zuletzt ausgeführt wurden. Daher müssen Sie auch den Kontrollfluss analysieren, der wiederum von bestimmten Bedingungen abhängig sein kann, sodass Sie mehrere Möglichkeiten haben. Um eine exponentielle Explosion zu erhalten, müssen Sie lediglich berücksichtigen, dass die RHS der Zuweisungen selbst von Variablen abhängig sind, und sie müssen daher auch rekursiv analysiert werden.

Das Fazit der obigen Analyse ist, dass es unhaltbar ist, wenn keine Kommentare zu Absicht, Invarianten und Semantik abgegeben werden: Diese können schwer zu interpretieren sein und es kann schwierig sein zu überprüfen, ob die Semantik im tatsächlichen Code eingehalten wird.

Diese Antwort ist im Grunde eine Erweiterung von @ Javiers Punkt 1.

Ich denke, es ist auch eine Erklärung für die Popularität des betrügerischen OO-Regimes: Bei OO ist der veränderbare Zustand eingekapselt, was die Analyse erheblich erleichtert, indem die Mutationen zu einem gewissen Grad lokalisiert werden und eine wesentlich robustere Darstellung und Verifizierung der Semantik ermöglicht wird.

In Anbetracht dessen ist funktionale Programmierung nicht die Antwort. Die richtige Antwort ist ein System, das sowohl induktive (funktionale) als auch koinduktive (prozedurale) Programmierung unterstützt, sodass die richtigen Tools sowohl für die zustandslose als auch für die zustandsbehaftete Programmierung geeignet sind. Es ist nur so, dass die konstruktive (funktionale) Theorie gut etabliert ist, während die Theorie des Staatsmanagements noch in den Kinderschuhen steckt.

Yttrill
quelle
Das Mischen von funktionaler und imperativer Programmierung ist genau das, was Haskell tut - normale Funktionen sind funktional, während zustandsbezogene Berechnungen mit einer Do-Notation ausgedrückt werden können, mit der Sie den veränderlichen Zustand (unter anderem) sorgfältig isolieren und steuern können. Aus diesem Grund ist Haskell die Sprache mit der praktischsten STM-Implementierung .
Tikhon Jelvis
Die Do-Notation hat an sich nichts zu tun, um zustandsbehaftete Berechnungen durchzuführen . Do-Notation ist nur eine einfachere Syntax über monadischen Funktionspipelines. Zustandsberechnung ist nur eines der Dinge, die mit Monaden und damit der Do-Notation ausgedrückt werden können.
Jonathan Sterling
Eine Mischung aus funktionaler und imperativer Programmierung ist das, was fast jede existierende Sprache tut. Haskell hat vielleicht eine Möglichkeit bereitgestellt, die zustandsbehafteten Teile zu isolieren, aber das macht es nicht zu einer richtigen Mischung: Wohltätigkeit ist eher so, wie es sein sollte (IMHO).
Yttrill
2

Als Autor von Siege , einem in Haskell geschriebenen DBMS, kann man meinen Standpunkt zu einem Konflikt zwischen veränderlichem Zustand bezeichnen. Ich hoffe es anders zu zeigen.

Der Zweck des veränderlichen Status ist es, den aktuellen Status eines Systems zu beschreiben. Angenommen, Sie haben ein Blog und es ist ein Backend einer Datenbank. In der Datenbank werden die Posts beschrieben, die Sie zum Zeitpunkt der Abfrage in Ihrem Blog haben es. Wie viele Posts gibt es gerade?

Vergleichen Sie dies mit einem unveränderlichen Zustand, der zur Vermittlung von Fakten verwendet wird. Wie viele Posts gab es am 12. August?

Tatsachen sind leicht zu überlegen, veränderlicher Zustand nicht. Der wandelbare Zustand ist jedoch kein böser, unreiner Effekt, der aus unseren Gedanken verbannt werden sollte. Wir brauchen es oft, um in der veränderlichen Welt, in der wir leben, koexistieren zu können. Wir müssen es nur sparsamer einsetzen.

dan_waterworth
quelle