Angenommen, ich habe die folgende Klasse:
%Vor% Ich möchte erklären, dass alle Instanzen dieser Klasse automatisch Instanzen von Show
sind. Mein erster Versuch wäre folgender:
Mein erster Versuch, diesen Weg gestern zu gehen, führte zu einem Rabbit Warren von Spracherweiterungen: Mir wurde zuerst gesagt, dass ich flexible Instanzen, dann unentscheidbare Instanzen, dann überlappende Instanzen einschalten und schließlich einen Fehler über überlappende Instanzdeklarationen bekommen sollte. Ich gab auf und kehrte zum Wiederholen des Codes zurück. Dies scheint jedoch grundsätzlich eine sehr einfache Forderung zu sein, die leicht erfüllt werden sollte.
Also, zwei Fragen:
UndecidableInstances
brauche, da ich anscheinend die Paterson-Bedingung verletze, aber es gibt keine überlappenden Instanzen hier: Es gibt keine Instanzen von P
, even. Warum glaubt der Typchecker, dass es mehrere Instanzen für Show Double
gibt (wie es in diesem Spielzeugbeispiel der Fall zu sein scheint)? Sie erhalten den Fehler "Überlappende Instanzen", weil einige Ihrer Instanzen von P
möglicherweise andere Instanzen von Show
haben und der Compiler dann nicht in der Lage ist zu entscheiden, welche davon verwendet werden soll. Wenn Sie eine Instanz von P
für Double
haben, dann erhalten Sie zwei Instanzen von Show
für Double
: Ihre allgemeine und die bereits in Haskells Basisbibliothek deklarierte. Wie dieser Fehler ausgelöst wird, wird von @augusts in den Kommentaren zu Ihrer Frage korrekt angegeben. Weitere Informationen finden Sie unter die Spezifikationen .
Wie Sie bereits wissen, gibt es keine Möglichkeit, das zu erreichen, was Sie ohne UndecidableInstances
versuchen. Wenn Sie dieses Flag aktivieren, müssen Sie verstehen, dass Sie die Verantwortung des Compilers übernehmen, um sicherzustellen, dass keine widersprüchlichen Instanzen entstehen. Dies bedeutet, dass natürlich keine weiteren Instanzen von Show
in Ihrer Bibliothek erzeugt werden dürfen. Dies bedeutet auch, dass Ihre Bibliothek die Klasse P
nicht exportiert, wodurch Benutzer der Bibliothek die Möglichkeit haben, die in Konflikt stehenden Instanzen zu deklarieren.
Wenn Ihr Fall irgendwie mit dem oben Gesagten in Konflikt gerät, ist das ein sicheres Zeichen dafür, dass etwas nicht in Ordnung ist. Und tatsächlich gibt es ...
Was Sie erreichen wollen, ist vor allem falsch. Ihnen fehlen einige wichtige Punkte in der Show
-Typenklasse, die sie von Konstrukten wie einer toString
-Methode beliebter OO-Sprachen unterscheidet:
Aus Show Schellfisch :
Das Ergebnis von show ist ein syntaktisch korrekter Haskell-Ausdruck, der nur Konstanten enthält, vorausgesetzt, die Festschreibungserklärungen sind an dem Punkt gültig, an dem der Typ deklariert wurde. Es enthält nur die Konstruktornamen, die im Datentyp, in Klammern und in Leerzeichen definiert sind. Wenn beschriftete Konstruktorfelder verwendet werden, werden auch geschweifte Klammern, Kommas, Feldnamen und Gleichheitszeichen verwendet.
Mit anderen Worten, eine Instanz von Show
zu deklarieren, die keinen gültigen Haskell-Ausdruck erzeugt, ist per se falsch.
Angesichts der obigen Ausführungen ist es einfach nicht sinnvoll, eine benutzerdefinierte Instanz von Show
zu deklarieren, wenn der Typ es einfach ableiten lässt.
Wenn ein Typ es nicht erlaubt, sie abzuleiten (z. B. GADT), müssen Sie sich im Allgemeinen immer noch an typspezifische Instanzen halten, um korrekte Ergebnisse zu erzielen.
Wenn Sie also eine benutzerdefinierte Repräsentationsfunktion benötigen, sollten Sie Show
nicht dafür verwenden. Erklären Sie einfach eine benutzerdefinierte Klasse, z. B .:
und nähern Sie sich der Deklaration der Instanzen verantwortlich.