Ein freies Foo ist zufällig die einfachste Sache, die alle 'Foo'-Gesetze erfüllt. Das heißt, es erfüllt genau die Gesetze, die notwendig sind, um ein Foo zu sein, und nichts Besonderes.
Ein vergesslicher Funktor ist einer, der einen Teil der Struktur "vergisst", wenn er von einer Kategorie zur anderen wechselt.
Gegebene Funktoren F : D -> C
, und G : C -> D
wir sagen F -| G
, F
ist links neben G
oder G
rechts neben, F
wann immer a, b: F a -> b
isomorph ist a -> G b
, wo die Pfeile aus den entsprechenden Kategorien stammen.
Formal bleibt ein freier Funktor neben einem vergesslichen Funktor.
Das freie Monoid
Beginnen wir mit einem einfacheren Beispiel, dem freien Monoid.
Nehmen Sie ein Monoid, das durch einen Trägersatz definiert ist T
, eine binäre Funktion, um ein Elementpaar zusammenzufügen f :: T → T → T
, und a unit :: T
, so dass Sie ein assoziatives Gesetz und ein Identitätsgesetz haben : f(unit,x) = x = f(x,unit)
.
Sie können einen Funktor machen U
aus der Kategorie der Monoide (wo Pfeile Monoid Homomorphismen sind, das heißt, sie sicherstellen , dass sie Karte unit
zu unit
auf der anderen Monoid, und dass Sie vor oder nach der Abbildung auf die andere Monoid ohne Änderung Bedeutung komponieren kann) in die Kategorie von Sätzen (wobei Pfeile nur Funktionspfeile sind), die die Operation "vergessen" unit
und Ihnen nur den Trägersatz geben.
Anschließend können Sie einen Funktor F
aus der Kategorie der Sets zurück in die Kategorie der Monoide definieren, die neben diesem Funktor verbleibt. Dieser Funktor ist der Funktor, der eine Menge a
dem Monoid zuordnet [a]
, wo unit = []
und mappend = (++)
.
Um unser bisheriges Beispiel in Pseudo-Haskell zu überprüfen:
U : Mon → Set -- is our forgetful functor
U (a,mappend,mempty) = a
F : Set → Mon -- is our free functor
F a = ([a],(++),[])
Dann, um zu zeigen, F
ist kostenlos, müssen wir zeigen, dass es neben U
einem vergesslichen Funktor bleibt, das heißt, wie wir oben erwähnt haben, müssen wir das zeigen
F a → b
ist isomorph zu a → U b
Denken Sie nun daran, dass das Ziel von F
in der Kategorie Mon
der Monoide liegt, in der Pfeile Monoidhomomorphismen sind. Wir müssen also zeigen, dass ein Monoidhomomorphismus von [a] → b
durch eine Funktion von genau beschrieben werden kann a → b
.
In Haskell nennen wir die Seite davon, in der wir leben Set
(ähm, Hask
die Kategorie der Haskell-Typen, die wir vorgeben, ist Set), nur foldMap
die, wenn sie von Data.Foldable
auf Listen spezialisiert ist, Typ hat Monoid m => (a → m) → [a] → m
.
Daraus ergeben sich Konsequenzen als Ergänzung. Insbesondere, wenn Sie vergessen, dann bauen Sie mit kostenlos auf, dann vergessen Sie wieder, es ist genau so, wie Sie es einmal vergessen haben, und wir können dies verwenden, um den monadischen Join aufzubauen. da UFUF
~ U(FUF)
~ UF
und wir den identitätsmonoiden Homomorphismus von [a]
bis [a]
durch den Isomorphismus übergeben können, der unsere Adjunktion definiert, erhalten Sie, dass ein Listenisomorphismus von [a] → [a]
eine Funktion des Typs ista -> [a]
, und dies ist nur eine Rückgabe für Listen.
Sie können dies alles direkter zusammenstellen, indem Sie eine Liste folgendermaßen beschreiben:
newtype List a = List (forall b. Monoid b => (a -> b) -> b)
Die freie Monade
Was ist also eine freie Monade? ?
Nun, wir machen das Gleiche wie zuvor. Wir beginnen mit einem vergesslichen Funktor U von der Kategorie der Monaden, bei der Pfeile Monadenhomomorphismen sind, zu einer Kategorie von Endofunktoren, bei denen die Pfeile natürliche Transformationen sind, und suchen nach einem Funktor, der nebeneinander bleibt dazu.
Wie hängt das mit der Vorstellung einer freien Monade zusammen, wie sie normalerweise verwendet wird?
Zu wissen, dass etwas eine freie Monade ist Free f
, sagt Ihnen, dass das Geben eines Monadenhomomorphismus von Free f -> m
dasselbe ist (isomorph zu) wie das Geben einer natürlichen Transformation (eines Funktorhomomorphismus) von f -> m
. Denken Sie daran, F a -> b
dass es isomorph zu sein muss, a -> U b
damit F neben U bleibt. Hier werden Monaden auf Funktoren abgebildet.
F ist mindestens isomorph zu dem Free
Typ, den ich in meinem free
Paket für Hackage verwende.
Wir könnten es auch in engerer Analogie zum obigen Code für die freie Liste konstruieren, indem wir es definieren
class Algebra f x where
phi :: f x -> x
newtype Free f a = Free (forall x. Algebra f x => (a -> x) -> x)
Kaffeefreie Comonaden
Wir können etwas Ähnliches konstruieren, indem wir den richtigen Zusatz zu einem vergesslichen Funktor betrachten, vorausgesetzt, er existiert. Ein Cofree-Funktor ist einfach / richtig neben einem vergesslichen Funktor, und aus Symmetriegründen ist das Wissen, dass etwas eine Cofree-Comonade ist, dasselbe wie das Wissen, dass das Geben eines Comonad-Homomorphismus aus w -> Cofree f
dasselbe ist wie das Geben einer natürlichen Transformation von w -> f
.