Immer noch neu in Haskell, ich habe eine Wand mit folgendem getroffen:
Ich versuche, einige Typklassen zu definieren, um eine Reihe von Funktionen zu verallgemeinern, die Gaußsche Eliminierung verwenden, um lineare Gleichungssysteme zu lösen.
Gegeben ein lineares System
%Vor% Der Typ a
der Elemente m(i,j) \elem M
kann sich vom Typ b
von x
und k
unterscheiden. Um das System zu lösen, sollte a
eine Instanz von Num
sein und b
sollte Multiplikations- / Additionsoperatoren mit b
haben, wie im Folgenden:
Nun, selbst in der trivialsten Implementierung dieser Operatoren, werde ich Could not deduce a ~ Int. a is a rigid type variable
errors bekommen (Vergessen wir ./.
, was Fractional
erfordert)
Ich habe mehrere Tutorials über Typklassen gelesen, aber ich kann keinen Hinweis darauf finden, was wirklich schief läuft.
Sehen wir uns die Art der Implementierung an, die Sie für (.*.)
bereitstellen müssten, um Wrap
zu einer Instanz von MixedRing
zu machen. Das Ersetzen von Wrap
für b
im Typ der Methode ergibt
Da Wrap
isomorph zu Int
ist und wir nicht über das Umbrechen und Entpacken mit Wrap
und get
nachdenken müssen, reduzieren wir unser Ziel, eine Implementierung von
(Sie sehen, dass dies die Herausforderung nicht einfacher oder schwerer macht, oder?)
Beachten Sie, dass eine solche Implementierung in der Lage sein muss, alle Typen a
zu verwenden, die sich in der Typklasse Num
befinden. (Dies ist, was eine Typvariable in einem solchen Typ bezeichnet: universelle Quantifizierung.) Hinweis: Dies ist nicht das Gleiche (eigentlich ist es das Gegenteil) zu sagen, dass Ihre Implementierung selbst wählen kann, was a
zu tun ist); Doch das scheint es in Ihrer Frage zu sein: dass Ihre Implementierung Int
als Auswahl für a
auswählen sollte.
Nun, da Sie diese bestimmte (.*.)
in (*)
für Werte vom Typ Int
implementieren möchten, benötigen wir etwas von der Form
mit
%Vor% Ich kann mir keine Funktion vorstellen, die aus einem beliebigen Num
-Typ a
in Int
sinnvoll konvertiert. Ich würde daher sagen, dass es keine sinnvolle Möglichkeit gibt, Int
(und damit Wrap
) zu einer Instanz von MixedRing
zu machen; Das heißt, nicht so, dass sich die Instanz so verhält, wie Sie es wahrscheinlich erwarten würden.
Wie wäre es mit etwas wie:
%Vor% Sie benötigen die Erweiterung MultiParamTypeClasses
.
Übrigens scheint mir, dass die mathematische Struktur, die Sie zu modellieren versuchen, wirklich Modul ist, kein Ring. Bei den oben angegebenen Typvariablen sagt man, dass b
ein a
-Modul ist.
Ihre Implementierung ist nicht polymorph genug.
Die Regel lautet: Wenn Sie a
in die Klassendefinition schreiben, können Sie in der Instanz keinen konkreten Typ verwenden. Weil die Instanz der Klasse und der Klasse entsprechen muss, die versprochen wurde, irgendeine a
zu akzeptieren, die Num
ist.
Um es anders auszudrücken: Genau die Klassenvariable muss mit einem konkreten Typ in einer Instanzdefinition instanziiert werden.
Hast du es versucht:
%Vor% Beachten Sie, dass, wenn Wrap a
eine Instanz ist, Sie sie immer noch mit Funktionen verwenden können, die nur Wrap Int
akzeptieren.