Ich habe ein kleines Problem mit der positiv bewerteten Antwort für Isomorphismus, da die kategorietheoretische Definition von Isomorphismus nichts über Objekte aussagt. Um zu sehen, warum, überprüfen wir die Definition.
Definition
Ein Isomorphismus ist ein Paar von Morphismen (dh Funktionen), f
und zwar g
so, dass:
f . g = id
g . f = id
Diese Morphismen werden dann "Iso" -Morphismen genannt. Viele Leute verstehen nicht, dass sich der "Morphismus" im Isomorphismus auf die Funktion und nicht auf das Objekt bezieht. Sie würden jedoch sagen, dass die Objekte, die sie verbinden, "isomorph" sind, was die andere Antwort beschreibt.
Beachten Sie, dass die Definition des Isomorphismus nicht sagt, was ( .
) id
oder sein =
muss. Die einzige Voraussetzung ist, dass sie, was auch immer sie sind, auch die Kategoriengesetze erfüllen:
f . id = f
id . f = f
(f . g) . h = f . (g . h)
Die Zusammensetzung (dh ( .
)) verbindet zwei Morphismen zu einem Morphismus und id
bezeichnet eine Art "Identitäts" -Übergang. Das heißt, wenn sich unsere Isomorphismen zum Identitätsmorphismus aufheben, id
können Sie sie als Umkehrungen voneinander betrachten.
Für den speziellen Fall, in dem die Morphismen Funktionen sind, wird dann id
als Identitätsfunktion definiert:
id x = x
... und Zusammensetzung ist definiert als:
(f . g) x = f (g x)
... und zwei Funktionen sind Isomorphismen, wenn sie sich beim Erstellen der Identitätsfunktion aufheben id
.
Morphismen gegen Objekte
Es gibt jedoch mehrere Möglichkeiten, wie zwei Objekte isomorph sein können. Zum Beispiel bei den folgenden zwei Typen:
data T1 = A | B
data T2 = C | D
Es gibt zwei Isomorphismen zwischen ihnen:
f1 t1 = case t1 of
A -> C
B -> D
g1 t2 = case t2 of
C -> A
D -> B
(f1 . g1) t2 = case t2 of
C -> C
D -> D
(f1 . g1) t2 = t2
f1 . g1 = id :: T2 -> T2
(g1 . f1) t1 = case t1 of
A -> A
B -> B
(g1 . f1) t1 = t1
g1 . f1 = id :: T1 -> T1
f2 t1 = case t1 of
A -> D
B -> C
g2 t2 = case t2 of
C -> B
D -> A
f2 . g2 = id :: T2 -> T2
g2 . f2 = id :: T1 -> T1
Deshalb ist es besser, den Isomorphismus anhand der spezifischen Funktionen zu beschreiben, die die beiden Objekte betreffen, als anhand der beiden Objekte, da es möglicherweise nicht unbedingt ein eindeutiges Funktionspaar zwischen zwei Objekten gibt, das die Isomorphismusgesetze erfüllt.
Beachten Sie außerdem, dass es nicht ausreicht, wenn die Funktionen invertierbar sind. Beispielsweise sind die folgenden Funktionspaare keine Isomorphismen:
f1 . g2 :: T2 -> T2
f2 . g1 :: T2 -> T2
Auch wenn beim Verfassen keine Informationen verloren f1 . g2
gehen, kehren Sie nicht in Ihren ursprünglichen Zustand zurück, selbst wenn der endgültige Zustand denselben Typ hat.
Außerdem müssen Isomorphismen nicht zwischen konkreten Datentypen liegen. Hier ist ein Beispiel für zwei kanonische Isomorphismen, die nicht zwischen konkreten algebraischen Datentypen liegen und stattdessen einfach Funktionen in Beziehung setzen: curry
und uncurry
:
curry . uncurry = id :: (a -> b -> c) -> (a -> b -> c)
uncurry . curry = id :: ((a, b) -> c) -> ((a, b) -> c)
Verwendung für Isomorphismen
Kodierung der Kirche
Eine Verwendung von Isomorphismen besteht darin, Datentypen als Funktionen in der Kirche zu kodieren. Zum Beispiel Bool
ist isomorph zu forall a . a -> a -> a
:
f :: Bool -> (forall a . a -> a -> a)
f True = \a b -> a
f False = \a b -> b
g :: (forall a . a -> a -> a) -> Bool
g b = b True False
Überprüfen Sie das f . g = id
und g . f = id
.
Der Vorteil von Church-Codierungsdatentypen besteht darin, dass sie manchmal schneller ausgeführt werden (da Church-Codierung ein Continuation-Passing-Stil ist) und in Sprachen implementiert werden können, die überhaupt keine Sprachunterstützung für algebraische Datentypen bieten.
Implementierungen übersetzen
Manchmal versucht man, die Implementierung einer Funktion einer Bibliothek mit der Implementierung einer anderen Bibliothek zu vergleichen. Wenn Sie beweisen können, dass sie isomorph sind, können Sie beweisen, dass sie gleich leistungsfähig sind. Die Isomorphismen beschreiben auch, wie eine Bibliothek in die andere übersetzt wird.
Beispielsweise gibt es zwei Ansätze, mit denen eine Monade aus der Signatur eines Funktors definiert werden kann. Eine ist die freie Monade, die vom free
Paket bereitgestellt wird , und die andere ist die operative Semantik, die vom operational
Paket bereitgestellt wird .
Wenn Sie sich die beiden Kerndatentypen ansehen, sehen sie unterschiedlich aus, insbesondere ihre zweiten Konstruktoren:
-- modified from the original to not be a monad transformer
data Program instr a where
Lift :: a -> Program instr a
Bind :: Program instr b -> (b -> Program instr a) -> Program instr a
Instr :: instr a -> Program instr a
data Free f r = Pure r | Free (f (Free f r))
... aber sie sind tatsächlich isomorph! Das bedeutet, dass beide Ansätze gleich leistungsfähig sind und jeder in einem Ansatz geschriebene Code mithilfe der Isomorphismen mechanisch in den anderen Ansatz übersetzt werden kann.
Isomorphismen, die keine Funktionen sind
Isomorphismen sind auch nicht auf Funktionen beschränkt. Sie sind tatsächlich für jede definiert Category
und Haskell hat viele Kategorien. Aus diesem Grund ist es sinnvoller, in Morphismen als in Datentypen zu denken.
Beispielsweise bildet der Lens
Typ (von data-lens
) eine Kategorie, in der Sie Linsen zusammenstellen und eine Identitätslinse haben können. Mit unserem obigen Datentyp können wir also zwei Linsen definieren, die Isomorphismen sind:
lens1 = iso f1 g1 :: Lens T1 T2
lens2 = iso g1 f1 :: Lens T2 T1
lens1 . lens2 = id :: Lens T1 T1
lens2 . lens1 = id :: Lens T2 T2
Beachten Sie, dass zwei Isomorphismen im Spiel sind. Einer ist der Isomorphismus, der zum Aufbau jeder Linse (dh f1
und g1
) verwendet wird (und deshalb wird diese Konstruktionsfunktion auch genannt iso
), und dann sind die Linsen selbst auch Isomorphismen. Es ist zu beachten, dass in der obigen Formulierung die verwendete Zusammensetzung ( .
) keine Funktionszusammensetzung, sondern eine Linsenzusammensetzung ist und id
nicht die Identitätsfunktion, sondern die Identitätslinse:
id = iso id id
Das heißt, wenn wir unsere beiden Linsen zusammensetzen, sollte das Ergebnis nicht von dieser Identitätslinse zu unterscheiden sein.