Haskell Type Promotion

8

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

aus %Vor%

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!

    
Taren 01.02.2017, 17:03
quelle

1 Antwort

12

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:

%Vor%

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.)

%Vor%

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.

%Vor%

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:

%Vor%

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.

%Vor%

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.)

    
Daniel Wagner 01.02.2017, 17:56
quelle

Tags und Links