Ihre Hauptbeschwerde ist über %code% , aber da es grundsätzlich gegen Ihre Ziele ist, warum verwenden Sie sie?
Denken Sie daran, dass der Hauptgrund für %code% darin liegt, dass nicht alles so definiert werden kann, wie es das Typsystem garantieren kann. Daher ist es sinnvoll, "Das kann nicht passieren, vertraue mir". %code% kommt aus dieser Denkweise von "manchmal weiß ich besser als der Compiler". Wenn Sie mit dieser Denkweise nicht einverstanden sind, benutzen Sie sie nicht. Alternativ missbrauche es nicht wie dieses Beispiel.
BEARBEITEN:
Um meinen Punkt zu erweitern, überlegen Sie sich, wie Sie das umsetzen würden, was Sie verlangen (Warnungen zur Verwendung von Teilfunktionen). Wo würde die Warnung im folgenden Code gelten?
%Vor%All diese sind statisch nicht partiell. (Entschuldigung, wenn die Syntax des nächsten deaktiviert ist, ist es spät)
%Vor%%code% ist hier wieder sicher, aber %code% ist nicht sicher. Welche Methode sollte die Warnung zurückgeben? Was tun wir, wenn einige oder alle dieser Methoden außerhalb unserer Funktion definiert sind? Was machen Sie bei %code% , wo es bedingt partiell ist? Sollten einige oder alle dieser Funktionen fehlschlagen?
Indem Sie den Compiler veranlassen, diesen Aufruf auszuführen, werden viele komplizierte Probleme zusammengeführt. Vor allem, wenn man bedenkt, dass eine sorgfältige Auswahl der Bibliothek dies vermeidet.
In beiden Fällen ist die Lösung IMO für diese Art von Problemen, ein Werkzeug nach oder während der Kompilierung zu verwenden, um nach Problemen zu suchen, anstatt den Compiler zu modifizieren. Solch ein Tool kann "Ihren Code" leichter als "ihren Code" verstehen und besser bestimmen, wo Sie am besten bei unangemessener Verwendung warnen sollten. Sie können es auch tunen, ohne eine Reihe von Anmerkungen zur Quelldatei hinzufügen zu müssen, um Fehlalarme zu vermeiden. Ich kenne kein Werkzeug oder ich würde es vorschlagen.
Die Antwort war, dass ich wollte, war eine Ebene der Vollständigkeitsprüfung, die Haskell leider nicht bietet (noch?).
Alternativ möchte ich abhängige Typen (zB Idris ) oder einen statischen Verifizierer (zB Liquid Haskell ) oder Syntax-Flusenerkennung (zB hlint ).
Ich denke jetzt wirklich an Idris, es scheint eine erstaunliche Sprache zu sein. Hier ist eine Rede des Idris-Gründers , die ich empfehlen kann.
Credits für diese Antworten gehen an @dublode, @chi, @ user3237465 und @luqui.
Haskell erlaubt willkürliche allgemeine Rekursion, es ist also nicht so, dass alle Haskell-Programme notwendigerweise total wären, wenn nur %code% in ihren verschiedenen Formen entfernt würde. Das heißt, Sie könnten einfach %code% definieren, um sich um jeden Fall zu kümmern, den Sie sowieso nicht behandeln wollen. Ein Laufzeitfehler ist nur hilfreicher als eine Endlosschleife.
Sie sollten nicht an %code% denken, das einer Garten-Java-Ausnahme ähnelt. %code% ist ein Assertionsfehler, der einen Programmierfehler darstellt, und eine Funktion wie %code% , die %code% aufrufen kann, ist eine Assertion. Sie sollten nicht versuchen, die von %code% erzeugte Ausnahme abzufangen, außer in speziellen Fällen wie einem Server, der weiter ausgeführt werden muss, selbst wenn der Handler für eine Anfrage einen Programmierfehler feststellt.
Ich lerne gerade Haskell. Eine der Motivationen, warum ich diese Sprache gewählt habe, war, Software mit einem sehr hohen Grad an Robustheit zu schreiben, d. H. Funktionen, die vollständig definiert, mathematisch deterministisch sind und niemals abstürzen oder Fehler erzeugen. Ich meine nicht Versagen, das durch Prädikate des Systems verursacht wird ("System aus dem Speicher", "Computer in Brand" usw.), diese sind nicht interessant und können einfach den gesamten Prozess zum Absturz bringen. Ich meine auch kein fehlerhaftes Verhalten aufgrund ungültiger Deklarationen ( %code% ).
Stattdessen beziehe ich mich auf Fehler, die durch fehlerhafte Zustände verursacht werden, die ich entfernen möchte, indem ich diese Zustände durch strenge statische Typisierung nicht darstellbar und nicht-kompilierbar (in einigen Funktionen) machen kann. In meinen Augen nannte ich diese Funktionen "rein" und dachte, dass das starke System mir erlauben würde, dies zu erreichen. Haskell definiert auf diese Weise jedoch nicht "rein" und lässt Programme in jedem Kontext über %code% abstürzen.
Warum ist Fang eine Ausnahme nicht rein, aber eine Ausnahme zu werfen ist rein?
Das ist völlig akzeptabel und überhaupt nicht seltsam. Die enttäuschende Sache ist jedoch, dass Haskell anscheinend keine Funktionalität bietet, um Funktionsdefinitionen zu verbieten, die zu Verzweigungen mit %code% führen könnten.
Hier ist ein künstliches Beispiel, warum ich das enttäuschend finde:
%Vor%Sagen wir, dass ich paranoid bin, dass die reinen Funktionen %code% und %code% aufgrund von nicht gehandelten Zuständen wirklich nicht fehlschlagen. Sie können sich vorstellen, dass der Code dafür gedacht ist, eine Rakete voller Astronauten zu starten, die in einer absolut kritischen Routine Fruchtwerte serialisieren und deserialisieren müssen.
Die erste Gefahr besteht natürlich darin, dass wir bei unserem Mustervergleich einen Fehler gemacht haben, da dies uns die gefürchteten fehlerhaften Zustände gibt, die nicht behandelt werden können. Zum Glück bietet Haskell eingebaute Möglichkeiten, dies zu verhindern, wir kompilieren unser Programm einfach mit %code% , das %code% und AHA enthält:
%Vor%Wir haben vergessen, Pfirsichfrüchte zu serialisieren und %code% hätte einen Fehler ausgelöst. Das ist eine einfache Lösung, wir fügen einfach hinzu:
%Vor%Das Programm kompiliert jetzt ohne Warnungen, Gefahr abgewendet! Wir starten die Rakete, aber plötzlich stürzt das Programm mit:
%Vor%Die Rakete ist zum Untergang verurteilt und trifft den Ozean, verursacht durch die folgende fehlerhafte Linie:
%Vor%Im Wesentlichen %code% hat einen Zweig, wo es %code% erhöht, also wollten wir nicht einmal das Programm kompilieren, wenn wir es benutzen wollten, da %code% absolut "super" rein sein musste. Wir hätten das zum Beispiel reparieren können, indem wir die Zeile durch ersetzen:
%Vor%Ich finde es merkwürdig, dass Haskell beschließt, strenge Typisierung und unvollständige Mustererkennung zu implementieren, alles in dem nobel-Streben, ungültige Zustände nicht darstellbar zu machen, sondern direkt vor die Ziellinie zu fallen, indem er Programmierern keine Möglichkeit gibt, Zweige zu erkennen %code% , wenn sie nicht erlaubt sind. In einem gewissen Sinn macht das Haskell weniger robust als Java, was Sie zwingt, die Ausnahmen zu deklarieren, die Ihre Funktionen auslösen dürfen.
Der einfachste Weg, dies zu implementieren, wäre einfach undefiniert %code% in irgendeiner Weise, lokal für eine Funktion und jede Funktion, die von ihrer Gleichung über eine Form der zugehörigen Deklaration verwendet wird. Dies scheint jedoch nicht möglich zu sein.
Die Wiki-Seite über Fehler im Vergleich zu Ausnahmen erwähnt zu diesem Zweck eine Erweiterung namens "Extended Static Checking" über Verträge, aber sie führt nur dazu zu einem defekten Link.
Es läuft im Grunde darauf hinaus: Wie bekomme ich das obige Programm, um nicht zu kompilieren, weil es %code% verwendet? Alle Ideen, Vorschläge und Lösungen sind willkommen.