Wie effizient ist die abgeleitete EQ-Instanz in GHC?

8

Gibt es einen Kurzschluss , der in GHCs (und im Allgemeinen Haskell) abgeleitete Eq Instanz eingebaut ist, die ausgelöst werden, wenn ich dieselbe Instanz eines Datentyps vergleiche?

%Vor%

Mein Plan ist es, eine faule Datenstruktur (sagen wir mal einen Baum) einzulesen, einige Werte zu ändern und dann die alte und die neue Version zu vergleichen, um ein Diff zu erstellen, das dann in die Datei zurückgeschrieben wird.

Wenn ein Kurzschluss eingebaut wäre, würde der Vergleichsschritt abgebrochen, sobald er feststellt, dass die neue Struktur auf alte Werte verweist. Gleichzeitig würde dies nicht mehr als notwendig von der Datei in erster Linie lesen.

Ich weiß, dass ich mir keine Gedanken über Referenzen in Haskell machen sollte, aber das scheint eine gute Möglichkeit zu sein, mit faulen Dateiänderungen umzugehen. Wenn es keinen Kurzschluss gibt, gibt es einen Weg dies zu implementieren? Vorschläge zu verschiedenen Programmen sind willkommen.

    
fho 09.10.2012, 10:36
quelle

2 Antworten

8

StableNames wurden speziell entwickelt, um Probleme wie Ihre zu lösen.

Beachten Sie, dass StableNames nur in der IO -Monade erstellt werden kann. Sie haben also zwei Möglichkeiten: entweder erstellen Ihre Objekte in der IO -Monade oder verwenden Sie unsafePerformIO in Ihrer (==) -Implementierung (was in dieser Situation mehr oder weniger gut ist).

Aber ich sollte betonen, dass dies auf absolut sichere Weise möglich ist (ohne unsafe* -Funktionen): nur die Erstellung stabiler Namen sollte in IO geschehen; Danach kannst du sie auf eine vollkommen reine Art vergleichen.

z. B.

%Vor%

Beachten Sie, dass Sie, wenn der stabile Namensvergleich "nein" sagt, immer noch einen vollständigen Vergleich durchführen müssen, um eine endgültige Antwort zu erhalten.

Nach meiner Erfahrung hat das ziemlich gut funktioniert, wenn Sie viel teilen und aus irgendeinem Grund nicht bereit sind, andere Methoden zu verwenden, um das Teilen zu zeigen.

(Apropos andere Methoden, Sie könnten zum Beispiel die IO monad durch eine State Integer monad ersetzen und eindeutige ganze Zahlen in dieser Monade als Äquivalent von "stable names" erzeugen.)

Ein weiterer Trick ist, wenn Sie eine rekursive Datenstruktur haben, dass die Rekursion durch SNWrapper geht. Z.B. statt

%Vor%

verwenden

%Vor%

Auf diese Weise, auch wenn das Kurzschließen nicht auf der obersten Schicht ausgelöst wird, könnte es irgendwo in der Mitte feuern und Ihnen trotzdem etwas Arbeit ersparen.

    
Roman Cheplyaka 09.10.2012, 12:57
quelle
4

Es gibt keinen Kurzschluss, wenn beide Argumente von (==) dasselbe Objekt sind. Die abgeleitete Eq -Instanz wird einen strukturellen Vergleich durchführen und im Falle der Gleichheit natürlich die gesamte Struktur durchlaufen müssen. Sie können eine mögliche Verknüpfung mit

selbst erstellen %Vor%

aber das wird tatsächlich nur selten schießen:

%Vor%

Und wenn Sie eine Struktur aus einer Datei lesen, wird sie sicherlich nicht das selbe Objekt finden wie ein Objekt, das bereits im Speicher war.

Sie können Umschreibregeln verwenden, um den Vergleich von lexikalisch identischen Objekten zu vermeiden

%Vor%

was zu

führt %Vor%

die Regel feuern (Hinweis: Es hat nicht mit let x = "foo" ausgelöst, aber mit benutzerdefinierten Typen sollte es).

    
Daniel Fischer 09.10.2012 10:57
quelle

Tags und Links