Können Literale in funktionalen Sprachen als Funktionen des leeren Typs betrachtet werden?

7

Vor einiger Zeit, glaube ich, habe ich bei Stack Overflow jemanden sagen sehen, dass Haskell-Literale als Funktionen betrachtet werden können, die mit nichts funktionieren. Das macht für mich Sinn, aber ich erinnere mich, dass jemand anderes ihm vehement widersprach.

Wenn ich das richtig verstehe, sind alle Werte in primitiven Typen oder zumindest die in BoolTypkonstruktoren, und Typkonstruktoren sind eine spezielle Art von Funktion für den Typ. Da die Werte mögen 2.87, Trueoder 'f'haben keine Parameter an sie übergeben es scheint , wie es nicht die Semantik der Sprache bewirken würde , ob Sie an sie denken nur als Elemente ihrer Art oder eine Funktion von einem Typ nichts in ihrer Art enthält , das gibt immer ihren Wert zurück. Ist etwas falsch daran, auf diese Weise an Literale zu denken?

Anon Ymous
quelle
3
Meinen Sie Funktionen vom Einheitentyp (dh das leere Tupel)? In diesem Fall ja.
Gallais
1
@gallais Ah ja, ich habe darüber aus der Perspektive einer abhängigen Typentheorie nachgedacht, in der die Einheit ein Element hat. Aber das macht Sinn, danke, du solltest daraus eine Antwort machen.
Anon Ymous

Antworten:

10

Beginnen wir in einer Gesamtsprache wie Agda. Dann ist dies, wie Gallais feststellt, nur dann sinnvoll, wenn Sie mit "leerer Typ" den Einheitentyp meinen, dh das 0-fache Tupel, das genau einen Wert hat. Der leere Typ kann als Summentyp mit 0 Fällen betrachtet werden und hat überhaupt keine Werte. In Agda können Sie leicht beweisen, dass dies Unit -> Aisomorph ist A. In diesem Sinne können Sie sie als gleich betrachten, obwohl sie immer noch nicht buchstäblich gleich sind. Ich kann zum Beispiel keine Fallanalyse für eine durchführen Unit -> Booloder True : Boolauf irgendetwas als Funktion anwenden .

Die Geschichte für Haskell ist ganz anders. () -> Aund Asind semantisch nicht isomorphe Typen. Insbesondere () -> ()vier Werte hat, während ()nur hat 2. Die vier beobachtungs unterschiedliche Werte sind undefined, \_ -> undefined, \x -> x, \_ -> (). Ist ()also eigentlich kein Einheitentyp in dem Sinne, dass es genau eine Funktion gibt (). (In Agda hingegen können wir beweisen, dass wenn x : Unitund y : Unitdann gleich sind [definitiv, wenn wir Unitmit der recordSyntax im Gegensatz zur dataSyntax definieren]. Das heißt, es Unithat nur einen Wert. Außerdem können wir das beweisen Unitund A -> Unitsind für jeden isomorph A.)

Tatsächlich ist ein "leerer" Typ, wie er Voiddefiniert data Voidist, in diesem Sinne eher ein Einheitentyp. Voidhat nur einen Wert, aber Void -> Voidimmer noch zwei. Tatsächlich hat jeder Funktionstyp A -> Bmindestens zwei beobachtungsmäßig unterschiedliche Werte, nämlich undefinedund \_ -> undefined. Daher hat Haskell keine echte Einheit oder keinen leeren Typ.

Vieles davon ist darauf zurückzuführen, dass Haskell eine nicht strenge Sprache ist und durch die Existenz von seq(und seinen Äquivalenten) verärgert ist . Zum Beispiel ist die Unterscheidung zwischen undefinedund \_ -> undefinednur mit zu sehen seq. Wenn wir seqHaskell und seine Äquivalente eliminieren Voidwürden , würde dies als Einheitentyp dienen, ironischerweise jedoch immer noch nicht als leerer Typ.

Wenn Leute in Haskell über solche Dinge sprechen, tun sie normalerweise stillschweigend so, als sei Haskell eine Sprache, die sich besser benimmt als sie. Das heißt, sie gehen davon aus, dass es für ihre Zwecke keine Bottoms gibt, dh dass Sie in einer Gesamtsprache wie Agda arbeiten. Für die Gestaltung Ihres Codes ist dies normalerweise ausreichend. Es ist nicht üblich, dass wir uns um Unterteile kümmern oder diese erwarten. Diese Unterscheidungen können wichtig werden, wenn wir so etwas wie zirkuläre Programmierung durchführen oder wenn Sicherheitsgarantien unseres Programms auf diesen Eigenschaften beruhen, z. B. kann eine Funktion niemals aufgerufen werden, wenn sie einen leeren Typ als Domäne hat.

Derek Elkins verließ SE
quelle
1
Definiert Haskell aus Neugier irgendwo offiziell den Begriff eines Wertes (im Gegensatz zu einem Begriff)?
Andrej Bauer
1
@AndrejBauer Wie Sie wissen, hat Haskell keine formale Semantik, daher gibt es keine formale Definition von Wert. Der Haskell-Bericht verwendet zwar das Wort " Wert ", definiert es jedoch nur teilweise nebenbei, da er Ausdrücke erklärt. Beispielsweise wird ausdrücklich angegeben, dass Fehler / Nichtbeendigung Werte sind .
Derek Elkins verließ SE
Ja, ich mag es einfach, Haskelliten wegen des Fehlens einer tatsächlichen Definition der Sprache zu ärgern.
Andrej Bauer
@AndrejBauer Das ist in der Tat unglücklich. Die Folklore möchte, dass einige Fragmente von Haskell semantisch sind, aber keine einheitliche Definition. Es ist wahrscheinlich zu viel geworden, um mit angemessenem Aufwand gehandhabt zu werden: Dinge wie STsicherer Zwang, eqTGADTs, Typenfamilien, sehr allgemeine Typklassen (inkohärent?!) Usw. sehen etwas umständlich aus. Hier könnte es sogar ein Return-of-Investment-Problem geben: Selbst wenn man (?) Eine formale Semantik zu hohen Kosten erstellen könnte, hätte dies eine entsprechend große Auswirkung? Wahrscheinlich nicht. Und in 2 Jahren würde eine neue GHC-Erweiterung es brechen ... :-(
Chi
1
@chi Eigentlich sieht das K Framework-Projekt im Allgemeinen ziemlich interessant aus und es gibt ein aktives Projekt , um eine mechanisierte Formulierung von GHC Core darin bereitzustellen. Die Arbeit, die das K Framework auf C, Java und JavaScript anwendet, scheint ziemlich vielversprechend, und die Idee hinter dem K Framework (und der zugehörigen Matching-Logik ) besteht darin, den ROI für mechanisierte Semantik zu erhöhen, indem mehrere Tools aus einer gemeinsamen Semantik generiert werden.
Derek Elkins verließ SE