Wie kann man mit höheren Rängen in Haskell interagieren?

8

Ich rannte in eine rätselhafte Situation mit einem höheren Rang ein. Ich habe herausgefunden, wie es funktioniert, aber ich verstehe den Unterschied zwischen den funktionierenden und nicht funktionierenden Versionen nicht.

Mit diesen Hintergrunddefinitionen:

%Vor%

... was ist der Unterschied zwischen diesen beiden Funktionen?

Version A (was ich ursprünglich geschrieben habe, funktioniert nicht)

%Vor%

Ergebnis:

%Vor%

Wenn Sie dem impredicative types-Vorschlag folgen, den ich nicht vollständig verstehe, ändert sich die Fehlermeldung zu:

%Vor%

Version B, die funktioniert

%Vor%

Andere nicht arbeitende Versionen

%Vor%

Zusammenfassung

Was ist hier los? In meinem Kopf sind diese 5 Definitionen alle syntaktisch unterschiedliche Arten, genau dasselbe zu sagen.

Notiz bearbeiten: Die irrtümliche Angabe, dass es sich um einen existentiellen Typ handelt, wurde entfernt.

    
Doug McClean 26.03.2015, 18:03
quelle

1 Antwort

8

(Nichts in Ihrer Frage verwendet existentielle Typen. Sie haben einen Konstruktor Approximate mit einem polymorphen Argument, was dazu führt, dass Approximate einen Rang-2-Typ hat und zu Problemen mit höherrangigen Typen und Typinferenz führt .)

Die kurze Antwort lautet: Punktfreier Stil und höherrangige Typen passen nicht gut zusammen. Vermeiden Sie die Verwendung der Funktionszusammensetzung, wenn polymorphe Argumente involviert sind und bleiben Sie bei der einfachen Funktionsanwendung oder $ und alles wird gut. Der direkte Weg, um approx auf eine akzeptierte Weise zu schreiben, ist dies:

%Vor%

Das Problem ist, dass GHC "impredicative" Typen nicht richtig unterstützt. Das bedeutet: Wenn eine Funktion polymorph ist, können ihre Typvariablen mit monomorphen Typen instanziiert werden, nicht jedoch mit Typen, die ihrerseits wieder polymorph sind. Warum ist das hier relevant?

Schauen wir uns an, was Sie geschrieben haben:

%Vor%

Sie verwenden die Funktion Zusammensetzung ( . ) hier zweimal. Der Typ der Funktionszusammensetzung ist dies:

%Vor%

Also wird die obige Definition als

geparst %Vor%

Aber

%Vor%

hat einen Rang-2-Typ. Wenn also der Typ von Approximate mit dem ersten Argument von (.) übereinstimmt, bedeutet das:

%Vor%

muss halten.

Es ist diese Instanziierung von b für einen polymorphen Typ, den GHC nicht zulässt. Es schlägt ImpredicativeTypes als eine Spracherweiterung vor, die es funktionieren lässt, aber leider ist es eine sehr fragile Spracherweiterung, und davon wird im Allgemeinen abgeraten. Und wie Sie gesehen haben, benötigt GHC auch mit ImpredicativeTypes in der Regel immer noch einige zusätzliche Typ-Anmerkungen, damit Ihr Programm ohne zusätzliche Änderungen nicht funktioniert.

Die normale Funktionsanwendung ist in GHC integriert und wird bei der Typprüfung anders behandelt. Deshalb funktioniert die direktere Definition von approx . Die Verwendung von $ ist auch in Ordnung, aber nur , weil in GHC ein spezieller Hack implementiert wurde, der dem Typ-Checker mitteilt, dass $ sich wirklich nicht von der Funktionsanwendung unterscheidet.

    
kosmikus 26.03.2015, 19:30
quelle