Variable des Typs Ambiguous, die mit der Gleichheitsbegrenzung des Typs korrigiert wird

8

Ich arbeite an einer monadischen Streaming-Bibliothek und bin in eine Art Sache geraten, die ich nicht verstehe. Ich habe es geschafft, es auf das folgende Beispiel zu reduzieren:

%Vor%

Wenn ich versuche es zu kompilieren, bekomme ich:

%Vor%

was, denke ich, mich ein wenig überrascht, obwohl vielleicht nicht zu viel. Was mich wirklich überrascht ist, dass, wenn ich die Instanz durch die folgenden ersetze, alles funktioniert:

%Vor%

Ich sehe den Unterschied zwischen den beiden Instanzdeklarationen nicht. Ich vermute, dass dies etwas damit zu tun hat, wie Typvariablen definiert sind. Kann jemand erklären, was vor sich geht?

[Nebenbei: Ich sehe dasselbe, wenn ich fundeps benutze.]

    
Itai Zukerman 01.10.2014, 17:22
quelle

1 Antwort

5

Bearbeiten : GHC-Benutzerhandbuch Abschnitt zur Instanzauflösung ist ein guter Anfang.

Hier erfahren Sie, wie Sie das Problem lösen können. Dein z entspricht ungefähr dem:

%Vor%

Ist es jetzt klarer, warum es nicht möglich ist? Der Fehler, den wir bekommen, ist:

%Vor%

Es gibt nichts zu zeigen, dass a ~ Int . Lass es uns umschreiben:

%Vor%

Dies funktioniert sogar mit Ihrer ursprünglichen Instanz. ( Bearbeiten : Ich vermute, der folgende Satz ist entweder nicht hilfreich oder irreführend oder beides.) z' ist (ungefähr), wo der Typchecker mit Ihrer neu geschriebenen Instanzdefinition endet: er sieht eine Instanz für (Bar a) (Bar a') Dies erfordert (a ~ a') und fügt diese Einschränkung nur dem Aufruf hinzu.

Grob gesagt geht die Instanzauflösung von rechts nach links, mit manchmal unerwarteten Konsequenzen.

Bearbeiten: Und das Ergebnis der rechts-nach-links-Auflösung ist, dass instance (x ~ x') => Foo (Bar x) (Bar x') mit den beliebigen zwei Typen x und x' übereinstimmt, unabhängig davon, ob x ~ x' ist tatsächlich der Fall. Die Einschränkung wird nur an die Aufrufstelle weitergegeben. Sie können dann keine weitere Instanz für bestimmte Typen schreiben. Es würde sich überschneiden, was standardmäßig verboten ist, und außerdem rückt GHC beim Auflösen von Instanzen nicht zurück. instance Foo (Bar x) (Bar x) wird dagegen nicht angewendet, es sei denn, es ist an beiden Stellen derselbe Typ - GHC wird die Einschränkung nicht erfinden, weil (x ~ y) => M x y nicht mit M x x identisch ist.

Abhängig von Ihrem tatsächlichen Anwendungsfall sollten Sie die Dokumentation für ÜberlappendeInstanzen . Je nach dem, was Sie gerade tun, sind einige der jüngsten Neuerungen in Familien , wie geschlossene Familien , kann relevant sein.

    
Christian Conkle 01.10.2014, 17:33
quelle

Tags und Links