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.