Vererbung zu erweitern, eine Datenstruktur in Haskell
Als C++ - Programmierer, die versuchen zu lernen, Haskell hier. Bitte entschuldigt diese wahrscheinlich einfache Frage. Ich will übersetzen ein Programm, das stellt 3D-Formen. In C++ habe ich sowas wie:
class Shape {
public:
std::string name;
Vector3d position;
};
class Sphere : public Shape {
public:
float radius;
};
class Prism : public Shape {
public:
float width, height, depth;
};
Ich versuche zu übersetzen, diese zu Haskell (unter Verwendung von Datensätzen?) so kann ich einige Funktionen, die wissen, wie zu bedienen, auf einer Form (wie der Zugriff auf name und position), und andere als nur wissen, wie zu bedienen, auf Kugeln, wie die Berechnung etwas, was sich auf seine position und radius.
In C++ eine member-Funktion kann der nur Zugriff auf diese Parameter, aber ich habe eine harte Zeit, herauszufinden, wie dies zu tun ist in Haskell mit Datensätzen, oder Typ-Klassen, oder was auch immer.
Dank.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Entgegen dem trend der Hindernisse für die Verwendung von typeclasses, empfehle ich (wie Sie lernen), erkunden die beiden eine Lösung ohne typeclasses und einen mit, bis man ein Gefühl für die verschiedenen Nachteile der verschiedenen Ansätze.
Den "einzigen geschlossenen Datentyp" Lösung ist sicherlich mehr "funktional" als typeclasses. Es bedeutet, dass Ihre Liste der Formen ist "Feste", die durch Ihre Form-Modul und nicht erweiterbar mit neuen Formen von außen. Es ist immer noch leicht um neue Funktionen hinzuzufügen, die operative Formen.
Haben Sie eine leichte Unannehmlichkeiten hier, wenn Sie eine Funktion, die funktioniert nur auf einer einzigen Form, da Sie das statische compiler überprüfen, dass die Form übergeben wird, wird die korrekte Funktion (siehe Nathan ' s Beispiel). Wenn Sie eine Menge von dieser partiellen Funktionen, die nur über einen Konstruktor Datentyp ist, würde ich ein überdenken der Herangehensweise.
Für eine typeclass Lösung, würde ich persönlich eher nicht Spiegel der shape-Klasse Hierarchie, sondern um die Art der Klassen, für "Dinge mit einer Fläche", "Dinge, die ein Volumen", "Dinge, die mit einem radius", ...
Dadurch können Sie Funktionen schreiben, nehmen bestimmte Arten von Formen, sagen Sphären, nur (wie jede Form ist seine eigene Art), aber Sie können nicht schreiben Sie eine Funktion, die "alle Formen" und dann unterscheidet die verschiedenen konkreten Arten von Formen.
Die straight-forward-translation.
Sie in der Regel nicht tun Sie dies, obwohl; es ist repetitious und polymorphe Listen erfordern Spracherweiterungen.
Statt, kleben Sie Sie in eine geschlossene Datentyp ist wahrscheinlich die erste Lösung, die Sie anstreben sollten.
Sicher kann man simulieren, sind mehrere Ebenen von Vererbung durch die Schaffung von mehr typeclasses:
Können Sie auch simulieren, indem Sie die Einbettung von Datentypen.
Aber die Simulation OO in Haskell ist nicht annähernd so befriedigend, wie tatsächlich mit dem Gedanken, in ein Haskellish Weg. Was wollen Sie tun?
(Beachten Sie auch, dass alle diese Lösungen erlauben nur upcasts, downcasting ist zu gefährlich und nicht zulässig.)
shape
->Prism
->RectangularPrism
Wie Nathan sagte, Modellierung von Datentypen ist völlig anders in Haskell von C++. Sie könnten den folgenden Ansatz:
In anderen Worten, das Modell Verweise auf super-Klassen als zusätzliche Felder in Ihrem Datentyp. Es ist leicht erweitert, um mehr erbschaft-Ketten.
Nicht verwenden Typ-Klassen, wie ephemient schlägt. Diese werden verwendet für das überladen von Funktionen und das ist nicht das Problem hier überhaupt: Ihre Frage betrifft die Modellierung von Daten, nicht Verhalten.
Hoffe, das hilft!
Einer einfachen übersetzung bricht der Teil, der variiert, aber vermeidet typeclasses:
dann
Dies ist nicht eine wirklich einfache Frage. Daten-Struktur-design ist sehr unterschiedlich zwischen C++ und Haskell, so dass ich Wette, dass die meisten Besucher aus einer OO-Sprache, Fragen die gleiche Sache.
Leider, der beste Weg, um zu lernen, ist zu tun; Ihre beste Wette ist zu versuchen, es auf einer Fall-zu-Fall-basis, bis Sie lernen, wie die Dinge funktionieren in Haskell.
Meine Antwort ist ziemlich einfach, aber es funktioniert nicht gut umgehen mit dem Fall, wo eine einzige C++ - Unterklasse verfügt über Methoden, die andere nicht. Er wirft einen runtime error und erfordert zusätzlichen code zu Booten. Sie haben auch zu entscheiden, ob die "Unterklasse" - Modul entscheidet, ob zu werfen, der Fehler oder die "Oberklasse" - Modul.