Vorschläge (P -> Q) -> Q
undP \/ Q
sind gleichwertig.
Gibt es eine Möglichkeit, diese Gleichwertigkeit in Haskell zu bezeugen:
from :: Either a b -> ((a -> b) -> b)
from x = case x of
Left a -> \f -> f a
Right b -> \f -> b
to :: ((a -> b) -> b) -> Either a b
to = ???
so dass
from . to = id
und to . from = id
?
((a -> b) -> b)
isomorph ist zua
: Die einzig mögliche Implementierung istg f = f someHardcodedA
.g = const someHardcodedB
a
oderb
. Macht Sinn.to f = callcc (\k -> k (Right (f (\a -> k (Left a)))))
würde das funktionieren. (Dies ist ein gültiger klassischer Beweis für die Implikation.)Antworten:
Dies gilt in der klassischen Logik, nicht jedoch in der konstruktiven Logik.
In der konstruktiven Logik haben wir kein Gesetz der ausgeschlossenen Mitte , dh wir können unser Denken nicht mit "entweder P ist wahr oder P ist nicht wahr" beginnen.
Klassisch argumentieren wir wie:
x :: P
)), dann kehre zurückLeft x
.nx :: P -> Void
Funktion. Dannabsurd . nx :: P -> Q
(wir jede Art Spitze können, nehmen wirQ
) und rufen gegebenf :: (P -> Q) -> Q)
mitabsurd . nx
Wert des Typs zu erhaltenQ
.Das Problem, dass es keine allgemeine Funktion eines Typs gibt:
Für einige konkrete Typen gibt es zB
Bool
bewohnt, damit wir schreiben könnenaber im Allgemeinen können wir nicht.
quelle
Nein, das ist unmöglich. Betrachten Sie den Sonderfall wo
Q = Void
.Either P Q
ist dannEither P Void
, was isomorph zu istP
.Wenn wir also einen Funktionsbegriff hätten
Wir könnten auch einen Begriff haben
Laut der Curry-Howard-Korrespondenz wäre dies eine Tautologie in der intuitionistischen Logik:
Aber das Obige ist die Eliminierung der doppelten Negation, die in der intuitionistischen Logik bekanntermaßen nicht zu beweisen ist - daher ein Widerspruch. (Die Tatsache, dass wir es in klassischer Sprache beweisen konnten Logik ist nicht relevant.)
(Schlussbemerkung: Dies setzt voraus, dass unser Haskell-Programm beendet wird. Natürlich
undefined
können wir mit unendlicher Rekursion und ähnlichen Methoden, um tatsächlich zu vermeiden, dass ein Ergebnis zurückgegeben wird, jeden Typ in Haskell bewohnen.)quelle
Nein, das ist nicht möglich, aber etwas subtil. Das Problem ist, dass die Typvariablen
a
undb
universell quantifiziert werden.a
undb
sind universell quantifiziert. Der Anrufer wählt den Typ aus, sodass Sie nicht einfach einen Wert für einen der beiden Typen erstellen können. Dies bedeutet, dass Sie nicht einfach einen Wert vom Typ erstellen können,Either a b
während Sie das Argument ignorierenf
. Die Verwendungf
ist aber auch unmöglich. Ohne zu wissen, welche Typena
und welche Typen vorhandenb
sind, können Sie keinen Wert für den Typ erstellen,a -> b
an den übergeben werden sollf
. Es sind einfach nicht genügend Informationen verfügbar, wenn die Typen universell quantifiziert werden.Was den Grund betrifft, warum der Isomorphismus in Haskell nicht funktioniert - sind Sie sicher, dass diese Sätze in einer konstruktiven intuitionistischen Logik gleichwertig sind? Haskell implementiert keine klassische deduktive Logik.
quelle
Wie andere betont haben, ist dies unmöglich, weil wir nicht das Gesetz der ausgeschlossenen Mitte haben. Lassen Sie mich das etwas expliziter durchgehen. Angenommen, wir haben
und wir setzen
b ~ Void
. Dann bekommen wirLassen Sie uns nun die doppelte Negation des Gesetzes der ausgeschlossenen Mitte beweisen, wie es auf einen bestimmten Satz angewendet wird .
Also jetzt
lem
kann eindeutig nicht existieren, weila
der Vorschlag kodiert werden kann, dass jede Turing-Maschinenkonfiguration, die ich zufällig auswähle, anhält.Lassen Sie uns überprüfen, ob dies
lem
ausreicht:quelle
Ich habe keine Ahnung, ob dies logisch gültig ist oder was es für Ihre Äquivalenz bedeutet, aber ja, es ist möglich, eine solche Funktion in Haskell zu schreiben.
Um einen zu konstruieren
Either a b
, benötigen wir entweder einena
oder einenb
Wert. Wir haben keine Möglichkeit, einena
Wert zu konstruieren , aber wir haben eine Funktion, die eine zurückgibtb
, die wir aufrufen könnten. Dazu müssen wir eine Funktion angeben , die eina
in ein konvertiert.b
Da die Typen jedoch unbekannt sind, können wir bestenfalls eine Funktion erstellen, die eine Konstante zurückgibtb
. Um diesenb
Wert zu erhalten, können wir ihn nicht anders als zuvor konstruieren, daher wird dies zu einer Zirkelschlussfolgerung - und wir können dies lösen, indem wir einfach einen Fixpunkt erstellen :quelle