Redundanz in OCaml type-Angabe (ml/mli)
Ich versuche zu verstehen, eine bestimmte Sache zu ocaml-Modulen und deren Zusammenstellung:
bin ich gezwungen zu deklarieren Typen schon erklärt in einem .mli
innerhalb der spezifischen .ml
Implementierungen?
Nur um ein Beispiel zu geben:
(* foo.mli *)
type foobar = Bool of bool | Float of float | Int of int
(* foo.ml *)
type baz = foobar option
Diese, nach meiner normalen Art des Denkens über interfaces, Implementierungen, sollte ok sein, aber es sagt
Error: Unbound Typ-Konstruktor foobar
beim Versuch zu kompilieren mit
ocamlc -c foo.mli
ocamlc -c foo.ml
Natürlich der Fehler verschwindet, wenn ich erkläre foobar
innen foo.ml
auch, aber es scheint ein komplexer Weg, da ich ständig Dinge, die synchronisiert auf jede Veränderung.
Gibt es eine Möglichkeit, diese Redundanz vermeiden oder bin ich gezwungen zu deklarieren Typen jedes mal?
Vielen Dank im Voraus
Du musst angemeldet sein, um einen Kommentar abzugeben.
OCaml zu zwingen versucht, Sie zu trennen, die Schnittstelle (
.mli
) von der Implementierung (.ml
. Die meisten der Zeit, ist dies eine gute Sache; für die Werte, die Sie veröffentlichen, ist die Art in die Schnittstelle, und halten Sie den code in der Umsetzung. Man könnte sagen, dass OCaml ist die Durchsetzung eine gewisse Abstraktion (Schnittstellen veröffentlicht werden müssen; kein code-in-Schnittstellen).Für die Arten, sehr oft, die Umsetzung ist die gleiche wie die Schnittstelle: beide besagen, dass der Typ hat eine bestimmte Darstellung (und vielleicht, dass die Typ-Deklaration ist die generative). Hier gibt es keine Abstraktion, denn die Durchführung keine Informationen über die Art, die er nicht veröffentlichen möchten. (Die Ausnahme ist, im Grunde, wenn Sie deklarieren eine abstrakte Typ.)
Einen Weg, es zu betrachten ist, dass das interface bereits enthält genug Informationen, um zu schreiben, die Umsetzung. Angesichts der Schnittstelle
type foobar = Bool of bool | Float of float | Int of int
, es ist nur eine mögliche Implementierung. Also nicht schreiben, der eine Implementierung!Einer gemeinsamen Sprache ist, ein Modul zu haben, das gewidmet ist, um Typ-Deklarationen, und machen es nur ein
.mli
. Da die Typen nicht angewiesen auf Werte, dieses Modul kommt in der Regel in sehr früh in die Abhängigkeit Kette. Die meisten Werkzeuge für die Kompilierung von gut bewältigen; zum Beispielocamldep
wird das richtige tun. (Dies ist ein Vorteil, über nur eine.ml
.)Die Einschränkung dieses Ansatzes ist, wenn Sie müssen auch ein paar Modul-Definitionen hier und da. (Ein typisches Beispiel ist die Bestimmung der Art
foo
, dann einOrderedFoo : Map.OrderedType
Modul mittype t = foo
, dann wird eine weitere Deklaration mit'a Map.Make(OrderedFoo).t
.) Diese kann nicht gesetzt werden in interface-Dateien. Manchmal ist es akzeptabel, zu brechen, Ihre Definitionen in mehrere Stücke, zunächst eine Reihe von Arten (types1.mli
), dann ein Modul (mod1.mli
undmod1.ml
), dann mehr Arten (types2.mli
). Zu anderen Zeiten (zum Beispiel, wenn die Definitionen sind rekursive) Sie haben zu Leben, mit entweder einer.ml
ohne.mli
oder Vervielfältigung.Ja, Sie gezwungen sind, zu deklarieren Typen. Die einzigen Möglichkeiten, um ihn herum, die ich kenne, sind
Nicht verwenden .mli-Datei; ansonsten machen die alles mit, kein interface. Schreckliche Idee.
Verwenden Sie ein literate-programming Werkzeug, oder andere Präprozessor zu vermeiden, duplizieren der interface-Deklarationen in der Einen Wahren Quelle. Für große Projekte, wir tun dies, in meiner Gruppe.
Für kleine Projekte, wir Dupliziere einfach Typ-Deklarationen. Und schimpfen über Sie.
.ml
Datei zu folgern Arten beshrieben im gekoppelten.mli
. Von dem, was ich verstehe, ist die tatsächliche Umsetzung Kräfte Redundanz aber auch, dass die beiden Signaturen gleich sein müssen,, so ist dies praktisch eine Verdoppelung der gleichen Erklärungen. Das ist, warum ich dachte, es sollte bewusst sein, diese Erklärungen ohne kopieren&einfügen. Der Typ-Inferenz-Algorithmus würde nicht leiden, Probleme nach mir.Lassen Sie ocamlc generieren die mli-Datei für Sie aus der ml-Datei:
In der Regel ja, sind Sie verpflichtet, das Duplikat der Arten.
Können Sie dies umgehen, jedoch mit Camlp4 und die
pa_macro
syntax-Erweiterung (findlib-Paket:camlp4.macro
). Es legt fest, unter anderem, und GEHÖREN zu konstruieren. Sie können es verwenden, um den Faktor der gemeinsamen Typ-Definitionen in eine separate Datei und schließen Sie die Datei, in der sowohl die.ml
und.mli
- Dateien. Ich habe nicht gesehen, dies in eine bereitgestellte OCaml-Projekt, allerdings, so ich weiß nicht, ob es gelten würde, wie empfohlen, aber es ist möglich.Des literate programming Lösung, jedoch ist sauberer IMO.
Nein, in der mli-Datei, sagen Sie einfach: "Typ foobar". Dies funktionieren wird.