Ich arbeite gerade meinen Weg durch Schreibe dir selbst ein Programm in 48 Stunden und bleibe bei der Typ-Promotion hängen.
Kurz gesagt, das Schema hat einen numerischen Turm (Integer- & gt; Rational- & gt; Real- & gt; Komplex) mit den numerischen Promotionen, die man erwarten würde. Ich modellierte Zahlen mit dem offensichtlichen
%Vor% Mit Rank2Types schien es also eine einfache Möglichkeit zu sein, Funktionen über diesen Bereich von Typen zu arbeiten. Für Num a
sieht das wie
was funktioniert, wird aber schnell verbose, weil für jede Typklasse ein separater Block benötigt wird.
Noch schlimmer ist, dass diese Implementierung von Complex vereinfacht wird, da das Schema separate Typen für den realen und den komplexen Teil verwenden kann. Dies zu implementieren würde eine angepasste Version erfordern, die zwei Number
enthält, was die Ausführlichkeit noch verschlimmern würde, wenn ich vermeiden wollte, dass der Typ rekursiv wird.
Soweit ich weiß, gibt es keine Möglichkeit, über den Kontext zu abstrahieren, also hoffe ich auf eine sauberere Art, diese Zahlenlogik zu implementieren.
Danke fürs Lesen!
Hier ist ein Vorschlag. Die primäre Sache, die Ihre typeEnum
-Funktion tun soll, ist, dass sie noch kein Num a
-Wörterbuch in den Geltungsbereich bringt. Lassen Sie uns also GADTs verwenden, um das zu ermöglichen. Ich werde ein paar Dinge vereinfachen, um die Idee einfacher zu machen und den Code zu schreiben, aber nichts Wesentliches: Ich konzentriere mich auf Number
und nicht auf LispVal
und ich werde keine detaillierten Fehler melden, wenn etwas schief läuft. Zuerst ein Beispiel:
Nun haben Sie Ihre Definition einer Typenzählung nicht angegeben. Aber ich werde meins geben, weil es Teil der geheimen Soße ist: meine Typenaufzählung wird eine Verbindung zwischen Haskells Term Level und Haskells Type Level über eine GADT haben.
%Vor% Wegen dieser Verbindung muss mein Number
-Typ nicht jeden dieser Fälle wiederholen. (Ich vermute, dass Ihre TypeEnum
und Number
Typen sich im Vergleich zueinander ziemlich repetitiv sind.)
Nun werden wir einen neuen Typ definieren, den Sie nicht hatten, der ein TypeEnum
mit einem Num
Dictionary für den entsprechenden Typ verbindet. Dies wird der Rückgabetyp unserer Funktion typeEnum
sein.
Die ordering
-Funktion spiegelt (meine Vermutung) die Richtung wider, in die die Umwandlungen gehen können. Wenn Sie versuchen, Eq
und Ord
selbst für diesen Typ zu implementieren, ohne nach meiner Lösung zu sehen, werden Sie vermutlich herausfinden, warum GHC diese Klassen für GADTs ableitet. (Zumindest brauchte ich ein paar Versuche! Die offensichtlichen Definitionen testeten nicht, und die etwas weniger offensichtlichen Definitionen hatten das falsche Verhalten.)
Jetzt können wir eine Funktion schreiben, die ein Wörterbuch für eine Zahl erzeugt.
%Vor% Wir werden auch die Casting-Funktion brauchen; Sie können im Wesentlichen einfach Ihre Definitionen von toComplex
und Freunde hier verketten:
Sobald wir diese Maschine installiert haben, ist liftNum
überraschend kurz. Wir finden nur den geeigneten Typ für die Umwandlung, ein Wörterbuch für diesen Typ und führen die Umwandlungen und die Operation durch.
An dieser Stelle beschweren Sie sich vielleicht: Ihr ultimatives Ziel war es, nicht einen Fall pro Klasseninstanz in liftNum
zu haben, und wir haben dieses Ziel erreicht, aber es sieht so aus, als hätten wir es einfach in die Definition von% verschoben. co_de%, wobei es einen Fall pro Klasseninstanz gibt. Ich wehre mich jedoch selbst: Sie haben uns nicht Ihre typeEnum
gezeigt, von der ich vermute, dass sie bereits einen Fall pro Klasseninstanz hatte. Wir haben also keine neuen Kosten in anderen Funktionen als typeEnum
angefallen und haben liftNum
tatsächlich erheblich vereinfacht. Dies bietet auch einen reibungslosen Upgrade-Pfad für komplexere liftNum
-Manipulationen: Erweitere die Complex
-Definition, die% cid_de% -Bearbeitung und die TypeEnum
-Funktion und du kannst loslegen; ordering
kann gleich bleiben. (Wenn sich herausstellt, dass Typen nicht linear geordnet sind, sondern eine Art Gitter oder ähnliches, dann können Sie von der Klasse to
wegschalten.)
Tags und Links haskell