2012-05-17 4 views
13
data Ray = Ray Vector Vector 

oderHaskell: Algebraische Daten vs Tuple

type Ray = (Vector, Vector) 

die in idiomatischen Haskell bevorzugt? Warum sollte ich eins über das andere benutzen?
Ich interessiere mich nicht für die Leistung.

Es scheint wenig Unterschied mit Funktionen zu machen, zB:

trace :: Ray -> … 

trace (Ray x d) = … 
-- OR 
trace (x, d) = … 

Antwort

10

Die data Version, da es eindeutig die Absicht des Programmierers zeigt mehr bevorzugt wird - durch eine neue Art zu schaffen, weisen Sie alle aus das ist nicht nur ein Tupel, sondern eine bedeutungsvolle semantische Einheit, ein Ray.

Das macht es dann möglich, sich auf das Typsystem mit benutzerdefinierten Instanzen für Ray und Optimierungen, die in Tupeln nicht möglich sind, zu stützen.

+1

Rechts. Und ein kritischer Punkt über Typen: Sie sind so viel mehr als nur die Darstellung von Daten; sie charakterisieren nützliche Struktur. – pigworker

+0

Okay, das macht Sinn. 'type' ist eigentlich nur ein Synonym, kein neuer Datentyp. Aber die Linie muss irgendwo gezeichnet werden - "type Color = (Int, Int, Int)" wäre angemessen, oder? – mk12

+2

Nein, aus Performance-Gründen ist es sinnvoller, einen gepackten Vektortyp für Color zu haben, wie im Farbpaket - aussagekräftige Typen wie diese können optimiert und spezialisiert werden. http://hackage.haskell.org/packages/archive/colour/2.3.3/doc/html/src/Data-Colour-Internal.html#Colour –

6

könnten Sie auch eine dritte Option in Betracht ziehen, die Art einer Kombination der beiden ist: newtype

newtype Ray = Ray (Vector, Vector) 

Algebraische Datentypen, meiner Meinung nach, in Situationen verwendet werden, wenn Sie mehrere Alternativen haben, oder in Fällen, in denen Sie benötigen den Typ, der rekursiv ist und sich selbst enthält. Aber es könnte für so etwas übertrieben sein.

Don Stewart wies darauf hin, dass die Erstellung eines Typ-Synonyms für Tupel dasselbe ist wie die direkte Verwendung des Tupeltyps; Typ Synonyme haben keine eigene Identität. Der Typprüfer kann also nicht zwischen Ihrem Typ und einem Tupel unterscheiden und kann daher nicht überprüfen, ob Sie den gewünschten Typ verwenden. Außerdem würde es genau dieselben Instanzen wie ein Tupel haben.

Ein newtype ermöglicht es Ihnen, den gleichen zugrunde liegenden Typ wie das Tupel zu verwenden; aber es ist ein separater Typ für den Typ Checker mit separaten Instanzen.

+0

Dies scheint weniger üblich als die Verwendung der Curry-Form. Vielleicht nur, weil es mehr Interpunktion ist. – luqui

3

Eine vierte Alternative, die ich sehr bequem gefunden sind Datensätze:

data Ray = Ray { from, to :: Vector } 

Sie haben im Grunde alle Eigenschaften von „normalen“ ADTs, aber mit einigen zusätzlichen syntaktischen Zucker. Insbesondere erleichtern sie es, teilweise modifizierte Kopien eines Wertes zu erhalten. Es ist wahr, dass die Aufzeichnungen in einigen Situationen zu begrenzt sind, aber dann können Sie mit "verbesserten Versionen" wie fclabels weiter gehen.