Warum hohe Implikationen werden in einigen Fällen ignoriert?

8

Ich habe einen seltsamen Compiler-Fehler bezüglich eines impliziten, der tatsächlich vorhanden ist, aber aus einem Grund nicht gefunden werden konnte. Also habe ich einen kleinen Testfall gebaut, der mysteriöses Verhalten reproduziert.

%Vor%

Einfacher Typ, der als eindeutiges Ziel für implizite Konvertierungen verwendet wird.

%Vor%

Methoden, die auf impliziten Konvertierungen beruhen. Es ist im Grunde 2x2-Matrix. id Methoden gibt den konvertierten Typ zurück und drop Methoden verwenden die Konvertierung intern und geben eine Konstante zurück. Normale Methoden arbeiten mit exakt implizit konvertierten Typ und Seq -Methoden arbeiten mit Sequenzen.

%Vor%

Oberhalb der impliziten Konvertierungen ist highString mit dem Typ höherer Ordnung definiert.

%Vor%

Der Versuch, Conversions tatsächlich zu verwenden, führt zu einem Fehler:

%Vor%

Das könnte in der folgenden Matrix zusammengefasst werden:

%Vor%

Wenn ich für die dropSeq -Methode eine genau definierte implizite Konvertierung verwende, wird normalerweise gefunden:

%Vor%

Und außerdem, wenn ich explizit das implizite Argument dropSeq zu arbeiten beginne:

%Vor%

Und das ist das Seltsamste. highString implizit passt zu allen Anforderungen. Und es wird als implicit deklariert, daher sollte es vom Compiler gefunden werden. Und im Fall von idSeq wird es tatsächlich gefunden. Warum wird es im Fall dropSeq ignoriert?

    
ayvango 27.02.2016, 00:41
quelle

1 Antwort

1

In deinem Fall ist der einzige Unterschied zwischen idSeq und dropSeq der Rückgabetyp: Du hast im Scala-Compiler einen Eckfall gefunden, der es wert ist, der Scala-Gemeinschaft zu signalisieren.

Das heißt, Ihre idSeq hat eine falsche Signatur: H#X bedeutet nicht den X-Typ für den angegebenen H -Typ, sondern X für jede Instanz von H (nicht die, die von der Compiler, siehe Daniel Sobral Erklärung hier Was bedeutet der # # Operator in Scala? )

Wahrscheinlich möchten Sie eine Beziehung zwischen H und Ihrem Ergebnistyp herstellen, was einfacher ist, wenn Sie Typaliase einführen, um eine lesbarere Signatur zu erhalten:

%Vor%

Sie können Ihren Code dann wie folgt neu schreiben:

%Vor%

Dieser Code kompiliert, und beachtet auch, dass Sie, wenn Sie generic und typeclasses korrekt verwenden, nicht zwei verschiedene Methoden benötigen: id und idSeq , da das dynamische Verhalten von typeclass selbst bereitgestellt wird.

    
Edmondo1984 29.02.2016 17:42
quelle

Tags und Links