2009-11-17 17 views
19

Ich habe in letzter Zeit einige OCaml-Programmierung gemacht, um die Sprache zu lernen und mehr über die funktionale Programmierung zu lernen. Vor kurzem habe ich angefangen zu denken, dass ich möchte in der Lage sein eine bestehende Art zu erweitern (entweder eingebaut in-oder einem meiner eigenen), zum Beispiel: JetztErweitern eines vorhandenen Typs in OCaml

type bexp = 
    And of bexp * bexp 
| Or of bexp * bexp 
| Xor of bexp * bexp 
| Not of bexp;; 

sagen wir, ich möchte hinzufügen eine Nop-Variante zu diesem Typ, aber nur für den Einsatz in einem neuen Typ - eine Art der Vererbung. Hey, das sollen Algebraische Datentypen sein, oder? Also warum nicht etwas wie:

type nbexp = bexp | Nop nbexp ;; 

... aber das ist nicht gültig OCaml, gibt es einen Syntaxfehler. Grundsätzlich versuche ich zu sagen, dass nbexp alles beinhalten soll, was bexp includes enthält, und auch einen Nop hinzufüge. Ich nehme an, das ist nicht möglich, denn wenn Sie zum Beispiel den And-Konstruktor verwendet hätten, gäbe es keine Möglichkeit festzustellen, ob es sich um einen Bexp-Typ oder einen Nbexp-Typ handelt. (Ich denke, der Konstruktor Nop, der ein nbexp nimmt, könnte auch problematisch sein.)

Gibt es also eine Möglichkeit, so etwas in OCaml zu tun? Und ist das in Haskell so machbar (vielleicht mit Typenklassen)?

+1

tun Vielleicht von Interesse: https://sites.google.com/site/ocamlopen/ –

Antwort

19

Eine interessante Lösung ist polymorphe Variante zu verwenden:

type bexp = 
[ `And of bexp * bexp 
| `Or of bexp * bexp 
| `Xor of bexp * bexp 
| `Not of bexp ];; 

type nbexp = [ bexp | `Nop of nbexp ];; 

Beachten Sie, dass polymorphe Varianten sind schwieriger als normale, aber Erweiterung des Typs zu ermöglichen.

Ein interessantes Beispiel für die Ausdrucksauswertung, mit der Erweiterung kann in einem Testverzeichnis der ocaml Quelle finden Sie in das svn

+1

Ich habe davon gehört, aber noch nicht um mit wirklich bekommen Sie. Dies gibt mir einen guten praktischen Grund, mehr über sie zu erfahren. Vielen Dank. – aneccodeal

4

Hey, das sollen algebraische Datentypen sein, oder?

Richtig. Und algebraic data types sind durch getaggte (aka diskriminierte) Gewerkschaften und Produkte aufgebaut. Was Sie wollen, ist nur eine (nicht markierte) Union, die nicht ist ein algebraischer Datentyp und wird nicht von Haskell unterstützt. OCaml hat polymorphe Varianten (siehe andere Antworten).

Typed Scheme unterstützt nicht getaggte Verbindungen, also sollten Sie es überprüfen.

4

Wie Sie selbst richtig vermuten, ist dies bei algebraischen Typen nicht möglich. Ich stimme Apocalisps Vorschlag zu, dass Sie einfach den "geerbten" Teil von nbexp in einen eigenen Konstruktor einfügen können.

Ich würde hinzufügen, dass der Mangel an Vererbung von algebraischen Typen Teil ihrer Wunderbarkeit ist. Das bedeutet, dass ein Ausdruck wie And(foo, bar) eindeutig typisiert ist und dass das Casting (entweder nach oben oder nach unten) im Typsystem keine Rolle spielt. Dies führt zu mehr Sicherheit und größerer Klarheit. Es erfordert natürlich von dem Programmierer, dass er/sie explizit die Fälle behandelt, in denen er/sie mit den bexp Teilen von nbexp interagieren möchte, aber wenn Sie darüber nachdenken, wird die erhöhte Sicherheit und Klarheit in der Praxis realisiert.

Verwandte Themen