2008-11-06 15 views
18

In Python arbeitet map() mit allen Daten, die dem Sequenzprotokoll folgen. Es tut das Richtige Ding TM, ob ich ihm eine Zeichenkette oder eine Liste oder sogar ein Tupel füttere.Hat OCaml allgemeine map()/reduce() Funktionen?

Kann ich meine Kuchen nicht auch in OCaml haben? Habe ich wirklich keine andere Wahl, als den verwendeten Collection-Typ zu betrachten und eine entsprechende List.map oder eine Array.map oder eine Buffer.map oder eine String.map zu finden? Einige davon existieren nicht einmal! Ist das, wonach ich frage, ungewöhnlich? Ich muss etwas verpassen.

+0

Also, was genau ist falsch mit der Dokumentation nachschlagen und die entsprechende Funktion verwenden? –

Antwort

17

Am nächsten kommt das Modul Enum in OCaml Batteries Included (früher von Extlib). Enum definiert Karten und Falten über Enum.t; Sie müssen nur eine Konvertierung zu/von Enum.t für Ihren Datentyp verwenden. Die Konvertierungen können ziemlich leicht sein, weil Enum.t faul ist.

Was Sie wirklich wollen, ist Haskell-Stil type classes, wie Foldable und Functor (die "Karten" verallgemeinert). Die Haskell-Bibliotheken definieren Instanzen von Foldable und Functor für Listen, Arrays und Bäume. Eine weitere relevante Technik ist die "Scrap Your Boilerplate" approach zur generischen Programmierung. Da OCaml keine Typklassen oder higher-kinded polymorphism unterstützt, glaube ich nicht, dass Sie in der Lage sind, solche Muster in ihrem Typsystem auszudrücken.

+0

In ML löst das übergeordnete Modulsystem dieses Problem. –

+0

Ich stimme nicht zu, dass das Umhüllen alles in einem funktor eine "Lösung" für dieses Problem ist. –

+0

Sie sind mit einer Tatsache nicht einverstanden.In Okasakis Buch finden Sie viele Beispiele und einen Vergleich, der erklärt, warum die OCaml-Lösung in diesem Kontext Klassen vorzuziehen ist. –

1

Das Problem ist, dass jeder Container eine andere Darstellung hat und anderen Code für map/reduce benötigt, um darüber zu iterieren. Deshalb gibt es separate Funktionen. Die meisten Sprachen bieten eine Art allgemeine Schnittstelle für Container (wie das von Ihnen erwähnte Sequenzprotokoll), so dass Funktionen wie map/reduce abstrakt implementiert werden können, aber dies wird nicht für die von Ihnen erwähnten Typen getan.

-3

Solange Sie in Ihrem Modul einen Typ t und val compare (: t-> t-> int) definieren, wird Map.Make Ihnen die gewünschte Karte geben.

10

Es gibt zwei Hauptlösungen in OCaml:

  1. Jacques Garrigue bereits vor einigen Jahren syntaktisch-Licht, aber ineffiziente Ansatz für viele Datenstrukturen implementiert. Sie wickeln die Sammlungen einfach in Objekte ein, die eine map-Methode bereitstellen. Dann können Sie collection#map tun, um die Kartenfunktion für jede Art von Sammlung zu verwenden. Dies ist allgemeiner als Ihre Anforderungen, da verschiedene Arten von Datenstrukturen zur Laufzeit ersetzt werden können. Dies ist jedoch in der Praxis nicht sehr nützlich, so dass der Ansatz nie weit verbreitet wurde.

  2. Eine syntaktisch schwerere, aber effiziente, robuste und statische Lösung besteht darin, Funktoren zu verwenden, um Ihren Code über die von Ihnen verwendete Datenstruktur zu parametrisieren. Dies macht es trivial, Ihren Code mit anderen Datenstrukturen wiederzuverwenden. Siehe Markus Mottls OCaml-Übersetzungen von Okasakis Buch "Purely Functional Data Structures" für einige großartige Beispiele.

Wenn Sie suchen nicht nach dieser Art von Macht und nur Kürze wollen, dann, natürlich, man kann nur ein Modul Alias ​​mit einem kürzeren Namen erstellen (zum Beispiel Modul S = String).