Haskell Funktion nub ineffizient

7

Ich bin verwirrt über die Implementierung der Funktion 'nub' (select unique values) in der Haskell-Standardbibliothek Data.List . Die GHC-Implementierung ist

%Vor%

Soweit ich das beurteilen kann, hat dies eine Zeitkomplexität von 0 (n ^ 2) im ungünstigsten Fall, da es für eine Liste eindeutiger Werte alle einmal vergleichen muss, um zu sehen, dass sie tatsächlich einzigartig sind / p>

Wenn man eine Hash-Tabelle verwendet, kann die Komplexität auf O (n) für den Aufbau der Tabelle + O (1) reduziert werden, um jeden Wert mit vorherigen Werten in der Hash-Tabelle zu vergleichen. Zugegeben, dies würde keine geordnete Liste ergeben, aber das wäre auch in O (n log n) möglich, wenn GHC eine eigene geordnete Data.Map verwendet, falls dies notwendig ist.

Warum sollten Sie eine solche ineffiziente Implementierung für eine wichtige Bibliotheksfunktion wählen? Ich verstehe, dass Effizienz in Haskell kein Hauptanliegen ist, aber zumindest die Standardbibliothek könnte sich bemühen, die (asymptotisch) beste Datenstruktur für den Job zu wählen.

    
jforberg 18.01.2014, 21:02
quelle

3 Antworten

9

Effizienz ist in Haskell ein ziemliches Problem, schließlich ist die Sprache vergleichbar mit Java und schlägt sich in Bezug auf den Speicherverbrauch, aber natürlich ist es nicht C.

Die Antwort auf Ihre Frage ist ziemlich einfach: Das nub des Präludiums erfordert nur eine Eq Einschränkung, während jede Implementierung, die auf Map oder Set basiert, ebenfalls entweder Ord oder Hashable benötigt.

    
Nikita Volkov 18.01.2014, 21:22
quelle
10

Sie sind absolut richtig - nub ist ein O (n ^ 2) -Algorithmus. Es gibt jedoch immer noch Gründe, warum Sie es verwenden möchten, anstatt eine Hashmap zu verwenden:

  • für kleine Listen ist es vielleicht noch schneller
  • nub benötigt nur die Einschränkung Eq ; Zum Vergleich benötigt Data.Map eine Ord Einschränkung für Schlüssel und Data.HashMap erfordert einen Schlüsseltyp mit den Klassen Hashable und Ord type
  • es ist faul - Sie müssen nicht die gesamte Eingabeliste durchlaufen, um Ergebnisse zu erhalten

Bearbeiten: Leichte Korrektur am dritten Punkt - Sie müssen nicht die gesamte Liste bearbeiten, um Ergebnisse zu erhalten; Sie müssen immer noch jedes Element der Eingabeliste prüfen (so funktioniert nub nicht auf unendlichen Listen), aber Sie werden die Ergebnisse zurückgeben, sobald Sie ein eindeutiges Element finden.

    
ErikR 18.01.2014 21:26
quelle
3

Ссылка

Meiner Erfahrung nach ignoriert "Anfänger" Haskell (einschließlich Prelude und die schlechten Pakete) die Leistung in vielen Fällen zugunsten der Einfachheit.

Die Haskell-Leistung ist ein komplexes Problem, das Sie lösen müssen, wenn Sie nicht genug Erfahrung haben, um Platform oder Hackage nach Alternativen zum einfachen nub zu durchsuchen (und insbesondere, wenn Ihre Eingabe in einer Liste enthalten ist) über alternative Strukturen nachgedacht), dann ist Data.List.nub wahrscheinlich nicht dein einziges großes Leistungsproblem und du schreibst wahrscheinlich Code für ein Spielzeugprojekt, bei dem die Leistung keine Rolle spielt.

Sie müssen nur darauf vertrauen, dass Sie, wenn Sie ein großes (in Code oder Daten) Projekt erstellen, erfahrener sind und wissen, wie Sie Ihre Programme effizienter einrichten können.

Mit anderen Worten, machen Sie sich darüber keine Sorgen und nehmen Sie an, dass alles in Haskell 98, das von Prelude oder Basis stammt, wahrscheinlich nicht der effizienteste Weg ist, um ein Problem zu lösen.

    
misterbee 19.01.2014 14:17
quelle

Tags und Links