Wie modelliere ich Vererbung in Haskell?

8

Ich versuche eine Spielengine zu erstellen, die aus ein paar verschiedenen Typen besteht:

%Vor%

Ich versuche jedoch, grundlegende Physik für alle diese Entitäten zu implementieren. Dies erfordert, dass sie jeweils ein pos :: (Double, Double, Double) und ein velocity :: (Double, Double, Double) enthalten.

In objektorientierten Sprachen würde ich es wie folgt implementieren:

%Vor%

wobei PhysicalObject die zwei Eigenschaften pos und velocity enthält.

Meine unmittelbare Reaktion war, sie alle auf den gleichen Typ zu setzen:

%Vor% Allerdings befürchte ich, dass dies die Implementierung von kameraspezifischen Funktionen, lichtspezifischen Funktionen usw. erschweren könnte. In Wirklichkeit haben sie nur noch sehr wenig gemeinsam, abgesehen davon, dass sie alle eine physische Position und Geschwindigkeit besitzen in der Welt.

Gibt es eine einfachere Möglichkeit, dies zu tun, als die beiden Eigenschaften in jedem Typkonstruktor zu definieren?

    
sdasdadas 03.01.2014, 18:26
quelle

3 Antworten

14

Ich kann mir zwei Ansätze vorstellen - Klassen und Linsen.

Geben Sie Klassen

ein %Vor%

Sie würden dann Instanzen für die Objekte entlang der folgenden Zeilen erstellen

%Vor%

und ähnlich für Ihre anderen Arten. Dann kann jede Funktion, die die Details eines Objekts nicht kennen muss, nur ihre Argumente als Instanzen von PhysicalObject angeben, zum Beispiel:

%Vor%

Sie werden jedoch Schwierigkeiten haben, Funktionen zu schreiben, die Ihre Objekte mit diesem Code modifizieren - die Klasse teilt Haskell mit, wie sie auf die Position und Geschwindigkeit eines Objekts zugreifen kann, aber nicht wie sie geändert werden / p>

Linsen

Die andere Möglichkeit besteht darin, sich an die Objektiv -Bibliothek zu wenden. Dies ist ein bisschen tierisch, aber es erlaubt Ihnen, einen sehr natürlichen Code zu schreiben. Zuerst gibt es ein bisschen Boilerplate

%Vor%

Definieren Sie nun einige Positions- und Geschwindigkeitsdatentypen. Mach dir keine Sorgen über die seltsamen Feldnamen, die mit Unterstrichen versehen sind - wir werden sie nicht verwenden.

%Vor%

Nun verwenden Sie ein wenig Template Haskell, um Objektive für Ihre Datentypen abzuleiten. Dadurch werden die Typklassen HasPos und HasVel generiert, deren Methoden Ihnen erlauben, auf alle Werte zuzugreifen und diese zu ändern, die eine Instanz dieser Klassen sind.

%Vor%

Definieren Sie nun Ihre Kamera-Klasse, die eine Position und eine Geschwindigkeit enthält.

%Vor%

Ein weiteres Bit von Template Haskell erstellt automatisch die Funktionen cameraPos und cameraVel , mit denen Sie auf die Position und Geschwindigkeit Ihrer Kamera zugreifen und diese ändern können.

%Vor%

Erklären Sie abschließend, dass Ihre Kamera eine Instanz der Klassen HasPos und HasVel ist, mit einer Standardimplementierung ihrer Methoden.

%Vor%

Jetzt sind wir bereit, echte Arbeit zu leisten. Lassen Sie uns eine Beispielkamera definieren

%Vor%

Eine Funktion zum Ändern der Kamera, die eine neue mit einer aktualisierten Position zurückgibt, ist

%Vor%

Beachten Sie, dass dies eine vollständig generische Funktion zum Verschieben eines Objekts mit einer Position und Geschwindigkeit ist - es ist überhaupt nicht spezifisch für den Camera -Typ. Es hat auch den Vorteil, viel wie Imperativ-Code zu sehen!

Wenn Sie nun all dies in GHCI laden, können Sie es in Aktion sehen

%Vor%     
Chris Taylor 03.01.2014, 18:58
quelle
4

Ich würde es ähnlich implementieren:

%Vor%

Dann können Sie für jeden definierten Typ, der PhysicalObject benötigt, ähnlich vorgehen.

    
bheklilr 03.01.2014 18:41
quelle
1

Sie wollen anfangen, von Dingen wie Typklassen und Objektkodierungen abhängig zu sein. Die erste Methode besteht darin, die allgemeine Schnittstelle als eine Typklasse zu codieren, von der jeder Typ erbt.

%Vor%

Die zweite besteht darin, ein gemeinsames Objekt zu erstellen

%Vor%

könnte sogar verwendet werden, um die erste Typklasse zu instanziieren

%Vor%

Seien Sie bei Typenklassen-Kodierungen jedoch vorsichtig, da ein zu großer Einsatz von ihnen oft zu Mehrdeutigkeiten beim Lesen von Code führt. Es kann schwierig sein, die Typen zu verstehen und zu wissen, welche Instanz verwendet wird.

    
J. Abrahamson 03.01.2014 18:41
quelle

Tags und Links