Produkttypen in Haskell sind leicht definierbar:
%Vor%ist ein Produkt zweier Arten. Das Nebenprodukt zweier Typen ist
%Vor%Aber während das Produkt leicht auf drei oder mehr Typen erweiterbar ist, erscheint es für Koprodukte nicht so einfach. Gibt es eine theoretische Begründung für diesen Unterschied oder ist der Grund rein technischer?
Hier ist Fruit
ein Koprodukt von Apple
, Orange
und Berry
1 .
Beachten Sie, dass nicht getaggte Unions nicht Co-Produkte sind.
1 : Nun, irgendwie. Fruit
enthält auch ein zusätzliches Element, ⊥
. Siehe unten.
Sie meinen wahrscheinlich:
%Vor% Wenn Sie data
verwenden, haben Sie einen Produkttyp mit einem einzelnen Konstruktor namens Either
definiert. Das ist vollkommen legal. Wenn Sie type
verwenden, haben Sie Shape
als anderen Namen für Either Circle Rectangle
definiert, was ein Nebenprodukt von Circle
und Rectangle
ist.
Nennen wir die Kategorie der Typen und Funktionen in Haskell, Hask. Dies ist der übliche Name dafür. Es erfüllt die Definition für Kategorie, vorausgesetzt, Sie betrachten diese endlichen Dinge, die wir Computer nennen, nicht zu genau.
Und vergleichen wir Hask mit der Kategorie Set. Das ist natürlich, weil Hask eine konkrete Kategorie ist. Vergleichen Sie den Konstruktor (,)
in Hask mit dem kartesischen Produkt in Set. Wenn wir das Produkt von Int
und Int
wollen, erhalten wir:
⊥ ∈ (Int, Int)
(in Hask), aber ⊥ ∉ Int ⨯ Int
(in Set). Sie sehen also, dass der Typkonstruktor (,)
nicht mit dem kartesischen Produkt identisch ist, da er ein zusätzliches Element ⊥
enthält. Wir können das Argument für die disjunkte Vereinigung wiederholen:
⊥ ∈ Either Int Int
(in Hask), aber ⊥ ∉ Int ⊔ Int
(in Set). In jedem Fall enthält die Struktur in Hask ein zusätzliches Element, ⊥
, das die äquivalente Struktur in Set nicht hätte.
Hask ist auch nicht die Kategorie der spitzen Sets. Zuallererst enthält Hask Morphismen, die keine zugespitzten Morphismen sind.
Für jeden Typ T
in Hask können wir eine Funktion T -> T
so erstellen, dass f x = ⊥
für alle x
. Daher muss ⊥
der Basispunkt sein, wenn Objekte in Hask spitz sind. Beachten Sie, dass alle diese f
strikte Funktionen sind.
Allerdings sollte g
eine beliebige Funktion sein (die korrekte Bezeichnung ist hier eigentlich "nicht-streng"). Nach der Definition der Strenge g ⊥ ≠ ⊥
. Mit # 1 widerspricht dies jedoch der Prämisse, dass Hask die Kategorie der spitzigen Mengen ist.
Zusätzlich sind die Produkt- und Koproduktstrukturen verschieden, ähnlich wie sich die Strukturen von den Strukturen von Set unterscheiden. Für Produkte
(⊥, ⊥) ∈ (Int, Int)
(in Hask), aber (⊥, ⊥) ∉ Int ⊗ Int
(in Pointed Set). Das folgt aus dem Problem mit Morphismen: In spitzen Mengen sind alle Funktionen streng - dies schließt Konstruktoren wie (,)
ein. Das Nebenprodukt hat das gleiche Problem:
Left ⊥ ∈ Either Int Int
(in Hask), aber Left ⊥ ∉ Int ⊕ Int
(in Pointed Set). Also, Set und Pointed Set sind beide nicht ganz gleich der Kategorie Hask. Wie in der Hask Seite im Haskell-Wiki vermerkt, sind die Typen "Produkt" und "Koprodukt" in Haskell einfach nicht vorhanden erfüllen nicht die Definition von kategorischen Produkten und Coprodukten. Genau genommen gibt es in Haskell keine Produkte und Coprodukte.
Das sind die schlechten Nachrichten. Es gibt gute Neuigkeiten.
Betrachte alle strikten Funktionen und strikten Konstruktoren in Hask. Das Ergebnis ist eine Unterkategorie von Hask, die ebenfalls eine Unterkategorie von Pointed Set ist. Diese Unterkategorie ist eine kartesische geschlossene Kategorie.
Betrachte alle totalen Funktionen in Hask und betrachte zwei Funktionen als den gleichen Morphismus, wenn sie die gleiche Ausgabe für jede Eingabe außer ⊥
erzeugen. (Diese Ausgaben müssen nicht unbedingt ⊥
sein, wenn Sie "total" definieren.) Das Ergebnis ist eine Unterkategorie von Set. Diese Unterkategorie ist eine kartesische geschlossene Kategorie.
Sie können also weiterhin mit kartesischen geschlossenen Kategorien arbeiten, solange Sie nach den richtigen Regeln spielen. Sie können sogar aus zwei verschiedenen Kategorien wählen, mit denen Sie arbeiten können! Wenn Sie jedoch nach diesen Regeln spielen, arbeiten Sie mit einer Teilmenge von Haskell.
Es gibt ein letztes bisschen gute Nachrichten. Strikte Funktionen können in Lazy-Funktionen geändert werden, ohne die Ausgaben des Programms als Ganzes zu ändern, vorausgesetzt, die strikte Version des Programms wird beendet. Sie können also so tun, als ob ⊥
nicht existiert und etwas Arbeit mit der Kategorientheorie machen, aber trotzdem Programme schreiben, die eine faule Auswertung ausnutzen.
Vorgeben, dass Hask Produkte und Coprodukte hat, bringt Sie nicht in Schwierigkeiten.
Tags und Links haskell computer-science functional-programming category-theory