Die Implementierung von 'Ord' für einen Typ ist umständlich?

8

Versuche, meinen Kopf wieder in Rust zu legen.

Also ich habe einen Typ, lass es ein newtype zum Zweck der Einfachheit sein:

%Vor%

Und ich möchte Ord implementieren.

Also tue ich:

%Vor%

Wenn ich nun zwei Variablen meiner Typen vergleichen will, bekomme ich folgende Fehler:

%Vor%

Nun, wenn ich PartialEq, Eq und PartialOrd (gt (), lt (), eq (), ge (), le () ...) implementiere, funktioniert alles gut. Was für ein Chaos. ABER: Wenn ich cmp angegeben habe, können wir Funktionen wie lt() und eq ! Das ist überflüssig! Ich mag das nicht!

Wenn ich in Dokumenten nachschaue, sehe ich das in der Definition von Ord:

%Vor%

Nun sieht es so aus, als ob das Merkmal von Eq und PartialOrd erbt. Warum kann das Merkmal keine Standardimplementierungen für die erforderlichen Methoden aus den geerbten Merkmalen mithilfe der Funktion cmp bereitstellen? Ich weiß nicht, wie das Erben von Merkmalen funktioniert (Googeln hat nicht geholfen, was beim Rotieren von Rost üblich ist), aber ich denke, das ist etwas, das möglich sein sollte.

Wie ist das in Rust? Ich hoffe nicht so ...

    
Kapichu 07.02.2015, 21:40
quelle

2 Antworten

6

Nun, für Ihren speziellen Fall würde ich wahrscheinlich einfach #[derive] verwenden:

%Vor%

Wenn Sie Ihre Ord -Implementierung speziell behandeln müssen, müssen Sie diesen Code schreiben, da gibt es nichts, was uns rettet! Sie können immer noch Implementierungen für die anderen Merkmale ableiten, wenn es sinnvoll ist.

Der andere Teil Ihrer Frage ist mehrdeutig, also werde ich ihn auf beide Arten beantworten:

  

Warum kann Ord nicht automatisch mit PartialOrd bereitgestellt werden?

Schauen wir uns die Dokumente für PartialOrd und Ord .

PartialOrd sagt: "Der Vergleich muss Antisymmetrie und Transitivität " erfüllen, während Ord sagt: "Typen, die eine Gesamtordnung " bilden. Das sind mathematische Begriffe und ich werde nicht so gut arbeiten, wie Wikipedia sie beschreiben wird.

Wir können jedoch Gleitkommazahlen als Beispiel verwenden. Floats haben einen speziellen Wert namens NaN . Ein Vergleich mit diesem Wert ist schwierig. Zum Beispiel sind alle von 1.0 < NaN , 1.0 == NaN und 1.0 > NaN falsch! Diese bilden keine Gesamtordnung, aber wir können immer noch einen Wert mit einem anderen vergleichen. Deshalb gibt es PartialOrd - um solche Typen vergleichen zu können. Übrigens existiert PartialEq aus ähnlichen Gründen.

Wir können Ord in PartialOrd nicht definieren, da wir nicht die entsprechenden Garantien für die zugrunde liegenden Typen haben. Dies ist Rust's Typsystem, das uns davor bewahrt, einen Fehler zu machen!

  

Warum kann PartialOrd nicht automatisch mit Ord bereitgestellt werden?

Das Problem hier ist, dass mehr Typen PartialOrd sind als Ord . Wenn wir möchten, dass alles Ord ist, dann könnten wir keine beliebigen Gleitkommavergleiche haben, weil sie keine vollständige Reihenfolge haben. Oder wir müssen aufgeben, wenn wir eine Gesamtbestellung haben und die Sicherheit verlieren, die es bietet.

  

wenn ich PartialOrd (gt (), lt (), eq (), ge (), le () ...) implementiere

Beachten Sie, dass PartialOrd Standardimplementierungen hat, Sie müssen nur cmp implementieren. Die anderen sind da für die Benutzerfreundlichkeit oder möglicherweise Leistungsaspekte.

    
Shepmaster 07.02.2015 22:23
quelle
5

Zunächst können Sie nur PartialOrd::partial_cmp implementieren, da lt , le , gt und ge Standardimplementierungen haben. Wenn Sie Ord implementieren, können Sie einfach cmp wie gewohnt implementieren und partial_cmp wird nur Some(self.cmp(other)) .

Wenn Sie jedoch nur an den Begriff Gleichheit und Ordnung eines Feldes delegieren möchten, ist es viel besser und einfacher abzuleiten:

%Vor%     
delnan 07.02.2015 22:20
quelle

Tags und Links