Ich verstehe, warum Sie dies tun möchten, aber leider kann es nur eine Illusion sein, dass Haskell-Klassen so "offen" zu sein scheinen, wie Sie es sagen. Viele Leute glauben, dass die Möglichkeit, dies zu tun, ein Fehler in der Haskell-Spezifikation ist, aus Gründen, die ich unten erläutern werde. Wenn es für die Instanz wirklich nicht geeignet ist, müssen Sie entweder in dem Modul deklariert werden, in dem die Klasse deklariert ist, oder in dem Modul, in dem der Typ deklariert ist. Dies ist wahrscheinlich ein Zeichen dafür, dass Sie einen newtype
oder einen anderen Wrapper verwenden sollten um Ihren Typ.
Die Gründe, warum verwaiste Instanzen vermieden werden müssen, liegen weit über dem Komfort des Compilers. Dieses Thema ist ziemlich kontrovers, wie Sie anderen Antworten entnehmen können. Um die Diskussion auszugleichen, werde ich den Standpunkt erläutern, dass man niemals verwaiste Instanzen schreiben sollte, was meiner Meinung nach die Mehrheitsmeinung unter erfahrenen Haskellern ist. Meine eigene Meinung ist irgendwo in der Mitte, was ich am Ende erklären werde.
Das Problem ergibt sich aus der Tatsache, dass es in Standard-Haskell keinen Mechanismus gibt, um anzugeben, welche verwendet werden soll, wenn mehr als eine Instanzdeklaration für dieselbe Klasse und denselben Typ vorhanden ist. Vielmehr wird das Programm vom Compiler abgelehnt.
Der einfachste Effekt davon ist, dass Sie ein perfekt funktionierendes Programm haben könnten, das plötzlich aufgrund einer Änderung, die jemand anderes in einer weit entfernten Abhängigkeit von Ihrem Modul vornimmt, nicht mehr kompiliert wird.
Schlimmer noch, es ist möglich, dass ein Arbeitsprogramm zur Laufzeit aufgrund einer entfernten Änderung abstürzt . Sie könnten eine Methode verwenden, von der Sie annehmen, dass sie aus einer bestimmten Instanzdeklaration stammt, und sie könnte stillschweigend durch eine andere Instanz ersetzt werden, die gerade so unterschiedlich ist, dass Ihr Programm unerklärlich abstürzt.
Personen, die garantieren möchten, dass ihnen diese Probleme niemals passieren, müssen die Regel befolgen, dass, wenn irgendjemand irgendwo jemals eine Instanz einer bestimmten Klasse für einen bestimmten Typ deklariert hat, keine andere Instanz in einem geschriebenen Programm jemals wieder deklariert werden darf von jemandem. Natürlich gibt es die Problemumgehung newtype
, eine neue Instanz mit de zu deklarieren, aber das ist immer zumindest eine kleine und manchmal eine große Unannehmlichkeit. In diesem Sinne sind diejenigen, die absichtlich verwaiste Instanzen schreiben, eher unhöflich.
Was ist also gegen dieses Problem zu tun? Das Anti-Orphan-Instance-Camp gibt an, dass die GHC-Warnung ein Fehler ist. Es muss sich um einen Fehler handeln, der jeden Versuch, eine Orphan-Instanz zu deklarieren, ablehnt. In der Zwischenzeit müssen wir Selbstdisziplin üben und sie um jeden Preis vermeiden.
Wie Sie gesehen haben, gibt es diejenigen, die sich über diese potenziellen Probleme nicht so viele Sorgen machen. Sie fördern tatsächlich die Verwendung von verwaisten Instanzen als Instrument zur Trennung von Bedenken, wie Sie vorschlagen, und sagen, dass man nur von Fall zu Fall sicherstellen sollte, dass es kein Problem gibt. Die verwaisten Instanzen anderer Leute haben mich oft genug belästigt, um davon überzeugt zu sein, dass diese Haltung zu unbekümmert ist.
Ich denke, die richtige Lösung wäre, dem Importmechanismus von Haskell eine Erweiterung hinzuzufügen, die den Import von Instanzen steuert. Das würde die Probleme nicht vollständig lösen, aber es würde helfen, unsere Programme vor Schäden durch die bereits auf der Welt existierenden verwaisten Instanzen zu schützen. Und dann könnte ich mit der Zeit davon überzeugt sein, dass in bestimmten begrenzten Fällen eine verwaiste Instanz möglicherweise nicht so schlecht ist. (Und genau diese Versuchung ist der Grund, warum einige im Lager gegen Waisen gegen meinen Vorschlag sind.)
Meine Schlussfolgerung aus all dem ist, dass ich zumindest vorerst dringend empfehlen würde, keine Orphan-Instanzen zu deklarieren, um anderen gegenüber rücksichtsvoll zu sein, wenn auch aus keinem anderen Grund. Verwenden Sie a newtype
.